From 9adb1a2d7a6fcd2f23268227a5c668993398b24d Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Thu, 1 Aug 2024 21:54:21 -0700 Subject: [PATCH 01/60] Update package-lock.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8d7a969a..375f92aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-autohotkey2-lsp", - "version": "2.4.6", + "version": "2.4.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-autohotkey2-lsp", - "version": "2.4.6", + "version": "2.4.8", "license": "LGPLv3.0", "dependencies": { "vscode-languageclient": "^9.0.1", From e60b909e59f73132178233458d7e65b78ce77692 Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Thu, 1 Aug 2024 21:54:51 -0700 Subject: [PATCH 02/60] Add recommended extensions --- .vscode/extensions.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..7a98c00d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "aaron-bond.better-comments", + "dbaeumer.vscode-eslint" + ] +} \ No newline at end of file From d486ad97631679f906e913f17ec45ce3e0a46c7e Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Thu, 1 Aug 2024 22:01:13 -0700 Subject: [PATCH 03/60] Add @vscode/test-web^0.0.56 --- package-lock.json | 1747 +++++++++++++++++++++++++++++++++++++++++++-- package.json | 16 +- 2 files changed, 1698 insertions(+), 65 deletions(-) diff --git a/package-lock.json b/package-lock.json index 375f92aa..aea2ebb2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "devDependencies": { "@eslint/js": "^9.4.0", "@types/vscode": "^1.82.0", + "@vscode/test-web": "^0.0.56", "@vscode/vsce": "^2.27.0", "eslint": "^9.4.0", "globals": "^15.4.0", @@ -416,6 +417,53 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -480,6 +528,36 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@koa/cors": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/@koa/cors/-/cors-5.0.0.tgz", + "integrity": "sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@koa/router": { + "version": "12.0.1", + "resolved": "https://registry.npmmirror.com/@koa/router/-/router-12.0.1.tgz", + "integrity": "sha512-ribfPYfHb+Uw3b27Eiw6NPqjhIhTpVFzEWLwyc/1Xp+DCdwRRyIlAUODX+9bPARF6aQtUu1+/PHzdNvRzcs/+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "http-errors": "^2.0.0", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.2.1" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -518,6 +596,31 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmmirror.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@playwright/browser-chromium": { + "version": "1.45.3", + "resolved": "https://registry.npmmirror.com/@playwright/browser-chromium/-/browser-chromium-1.45.3.tgz", + "integrity": "sha512-UVPW8HveE8SghaahoMy8CfG0QdJ2mO0BZLOcPT8nlQh7Z97Gkv4e3Ad69D1oCqM3m3zYkDPAiGB+hOASNS0d/g==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.45.3" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@types/eslint": { "version": "8.56.10", "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.10.tgz", @@ -689,6 +792,110 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@vscode/test-web": { + "version": "0.0.56", + "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", + "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@koa/cors": "^5.0.0", + "@koa/router": "^12.0.1", + "@playwright/browser-chromium": "^1.45.0", + "glob": "^10.4.2", + "gunzip-maybe": "^1.4.2", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.4", + "koa": "^2.15.3", + "koa-morgan": "^1.0.1", + "koa-mount": "^4.0.0", + "koa-static": "^5.0.0", + "minimist": "^1.2.8", + "playwright": "^1.45.0", + "tar-fs": "^3.0.6", + "vscode-uri": "^3.0.8" + }, + "bin": { + "vscode-test-web": "out/index.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@vscode/test-web/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vscode/test-web/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-web/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-web/node_modules/tar-fs": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/@vscode/test-web/node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/@vscode/vsce": { "version": "2.27.0", "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-2.27.0.tgz", @@ -1090,6 +1297,20 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.11.3.tgz", @@ -1221,12 +1442,70 @@ "typed-rest-client": "^1.8.4" } }, + "node_modules/b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmmirror.com/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, + "node_modules/bare-events": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/bare-events/-/bare-events-2.4.2.tgz", + "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "dev": true, + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-fs": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/bare-fs/-/bare-fs-2.3.1.tgz", + "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-events": "^2.0.0", + "bare-path": "^2.0.0", + "bare-stream": "^2.0.0" + } + }, + "node_modules/bare-os": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/bare-os/-/bare-os-2.4.0.tgz", + "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", + "dev": true, + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-path": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/bare-path/-/bare-path-2.1.3.tgz", + "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-os": "^2.1.0" + } + }, + "node_modules/bare-stream": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/bare-stream/-/bare-stream-2.1.3.tgz", + "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "streamx": "^2.18.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", @@ -1249,6 +1528,26 @@ "license": "MIT", "optional": true }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", @@ -1293,6 +1592,16 @@ "node": ">=8" } }, + "node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "~0.2.0" + } + }, "node_modules/browserslist": { "version": "4.23.0", "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.23.0.tgz", @@ -1376,6 +1685,20 @@ "dev": true, "license": "MIT" }, + "node_modules/cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz", @@ -1515,6 +1838,17 @@ "node": ">=6" } }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmmirror.com/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, "node_modules/cockatiel": { "version": "3.1.3", "resolved": "https://registry.npmmirror.com/cockatiel/-/cockatiel-3.1.3.tgz", @@ -1579,6 +1913,50 @@ "dev": true, "license": "MIT" }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookies": { + "version": "0.9.1", + "resolved": "https://registry.npmmirror.com/cookies/-/cookies-0.9.1.tgz", + "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1659,6 +2037,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", + "dev": true, + "license": "MIT" + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz", @@ -1715,6 +2100,34 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.3.tgz", @@ -1798,30 +2211,106 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmmirror.com/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.796", - "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.796.tgz", - "integrity": "sha512-NglN/xprcM+SHD2XCli4oC6bWe6kHoytcyLKCWXmRL854F0qhPhaYgUswUsglnPxYaNQIg2uMY4BvaomIf3kLA==", - "dev": true, - "license": "ISC" - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.796", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.796.tgz", + "integrity": "sha512-NglN/xprcM+SHD2XCli4oC6bWe6kHoytcyLKCWXmRL854F0qhPhaYgUswUsglnPxYaNQIg2uMY4BvaomIf3kLA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "once": "^1.4.0" } @@ -1906,6 +2395,13 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -2288,6 +2784,13 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz", @@ -2433,6 +2936,23 @@ "dev": true, "license": "ISC" }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz", @@ -2448,6 +2968,16 @@ "node": ">= 6" } }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz", @@ -2463,6 +2993,21 @@ "dev": true, "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", @@ -2604,6 +3149,24 @@ "dev": true, "license": "MIT" }, + "node_modules/gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "bin": { + "gunzip-maybe": "bin.js" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", @@ -2653,6 +3216,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", @@ -2699,6 +3278,74 @@ "entities": "^4.4.0" } }, + "node_modules/http-assert": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-assert/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -2866,6 +3513,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", @@ -2892,6 +3546,32 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmmirror.com/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", @@ -2905,6 +3585,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", @@ -2951,6 +3641,13 @@ "node": ">=8" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", @@ -2968,6 +3665,22 @@ "node": ">=0.10.0" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", @@ -3126,6 +3839,19 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/keytar": { "version": "7.9.0", "resolved": "https://registry.npmmirror.com/keytar/-/keytar-7.9.0.tgz", @@ -3159,74 +3885,267 @@ "node": ">=0.10.0" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "node_modules/koa": { + "version": "2.15.3", + "resolved": "https://registry.npmmirror.com/koa/-/koa-2.15.3.tgz", + "integrity": "sha512-j/8tY9j5t+GVMLeioLaxweJiKUayFhlGqNTzf2ZGwL0ZCQijd2RLHK0SLW5Tsko8YyyqCZC2cojIb0/s62qTAg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" - } + "dependencies": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.9.0", + "debug": "^4.3.2", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^2.0.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "engines": { + "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + } + }, + "node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "dev": true, + "license": "MIT" }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/koa-convert": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/koa-convert/-/koa-convert-2.0.0.tgz", + "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "co": "^4.6.0", + "koa-compose": "^4.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 10" } }, - "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "node_modules/koa-morgan": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/koa-morgan/-/koa-morgan-1.0.1.tgz", + "integrity": "sha512-JOUdCNlc21G50afBXfErUrr1RKymbgzlrO5KURY+wmDG1Uvd2jmxUJcHgylb/mYXy2SjiNZyYim/ptUBGsIi3A==", "dev": true, "license": "MIT", "dependencies": { - "uc.micro": "^1.0.1" + "morgan": "^1.6.1" } }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "node_modules/koa-mount": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/koa-mount/-/koa-mount-4.0.0.tgz", + "integrity": "sha512-rm71jaA/P+6HeCpoRhmCv8KVBIi0tfGuO/dMKicbQnQW/YJntJ6MnnspkodoA4QstMVEZArsCphmd0bJEtoMjQ==", "dev": true, "license": "MIT", + "dependencies": { + "debug": "^4.0.1", + "koa-compose": "^4.1.0" + }, "engines": { - "node": ">=6.11.5" + "node": ">= 7.6.0" } }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/koa-send": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/koa-send/-/koa-send-5.0.1.tgz", + "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "resolve-path": "^1.4.0" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "node_modules/koa-send/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "node_modules/koa-send/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa-send/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa-static": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/koa-static/-/koa-static-5.0.0.tgz", + "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.1.0", + "koa-send": "^5.0.0" + }, + "engines": { + "node": ">= 7.6.0" + } + }, + "node_modules/koa-static/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/koa/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", "dev": true, "license": "MIT" }, @@ -3319,6 +4238,16 @@ "dev": true, "license": "MIT" }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", @@ -3336,6 +4265,16 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.7", "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.7.tgz", @@ -3419,11 +4358,20 @@ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", - "optional": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmmirror.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -3432,6 +4380,53 @@ "license": "MIT", "optional": true }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", @@ -3461,6 +4456,16 @@ "dev": true, "license": "MIT" }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", @@ -3520,6 +4525,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", @@ -3530,6 +4558,12 @@ "wrappy": "1" } }, + "node_modules/only": { + "version": "0.0.2", + "resolved": "https://registry.npmmirror.com/only/-/only-0.0.2.tgz", + "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==", + "dev": true + }, "node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz", @@ -3605,6 +4639,20 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmmirror.com/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "dev": true, + "license": "MIT" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", @@ -3665,6 +4713,16 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", @@ -3709,6 +4767,37 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "dev": true, + "license": "MIT" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", @@ -3719,6 +4808,18 @@ "node": ">=8" } }, + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", @@ -3759,6 +4860,38 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.45.3", + "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.45.3.tgz", + "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.45.3" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.45.3", + "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.45.3.tgz", + "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/prebuild-install": { "version": "7.1.2", "resolved": "https://registry.npmmirror.com/prebuild-install/-/prebuild-install-7.1.2.tgz", @@ -3797,13 +4930,42 @@ "node": ">= 0.8.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "license": "MIT", - "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -3856,6 +5018,13 @@ ], "license": "MIT" }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true, + "license": "MIT" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", @@ -3963,7 +5132,71 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=8" + } + }, + "node_modules/resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/resolve-path/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/resolve-path/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/resolve-path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true, + "license": "ISC" + }, + "node_modules/resolve-path/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/resolve-path/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, "node_modules/reusify": { @@ -4088,6 +5321,13 @@ "node": ">= 0.4" } }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -4143,6 +5383,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz", @@ -4233,6 +5486,16 @@ "node": ">=0.10.0" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/stoppable": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/stoppable/-/stoppable-1.1.0.tgz", @@ -4244,6 +5507,28 @@ "npm": ">=6" } }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/streamx": { + "version": "2.18.0", + "resolved": "https://registry.npmmirror.com/streamx/-/streamx-2.18.0.tgz", + "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4255,6 +5540,76 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4268,6 +5623,20 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -4408,6 +5777,16 @@ "dev": true, "license": "MIT" }, + "node_modules/text-decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/text-decoder/-/text-decoder-1.1.1.tgz", + "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", @@ -4415,6 +5794,50 @@ "dev": true, "license": "MIT" }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.3.tgz", @@ -4438,6 +5861,16 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -4555,6 +5988,16 @@ "dev": true, "license": "0BSD" }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.x" + } + }, "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmmirror.com/tunnel/-/tunnel-0.0.6.tgz", @@ -4592,6 +6035,20 @@ "node": ">= 0.8.0" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typed-rest-client": { "version": "1.8.11", "resolved": "https://registry.npmmirror.com/typed-rest-client/-/typed-rest-client-1.8.11.tgz", @@ -4833,8 +6290,7 @@ "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/uuid": { "version": "8.3.2", @@ -4846,6 +6302,16 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", @@ -5108,6 +6574,143 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", @@ -5139,6 +6742,16 @@ "node": ">=4.0" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", @@ -5167,6 +6780,16 @@ "buffer-crc32": "~0.2.3" } }, + "node_modules/ylru": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/ylru/-/ylru-1.4.0.tgz", + "integrity": "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index afe3ce90..89cb9228 100644 --- a/package.json +++ b/package.json @@ -56,8 +56,15 @@ "light": "icon_filetype.png" } }, - { "id": "ahk", "aliases": ["AutoHotkey"] }, - { "id": "~ahk2-output" } + { + "id": "ahk", + "aliases": [ + "AutoHotkey" + ] + }, + { + "id": "~ahk2-output" + } ], "grammars": [ { @@ -584,6 +591,7 @@ "devDependencies": { "@eslint/js": "^9.4.0", "@types/vscode": "^1.82.0", + "@vscode/test-web": "^0.0.56", "@vscode/vsce": "^2.27.0", "eslint": "^9.4.0", "globals": "^15.4.0", @@ -600,5 +608,7 @@ "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, - "overrides": { "eslint": "^9.4.0" } + "overrides": { + "eslint": "^9.4.0" + } } From 302e1d70aaca49bed868c2fd145b18589cda8bff Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Fri, 2 Aug 2024 11:35:56 -0700 Subject: [PATCH 04/60] Add test-data folder --- test-data/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 test-data/.gitignore diff --git a/test-data/.gitignore b/test-data/.gitignore new file mode 100644 index 00000000..ac456bfc --- /dev/null +++ b/test-data/.gitignore @@ -0,0 +1 @@ +# this file is present so the test-data folder is present when others clone the repo \ No newline at end of file From 299b79a3b352770c3ef26a11f18c5705f8b15637 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 11 Aug 2024 20:30:55 -0700 Subject: [PATCH 05/60] Add first formatter test (#5) --- .vscode/settings.json | 7 +- client/.vscode-test.mjs | 7 +- client/src/test/formattingProvider.test.ts | 90 ++ client/src/test/samples/0-format.in.ahk2 | 4 + client/src/test/samples/0-format.out.ahk2 | 4 + client/src/test/utils.ts | 13 + package-lock.json | 1044 +++++++++++++++++--- package.json | 15 +- 8 files changed, 1062 insertions(+), 122 deletions(-) create mode 100644 client/src/test/formattingProvider.test.ts create mode 100644 client/src/test/samples/0-format.in.ahk2 create mode 100644 client/src/test/samples/0-format.out.ahk2 create mode 100644 client/src/test/utils.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 0b400d3d..d4d6356d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,8 @@ "typescript.tsc.autoDetect": "off", "typescript.preferences.quoteStyle": "single", "git.ignoreLimitWarning": true, - "AutoHotkey2.InterpreterPath": "c:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe" -} \ No newline at end of file + "AutoHotkey2.InterpreterPath": "c:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe", + "[ahk2]": { + "editor.formatOnSave": false + } +} diff --git a/client/.vscode-test.mjs b/client/.vscode-test.mjs index 5812c63a..efac995e 100644 --- a/client/.vscode-test.mjs +++ b/client/.vscode-test.mjs @@ -1,6 +1,7 @@ // https://github.com/microsoft/vscode-test-cli import { defineConfig } from '@vscode/test-cli'; export default defineConfig({ - files: 'dist/test/**/*.test.js', - version: '1.92.0' -}); \ No newline at end of file + extensionDevelopmentPath: '..', + files: 'dist/**/*.test.js', + version: '1.92.0', +}); diff --git a/client/src/test/formattingProvider.test.ts b/client/src/test/formattingProvider.test.ts new file mode 100644 index 00000000..69694f44 --- /dev/null +++ b/client/src/test/formattingProvider.test.ts @@ -0,0 +1,90 @@ +import { getDocument, sleep } from '../test/utils'; +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as vscode from 'vscode'; + +const inFilenameSuffix = '.in.ahk2'; +const outFilenameSuffix = '.out.ahk2'; +interface FormatTest { + /** Name of the file, excluding the suffix (@see inFilenameSuffix, @see outFilenameSuffix) */ + filenameRoot: string; +} + +// Currently in `out` folder, need to get back to main `src` folder +// * this path changes if you import from the server folder +const filesParentPath = path.join( + __dirname, // client/dist/test + '..', // client/dist + '..', // client + 'src', // client/src + 'test', // client/src/test + 'samples', // client/src/test/samples +); + +suite('External formatter', () => { + const externalFormatTests: FormatTest[] = [{ filenameRoot: '0-format' }]; + + externalFormatTests.forEach((formatTest) => { + test(`${formatTest.filenameRoot} external format`, async () => { + // Arrange + const inFilename = formatTest.filenameRoot + inFilenameSuffix; + const outFilename = formatTest.filenameRoot + outFilenameSuffix; + const outFileString = fs + .readFileSync(path.join(filesParentPath, outFilename)) + .toString(); + const unformattedSampleFile = await getDocument( + path.join(filesParentPath, inFilename), + ); + const originalText = unformattedSampleFile.getText(); + const textEditor = await vscode.window.showTextDocument( + unformattedSampleFile, + ); + let eventFired = false; + const formattingPromise = new Promise((resolve) => { + const disposable = vscode.workspace.onDidChangeTextDocument( + (event) => { + if (event.document === textEditor.document) { + eventFired = true; + disposable.dispose(); + resolve(); + } + }, + ); + }); + + // Act + while (!eventFired) { + await vscode.commands.executeCommand( + 'editor.action.formatDocument', + ); + await sleep(50); + } + await formattingPromise; + + // Assert + assert.strictEqual(textEditor.document.getText(), outFileString); + + // Teardown - revert the file to its original state + const lastLineIndex = unformattedSampleFile.lineCount - 1; + const lastLineLength = + unformattedSampleFile.lineAt(lastLineIndex).text.length; + const fullDocumentRange = unformattedSampleFile.validateRange( + new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position(lastLineIndex + 1, lastLineLength + 1), // + 1 to ensure full coverage + ), + ); + + // editing the file also saves the file + await textEditor.edit((editBuilder) => + editBuilder.replace(fullDocumentRange, originalText), + ); + + // Close opened file + await vscode.commands.executeCommand( + 'workbench.action.closeActiveEditor', + ); + }); + }); +}); diff --git a/client/src/test/samples/0-format.in.ahk2 b/client/src/test/samples/0-format.in.ahk2 new file mode 100644 index 00000000..7daa338b --- /dev/null +++ b/client/src/test/samples/0-format.in.ahk2 @@ -0,0 +1,4 @@ +#Requires AutoHotkey v2 + +; This is a comment + MsgBox("Hello, world!") \ No newline at end of file diff --git a/client/src/test/samples/0-format.out.ahk2 b/client/src/test/samples/0-format.out.ahk2 new file mode 100644 index 00000000..ea097373 --- /dev/null +++ b/client/src/test/samples/0-format.out.ahk2 @@ -0,0 +1,4 @@ +#Requires AutoHotkey v2 + +; This is a comment +MsgBox("Hello, world!") \ No newline at end of file diff --git a/client/src/test/utils.ts b/client/src/test/utils.ts new file mode 100644 index 00000000..d3318b63 --- /dev/null +++ b/client/src/test/utils.ts @@ -0,0 +1,13 @@ +import * as vscode from 'vscode'; + +/** + * Shortcut for `vscode.workspace.openTextDocument(Uri.file(fileName))` + * @param path A name of a file on disk. This is the full path to the file. + */ +export const getDocument = async (path: string): Promise => + await vscode.workspace.openTextDocument(path); + +// Copying to test helpers for easy import +export async function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} diff --git a/package-lock.json b/package-lock.json index c646a7a2..c9419c12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,11 +22,11 @@ "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", "@vscode/vsce": "^2.27.0", + "del-cli": "^5.1.0", "eslint": "^9.4.0", "globals": "^15.4.0", "mocha": "^10.7.0", "path-browserify": "^1.0.1", - "rimraf": "^6.0.1", "sinon": "^18.0.0", "ts-loader": "^9.4.0", "typescript": "^5.3.2", @@ -261,6 +261,46 @@ "node": ">=16" } }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -736,6 +776,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/mocha": { "version": "10.0.7", "resolved": "https://registry.npmmirror.com/@types/mocha/-/mocha-10.0.7.tgz", @@ -753,6 +800,13 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/sinon": { "version": "17.0.3", "resolved": "https://registry.npmmirror.com/@types/sinon/-/sinon-17.0.3.tgz", @@ -1561,6 +1615,23 @@ "node": ">= 14" } }, + "node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", @@ -1652,6 +1723,16 @@ "node": ">=8" } }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", @@ -1753,8 +1834,7 @@ "url": "https://feross.org/support" } ], - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/basic-auth": { "version": "2.0.1", @@ -2081,6 +2161,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001629", "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001629.tgz", @@ -2213,6 +2312,35 @@ "node": ">=6.0" } }, + "node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clean-stack/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-cursor": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", @@ -2257,6 +2385,82 @@ "node": ">=12" } }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz", @@ -2474,6 +2678,43 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz", @@ -2544,6 +2785,96 @@ "node": ">=8" } }, + "node_modules/del": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/del/-/del-7.1.0.tgz", + "integrity": "sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "^13.1.2", + "graceful-fs": "^4.2.10", + "is-glob": "^4.0.3", + "is-path-cwd": "^3.0.0", + "is-path-inside": "^4.0.0", + "p-map": "^5.5.0", + "rimraf": "^3.0.2", + "slash": "^4.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del-cli": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/del-cli/-/del-cli-5.1.0.tgz", + "integrity": "sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "del": "^7.1.0", + "meow": "^10.1.3" + }, + "bin": { + "del": "cli.js", + "del-cli": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmmirror.com/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2819,6 +3150,16 @@ "node": ">=4" } }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz", @@ -3641,6 +3982,16 @@ "gunzip-maybe": "bin.js" } }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", @@ -3884,8 +4235,7 @@ "url": "https://feross.org/support" } ], - "license": "BSD-3-Clause", - "optional": true + "license": "BSD-3-Clause" }, "node_modules/ignore": { "version": "5.3.1", @@ -3961,9 +4311,22 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, @@ -3998,6 +4361,13 @@ "node": ">= 0.10" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -4106,6 +4476,19 @@ "node": ">=0.10.0" } }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", @@ -4116,6 +4499,19 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-path-cwd/-/is-path-cwd-3.0.0.tgz", + "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -4318,6 +4714,13 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", @@ -4425,6 +4828,13 @@ "setimmediate": "^1.0.5" } }, + "node_modules/jszip/node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/jszip/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", @@ -4761,6 +5171,13 @@ "immediate": "~3.0.5" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-3.0.3.tgz", @@ -4979,6 +5396,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-12.3.2.tgz", @@ -5023,6 +5453,56 @@ "node": ">= 0.6" } }, + "node_modules/meow": { + "version": "10.1.5", + "resolved": "https://registry.npmmirror.com/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", @@ -5100,6 +5580,16 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz", @@ -5114,6 +5604,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", @@ -5137,6 +5637,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minimist-options/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz", @@ -5612,6 +6137,22 @@ "dev": true, "license": "MIT" }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", @@ -5678,6 +6219,22 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/only": { "version": "0.0.2", "resolved": "https://registry.npmmirror.com/only/-/only-0.0.2.tgz", @@ -5870,6 +6427,22 @@ "node": ">=8" } }, + "node_modules/p-map": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-5.5.0.tgz", + "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", @@ -5907,6 +6480,25 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse-semver": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/parse-semver/-/parse-semver-1.1.1.tgz", @@ -6266,6 +6858,19 @@ "dev": true, "license": "MIT" }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", @@ -6306,13 +6911,114 @@ "node": ">=0.8" } }, + "node_modules/read-pkg": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -6348,6 +7054,23 @@ "node": ">= 0.10" } }, + "node_modules/redent": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", @@ -6463,128 +7186,53 @@ "node": ">= 0.6" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmmirror.com/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": "20 || >=22" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rimraf/node_modules/jackspeak": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-4.0.1.tgz", - "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } + "license": "ISC" }, - "node_modules/rimraf/node_modules/lru-cache": { - "version": "11.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.0.0.tgz", - "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": "20 || >=22" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "glob": "^7.1.3" }, - "engines": { - "node": "20 || >=22" + "bin": { + "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -6701,6 +7349,13 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -6908,6 +7563,42 @@ "node": ">=0.10.0" } }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.18", + "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", @@ -6918,6 +7609,59 @@ "node": ">= 0.8" } }, + "node_modules/stdin-discarder": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", + "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stdin-discarder/node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/stdin-discarder/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/stoppable": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/stoppable/-/stoppable-1.1.0.tgz", @@ -6957,7 +7701,6 @@ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -7059,6 +7802,22 @@ "node": ">=8" } }, + "node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -7308,6 +8067,19 @@ "node": ">=0.6" } }, + "node_modules/trim-newlines": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -7482,6 +8254,19 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz", @@ -7764,6 +8549,17 @@ "node": ">=10.12.0" } }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", @@ -8283,6 +9079,28 @@ "node": ">=10" } }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmmirror.com/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index 94e2159d..a9d3f651 100644 --- a/package.json +++ b/package.json @@ -578,7 +578,10 @@ }, "scripts": { "vscode:prepublish": "webpack --mode production --devtool hidden-source-map", - "compile": "rimraf client/dist && webpack", + "clean//": "Remove both the compiled extension and compiled test files", + "clean": "del-cli client/dist server/dist/*.js*", + "compile//": "Compile the extension for packaging and publishing", + "compile": "webpack", "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", "eslint": "eslint --fix", "watch": "tsc -b -w", @@ -587,8 +590,12 @@ "publish": "vsce publish", "package": "vsce package", "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", - "test": "cd client && tsc && vscode-test", - "validate": "npm run compile && npm run test && npm run package" + "compile-test//": "Compile test files", + "compile-test": "cd client && tsc", + "pretest": "npm run compile-test", + "test//": "Run tests. Requires the extension to be compiled", + "test": "cd client && vscode-test", + "validate": "npm run clean && npm run vscode:prepublish && npm run test && npm run package" }, "devDependencies": { "@eslint/js": "^9.4.0", @@ -598,11 +605,11 @@ "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", "@vscode/vsce": "^2.27.0", + "del-cli": "^5.1.0", "eslint": "^9.4.0", "globals": "^15.4.0", "mocha": "^10.7.0", "path-browserify": "^1.0.1", - "rimraf": "^6.0.1", "sinon": "^18.0.0", "ts-loader": "^9.4.0", "typescript": "^5.3.2", From 81a3c14e98d7bb1547d9c41f9664903251100678 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Mon, 12 Aug 2024 19:00:49 -0700 Subject: [PATCH 06/60] Add grammar test (#6) --- package-lock.json | 62 ++++++++++++++++++++++++++++ package.json | 2 + syntaxes/samples/0-v2-demo.ahk2 | 3 ++ syntaxes/samples/0-v2-demo.ahk2.snap | 31 ++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 syntaxes/samples/0-v2-demo.ahk2 create mode 100644 syntaxes/samples/0-v2-demo.ahk2.snap diff --git a/package-lock.json b/package-lock.json index c9419c12..4e7eb7c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", + "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" }, @@ -1889,6 +1890,13 @@ "dev": true, "license": "ISC" }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmmirror.com/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true, + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -8648,6 +8656,60 @@ "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", "license": "MIT" }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-textmate": { + "version": "7.0.4", + "resolved": "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-7.0.4.tgz", + "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-tmgrammar-test": { + "version": "0.1.3", + "resolved": "https://registry.npmmirror.com/vscode-tmgrammar-test/-/vscode-tmgrammar-test-0.1.3.tgz", + "integrity": "sha512-Wg6Pz+ePAT1O+F/A1Fc4wS5vY2X+HNtgN4qMdL+65NLQYd1/zdDWH4fhwsLjX8wTzeXkMy49Cr4ZqWTJ7VnVxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bottleneck": "^2.19.5", + "chalk": "^2.4.2", + "commander": "^9.2.0", + "diff": "^4.0.2", + "glob": "^7.1.6", + "vscode-oniguruma": "^1.5.1", + "vscode-textmate": "^7.0.1" + }, + "bin": { + "vscode-tmgrammar-snap": "dist/snapshot.js", + "vscode-tmgrammar-test": "dist/unit.js" + } + }, + "node_modules/vscode-tmgrammar-test/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/vscode-tmgrammar-test/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/vscode-uri": { "version": "3.0.8", "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.0.8.tgz", diff --git a/package.json b/package.json index a9d3f651..0f19c49b 100644 --- a/package.json +++ b/package.json @@ -595,6 +595,7 @@ "pretest": "npm run compile-test", "test//": "Run tests. Requires the extension to be compiled", "test": "cd client && vscode-test", + "test_grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", "validate": "npm run clean && npm run vscode:prepublish && npm run test && npm run package" }, "devDependencies": { @@ -614,6 +615,7 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", + "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" }, diff --git a/syntaxes/samples/0-v2-demo.ahk2 b/syntaxes/samples/0-v2-demo.ahk2 new file mode 100644 index 00000000..6dd66f59 --- /dev/null +++ b/syntaxes/samples/0-v2-demo.ahk2 @@ -0,0 +1,3 @@ +#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle) +#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle +#HotIf diff --git a/syntaxes/samples/0-v2-demo.ahk2.snap b/syntaxes/samples/0-v2-demo.ahk2.snap new file mode 100644 index 00000000..e9f040a5 --- /dev/null +++ b/syntaxes/samples/0-v2-demo.ahk2.snap @@ -0,0 +1,31 @@ +>#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle) +#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 +# ^^^^^ source.ahk2 keyword.control.directive.ahk2 +# ^ source.ahk2 +# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 +# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 +# ^^^^^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 +# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 +# ^ source.ahk2 +# ^^ source.ahk2 keyword.operator.expression.ahk2 +# ^ source.ahk2 +# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 +# ^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 variable.other.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 +>#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle +#^^^^^^ source.ahk2 hotkey.ahk2 keyword.keys.ahk2 +# ^^ source.ahk2 punctuation.definition.colon +# ^^^^^^ source.ahk2 variable.other.ahk2 support.function.ahk2 +# ^ source.ahk2 +# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.ahk2 string.quoted.ahk2 +# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 +# ^ source.ahk2 +# ^^^^^^^^^^^^^ source.ahk2 variable.other.ahk2 +>#HotIf +#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 +# ^^^^^ source.ahk2 keyword.control.directive.ahk2 +> \ No newline at end of file From 79b8722b4e65f540f4d689f4705d726687bf0e5c Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Mon, 12 Aug 2024 19:04:04 -0700 Subject: [PATCH 07/60] Validate grammar in validate script (#7) --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 0f19c49b..e70dc693 100644 --- a/package.json +++ b/package.json @@ -595,8 +595,8 @@ "pretest": "npm run compile-test", "test//": "Run tests. Requires the extension to be compiled", "test": "cd client && vscode-test", - "test_grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", - "validate": "npm run clean && npm run vscode:prepublish && npm run test && npm run package" + "test-grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", + "validate": "npm run clean && npm run vscode:prepublish && npm run test-grammar && npm run test && npm run package" }, "devDependencies": { "@eslint/js": "^9.4.0", From d936c0a0798557cbc8bb87d399532c66c89b6e05 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 17 Aug 2024 18:30:36 -0700 Subject: [PATCH 08/60] Cleanup package.json (#8) --- package.json | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index e70dc693..98c13b07 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,32 @@ { "name": "vscode-autohotkey2-lsp", "displayName": "AutoHotkey v2 Language Support", - "description": "AutoHotkey v2 Language Support, based on vscode-lsp.", - "author": "thqby", - "publisher": "thqby", + "description": "AutoHotkey v2 language support, forked from thqby's extension", + "author": "thqby and Mark Wiemer", + "publisher": "mark-wiemer", "version": "2.4.9", "license": "LGPLv3.0", "categories": [ - "Formatters", - "Programming Languages", - "Snippets" - ], + "Debuggers", + "Formatters", + "Programming Languages", + "Snippets" + ], "keywords": [ - "ahk", - "ahk2", - "autohotkey", - "autohotkey2" - ], + "vscode", + "autohotkey", + "ahk", + "ahk2", + "ahk v2" + ], "repository": { "type": "git", - "url": "https://github.com/thqby/vscode-autohotkey2-lsp" + "url": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp" }, - "homepage": "https://github.com/thqby/vscode-autohotkey2-lsp/blob/main/README.md", + "homepage": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp/blob/main/README.md", "icon": "icon.png", "bugs": { - "url": "https://github.com/thqby/vscode-autohotkey2-lsp/issues" + "url": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp/issues" }, "engines": { "vscode": "^1.82.0" @@ -348,7 +350,7 @@ }, "configurationDefaults": { "[ahk2]": { - "editor.defaultFormatter": "thqby.vscode-autohotkey2-lsp", + "editor.defaultFormatter": "mark-wiemer.vscode-autohotkey2-lsp", "editor.quickSuggestions": { "other": true, "comments": false, From c9589948db2b7136722e6d425e186696f1a52c92 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 18 Aug 2024 08:03:57 -0700 Subject: [PATCH 09/60] Update build for compositing with AHK++ (#9) --- .editorconfig | 9 - client/tsconfig.json | 3 +- package-lock.json | 135 +++++++++- package.json | 435 ++++++++++++++++--------------- server/src/Lexer.ts | 17 +- server/src/ahkProvider.ts | 2 +- server/src/common.ts | 5 +- server/src/completionProvider.ts | 2 +- server/src/server.ts | 1 + server/src/symbolProvider.ts | 2 +- tsconfig.json | 3 +- 11 files changed, 367 insertions(+), 247 deletions(-) delete mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index ab00b5cd..00000000 --- a/.editorconfig +++ /dev/null @@ -1,9 +0,0 @@ -# EditorConfig is awesome: https://EditorConfig.org - -# top-most EditorConfig file -root = true - -[md] -indent_style = space -indent_size = 2 -charset = utf-8 diff --git a/client/tsconfig.json b/client/tsconfig.json index f21e165c..5f41caf1 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -7,7 +7,8 @@ "sourceMap": true, "strict": true, "outDir": "dist", - "rootDirs": ["src", "../server/src"] + "rootDirs": ["src", "../server/src"], + "composite": true }, "include": ["src"], "exclude": ["node_modules", ".vscode-test", ".vscode-test-web"] diff --git a/package-lock.json b/package-lock.json index 4e7eb7c0..0f647b30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ }, "devDependencies": { "@eslint/js": "^9.4.0", + "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", "@vscode/test-cli": "^0.0.10", @@ -28,6 +29,7 @@ "mocha": "^10.7.0", "path-browserify": "^1.0.1", "sinon": "^18.0.0", + "sort-package-json": "^2.10.0", "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", @@ -792,13 +794,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "20.16.0", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.16.0.tgz", + "integrity": "sha512-vDxceJcoZhIVh67S568bm1UGZO0DX0hpplJZxzeXMKwIPLn190ec5RRxQ69BKhX44SUGIxxgMdDY557lGLKprQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/normalize-package-data": { @@ -2921,6 +2923,16 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-indent": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.3.tgz", @@ -2932,6 +2944,19 @@ "node": ">=8" } }, + "node_modules/detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmmirror.com/diff/-/diff-5.2.0.tgz", @@ -3861,6 +3886,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-hooks-list": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/git-hooks-list/-/git-hooks-list-3.1.0.tgz", + "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmmirror.com/github-from-package/-/github-from-package-0.0.0.tgz", @@ -7540,6 +7588,79 @@ "node": ">=8" } }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sort-package-json": { + "version": "2.10.0", + "resolved": "https://registry.npmmirror.com/sort-package-json/-/sort-package-json-2.10.0.tgz", + "integrity": "sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.0", + "get-stdin": "^9.0.0", + "git-hooks-list": "^3.0.0", + "globby": "^13.1.2", + "is-plain-obj": "^4.1.0", + "semver": "^7.6.0", + "sort-object-keys": "^1.1.3" + }, + "bin": { + "sort-package-json": "cli.js" + } + }, + "node_modules/sort-package-json/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmmirror.com/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-package-json/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-package-json/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.7.4.tgz", @@ -8471,9 +8592,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.19.6", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.19.6.tgz", + "integrity": "sha512-e/vggGopEfTKSvj4ihnOLTsqhrKRN3LeO6qSN/GxohhuRv8qH9bNQ4B8W7e/vFL+0XTnmHPB4/kegunZGA4Org==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index 98c13b07..b695dcd5 100644 --- a/package.json +++ b/package.json @@ -1,89 +1,163 @@ { "name": "vscode-autohotkey2-lsp", "displayName": "AutoHotkey v2 Language Support", - "description": "AutoHotkey v2 language support, forked from thqby's extension", - "author": "thqby and Mark Wiemer", - "publisher": "mark-wiemer", "version": "2.4.9", - "license": "LGPLv3.0", + "description": "AutoHotkey v2 language support, forked from thqby's extension", "categories": [ - "Debuggers", - "Formatters", - "Programming Languages", - "Snippets" - ], + "Debuggers", + "Formatters", + "Programming Languages", + "Snippets" + ], "keywords": [ - "vscode", - "autohotkey", - "ahk", - "ahk2", - "ahk v2" - ], - "repository": { - "type": "git", - "url": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp" - }, + "vscode", + "autohotkey", + "ahk", + "ahk2", + "ahk v2" + ], "homepage": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp/blob/main/README.md", - "icon": "icon.png", "bugs": { "url": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp/issues" }, - "engines": { - "vscode": "^1.82.0" + "repository": { + "type": "git", + "url": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp" }, + "license": "LGPLv3.0", + "author": "thqby and Mark Wiemer", + "publisher": "mark-wiemer", "main": "./client/dist/extension", "browser": "./client/dist/browserClientMain", + "scripts": { + "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", + "clean": "del-cli client/dist server/dist/*.js*", + "clean//": "Remove both the compiled extension and compiled test files", + "compile": "webpack", + "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", + "compile-test": "cd client && tsc", + "compile-test//": "Compile test files", + "compile//": "Compile the extension for packaging and publishing", + "eslint": "eslint --fix", + "package": "vsce package", + "patch": "npm version patch", + "publish": "vsce publish", + "sort-package-json": "sort-package-json --check", + "sort-package-json:fix": "sort-package-json", + "pretest": "npm run compile-test", + "test": "cd client && vscode-test", + "test-grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", + "test//": "Run tests. Requires the extension to be compiled", + "validate": "npm run clean && npm run vscode:prepublish && npm run test-grammar && npm run test && npm run package", + "vscode:prepublish": "webpack --mode production --devtool hidden-source-map", + "watch": "tsc -b -w", + "watch-web": "webpack --watch" + }, "contributes": { "breakpoints": [ { "language": "ahk2" } ], - "languages": [ + "commands": [ { - "id": "ahk2", - "aliases": [ - "AutoHotkey2", - "autohotkey2", - "ahk2" - ], - "extensions": [ - ".ahk", - ".ah2", - ".ahk2" - ], - "configuration": "./ahk2.configuration.json", - "icon": { - "dark": "icon_filetype.png", - "light": "icon_filetype.png" - } + "enablement": "editorLangId == ahk2 && shellExecutionSupported", + "command": "ahk2.debug", + "title": "%ahk2.debug%", + "icon": "$(debug)", + "category": "ahk2" }, { - "id": "ahk", - "aliases": [ - "AutoHotkey" - ] + "enablement": "!isWeb", + "command": "ahk2.debug.attach", + "title": "%ahk2.debug.attach%", + "category": "ahk2" }, { - "id": "~ahk2-output" - } - ], - "grammars": [ + "enablement": "editorLangId == ahk2 && shellExecutionSupported", + "command": "ahk2.debug.params", + "title": "%ahk2.debug.params%", + "category": "ahk2" + }, { - "language": "ahk2", - "scopeName": "source.ahk2", - "path": "./syntaxes/ahk2.tmLanguage.json", - "embeddedLanguages": { - "meta.embedded.ahk2": "ahk2" - }, - "unbalancedBracketScopes": [ - "keyword.keys.ahk2" - ] + "enablement": "editorLangId == ahk2", + "command": "ahk2.diagnostic.full", + "title": "%ahk2.diagnostic.full%", + "category": "ahk2" }, { - "language": "~ahk2-output", - "scopeName": "ahk2.output", - "path": "./syntaxes/ahk2-output.tmLanguage.json" + "enablement": "editorLangId == ahk2", + "command": "ahk2.export.symbols", + "title": "%ahk2.export.symbols%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && shellExecutionSupported", + "command": "ahk2.run", + "title": "%ahk2.run%", + "icon": "$(play)", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.selection.run", + "title": "%ahk2.selection.run%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.stop", + "title": "%ahk2.stop%", + "icon": "$(stop)", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && shellExecutionSupported", + "command": "ahk2.compile", + "title": "%ahk2.compile%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.help", + "title": "%ahk2.help%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2", + "command": "ahk2.generate.comment", + "title": "%ahk2.generatecomment%", + "category": "ahk2" + }, + { + "enablement": "!isWeb", + "command": "ahk2.setinterpreter", + "title": "%ahk2.setinterpreter%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2", + "command": "ahk2.updateversioninfo", + "title": "%ahk2.updateversioninfo%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 || editorLangId == ahk", + "command": "ahk2.switch", + "title": "Switch v1/v2", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.selectsyntaxes", + "title": "Select syntaxes", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && resourceScheme == file", + "command": "ahk2.setscriptdir", + "title": "%ahk2.setscriptdir%", + "category": "ahk2" } ], "configuration": { @@ -350,7 +424,7 @@ }, "configurationDefaults": { "[ahk2]": { - "editor.defaultFormatter": "mark-wiemer.vscode-autohotkey2-lsp", + "editor.defaultFormatter": "mark-wiemer.vscode-autohotkey-plus-plus", "editor.quickSuggestions": { "other": true, "comments": false, @@ -358,105 +432,88 @@ } } }, - "commands": [ - { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk2.debug", - "title": "%ahk2.debug%", - "icon": "$(debug)", - "category": "ahk2" - }, - { - "enablement": "!isWeb", - "command": "ahk2.debug.attach", - "title": "%ahk2.debug.attach%", - "category": "ahk2" - }, - { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk2.debug.params", - "title": "%ahk2.debug.params%", - "category": "ahk2" - }, + "grammars": [ { - "enablement": "editorLangId == ahk2", - "command": "ahk2.diagnostic.full", - "title": "%ahk2.diagnostic.full%", - "category": "ahk2" + "language": "ahk2", + "scopeName": "source.ahk2", + "path": "./syntaxes/ahk2.tmLanguage.json", + "embeddedLanguages": { + "meta.embedded.ahk2": "ahk2" + }, + "unbalancedBracketScopes": [ + "keyword.keys.ahk2" + ] }, { - "enablement": "editorLangId == ahk2", - "command": "ahk2.export.symbols", - "title": "%ahk2.export.symbols%", - "category": "ahk2" - }, + "language": "~ahk2-output", + "scopeName": "ahk2.output", + "path": "./syntaxes/ahk2-output.tmLanguage.json" + } + ], + "keybindings": [ { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", "command": "ahk2.run", - "title": "%ahk2.run%", - "icon": "$(play)", - "category": "ahk2" + "key": "ctrl+f5", + "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection" }, { - "enablement": "editorLangId == ahk2 && !isWeb", "command": "ahk2.selection.run", - "title": "%ahk2.selection.run%", - "category": "ahk2" - }, - { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.stop", - "title": "%ahk2.stop%", - "icon": "$(stop)", - "category": "ahk2" + "key": "ctrl+f5", + "when": "editorLangId == ahk2 && !isWeb && editorHasSelection" }, { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", "command": "ahk2.compile", - "title": "%ahk2.compile%", - "category": "ahk2" + "key": "ctrl+shift+f5", + "when": "editorLangId == ahk2 && !isWeb" }, { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.help", - "title": "%ahk2.help%", - "category": "ahk2" + "command": "ahk2.debug", + "key": "f5", + "when": "editorLangId == ahk2 && !isWeb && !inDebugMode" }, { - "enablement": "editorLangId == ahk2", - "command": "ahk2.generate.comment", - "title": "%ahk2.generatecomment%", - "category": "ahk2" + "command": "ahk2.debug.params", + "key": "shift+f5", + "when": "editorLangId == ahk2 && !isWeb" }, { - "enablement": "!isWeb", - "command": "ahk2.setinterpreter", - "title": "%ahk2.setinterpreter%", - "category": "ahk2" + "command": "ahk2.help", + "key": "ctrl+f1", + "when": "editorLangId == ahk2 && !isWeb" }, { - "enablement": "editorLangId == ahk2", - "command": "ahk2.updateversioninfo", - "title": "%ahk2.updateversioninfo%", - "category": "ahk2" - }, + "command": "ahk2.stop", + "key": "ctrl+f6", + "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning" + } + ], + "languages": [ { - "enablement": "editorLangId == ahk2 || editorLangId == ahk", - "command": "ahk2.switch", - "title": "Switch v1/v2", - "category": "ahk2" + "id": "ahk2", + "aliases": [ + "AutoHotkey2", + "autohotkey2", + "ahk2" + ], + "extensions": [ + ".ahk", + ".ah2", + ".ahk2" + ], + "configuration": "./ahk2.configuration.json", + "icon": { + "dark": "icon_filetype.png", + "light": "icon_filetype.png" + } }, { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.selectsyntaxes", - "title": "Select syntaxes", - "category": "ahk2" + "id": "ahk", + "aliases": [ + "AutoHotkey" + ] }, { - "enablement": "editorLangId == ahk2 && resourceScheme == file", - "command": "ahk2.setscriptdir", - "title": "%ahk2.setscriptdir%", - "category": "ahk2" + "id": "~ahk2-output" } ], "menus": { @@ -530,43 +587,6 @@ } ] }, - "keybindings": [ - { - "command": "ahk2.run", - "key": "ctrl+f5", - "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection" - }, - { - "command": "ahk2.selection.run", - "key": "ctrl+f5", - "when": "editorLangId == ahk2 && !isWeb && editorHasSelection" - }, - { - "command": "ahk2.compile", - "key": "ctrl+shift+f5", - "when": "editorLangId == ahk2 && !isWeb" - }, - { - "command": "ahk2.debug", - "key": "f5", - "when": "editorLangId == ahk2 && !isWeb && !inDebugMode" - }, - { - "command": "ahk2.debug.params", - "key": "shift+f5", - "when": "editorLangId == ahk2 && !isWeb" - }, - { - "command": "ahk2.help", - "key": "ctrl+f1", - "when": "editorLangId == ahk2 && !isWeb" - }, - { - "command": "ahk2.stop", - "key": "ctrl+f6", - "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning" - } - ], "semanticTokenScopes": [ { "language": "ahk2", @@ -578,30 +598,32 @@ } ] }, - "scripts": { - "vscode:prepublish": "webpack --mode production --devtool hidden-source-map", - "clean//": "Remove both the compiled extension and compiled test files", - "clean": "del-cli client/dist server/dist/*.js*", - "compile//": "Compile the extension for packaging and publishing", - "compile": "webpack", - "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", - "eslint": "eslint --fix", - "watch": "tsc -b -w", - "watch-web": "webpack --watch", - "patch": "npm version patch", - "publish": "vsce publish", - "package": "vsce package", - "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", - "compile-test//": "Compile test files", - "compile-test": "cd client && tsc", - "pretest": "npm run compile-test", - "test//": "Run tests. Requires the extension to be compiled", - "test": "cd client && vscode-test", - "test-grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", - "validate": "npm run clean && npm run vscode:prepublish && npm run test-grammar && npm run test && npm run package" + "prettier": { + "singleQuote": true, + "tabWidth": 4, + "trailingComma": "all", + "useTabs": true, + "overrides": [ + { + "files": [ + "*.yml", + "*.yaml" + ], + "options": { + "tabWidth": 2 + } + } + ] + }, + "dependencies": { + "vscode-languageclient": "^9.0.1", + "vscode-languageserver": "^9.0.1", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" }, "devDependencies": { "@eslint/js": "^9.4.0", + "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", "@vscode/test-cli": "^0.0.10", @@ -614,6 +636,7 @@ "mocha": "^10.7.0", "path-browserify": "^1.0.1", "sinon": "^18.0.0", + "sort-package-json": "^2.10.0", "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", @@ -621,31 +644,11 @@ "webpack": "^5.74.0", "webpack-cli": "^4.10.0" }, - "dependencies": { - "vscode-languageclient": "^9.0.1", - "vscode-languageserver": "^9.0.1", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" + "engines": { + "vscode": "^1.82.0" }, + "icon": "icon.png", "overrides": { "eslint": "^9.4.0" - }, - "prettier": { - "useTabs": true, - "singleQuote": true, - "tabWidth": 4, - "trailingComma": "all", - "overrides": [ - { - "files": [ - "*.yml", - "*.yaml", - ".prettierrc" - ], - "options": { - "tabWidth": 2 - } - } - ] } } diff --git a/server/src/Lexer.ts b/server/src/Lexer.ts index 3f82c23c..1e36db90 100644 --- a/server/src/Lexer.ts +++ b/server/src/Lexer.ts @@ -894,19 +894,20 @@ export class Lexer { if (this.d & 2) { const overwrite = uri.endsWith('/ahk2_h.d.ahk') ? 1 : 0; let t; - for (const [k, it] of Object.entries(this.declaration)) { + for (const [k, i] of Object.entries(this.declaration)) { + const it = i as AhkSymbol; // ts is being weird switch (it.kind) { case SymbolKind.Function: - it.def = false, it.uri = uri; + it.def = false; it.uri = uri; // fall through case SymbolKind.Class: - it.overwrite ??= overwrite, it.def ??= true; + it.overwrite ??= overwrite; it.def ??= true; if (!(t = ahkvars[k]) || overwrite >= (t.overwrite ?? 0)) ahkvars[k] = it; break; case SymbolKind.Variable: if (it.def) - ahkvars[k] = it, it.uri = uri; + ahkvars[k] = it; it.uri = uri; break; } } @@ -2525,7 +2526,7 @@ export class Lexer { if ((m = l.match(/^\w+[ \t]+v(1|2)/))) { if (m[1] === '2') requirev2 = true; - else if (_this.maybev1 = 3, !stop_parse(data, false, diagnostic.requirev1())) + else if (_this.maybev1 = 3, !stop_parse(data as Token, false, diagnostic.requirev1())) _this.addDiagnostic(diagnostic.unexpected(data.content), data.offset, data.length); } break; @@ -4047,7 +4048,7 @@ export class Lexer { }); } - function add_include_dllload(text: string, tk?: Token, mode = 0, isdll = false) { + function add_include_dllload(text: string, tk?: Pick, mode = 0, isdll = false) { let m, raw: string, ignore = false; const q = text[0]; if (`'"`.includes(q) && text.endsWith(q)) @@ -6440,8 +6441,8 @@ export class Lexer { else break; } if (l <= r && it) - return this.tokens[it.start] ?? ((it = this.tokens[it.previous!])?.data - && { ...it.data, previous_token: it, type: '' }); + return (this.tokens[it.start] ?? ((it = this.tokens[it.previous!])?.data + && { ...it.data as {}, previous_token: it, type: '' })) as Token; } } diff --git a/server/src/ahkProvider.ts b/server/src/ahkProvider.ts index 2651ae84..22f67acd 100644 --- a/server/src/ahkProvider.ts +++ b/server/src/ahkProvider.ts @@ -30,7 +30,7 @@ async function get_ahkProvider_port(): Promise { }; process.on('close', () => resolve2?.()); server.onConnected().then( - m => resolve2?.(createMessageConnection(...m)), + m => resolve2?.(createMessageConnection(m[0], m[1])), () => resolve2?.() ); }); diff --git a/server/src/common.ts b/server/src/common.ts index 24010e6c..05f1a482 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -444,8 +444,9 @@ export function update_settings(configs: AHKLSSettings) { } for (const k of ['array_style', 'object_style'] as Array) if (typeof configs.FormatOptions?.[k] === 'string') - // eslint-disable-next-line @typescript-eslint/no-explicit-any - configs.FormatOptions[k] = { collapse: 2, expand: 1, none: 0 }[configs.FormatOptions[k] as string] as any; + // todo fix update_settings + // @ts-expect-error undefined not assignable to never + configs.FormatOptions[k] = { collapse: 2, expand: 1, none: 0 }[configs.FormatOptions[k] as string]; try { update_comment_tags(configs.CommentTags!); // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index 975f1dcb..fe2d8a79 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -84,7 +84,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance // eslint-disable-next-line prefer-const let { text, word, token, range, linetext, kind, symbol } = doc.getContext(position, true); const list = doc.relevance, { line, character } = position; - let isexpr = false, expg = make_search_re(word), offset; + let isexpr = false, expg = make_search_re(word), offset: number; switch (token.type) { case 'TK_UNKNOWN': diff --git a/server/src/server.ts b/server/src/server.ts index c8d415aa..4fb96954 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -18,6 +18,7 @@ import { } from './common'; import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; import { resolvePath, runscript } from './scriptrunner'; +import { TextDecoder } from 'util'; const languageServer = 'ahk2-language-server'; const documents = new TextDocuments(TextDocument); diff --git a/server/src/symbolProvider.ts b/server/src/symbolProvider.ts index 164c7413..01fbec45 100644 --- a/server/src/symbolProvider.ts +++ b/server/src/symbolProvider.ts @@ -267,7 +267,7 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio if (st < 3) stk.modifier = (stk.modifier ?? 0) | (SemanticTokenModifiers.readonly) | (islib ? SemanticTokenModifiers.defaultLibrary : 0); } - return tk ?? {}; + return tk ?? {} as Token; } } diff --git a/tsconfig.json b/tsconfig.json index f8b30f3c..737f49b4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,8 @@ "lib": ["ES2021"], "outDir": "out", "rootDir": "src", - "sourceMap": true + "sourceMap": true, + "composite": true, }, "include": [ "src" From bfda9c142c2f558834ccdaa60ef24567df297f54 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:24:42 -0700 Subject: [PATCH 10/60] Integrate with parent project (#10) --- .vscode/launch.json | 24 +++++++----------------- .vscode/settings.json | 4 +--- client/src/extension.ts | 7 +++++-- package.json | 8 ++++++-- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index f5da156c..299a2681 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,9 +11,7 @@ "--extensionDevelopmentPath=${workspaceFolder}", "--extensionDevelopmentKind=web" ], - "outFiles": [ - "${workspaceFolder}/client/dist/**/*.js" - ], + "outFiles": ["${workspaceFolder}/client/dist/**/*.js"], "preLaunchTask": "npm: watch-web" }, { @@ -21,15 +19,10 @@ "request": "launch", "name": "Launch Client", "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceRoot}" - ], - "env": { - "VSCODE_AHK_SERVER_PATH": "out" - }, - "outFiles": [ - "${workspaceRoot}/client/dist/**/*.js" - ] + "args": ["--extensionDevelopmentPath=${workspaceRoot}"], + "env": { "VSCODE_AHK_SERVER_PATH": "server/dist/server.js" }, + "outFiles": ["${workspaceRoot}/client/dist/**/*.js"], + "preLaunchTask": "npm: build:dev" }, { "type": "node", @@ -46,10 +39,7 @@ "compounds": [ { "name": "Client + Server", - "configurations": [ - "Launch Client", - "Attach to Server" - ] + "configurations": ["Launch Client", "Attach to Server"] } ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index d4d6356d..371738b1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,7 +4,5 @@ "typescript.preferences.quoteStyle": "single", "git.ignoreLimitWarning": true, "AutoHotkey2.InterpreterPath": "c:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe", - "[ahk2]": { - "editor.formatOnSave": false - } + "editor.formatOnSave": false } diff --git a/client/src/extension.ts b/client/src/extension.ts index 9c00df3a..066bdf7f 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -42,9 +42,11 @@ const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), n const isWindows = process.platform === 'win32'; export async function activate(context: ExtensionContext) { + console.log('ahk2 activated'); /** Absolute path to `server.js` */ - // .replace(/^.*[\\/]/, '') is used to get the last part of the path - const serverModule = context.asAbsolutePath(`server/${process.env.VSCODE_AHK_SERVER_PATH ?? __dirname.replace(/^.*[\\/]/, '')}/server.js`); + const defaultServerModule = context.asAbsolutePath(`ahk2/server/dist/server.js`); + const serverModule = process.env.VSCODE_AHK_SERVER_PATH ? context.asAbsolutePath(process.env.VSCODE_AHK_SERVER_PATH) : defaultServerModule; + console.log('serverModule:', serverModule); // If the extension is launched in debug mode then the debug server options are used // Otherwise the run options are used @@ -113,6 +115,7 @@ export async function activate(context: ExtensionContext) { // Start the client. This will also launch the server client.start().then(() => { + console.log('Language client started'); Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); onDidChangegetInterpreter(); if (window.activeTextEditor?.document.languageId === 'ahk2') diff --git a/package.json b/package.json index b695dcd5..d2137c87 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,10 @@ "main": "./client/dist/extension", "browser": "./client/dist/browserClientMain", "scripts": { + "prebuild": "npm run clean", + "build": "webpack --mode production --devtool hidden-source-map", + "prebuild:dev": "npm run clean", + "build:dev": "webpack", "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", "clean": "del-cli client/dist server/dist/*.js*", "clean//": "Remove both the compiled extension and compiled test files", @@ -47,9 +51,9 @@ "pretest": "npm run compile-test", "test": "cd client && vscode-test", "test-grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", - "test//": "Run tests. Requires the extension to be compiled", + "test//": "Run tests", "validate": "npm run clean && npm run vscode:prepublish && npm run test-grammar && npm run test && npm run package", - "vscode:prepublish": "webpack --mode production --devtool hidden-source-map", + "vscode:prepublish": "npm run build", "watch": "tsc -b -w", "watch-web": "webpack --watch" }, From c6272f3f83564cdfddde826efeffe23a6dfb5f08 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:32:15 -0700 Subject: [PATCH 11/60] Misc cleanup for AHK++ integration (#11) * Fix lint and format server.ts * Format with Prettier 3.3.3 * Fix lint * Fix eslint:fix ;) * Mark loadahk2 as todo * Mark prod build for minification --- .github/FUNDING.yml | 2 +- .prettierignore | 36 + .vscode/tasks.json | 10 +- CHANGELOG.md | 1248 ++++--- README.md | 187 +- README.zh-CN.md | 187 +- ahk2.configuration.json | 84 +- eslint.config.mjs | 68 +- package-lock.json | 17 + package.json | 7 +- package.nls.json | 2 +- package.nls.zh-cn.json | 2 +- server/cli/cli.ts | 10 +- server/src/Lexer.ts | 2 +- server/src/common.ts | 1 + server/src/server.ts | 476 ++- syntaxes/ahk2-output.tmLanguage.json | 224 +- syntaxes/ahk2.json | 2 +- syntaxes/ahk2.tmLanguage.json | 4720 +++++++++++++------------- syntaxes/ahk2_common.json | 2 +- syntaxes/ahk2_h.json | 2 +- syntaxes/zh-cn/ahk2.json | 2 +- syntaxes/zh-cn/ahk2_h.json | 2 +- tools/install.js | 391 ++- tsconfig.json | 18 +- webpack.config.cli.js | 6 +- webpack.config.js | 22 +- 27 files changed, 4135 insertions(+), 3595 deletions(-) create mode 100644 .prettierignore diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 0b3df0ae..508324cc 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -2,4 +2,4 @@ github: thqby custom: - - https://www.paypal.me/thqby \ No newline at end of file + - https://www.paypal.me/thqby diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..c33eba81 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,36 @@ +out +dist +node_modules +.test-data +.vscode-test +.vscode-test-web +*.vsix +scripts/* +server/expr_parser/* + +client/src/browserClientMain.ts +client/src/extension.ts +client/src/test/extension.test.ts +client/src/test/formattingProvider.test.ts +client/src/test/utils.ts +server/src/ahkProvider.ts +server/src/browserServerMain.ts +server/src/codeActionProvider.ts +server/src/colorProvider.ts +server/src/commandProvider.ts +server/src/common.ts +server/src/completionProvider.ts +server/src/constants.ts +server/src/definitionProvider.ts +server/src/formattingProvider.ts +server/src/hoverProvider.ts +server/src/Lexer.ts +server/src/localize.ts +server/src/PEFile.ts +server/src/referencesProvider.ts +server/src/renameProvider.ts +server/src/scriptrunner.ts +server/src/semanticTokensProvider.ts +server/src/server.ts +server/src/signatureProvider.ts +server/src/symbolProvider.ts \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 2d11eb6b..9c72b15c 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -6,18 +6,14 @@ "script": "watch-web", "group": "build", "isBackground": true, - "problemMatcher": [ - "$ts-webpack-watch" - ] + "problemMatcher": ["$ts-webpack-watch"] }, { "type": "npm", "script": "watch", "group": "build", "isBackground": true, - "problemMatcher": [ - "$tsc-watch" - ] + "problemMatcher": ["$tsc-watch"] } ] -} \ No newline at end of file +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b4ed3f4..1f5ae961 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,899 +1,1075 @@ ## 2.4.9 -- 修复[#548](https://github.com/thqby/vscode-autohotkey2-lsp/issues/548) -- 修复[#551](https://github.com/thqby/vscode-autohotkey2-lsp/issues/551) -- 修复[#552](https://github.com/thqby/vscode-autohotkey2-lsp/issues/552) -- 修复[#554](https://github.com/thqby/vscode-autohotkey2-lsp/issues/554) -- 修复[#556](https://github.com/thqby/vscode-autohotkey2-lsp/issues/556) -- [FR #550](https://github.com/thqby/vscode-autohotkey2-lsp/issues/550) + +- 修复[#548](https://github.com/thqby/vscode-autohotkey2-lsp/issues/548) +- 修复[#551](https://github.com/thqby/vscode-autohotkey2-lsp/issues/551) +- 修复[#552](https://github.com/thqby/vscode-autohotkey2-lsp/issues/552) +- 修复[#554](https://github.com/thqby/vscode-autohotkey2-lsp/issues/554) +- 修复[#556](https://github.com/thqby/vscode-autohotkey2-lsp/issues/556) +- [FR #550](https://github.com/thqby/vscode-autohotkey2-lsp/issues/550) ## 2.4.8 -- 修复[#540](https://github.com/thqby/vscode-autohotkey2-lsp/issues/540) -- 修复[#544](https://github.com/thqby/vscode-autohotkey2-lsp/issues/544) -- [FR #543](https://github.com/thqby/vscode-autohotkey2-lsp/issues/543) + +- 修复[#540](https://github.com/thqby/vscode-autohotkey2-lsp/issues/540) +- 修复[#544](https://github.com/thqby/vscode-autohotkey2-lsp/issues/544) +- [FR #543](https://github.com/thqby/vscode-autohotkey2-lsp/issues/543) ## 2.4.7 -- 修复[#523](https://github.com/thqby/vscode-autohotkey2-lsp/issues/523) -- 修复[#529](https://github.com/thqby/vscode-autohotkey2-lsp/issues/529) -- [FR #518](https://github.com/thqby/vscode-autohotkey2-lsp/issues/518) + +- 修复[#523](https://github.com/thqby/vscode-autohotkey2-lsp/issues/523) +- 修复[#529](https://github.com/thqby/vscode-autohotkey2-lsp/issues/529) +- [FR #518](https://github.com/thqby/vscode-autohotkey2-lsp/issues/518) ## 2.4.6 -- 修复[#511](https://github.com/thqby/vscode-autohotkey2-lsp/issues/511) -- 修复[#511](https://github.com/thqby/vscode-autohotkey2-lsp/issues/517) -- 修复[#521](https://github.com/thqby/vscode-autohotkey2-lsp/issues/521) -- 修复[#524](https://github.com/thqby/vscode-autohotkey2-lsp/issues/524) -- 修复[#525](https://github.com/thqby/vscode-autohotkey2-lsp/issues/525) -- 修复[#526](https://github.com/thqby/vscode-autohotkey2-lsp/issues/526) -- 修复[#527](https://github.com/thqby/vscode-autohotkey2-lsp/issues/527) -- 修复[#528](https://github.com/thqby/vscode-autohotkey2-lsp/issues/528) + +- 修复[#511](https://github.com/thqby/vscode-autohotkey2-lsp/issues/511) +- 修复[#511](https://github.com/thqby/vscode-autohotkey2-lsp/issues/517) +- 修复[#521](https://github.com/thqby/vscode-autohotkey2-lsp/issues/521) +- 修复[#524](https://github.com/thqby/vscode-autohotkey2-lsp/issues/524) +- 修复[#525](https://github.com/thqby/vscode-autohotkey2-lsp/issues/525) +- 修复[#526](https://github.com/thqby/vscode-autohotkey2-lsp/issues/526) +- 修复[#527](https://github.com/thqby/vscode-autohotkey2-lsp/issues/527) +- 修复[#528](https://github.com/thqby/vscode-autohotkey2-lsp/issues/528) ## 2.4.4 -- 修复[#509](https://github.com/thqby/vscode-autohotkey2-lsp/issues/509) -- 修复[#510](https://github.com/thqby/vscode-autohotkey2-lsp/issues/510) + +- 修复[#509](https://github.com/thqby/vscode-autohotkey2-lsp/issues/509) +- 修复[#510](https://github.com/thqby/vscode-autohotkey2-lsp/issues/510) ## 2.4.3 -- 修复[#506](https://github.com/thqby/vscode-autohotkey2-lsp/issues/506) -- 修复[#507](https://github.com/thqby/vscode-autohotkey2-lsp/issues/507) -- 修复[#508](https://github.com/thqby/vscode-autohotkey2-lsp/issues/508) + +- 修复[#506](https://github.com/thqby/vscode-autohotkey2-lsp/issues/506) +- 修复[#507](https://github.com/thqby/vscode-autohotkey2-lsp/issues/507) +- 修复[#508](https://github.com/thqby/vscode-autohotkey2-lsp/issues/508) ## 2.4.2 -- 修复[#499](https://github.com/thqby/vscode-autohotkey2-lsp/issues/499) -- 修复[#503](https://github.com/thqby/vscode-autohotkey2-lsp/issues/503) -- 修复[#505](https://github.com/thqby/vscode-autohotkey2-lsp/issues/505) -- 设置`DefaultDebugger`更改为`DebugConfiguration`, 该设置用于将调试配置追加到当前启动的调试器 [#504](https://github.com/thqby/vscode-autohotkey2-lsp/issues/504) + +- 修复[#499](https://github.com/thqby/vscode-autohotkey2-lsp/issues/499) +- 修复[#503](https://github.com/thqby/vscode-autohotkey2-lsp/issues/503) +- 修复[#505](https://github.com/thqby/vscode-autohotkey2-lsp/issues/505) +- 设置`DefaultDebugger`更改为`DebugConfiguration`, 该设置用于将调试配置追加到当前启动的调试器 [#504](https://github.com/thqby/vscode-autohotkey2-lsp/issues/504) ## 2.4.1 -- 修复[#496](https://github.com/thqby/vscode-autohotkey2-lsp/issues/496) -- 修复[#497](https://github.com/thqby/vscode-autohotkey2-lsp/issues/497) + +- 修复[#496](https://github.com/thqby/vscode-autohotkey2-lsp/issues/496) +- 修复[#497](https://github.com/thqby/vscode-autohotkey2-lsp/issues/497) ## 2.4.0 -- 修复[#495](https://github.com/thqby/vscode-autohotkey2-lsp/issues/495) + +- 修复[#495](https://github.com/thqby/vscode-autohotkey2-lsp/issues/495) ## 2.3.9 -- 修复[#491](https://github.com/thqby/vscode-autohotkey2-lsp/issues/491) -- 增加路径补全和dll导出函数补全通过标注类型`$DirPath`、`$FilePath<'jpg|png'>`、`$DllFunc` + +- 修复[#491](https://github.com/thqby/vscode-autohotkey2-lsp/issues/491) +- 增加路径补全和dll导出函数补全通过标注类型`$DirPath`、`$FilePath<'jpg|png'>`、`$DllFunc` ## 2.3.8 -- 修复[#488](https://github.com/thqby/vscode-autohotkey2-lsp/issues/488) + +- 修复[#488](https://github.com/thqby/vscode-autohotkey2-lsp/issues/488) ## 2.3.6 -- 修复[#484](https://github.com/thqby/vscode-autohotkey2-lsp/issues/484) -- 修复[#485](https://github.com/thqby/vscode-autohotkey2-lsp/issues/485) -- 修复[#487](https://github.com/thqby/vscode-autohotkey2-lsp/issues/487) -- [FR #486](https://github.com/thqby/vscode-autohotkey2-lsp/issues/486) + +- 修复[#484](https://github.com/thqby/vscode-autohotkey2-lsp/issues/484) +- 修复[#485](https://github.com/thqby/vscode-autohotkey2-lsp/issues/485) +- 修复[#487](https://github.com/thqby/vscode-autohotkey2-lsp/issues/487) +- [FR #486](https://github.com/thqby/vscode-autohotkey2-lsp/issues/486) ## 2.3.5 -- 修复[#483](https://github.com/thqby/vscode-autohotkey2-lsp/issues/483) + +- 修复[#483](https://github.com/thqby/vscode-autohotkey2-lsp/issues/483) ## 2.3.4 -- 修复[#479](https://github.com/thqby/vscode-autohotkey2-lsp/issues/479) -- 修复[#480](https://github.com/thqby/vscode-autohotkey2-lsp/issues/480) -- 修复[#481](https://github.com/thqby/vscode-autohotkey2-lsp/issues/481) + +- 修复[#479](https://github.com/thqby/vscode-autohotkey2-lsp/issues/479) +- 修复[#480](https://github.com/thqby/vscode-autohotkey2-lsp/issues/480) +- 修复[#481](https://github.com/thqby/vscode-autohotkey2-lsp/issues/481) ## 2.3.3 -- 修复[#474](https://github.com/thqby/vscode-autohotkey2-lsp/issues/474) -- 修复[#475](https://github.com/thqby/vscode-autohotkey2-lsp/issues/475) -- 修复[#476](https://github.com/thqby/vscode-autohotkey2-lsp/issues/476) -- 修复[#477](https://github.com/thqby/vscode-autohotkey2-lsp/issues/477) + +- 修复[#474](https://github.com/thqby/vscode-autohotkey2-lsp/issues/474) +- 修复[#475](https://github.com/thqby/vscode-autohotkey2-lsp/issues/475) +- 修复[#476](https://github.com/thqby/vscode-autohotkey2-lsp/issues/476) +- 修复[#477](https://github.com/thqby/vscode-autohotkey2-lsp/issues/477) ## 2.3.2 -- 修复[#469](https://github.com/thqby/vscode-autohotkey2-lsp/issues/469) -- 修复[#470](https://github.com/thqby/vscode-autohotkey2-lsp/issues/470) -- 修复[#472](https://github.com/thqby/vscode-autohotkey2-lsp/issues/472) -- 修复[#473](https://github.com/thqby/vscode-autohotkey2-lsp/issues/473) + +- 修复[#469](https://github.com/thqby/vscode-autohotkey2-lsp/issues/469) +- 修复[#470](https://github.com/thqby/vscode-autohotkey2-lsp/issues/470) +- 修复[#472](https://github.com/thqby/vscode-autohotkey2-lsp/issues/472) +- 修复[#473](https://github.com/thqby/vscode-autohotkey2-lsp/issues/473) ## 2.3.1 -- 修复[#462](https://github.com/thqby/vscode-autohotkey2-lsp/issues/462) -- [FR #466](https://github.com/thqby/vscode-autohotkey2-lsp/issues/466) + +- 修复[#462](https://github.com/thqby/vscode-autohotkey2-lsp/issues/462) +- [FR #466](https://github.com/thqby/vscode-autohotkey2-lsp/issues/466) ## 2.2.9 -- 修复[#450](https://github.com/thqby/vscode-autohotkey2-lsp/issues/450) -- 修复[#453](https://github.com/thqby/vscode-autohotkey2-lsp/issues/453) -- 修复[#456](https://github.com/thqby/vscode-autohotkey2-lsp/issues/456) -- [FR #449](https://github.com/thqby/vscode-autohotkey2-lsp/issues/449) -- [FR #452](https://github.com/thqby/vscode-autohotkey2-lsp/issues/452) + +- 修复[#450](https://github.com/thqby/vscode-autohotkey2-lsp/issues/450) +- 修复[#453](https://github.com/thqby/vscode-autohotkey2-lsp/issues/453) +- 修复[#456](https://github.com/thqby/vscode-autohotkey2-lsp/issues/456) +- [FR #449](https://github.com/thqby/vscode-autohotkey2-lsp/issues/449) +- [FR #452](https://github.com/thqby/vscode-autohotkey2-lsp/issues/452) ## 2.2.8 -- 修复[#443](https://github.com/thqby/vscode-autohotkey2-lsp/issues/443) -- 修复[#445](https://github.com/thqby/vscode-autohotkey2-lsp/issues/445) -- 修复[#446](https://github.com/thqby/vscode-autohotkey2-lsp/issues/446) -- [FR #444](https://github.com/thqby/vscode-autohotkey2-lsp/issues/444) + +- 修复[#443](https://github.com/thqby/vscode-autohotkey2-lsp/issues/443) +- 修复[#445](https://github.com/thqby/vscode-autohotkey2-lsp/issues/445) +- 修复[#446](https://github.com/thqby/vscode-autohotkey2-lsp/issues/446) +- [FR #444](https://github.com/thqby/vscode-autohotkey2-lsp/issues/444) ## 2.2.7 -- 修复[#432](https://github.com/thqby/vscode-autohotkey2-lsp/issues/432) -- 修复[#435](https://github.com/thqby/vscode-autohotkey2-lsp/issues/435) -- 修复[#438](https://github.com/thqby/vscode-autohotkey2-lsp/issues/438) -- 修复[#439](https://github.com/thqby/vscode-autohotkey2-lsp/issues/439) + +- 修复[#432](https://github.com/thqby/vscode-autohotkey2-lsp/issues/432) +- 修复[#435](https://github.com/thqby/vscode-autohotkey2-lsp/issues/435) +- 修复[#438](https://github.com/thqby/vscode-autohotkey2-lsp/issues/438) +- 修复[#439](https://github.com/thqby/vscode-autohotkey2-lsp/issues/439) ## 2.2.6 -- 修复[#428](https://github.com/thqby/vscode-autohotkey2-lsp/issues/428) -- 修复[#429](https://github.com/thqby/vscode-autohotkey2-lsp/issues/429) -- 修复[#431](https://github.com/thqby/vscode-autohotkey2-lsp/issues/431) + +- 修复[#428](https://github.com/thqby/vscode-autohotkey2-lsp/issues/428) +- 修复[#429](https://github.com/thqby/vscode-autohotkey2-lsp/issues/429) +- 修复[#431](https://github.com/thqby/vscode-autohotkey2-lsp/issues/431) ## 2.2.5 -- 修复[#422](https://github.com/thqby/vscode-autohotkey2-lsp/issues/422) -- 修复[#426](https://github.com/thqby/vscode-autohotkey2-lsp/issues/426) -- 修复[#427](https://github.com/thqby/vscode-autohotkey2-lsp/issues/427) + +- 修复[#422](https://github.com/thqby/vscode-autohotkey2-lsp/issues/422) +- 修复[#426](https://github.com/thqby/vscode-autohotkey2-lsp/issues/426) +- 修复[#427](https://github.com/thqby/vscode-autohotkey2-lsp/issues/427) ## 2.2.4 -- 修复[#416](https://github.com/thqby/vscode-autohotkey2-lsp/issues/416) -- 修复[#418](https://github.com/thqby/vscode-autohotkey2-lsp/issues/418) -- 增加@补全 + +- 修复[#416](https://github.com/thqby/vscode-autohotkey2-lsp/issues/416) +- 修复[#418](https://github.com/thqby/vscode-autohotkey2-lsp/issues/418) +- 增加@补全 ## 2.2.2 -- 修复[#412](https://github.com/thqby/vscode-autohotkey2-lsp/issues/412) -- 修复[#413](https://github.com/thqby/vscode-autohotkey2-lsp/issues/413) + +- 修复[#412](https://github.com/thqby/vscode-autohotkey2-lsp/issues/412) +- 修复[#413](https://github.com/thqby/vscode-autohotkey2-lsp/issues/413) ## 2.2.1 -- 修复[#408](https://github.com/thqby/vscode-autohotkey2-lsp/issues/408) -- 修复[#409](https://github.com/thqby/vscode-autohotkey2-lsp/issues/409) -- 修复[#411](https://github.com/thqby/vscode-autohotkey2-lsp/issues/411) + +- 修复[#408](https://github.com/thqby/vscode-autohotkey2-lsp/issues/408) +- 修复[#409](https://github.com/thqby/vscode-autohotkey2-lsp/issues/409) +- 修复[#411](https://github.com/thqby/vscode-autohotkey2-lsp/issues/411) ## 2.2.0 -- 修复[#402](https://github.com/thqby/vscode-autohotkey2-lsp/issues/402) -- 修复[#403](https://github.com/thqby/vscode-autohotkey2-lsp/issues/403) -- 修复[#405](https://github.com/thqby/vscode-autohotkey2-lsp/issues/405) -- 修复[#407](https://github.com/thqby/vscode-autohotkey2-lsp/issues/407) + +- 修复[#402](https://github.com/thqby/vscode-autohotkey2-lsp/issues/402) +- 修复[#403](https://github.com/thqby/vscode-autohotkey2-lsp/issues/403) +- 修复[#405](https://github.com/thqby/vscode-autohotkey2-lsp/issues/405) +- 修复[#407](https://github.com/thqby/vscode-autohotkey2-lsp/issues/407) ## 2.1.8 -- 修复[#399](https://github.com/thqby/vscode-autohotkey2-lsp/issues/399) -- 修复[#400](https://github.com/thqby/vscode-autohotkey2-lsp/issues/400) + +- 修复[#399](https://github.com/thqby/vscode-autohotkey2-lsp/issues/399) +- 修复[#400](https://github.com/thqby/vscode-autohotkey2-lsp/issues/400) ## 2.1.7 -- 修复[#392](https://github.com/thqby/vscode-autohotkey2-lsp/issues/392) -- 修复[#394](https://github.com/thqby/vscode-autohotkey2-lsp/issues/394) -- 修复[#396](https://github.com/thqby/vscode-autohotkey2-lsp/issues/396) -- 修复[#397](https://github.com/thqby/vscode-autohotkey2-lsp/issues/397) -- [FR #393](https://github.com/thqby/vscode-autohotkey2-lsp/issues/393) + +- 修复[#392](https://github.com/thqby/vscode-autohotkey2-lsp/issues/392) +- 修复[#394](https://github.com/thqby/vscode-autohotkey2-lsp/issues/394) +- 修复[#396](https://github.com/thqby/vscode-autohotkey2-lsp/issues/396) +- 修复[#397](https://github.com/thqby/vscode-autohotkey2-lsp/issues/397) +- [FR #393](https://github.com/thqby/vscode-autohotkey2-lsp/issues/393) ## 2.1.6 -- 修复[#387](https://github.com/thqby/vscode-autohotkey2-lsp/issues/387) -- 修复[#390](https://github.com/thqby/vscode-autohotkey2-lsp/issues/390) + +- 修复[#387](https://github.com/thqby/vscode-autohotkey2-lsp/issues/387) +- 修复[#390](https://github.com/thqby/vscode-autohotkey2-lsp/issues/390) ## 2.1.5 -- 修复[#368](https://github.com/thqby/vscode-autohotkey2-lsp/issues/368) -- 修复[#381](https://github.com/thqby/vscode-autohotkey2-lsp/issues/381) -- 修复[#383](https://github.com/thqby/vscode-autohotkey2-lsp/issues/383) -- 修复[#384](https://github.com/thqby/vscode-autohotkey2-lsp/issues/384) -- [FR #380](https://github.com/thqby/vscode-autohotkey2-lsp/issues/380) -- [FR #382](https://github.com/thqby/vscode-autohotkey2-lsp/issues/382) + +- 修复[#368](https://github.com/thqby/vscode-autohotkey2-lsp/issues/368) +- 修复[#381](https://github.com/thqby/vscode-autohotkey2-lsp/issues/381) +- 修复[#383](https://github.com/thqby/vscode-autohotkey2-lsp/issues/383) +- 修复[#384](https://github.com/thqby/vscode-autohotkey2-lsp/issues/384) +- [FR #380](https://github.com/thqby/vscode-autohotkey2-lsp/issues/380) +- [FR #382](https://github.com/thqby/vscode-autohotkey2-lsp/issues/382) ## 2.1.4 -- 修复[#378](https://github.com/thqby/vscode-autohotkey2-lsp/issues/378) -- 修复[#379](https://github.com/thqby/vscode-autohotkey2-lsp/issues/379) + +- 修复[#378](https://github.com/thqby/vscode-autohotkey2-lsp/issues/378) +- 修复[#379](https://github.com/thqby/vscode-autohotkey2-lsp/issues/379) ## 2.1.3 -- 修复[#371](https://github.com/thqby/vscode-autohotkey2-lsp/issues/371) -- 修复[#373](https://github.com/thqby/vscode-autohotkey2-lsp/issues/373) -- 修复[#375](https://github.com/thqby/vscode-autohotkey2-lsp/issues/375) -- 修复[#377](https://github.com/thqby/vscode-autohotkey2-lsp/issues/377) + +- 修复[#371](https://github.com/thqby/vscode-autohotkey2-lsp/issues/371) +- 修复[#373](https://github.com/thqby/vscode-autohotkey2-lsp/issues/373) +- 修复[#375](https://github.com/thqby/vscode-autohotkey2-lsp/issues/375) +- 修复[#377](https://github.com/thqby/vscode-autohotkey2-lsp/issues/377) ## 2.1.2 -- 修复[#364](https://github.com/thqby/vscode-autohotkey2-lsp/issues/364) -- 修复[#366](https://github.com/thqby/vscode-autohotkey2-lsp/issues/366) -- 修复[#370](https://github.com/thqby/vscode-autohotkey2-lsp/issues/370) -- 修复[#371](https://github.com/thqby/vscode-autohotkey2-lsp/issues/371) -- 修复[#372](https://github.com/thqby/vscode-autohotkey2-lsp/issues/372) -- 支持v2.1-alpha.3语法 + +- 修复[#364](https://github.com/thqby/vscode-autohotkey2-lsp/issues/364) +- 修复[#366](https://github.com/thqby/vscode-autohotkey2-lsp/issues/366) +- 修复[#370](https://github.com/thqby/vscode-autohotkey2-lsp/issues/370) +- 修复[#371](https://github.com/thqby/vscode-autohotkey2-lsp/issues/371) +- 修复[#372](https://github.com/thqby/vscode-autohotkey2-lsp/issues/372) +- 支持v2.1-alpha.3语法 ## 2.1.1 -- 支持v2.1新语法, 可选链操作符`?.`、空值合并`??=` -- 支持v2.1新语法, 类型化属性`prop: type := val` + +- 支持v2.1新语法, 可选链操作符`?.`、空值合并`??=` +- 支持v2.1新语法, 类型化属性`prop: type := val` ## 2.1.0 -- 修复[#354](https://github.com/thqby/vscode-autohotkey2-lsp/issues/354) -- 修复[#356](https://github.com/thqby/vscode-autohotkey2-lsp/issues/356) -- 修复[#358](https://github.com/thqby/vscode-autohotkey2-lsp/issues/358) + +- 修复[#354](https://github.com/thqby/vscode-autohotkey2-lsp/issues/354) +- 修复[#356](https://github.com/thqby/vscode-autohotkey2-lsp/issues/356) +- 修复[#358](https://github.com/thqby/vscode-autohotkey2-lsp/issues/358) ## 2.0.9 -- 修复[#351](https://github.com/thqby/vscode-autohotkey2-lsp/issues/351) -- 修复[#352](https://github.com/thqby/vscode-autohotkey2-lsp/issues/352) + +- 修复[#351](https://github.com/thqby/vscode-autohotkey2-lsp/issues/351) +- 修复[#352](https://github.com/thqby/vscode-autohotkey2-lsp/issues/352) ## 2.0.8 -- 修复[#345](https://github.com/thqby/vscode-autohotkey2-lsp/issues/345) -- 修复[#348](https://github.com/thqby/vscode-autohotkey2-lsp/issues/348) + +- 修复[#345](https://github.com/thqby/vscode-autohotkey2-lsp/issues/345) +- 修复[#348](https://github.com/thqby/vscode-autohotkey2-lsp/issues/348) ## 2.0.7 -- 修复[#339](https://github.com/thqby/vscode-autohotkey2-lsp/issues/339) -- 修复[#340](https://github.com/thqby/vscode-autohotkey2-lsp/issues/340) -- 修复[#341](https://github.com/thqby/vscode-autohotkey2-lsp/issues/341) -- 修复[#342](https://github.com/thqby/vscode-autohotkey2-lsp/issues/342) + +- 修复[#339](https://github.com/thqby/vscode-autohotkey2-lsp/issues/339) +- 修复[#340](https://github.com/thqby/vscode-autohotkey2-lsp/issues/340) +- 修复[#341](https://github.com/thqby/vscode-autohotkey2-lsp/issues/341) +- 修复[#342](https://github.com/thqby/vscode-autohotkey2-lsp/issues/342) ## 2.0.6 -- 修复[#337](https://github.com/thqby/vscode-autohotkey2-lsp/issues/337) -- 修复[#338](https://github.com/thqby/vscode-autohotkey2-lsp/issues/338) + +- 修复[#337](https://github.com/thqby/vscode-autohotkey2-lsp/issues/337) +- 修复[#338](https://github.com/thqby/vscode-autohotkey2-lsp/issues/338) ## 2.0.5 -- 修复[#333](https://github.com/thqby/vscode-autohotkey2-lsp/issues/333) -- 修复[#334](https://github.com/thqby/vscode-autohotkey2-lsp/issues/334) -- 修复[#336](https://github.com/thqby/vscode-autohotkey2-lsp/issues/336) + +- 修复[#333](https://github.com/thqby/vscode-autohotkey2-lsp/issues/333) +- 修复[#334](https://github.com/thqby/vscode-autohotkey2-lsp/issues/334) +- 修复[#336](https://github.com/thqby/vscode-autohotkey2-lsp/issues/336) ## 2.0.4 -- 修复[#331](https://github.com/thqby/vscode-autohotkey2-lsp/issues/331) -- 修复[#332](https://github.com/thqby/vscode-autohotkey2-lsp/issues/332) + +- 修复[#331](https://github.com/thqby/vscode-autohotkey2-lsp/issues/331) +- 修复[#332](https://github.com/thqby/vscode-autohotkey2-lsp/issues/332) ## 2.0.2 -- 修复[#324](https://github.com/thqby/vscode-autohotkey2-lsp/issues/324) -- 修复[#327](https://github.com/thqby/vscode-autohotkey2-lsp/issues/327) -- 修复[#328](https://github.com/thqby/vscode-autohotkey2-lsp/issues/328) -- 修复[#329](https://github.com/thqby/vscode-autohotkey2-lsp/issues/329) -- 修复[#330](https://github.com/thqby/vscode-autohotkey2-lsp/issues/330) -- 增加设置项`AutoHotkey2.Files.Exclude`支持扫描时跳过指定文件或文件夹 [FR #326](https://github.com/thqby/vscode-autohotkey2-lsp/issues/326) + +- 修复[#324](https://github.com/thqby/vscode-autohotkey2-lsp/issues/324) +- 修复[#327](https://github.com/thqby/vscode-autohotkey2-lsp/issues/327) +- 修复[#328](https://github.com/thqby/vscode-autohotkey2-lsp/issues/328) +- 修复[#329](https://github.com/thqby/vscode-autohotkey2-lsp/issues/329) +- 修复[#330](https://github.com/thqby/vscode-autohotkey2-lsp/issues/330) +- 增加设置项`AutoHotkey2.Files.Exclude`支持扫描时跳过指定文件或文件夹 [FR #326](https://github.com/thqby/vscode-autohotkey2-lsp/issues/326) ## 2.0.1 -- 修复[#321](https://github.com/thqby/vscode-autohotkey2-lsp/issues/321) -- 修复[#244](https://github.com/thqby/vscode-autohotkey2-lsp/issues/244#issuecomment-1547153582) + +- 修复[#321](https://github.com/thqby/vscode-autohotkey2-lsp/issues/321) +- 修复[#244](https://github.com/thqby/vscode-autohotkey2-lsp/issues/244#issuecomment-1547153582) ## 2.0.0 -- 修复[#319](https://github.com/thqby/vscode-autohotkey2-lsp/issues/319) -- 修复[#320](https://github.com/thqby/vscode-autohotkey2-lsp/issues/320) + +- 修复[#319](https://github.com/thqby/vscode-autohotkey2-lsp/issues/319) +- 修复[#320](https://github.com/thqby/vscode-autohotkey2-lsp/issues/320) ## 1.9.9 -- 修复[#311](https://github.com/thqby/vscode-autohotkey2-lsp/issues/311) -- 修复[#313](https://github.com/thqby/vscode-autohotkey2-lsp/issues/313) -- 修复[#317](https://github.com/thqby/vscode-autohotkey2-lsp/issues/317) -- 修复[#318](https://github.com/thqby/vscode-autohotkey2-lsp/issues/318) + +- 修复[#311](https://github.com/thqby/vscode-autohotkey2-lsp/issues/311) +- 修复[#313](https://github.com/thqby/vscode-autohotkey2-lsp/issues/313) +- 修复[#317](https://github.com/thqby/vscode-autohotkey2-lsp/issues/317) +- 修复[#318](https://github.com/thqby/vscode-autohotkey2-lsp/issues/318) ## 1.9.8 -- ahk_h增加winapi函数补全项(`;@include-winapi`启用) -- 诊断未赋值的变量[FR #308](https://github.com/thqby/vscode-autohotkey2-lsp/issues/308) + +- ahk_h增加winapi函数补全项(`;@include-winapi`启用) +- 诊断未赋值的变量[FR #308](https://github.com/thqby/vscode-autohotkey2-lsp/issues/308) ## 1.9.7 -- 修复[#306](https://github.com/thqby/vscode-autohotkey2-lsp/issues/306) -- 支持同时运行多个脚本[#307] -- 增加命令`ahk2.export.symbols`, 导出类、函数等信息 + +- 修复[#306](https://github.com/thqby/vscode-autohotkey2-lsp/issues/306) +- 支持同时运行多个脚本[#307] +- 增加命令`ahk2.export.symbols`, 导出类、函数等信息 ## 1.9.5 -- 修复[#300](https://github.com/thqby/vscode-autohotkey2-lsp/issues/300) -- 修复[#302](https://github.com/thqby/vscode-autohotkey2-lsp/issues/302) -- 修复[#303](https://github.com/thqby/vscode-autohotkey2-lsp/issues/303) + +- 修复[#300](https://github.com/thqby/vscode-autohotkey2-lsp/issues/300) +- 修复[#302](https://github.com/thqby/vscode-autohotkey2-lsp/issues/302) +- 修复[#303](https://github.com/thqby/vscode-autohotkey2-lsp/issues/303) ## 1.9.3 -- 修复[#294](https://github.com/thqby/vscode-autohotkey2-lsp/issues/294) + +- 修复[#294](https://github.com/thqby/vscode-autohotkey2-lsp/issues/294) ## 1.9.2 -- 修复[#295](https://github.com/thqby/vscode-autohotkey2-lsp/issues/295) -- 修复[#296](https://github.com/thqby/vscode-autohotkey2-lsp/issues/296) -- 修复符号重命名失效 -- 行末注释默认保留前缀留白 + +- 修复[#295](https://github.com/thqby/vscode-autohotkey2-lsp/issues/295) +- 修复[#296](https://github.com/thqby/vscode-autohotkey2-lsp/issues/296) +- 修复符号重命名失效 +- 行末注释默认保留前缀留白 ## 1.9.1 -- 修复[#286](https://github.com/thqby/vscode-autohotkey2-lsp/issues/286) -- 修复[#287](https://github.com/thqby/vscode-autohotkey2-lsp/issues/287) -- 修复[#290](https://github.com/thqby/vscode-autohotkey2-lsp/issues/290) -- 修复[#292](https://github.com/thqby/vscode-autohotkey2-lsp/issues/292) + +- 修复[#286](https://github.com/thqby/vscode-autohotkey2-lsp/issues/286) +- 修复[#287](https://github.com/thqby/vscode-autohotkey2-lsp/issues/287) +- 修复[#290](https://github.com/thqby/vscode-autohotkey2-lsp/issues/290) +- 修复[#292](https://github.com/thqby/vscode-autohotkey2-lsp/issues/292) ## 1.9.0 -- 修复[#282](https://github.com/thqby/vscode-autohotkey2-lsp/issues/282) -- 增加编辑器标题菜单`运行`和`调试`子菜单 + +- 修复[#282](https://github.com/thqby/vscode-autohotkey2-lsp/issues/282) +- 增加编辑器标题菜单`运行`和`调试`子菜单 ## 1.8.9 -- 修复[#273](https://github.com/thqby/vscode-autohotkey2-lsp/issues/273) -- 修复[#279](https://github.com/thqby/vscode-autohotkey2-lsp/issues/279) -- 修复[#280](https://github.com/thqby/vscode-autohotkey2-lsp/issues/280) + +- 修复[#273](https://github.com/thqby/vscode-autohotkey2-lsp/issues/273) +- 修复[#279](https://github.com/thqby/vscode-autohotkey2-lsp/issues/279) +- 修复[#280](https://github.com/thqby/vscode-autohotkey2-lsp/issues/280) ## 1.8.8 -- 增加Com对象成员补全 -- 修复[#272](https://github.com/thqby/vscode-autohotkey2-lsp/issues/272) -- 修复[#278](https://github.com/thqby/vscode-autohotkey2-lsp/issues/278) -- 增加格式化选项`keyword_start_with_uppercase`,`symbol_with_same_case` -- 增加支持Com对象成员补全, ProgID补全 + +- 增加Com对象成员补全 +- 修复[#272](https://github.com/thqby/vscode-autohotkey2-lsp/issues/272) +- 修复[#278](https://github.com/thqby/vscode-autohotkey2-lsp/issues/278) +- 增加格式化选项`keyword_start_with_uppercase`,`symbol_with_same_case` +- 增加支持Com对象成员补全, ProgID补全 ## 1.8.7 -- 修复[#265](https://github.com/thqby/vscode-autohotkey2-lsp/issues/265) -- 修复[#266](https://github.com/thqby/vscode-autohotkey2-lsp/issues/266) -- 修复[#268](https://github.com/thqby/vscode-autohotkey2-lsp/issues/268) -- 修复[#269](https://github.com/thqby/vscode-autohotkey2-lsp/issues/269) -- 修复[#270](https://github.com/thqby/vscode-autohotkey2-lsp/issues/270) -- 增加`CompletionCommitCharacters`设置项 + +- 修复[#265](https://github.com/thqby/vscode-autohotkey2-lsp/issues/265) +- 修复[#266](https://github.com/thqby/vscode-autohotkey2-lsp/issues/266) +- 修复[#268](https://github.com/thqby/vscode-autohotkey2-lsp/issues/268) +- 修复[#269](https://github.com/thqby/vscode-autohotkey2-lsp/issues/269) +- 修复[#270](https://github.com/thqby/vscode-autohotkey2-lsp/issues/270) +- 增加`CompletionCommitCharacters`设置项 ## 1.8.6 -- 修复[#260](https://github.com/thqby/vscode-autohotkey2-lsp/issues/260) -- 修复[#262](https://github.com/thqby/vscode-autohotkey2-lsp/issues/262) -- 修复[#263](https://github.com/thqby/vscode-autohotkey2-lsp/issues/263) + +- 修复[#260](https://github.com/thqby/vscode-autohotkey2-lsp/issues/260) +- 修复[#262](https://github.com/thqby/vscode-autohotkey2-lsp/issues/262) +- 修复[#263](https://github.com/thqby/vscode-autohotkey2-lsp/issues/263) ## 1.8.5 -- 修复[#246](https://github.com/thqby/vscode-autohotkey2-lsp/issues/246) -- 修复[#254](https://github.com/thqby/vscode-autohotkey2-lsp/issues/254) -- 修复[#255](https://github.com/thqby/vscode-autohotkey2-lsp/issues/255) -- 修复[#256](https://github.com/thqby/vscode-autohotkey2-lsp/issues/256) + +- 修复[#246](https://github.com/thqby/vscode-autohotkey2-lsp/issues/246) +- 修复[#254](https://github.com/thqby/vscode-autohotkey2-lsp/issues/254) +- 修复[#255](https://github.com/thqby/vscode-autohotkey2-lsp/issues/255) +- 修复[#256](https://github.com/thqby/vscode-autohotkey2-lsp/issues/256) ## 1.8.4 -- 增加`FormatOptions.space_after_double_colon`选项[#252](https://github.com/thqby/vscode-autohotkey2-lsp/issues/252) -- 修复[#253](https://github.com/thqby/vscode-autohotkey2-lsp/issues/253) -- 修复一些bug + +- 增加`FormatOptions.space_after_double_colon`选项[#252](https://github.com/thqby/vscode-autohotkey2-lsp/issues/252) +- 修复[#253](https://github.com/thqby/vscode-autohotkey2-lsp/issues/253) +- 修复一些bug ## 1.8.3 -- 修复[#242](https://github.com/thqby/vscode-autohotkey2-lsp/issues/242) -- 修复[#245](https://github.com/thqby/vscode-autohotkey2-lsp/issues/245) -- 修复[#247](https://github.com/thqby/vscode-autohotkey2-lsp/issues/247) + +- 修复[#242](https://github.com/thqby/vscode-autohotkey2-lsp/issues/242) +- 修复[#245](https://github.com/thqby/vscode-autohotkey2-lsp/issues/245) +- 修复[#247](https://github.com/thqby/vscode-autohotkey2-lsp/issues/247) ## 1.8.2 -- 修复[#236](https://github.com/thqby/vscode-autohotkey2-lsp/issues/236) -- 修复[#238](https://github.com/thqby/vscode-autohotkey2-lsp/issues/238) -- 修复[#239](https://github.com/thqby/vscode-autohotkey2-lsp/issues/239) -- 修复[#240](https://github.com/thqby/vscode-autohotkey2-lsp/issues/240) -- 增加注释开关`;@lint-disable class-static-member-check` + +- 修复[#236](https://github.com/thqby/vscode-autohotkey2-lsp/issues/236) +- 修复[#238](https://github.com/thqby/vscode-autohotkey2-lsp/issues/238) +- 修复[#239](https://github.com/thqby/vscode-autohotkey2-lsp/issues/239) +- 修复[#240](https://github.com/thqby/vscode-autohotkey2-lsp/issues/240) +- 增加注释开关`;@lint-disable class-static-member-check` ## 1.8.1 -- 修复[#234](https://github.com/thqby/vscode-autohotkey2-lsp/issues/234) -- 修复[#235](https://github.com/thqby/vscode-autohotkey2-lsp/issues/235) -- 增强[#233](https://github.com/thqby/vscode-autohotkey2-lsp/issues/233) + +- 修复[#234](https://github.com/thqby/vscode-autohotkey2-lsp/issues/234) +- 修复[#235](https://github.com/thqby/vscode-autohotkey2-lsp/issues/235) +- 增强[#233](https://github.com/thqby/vscode-autohotkey2-lsp/issues/233) ## 1.8.0 -- 修复[#231](https://github.com/thqby/vscode-autohotkey2-lsp/issues/231) -- 增强[#230](https://github.com/thqby/vscode-autohotkey2-lsp/issues/230) 在工作区中, 解释器路径可以设置为相对路径 -- 修复一些bug + +- 修复[#231](https://github.com/thqby/vscode-autohotkey2-lsp/issues/231) +- 增强[#230](https://github.com/thqby/vscode-autohotkey2-lsp/issues/230) 在工作区中, 解释器路径可以设置为相对路径 +- 修复一些bug ## 1.7.9 -- 修复[#227](https://github.com/thqby/vscode-autohotkey2-lsp/issues/227) -- 修复[#228](https://github.com/thqby/vscode-autohotkey2-lsp/issues/228) -- 增强[#229](https://github.com/thqby/vscode-autohotkey2-lsp/issues/229) + +- 修复[#227](https://github.com/thqby/vscode-autohotkey2-lsp/issues/227) +- 修复[#228](https://github.com/thqby/vscode-autohotkey2-lsp/issues/228) +- 增强[#229](https://github.com/thqby/vscode-autohotkey2-lsp/issues/229) ## 1.7.8 -- 修复格式化错误 -- 修复[#224](https://github.com/thqby/vscode-autohotkey2-lsp/issues/224) -- 修复[#225](https://github.com/thqby/vscode-autohotkey2-lsp/issues/225) + +- 修复格式化错误 +- 修复[#224](https://github.com/thqby/vscode-autohotkey2-lsp/issues/224) +- 修复[#225](https://github.com/thqby/vscode-autohotkey2-lsp/issues/225) ## 1.7.7 -- 修复格式化错误 -- 加入简单返回值检查[#221](https://github.com/thqby/vscode-autohotkey2-lsp/issues/221) -- 对一部分无效的函数调用进行提示`a := MsgBox b` + +- 修复格式化错误 +- 加入简单返回值检查[#221](https://github.com/thqby/vscode-autohotkey2-lsp/issues/221) +- 对一部分无效的函数调用进行提示`a := MsgBox b` ## 1.7.6 -- 增加v1/v2切换命令`ahk2.switch` -- 从其他语言切换到ahk2将不触发SwitchToV1 -- 修复格式化和查找所有引用的错误 -- 减少类似警告[#220](https://github.com/thqby/vscode-autohotkey2-lsp/issues/220) + +- 增加v1/v2切换命令`ahk2.switch` +- 从其他语言切换到ahk2将不触发SwitchToV1 +- 修复格式化和查找所有引用的错误 +- 减少类似警告[#220](https://github.com/thqby/vscode-autohotkey2-lsp/issues/220) ## 1.7.5 -- 优化v1脚本识别并切换 + +- 优化v1脚本识别并切换 ## 1.7.4 -- 支持指定在检测到v1脚本时触发的行为(切换至v1, 跳过触发行, 停止解析, 警告选择框)[#214](https://github.com/thqby/vscode-autohotkey2-lsp/issues/214) -- 修复[#217](https://github.com/thqby/vscode-autohotkey2-lsp/issues/217) -- 关闭未被引用的v1缓存 + +- 支持指定在检测到v1脚本时触发的行为(切换至v1, 跳过触发行, 停止解析, 警告选择框)[#214](https://github.com/thqby/vscode-autohotkey2-lsp/issues/214) +- 修复[#217](https://github.com/thqby/vscode-autohotkey2-lsp/issues/217) +- 关闭未被引用的v1缓存 ## 1.7.3 -- 修复[#212](https://github.com/thqby/vscode-autohotkey2-lsp/issues/212) -- 修复[#213](https://github.com/thqby/vscode-autohotkey2-lsp/issues/213) + +- 修复[#212](https://github.com/thqby/vscode-autohotkey2-lsp/issues/212) +- 修复[#213](https://github.com/thqby/vscode-autohotkey2-lsp/issues/213) ## 1.7.2 -- 修复[#208](https://github.com/thqby/vscode-autohotkey2-lsp/issues/208) -- 修复[#210](https://github.com/thqby/vscode-autohotkey2-lsp/issues/210) -- 支持`case`和`default`块折叠[#209](https://github.com/thqby/vscode-autohotkey2-lsp/issues/209) + +- 修复[#208](https://github.com/thqby/vscode-autohotkey2-lsp/issues/208) +- 修复[#210](https://github.com/thqby/vscode-autohotkey2-lsp/issues/210) +- 支持`case`和`default`块折叠[#209](https://github.com/thqby/vscode-autohotkey2-lsp/issues/209) ## 1.7.1 -- 修复[#205](https://github.com/thqby/vscode-autohotkey2-lsp/issues/205) -- 修复[#206](https://github.com/thqby/vscode-autohotkey2-lsp/issues/206) + +- 修复[#205](https://github.com/thqby/vscode-autohotkey2-lsp/issues/205) +- 修复[#206](https://github.com/thqby/vscode-autohotkey2-lsp/issues/206) ## 1.7.0 -- 更新lsp for sublime text4设置 + +- 更新lsp for sublime text4设置 ## 1.6.8 -- 修复[#200](https://github.com/thqby/vscode-autohotkey2-lsp/issues/200) -- 修复[#202](https://github.com/thqby/vscode-autohotkey2-lsp/issues/202) -- 修复[#203](https://github.com/thqby/vscode-autohotkey2-lsp/issues/203) -- 修复`MsgBox []`格式化错误 + +- 修复[#200](https://github.com/thqby/vscode-autohotkey2-lsp/issues/200) +- 修复[#202](https://github.com/thqby/vscode-autohotkey2-lsp/issues/202) +- 修复[#203](https://github.com/thqby/vscode-autohotkey2-lsp/issues/203) +- 修复`MsgBox []`格式化错误 ## 1.6.6 -- 增加了对在资源文件中的库的读取支持, `#include *libname` -- 在ahk.exe选取列表移除有UIAccess特权的exe -- 修复[#198](https://github.com/thqby/vscode-autohotkey2-lsp/issues/198) + +- 增加了对在资源文件中的库的读取支持, `#include *libname` +- 在ahk.exe选取列表移除有UIAccess特权的exe +- 修复[#198](https://github.com/thqby/vscode-autohotkey2-lsp/issues/198) ## 1.6.5 -- 增强jsdoc类型标注 -- 修复热键定义处补全丢失 -- 修复[#195](https://github.com/thqby/vscode-autohotkey2-lsp/issues/195) -- 修复[#196](https://github.com/thqby/vscode-autohotkey2-lsp/issues/196) -- 修复递归超出最大调用栈[#197](https://github.com/thqby/vscode-autohotkey2-lsp/issues/197) + +- 增强jsdoc类型标注 +- 修复热键定义处补全丢失 +- 修复[#195](https://github.com/thqby/vscode-autohotkey2-lsp/issues/195) +- 修复[#196](https://github.com/thqby/vscode-autohotkey2-lsp/issues/196) +- 修复递归超出最大调用栈[#197](https://github.com/thqby/vscode-autohotkey2-lsp/issues/197) ## 1.6.4 -- 增加jsdoc类型标注 -- 增加brace样式, `brace_style=-1` -- 修复函数定义未应用`brace_style`样式 -- 代码块补全应用格式化设置指定的样式[#194](https://github.com/thqby/vscode-autohotkey2-lsp/issues/194) -- 修复[#191](https://github.com/thqby/vscode-autohotkey2-lsp/issues/191) -- 修复[#193](https://github.com/thqby/vscode-autohotkey2-lsp/issues/193) + +- 增加jsdoc类型标注 +- 增加brace样式, `brace_style=-1` +- 修复函数定义未应用`brace_style`样式 +- 代码块补全应用格式化设置指定的样式[#194](https://github.com/thqby/vscode-autohotkey2-lsp/issues/194) +- 修复[#191](https://github.com/thqby/vscode-autohotkey2-lsp/issues/191) +- 修复[#193](https://github.com/thqby/vscode-autohotkey2-lsp/issues/193) ## 1.6.3 -- `formatOnType`支持换行时格式化代码行并缩进 -- jsdoc支持重载函数提示 -- 修复[#185](https://github.com/thqby/vscode-autohotkey2-lsp/issues/185) -- 修复[#186](https://github.com/thqby/vscode-autohotkey2-lsp/issues/186) -- 修复[#188](https://github.com/thqby/vscode-autohotkey2-lsp/issues/188) + +- `formatOnType`支持换行时格式化代码行并缩进 +- jsdoc支持重载函数提示 +- 修复[#185](https://github.com/thqby/vscode-autohotkey2-lsp/issues/185) +- 修复[#186](https://github.com/thqby/vscode-autohotkey2-lsp/issues/186) +- 修复[#188](https://github.com/thqby/vscode-autohotkey2-lsp/issues/188) ## 1.6.2 -- 优化局部格式化 -- 增加格式化选项`brace_style` -- 修复自定义设置未生效 + +- 优化局部格式化 +- 增加格式化选项`brace_style` +- 修复自定义设置未生效 ## 1.6.1 -- 输入时替换中文标点 -- 优化代码格式化 -- 修复[#181](https://github.com/thqby/vscode-autohotkey2-lsp/issues/181) -- 修复[#182](https://github.com/thqby/vscode-autohotkey2-lsp/issues/182) -- 修复[#183](https://github.com/thqby/vscode-autohotkey2-lsp/issues/183) + +- 输入时替换中文标点 +- 优化代码格式化 +- 修复[#181](https://github.com/thqby/vscode-autohotkey2-lsp/issues/181) +- 修复[#182](https://github.com/thqby/vscode-autohotkey2-lsp/issues/182) +- 修复[#183](https://github.com/thqby/vscode-autohotkey2-lsp/issues/183) ## 1.6.0 -- 修复[#176-#180](https://github.com/thqby/vscode-autohotkey2-lsp/issues/176) -- 修复静态函数部分bug + +- 修复[#176-#180](https://github.com/thqby/vscode-autohotkey2-lsp/issues/176) +- 修复静态函数部分bug ## 1.5.9 -- 修复部分格式化错误 -- 修复符号搜索错误 -- 增加延续片段、热字串选项着色 -- 增加设置项[#173](https://github.com/thqby/vscode-autohotkey2-lsp/issues/173) -- 修复[#171](https://github.com/thqby/vscode-autohotkey2-lsp/issues/171) -- 修复[#172](https://github.com/thqby/vscode-autohotkey2-lsp/issues/172) -- 修复[#174](https://github.com/thqby/vscode-autohotkey2-lsp/issues/174) + +- 修复部分格式化错误 +- 修复符号搜索错误 +- 增加延续片段、热字串选项着色 +- 增加设置项[#173](https://github.com/thqby/vscode-autohotkey2-lsp/issues/173) +- 修复[#171](https://github.com/thqby/vscode-autohotkey2-lsp/issues/171) +- 修复[#172](https://github.com/thqby/vscode-autohotkey2-lsp/issues/172) +- 修复[#174](https://github.com/thqby/vscode-autohotkey2-lsp/issues/174) ## 1.5.8 -- 修复[#169](https://github.com/thqby/vscode-autohotkey2-lsp/issues/169) -- 修复[#170](https://github.com/thqby/vscode-autohotkey2-lsp/issues/170) -- 增加`代码格式化`、`类静态成员检查`选项 + +- 修复[#169](https://github.com/thqby/vscode-autohotkey2-lsp/issues/169) +- 修复[#170](https://github.com/thqby/vscode-autohotkey2-lsp/issues/170) +- 增加`代码格式化`、`类静态成员检查`选项 ## 1.5.7 -- 修复[#164](https://github.com/thqby/vscode-autohotkey2-lsp/issues/164) -- 修复[#165](https://github.com/thqby/vscode-autohotkey2-lsp/issues/165) -- 修复[#166](https://github.com/thqby/vscode-autohotkey2-lsp/issues/166) -- 修复[#167](https://github.com/thqby/vscode-autohotkey2-lsp/issues/167) -- 修复[#168](https://github.com/thqby/vscode-autohotkey2-lsp/issues/168) -- 当选择`AutoHotkeyUX.exe`时, 使用UX Launcher启动脚本 [#157](https://github.com/thqby/vscode-autohotkey2-lsp/issues/157) + +- 修复[#164](https://github.com/thqby/vscode-autohotkey2-lsp/issues/164) +- 修复[#165](https://github.com/thqby/vscode-autohotkey2-lsp/issues/165) +- 修复[#166](https://github.com/thqby/vscode-autohotkey2-lsp/issues/166) +- 修复[#167](https://github.com/thqby/vscode-autohotkey2-lsp/issues/167) +- 修复[#168](https://github.com/thqby/vscode-autohotkey2-lsp/issues/168) +- 当选择`AutoHotkeyUX.exe`时, 使用UX Launcher启动脚本 [#157](https://github.com/thqby/vscode-autohotkey2-lsp/issues/157) ## 1.5.6 -- 修复[#158](https://github.com/thqby/vscode-autohotkey2-lsp/issues/158) -- 修复[#159](https://github.com/thqby/vscode-autohotkey2-lsp/issues/159) -- 修复[#160](https://github.com/thqby/vscode-autohotkey2-lsp/issues/160) -- 修复[#161](https://github.com/thqby/vscode-autohotkey2-lsp/issues/161) -- 修复[#162](https://github.com/thqby/vscode-autohotkey2-lsp/issues/162) -- 修复延续片段字符串 + +- 修复[#158](https://github.com/thqby/vscode-autohotkey2-lsp/issues/158) +- 修复[#159](https://github.com/thqby/vscode-autohotkey2-lsp/issues/159) +- 修复[#160](https://github.com/thqby/vscode-autohotkey2-lsp/issues/160) +- 修复[#161](https://github.com/thqby/vscode-autohotkey2-lsp/issues/161) +- 修复[#162](https://github.com/thqby/vscode-autohotkey2-lsp/issues/162) +- 修复延续片段字符串 ## 1.5.5 -- 修复[#154](https://github.com/thqby/vscode-autohotkey2-lsp/issues/154) -- 修复[#155](https://github.com/thqby/vscode-autohotkey2-lsp/issues/155) -- 修复[#156](https://github.com/thqby/vscode-autohotkey2-lsp/issues/156) + +- 修复[#154](https://github.com/thqby/vscode-autohotkey2-lsp/issues/154) +- 修复[#155](https://github.com/thqby/vscode-autohotkey2-lsp/issues/155) +- 修复[#156](https://github.com/thqby/vscode-autohotkey2-lsp/issues/156) ## 1.5.4 -- 修复[#145-#152] -- 增加支持简单`延续部分`, `::abc::\n(\nstr\n)` + +- 修复[#145-#152] +- 增加支持简单`延续部分`, `::abc::\n(\nstr\n)` ## 1.5.3 -- 修复[#143](https://github.com/thqby/vscode-autohotkey2-lsp/issues/143) -- 修复[#144](https://github.com/thqby/vscode-autohotkey2-lsp/issues/144) + +- 修复[#143](https://github.com/thqby/vscode-autohotkey2-lsp/issues/143) +- 修复[#144](https://github.com/thqby/vscode-autohotkey2-lsp/issues/144) ## 1.5.2 -- 修复[#139](https://github.com/thqby/vscode-autohotkey2-lsp/issues/139) -- 修复[#140](https://github.com/thqby/vscode-autohotkey2-lsp/issues/140) -- 修复[#141](https://github.com/thqby/vscode-autohotkey2-lsp/issues/141) + +- 修复[#139](https://github.com/thqby/vscode-autohotkey2-lsp/issues/139) +- 修复[#140](https://github.com/thqby/vscode-autohotkey2-lsp/issues/140) +- 修复[#141](https://github.com/thqby/vscode-autohotkey2-lsp/issues/141) ## 1.5.1 -- 修复[#133](https://github.com/thqby/vscode-autohotkey2-lsp/issues/133) -- 修复[#134](https://github.com/thqby/vscode-autohotkey2-lsp/issues/134) -- 修复[#135](https://github.com/thqby/vscode-autohotkey2-lsp/issues/135) -- 修复[#136](https://github.com/thqby/vscode-autohotkey2-lsp/issues/136) -- 修复[#137](https://github.com/thqby/vscode-autohotkey2-lsp/issues/137) -- 修复[#138](https://github.com/thqby/vscode-autohotkey2-lsp/issues/138) -- 识别stdout,stderr输出的字符编码 -- `ahk2exe`的`/base`命令行参数现在是可选的 + +- 修复[#133](https://github.com/thqby/vscode-autohotkey2-lsp/issues/133) +- 修复[#134](https://github.com/thqby/vscode-autohotkey2-lsp/issues/134) +- 修复[#135](https://github.com/thqby/vscode-autohotkey2-lsp/issues/135) +- 修复[#136](https://github.com/thqby/vscode-autohotkey2-lsp/issues/136) +- 修复[#137](https://github.com/thqby/vscode-autohotkey2-lsp/issues/137) +- 修复[#138](https://github.com/thqby/vscode-autohotkey2-lsp/issues/138) +- 识别stdout,stderr输出的字符编码 +- `ahk2exe`的`/base`命令行参数现在是可选的 ## 1.5.0 -- 检测到v1脚本, 词法解析器将停止解析 + +- 检测到v1脚本, 词法解析器将停止解析 ## 1.4.9 -- 修复[#130](https://github.com/thqby/vscode-autohotkey2-lsp/issues/130) + +- 修复[#130](https://github.com/thqby/vscode-autohotkey2-lsp/issues/130) ## 1.4.7 -- 修复[#127](https://github.com/thqby/vscode-autohotkey2-lsp/issues/127) -- 修复[#128](https://github.com/thqby/vscode-autohotkey2-lsp/issues/128) + +- 修复[#127](https://github.com/thqby/vscode-autohotkey2-lsp/issues/127) +- 修复[#128](https://github.com/thqby/vscode-autohotkey2-lsp/issues/128) ## 1.4.6 -- 修复[#125](https://github.com/thqby/vscode-autohotkey2-lsp/issues/125) -- 修复[#126](https://github.com/thqby/vscode-autohotkey2-lsp/issues/126) -- 增加`[]`,`()`折叠 +- 修复[#125](https://github.com/thqby/vscode-autohotkey2-lsp/issues/125) +- 修复[#126](https://github.com/thqby/vscode-autohotkey2-lsp/issues/126) +- 增加`[]`,`()`折叠 ## 1.4.5 -- 修复[#118](https://github.com/thqby/vscode-autohotkey2-lsp/issues/118) -- 修复[#119](https://github.com/thqby/vscode-autohotkey2-lsp/issues/119) -- 修复[#120](https://github.com/thqby/vscode-autohotkey2-lsp/issues/120) -- 修复[#121](https://github.com/thqby/vscode-autohotkey2-lsp/issues/121) -- 增加beta.7函数信息 + +- 修复[#118](https://github.com/thqby/vscode-autohotkey2-lsp/issues/118) +- 修复[#119](https://github.com/thqby/vscode-autohotkey2-lsp/issues/119) +- 修复[#120](https://github.com/thqby/vscode-autohotkey2-lsp/issues/120) +- 修复[#121](https://github.com/thqby/vscode-autohotkey2-lsp/issues/121) +- 增加beta.7函数信息 ## 1.4.4 -- 修复[#117](https://github.com/thqby/vscode-autohotkey2-lsp/issues/117) -- 修复部分`寻找所有引用`不正确 + +- 修复[#117](https://github.com/thqby/vscode-autohotkey2-lsp/issues/117) +- 修复部分`寻找所有引用`不正确 ## 1.4.3 -- 修复解析时部分变量丢失 + +- 修复解析时部分变量丢失 ## 1.4.2 -- 修复[#116](https://github.com/thqby/vscode-autohotkey2-lsp/issues/116) -- 优化关联脚本识别 + +- 修复[#116](https://github.com/thqby/vscode-autohotkey2-lsp/issues/116) +- 优化关联脚本识别 ## 1.4.1 -- 修复[#114](https://github.com/thqby/vscode-autohotkey2-lsp/issues/114) -- 修复[#115](https://github.com/thqby/vscode-autohotkey2-lsp/issues/115) + +- 修复[#114](https://github.com/thqby/vscode-autohotkey2-lsp/issues/114) +- 修复[#115](https://github.com/thqby/vscode-autohotkey2-lsp/issues/115) ## 1.4.0 -- 适配beta.6语法解析 -- 增加遗漏的内置函数[#111](https://github.com/thqby/vscode-autohotkey2-lsp/issues/111) -- 修复格式化错误[#110](https://github.com/thqby/vscode-autohotkey2-lsp/issues/110) + +- 适配beta.6语法解析 +- 增加遗漏的内置函数[#111](https://github.com/thqby/vscode-autohotkey2-lsp/issues/111) +- 修复格式化错误[#110](https://github.com/thqby/vscode-autohotkey2-lsp/issues/110) ## 1.3.7 -- 增加空值合并运算符`??`和可选参数操作符`?` -- 修复部分dllcall补全未触发 -- 修复[#106](https://github.com/thqby/vscode-autohotkey2-lsp/issues/106) -- 修复[#107](https://github.com/thqby/vscode-autohotkey2-lsp/issues/107) -- 修复[#108](https://github.com/thqby/vscode-autohotkey2-lsp/issues/108) + +- 增加空值合并运算符`??`和可选参数操作符`?` +- 修复部分dllcall补全未触发 +- 修复[#106](https://github.com/thqby/vscode-autohotkey2-lsp/issues/106) +- 修复[#107](https://github.com/thqby/vscode-autohotkey2-lsp/issues/107) +- 修复[#108](https://github.com/thqby/vscode-autohotkey2-lsp/issues/108) ## 1.3.6 -- 修复格式化错误 -- 修复部分类型推导失败 -- 修复在`coc.nvim`中获取配置失败导致语言服务器无法启动 -- 修复[#102](https://github.com/thqby/vscode-autohotkey2-lsp/issues/102) -- 修复[#104](https://github.com/thqby/vscode-autohotkey2-lsp/issues/104) -- 修复[#105](https://github.com/thqby/vscode-autohotkey2-lsp/issues/105) + +- 修复格式化错误 +- 修复部分类型推导失败 +- 修复在`coc.nvim`中获取配置失败导致语言服务器无法启动 +- 修复[#102](https://github.com/thqby/vscode-autohotkey2-lsp/issues/102) +- 修复[#104](https://github.com/thqby/vscode-autohotkey2-lsp/issues/104) +- 修复[#105](https://github.com/thqby/vscode-autohotkey2-lsp/issues/105) ## 1.3.5 -- 修复[#99](https://github.com/thqby/vscode-autohotkey2-lsp/issues/99) -- 修复语法高亮的错误 [#101](https://github.com/thqby/vscode-autohotkey2-lsp/issues/101) + +- 修复[#99](https://github.com/thqby/vscode-autohotkey2-lsp/issues/99) +- 修复语法高亮的错误 [#101](https://github.com/thqby/vscode-autohotkey2-lsp/issues/101) ## 1.3.4 -- 修复部分行语句无法触发参数提示 -- 修复格式化错误 [#95](https://github.com/thqby/vscode-autohotkey2-lsp/issues/95) + +- 修复部分行语句无法触发参数提示 +- 修复格式化错误 [#95](https://github.com/thqby/vscode-autohotkey2-lsp/issues/95) ## 1.3.3 -- 功能移至上下文菜单 [#94](https://github.com/thqby/vscode-autohotkey2-lsp/issues/94) + +- 功能移至上下文菜单 [#94](https://github.com/thqby/vscode-autohotkey2-lsp/issues/94) ## 1.3.2 -- 修复[#92](https://github.com/thqby/vscode-autohotkey2-lsp/issues/92) -- 增加打开工作区时, 子目录存在`lib`文件夹时, 将被视为脚本入口目录 [#91](https://github.com/thqby/vscode-autohotkey2-lsp/issues/91) + +- 修复[#92](https://github.com/thqby/vscode-autohotkey2-lsp/issues/92) +- 增加打开工作区时, 子目录存在`lib`文件夹时, 将被视为脚本入口目录 [#91](https://github.com/thqby/vscode-autohotkey2-lsp/issues/91) ## 1.3.1 -- 修复[#84](https://github.com/thqby/vscode-autohotkey2-lsp/issues/84) -- 修复[#85](https://github.com/thqby/vscode-autohotkey2-lsp/issues/85) + +- 修复[#84](https://github.com/thqby/vscode-autohotkey2-lsp/issues/84) +- 修复[#85](https://github.com/thqby/vscode-autohotkey2-lsp/issues/85) ## 1.2.9 -- 修复`try ... catch ... catch`诊断错误 -- 修复`this()`参数提示错误, 着色错误 -- 修复`prop => ...`着色错误 -- 优化代码格式化 -- 修正头文件 + +- 修复`try ... catch ... catch`诊断错误 +- 修复`this()`参数提示错误, 着色错误 +- 修复`prop => ...`着色错误 +- 优化代码格式化 +- 修正头文件 ## 1.2.8 -- 修复[#79](https://github.com/thqby/vscode-autohotkey2-lsp/issues/79) -- 修复[#80](https://github.com/thqby/vscode-autohotkey2-lsp/issues/80) + +- 修复[#79](https://github.com/thqby/vscode-autohotkey2-lsp/issues/79) +- 修复[#80](https://github.com/thqby/vscode-autohotkey2-lsp/issues/80) ## 1.2.7 -- 修复[#75](https://github.com/thqby/vscode-autohotkey2-lsp/issues/75) -- 修复[#76](https://github.com/thqby/vscode-autohotkey2-lsp/issues/76) -- 修复[#77](https://github.com/thqby/vscode-autohotkey2-lsp/issues/77) -- 修复[#78](https://github.com/thqby/vscode-autohotkey2-lsp/issues/78) -- 增加`#DllLoad `补全支持, `DllCall`对`#DllLoad`加载的dll提供补全及导出函数解析 -- `;@include custom.d.ahk`导入头文件增加自定义补全 + +- 修复[#75](https://github.com/thqby/vscode-autohotkey2-lsp/issues/75) +- 修复[#76](https://github.com/thqby/vscode-autohotkey2-lsp/issues/76) +- 修复[#77](https://github.com/thqby/vscode-autohotkey2-lsp/issues/77) +- 修复[#78](https://github.com/thqby/vscode-autohotkey2-lsp/issues/78) +- 增加`#DllLoad `补全支持, `DllCall`对`#DllLoad`加载的dll提供补全及导出函数解析 +- `;@include custom.d.ahk`导入头文件增加自定义补全 ## 1.2.6 -- 修复[#71](https://github.com/thqby/vscode-autohotkey2-lsp/issues/71) -- 修复[#72](https://github.com/thqby/vscode-autohotkey2-lsp/issues/72) -- 修复[#73](https://github.com/thqby/vscode-autohotkey2-lsp/issues/73) -- 修复[#74](https://github.com/thqby/vscode-autohotkey2-lsp/issues/74) + +- 修复[#71](https://github.com/thqby/vscode-autohotkey2-lsp/issues/71) +- 修复[#72](https://github.com/thqby/vscode-autohotkey2-lsp/issues/72) +- 修复[#73](https://github.com/thqby/vscode-autohotkey2-lsp/issues/73) +- 修复[#74](https://github.com/thqby/vscode-autohotkey2-lsp/issues/74) ## 1.2.5 -- 修复[#70](https://github.com/thqby/vscode-autohotkey2-lsp/issues/70) -- 优化代码格式化 -- 增加静态函数调用的参数检查[#23](https://github.com/thqby/vscode-autohotkey2-lsp/issues/23) + +- 修复[#70](https://github.com/thqby/vscode-autohotkey2-lsp/issues/70) +- 优化代码格式化 +- 增加静态函数调用的参数检查[#23](https://github.com/thqby/vscode-autohotkey2-lsp/issues/23) ## 1.2.4 -- 修复[#69](https://github.com/thqby/vscode-autohotkey2-lsp/issues/69) + +- 修复[#69](https://github.com/thqby/vscode-autohotkey2-lsp/issues/69) ## 1.2.3 -- 修复[#68](https://github.com/thqby/vscode-autohotkey2-lsp/issues/68) + +- 修复[#68](https://github.com/thqby/vscode-autohotkey2-lsp/issues/68) ## 1.2.2 -- 修复[#64](https://github.com/thqby/vscode-autohotkey2-lsp/issues/64) -- 修复[#66](https://github.com/thqby/vscode-autohotkey2-lsp/issues/66) -- 修复[#67](https://github.com/thqby/vscode-autohotkey2-lsp/issues/67) -- 诊断控制流语句[#21](https://github.com/thqby/vscode-autohotkey2-lsp/issues/21) + +- 修复[#64](https://github.com/thqby/vscode-autohotkey2-lsp/issues/64) +- 修复[#66](https://github.com/thqby/vscode-autohotkey2-lsp/issues/66) +- 修复[#67](https://github.com/thqby/vscode-autohotkey2-lsp/issues/67) +- 诊断控制流语句[#21](https://github.com/thqby/vscode-autohotkey2-lsp/issues/21) ## 1.2.1 -- 修复[#63](https://github.com/thqby/vscode-autohotkey2-lsp/issues/63) + +- 修复[#63](https://github.com/thqby/vscode-autohotkey2-lsp/issues/63) ## 1.2.0 -- 修复一些bug + +- 修复一些bug ## 1.1.9 -- 修复[#61](https://github.com/thqby/vscode-autohotkey2-lsp/issues/61) -- 修复格式化时丢失部分行 + +- 修复[#61](https://github.com/thqby/vscode-autohotkey2-lsp/issues/61) +- 修复格式化时丢失部分行 ## 1.1.8 -- 修复一些问题 + +- 修复一些问题 ## 1.1.6 -- 增加`DllCall`补全支持 -- 增加`WorkspaceSymbolProvider` [#60](https://github.com/thqby/vscode-autohotkey2-lsp/issues/60) + +- 增加`DllCall`补全支持 +- 增加`WorkspaceSymbolProvider` [#60](https://github.com/thqby/vscode-autohotkey2-lsp/issues/60) ## 1.1.5 -- 修复[#59](https://github.com/thqby/vscode-autohotkey2-lsp/issues/59) -- 调整`AutoHotkey2.AutoLibInclude`设置项值为`'Disabled','Local','User and Standard','All'` [#58](https://github.com/thqby/vscode-autohotkey2-lsp/issues/58) -- 取消补全自动导入被`.`和`(`触发 -- 修复在无标题文件`Untitled`中,部分功能异常 + +- 修复[#59](https://github.com/thqby/vscode-autohotkey2-lsp/issues/59) +- 调整`AutoHotkey2.AutoLibInclude`设置项值为`'Disabled','Local','User and Standard','All'` [#58](https://github.com/thqby/vscode-autohotkey2-lsp/issues/58) +- 取消补全自动导入被`.`和`(`触发 +- 修复在无标题文件`Untitled`中,部分功能异常 ## 1.1.4 -- 修复[#54](https://github.com/thqby/vscode-autohotkey2-lsp/issues/54) -- 修复[#55](https://github.com/thqby/vscode-autohotkey2-lsp/issues/55) -- 修复[#56](https://github.com/thqby/vscode-autohotkey2-lsp/issues/56) -- 修复[#57](https://github.com/thqby/vscode-autohotkey2-lsp/issues/57) + +- 修复[#54](https://github.com/thqby/vscode-autohotkey2-lsp/issues/54) +- 修复[#55](https://github.com/thqby/vscode-autohotkey2-lsp/issues/55) +- 修复[#56](https://github.com/thqby/vscode-autohotkey2-lsp/issues/56) +- 修复[#57](https://github.com/thqby/vscode-autohotkey2-lsp/issues/57) ## 1.1.3 -- 修复关键字着色错误 + +- 修复关键字着色错误 ## 1.1.2 -- 修复Node版服务器启动失败 -- 增加`给函数补全添加括号`设置项 + +- 修复Node版服务器启动失败 +- 增加`给函数补全添加括号`设置项 ## 1.1.0 -- 修复[#49](https://github.com/thqby/vscode-autohotkey2-lsp/issues/49) -- 修复[#50](https://github.com/thqby/vscode-autohotkey2-lsp/issues/50) -- 支持类静态属性符号重命名, 查找所有引用 -- 插件适配web端编辑器 https://vscode.dev 和 https://github.dev + +- 修复[#49](https://github.com/thqby/vscode-autohotkey2-lsp/issues/49) +- 修复[#50](https://github.com/thqby/vscode-autohotkey2-lsp/issues/50) +- 支持类静态属性符号重命名, 查找所有引用 +- 插件适配web端编辑器 https://vscode.dev 和 https://github.dev ## 1.0.8 -- 修复[#47](https://github.com/thqby/vscode-autohotkey2-lsp/issues/47)`/**\n...\n*/`将按照JSDoc格式化 -- 修复[#48](https://github.com/thqby/vscode-autohotkey2-lsp/issues/48) + +- 修复[#47](https://github.com/thqby/vscode-autohotkey2-lsp/issues/47)`/**\n...\n*/`将按照JSDoc格式化 +- 修复[#48](https://github.com/thqby/vscode-autohotkey2-lsp/issues/48) ## 1.0.7 -- 优化代码格式化 -- 修复类动态属性未能准确识别this + +- 优化代码格式化 +- 修复类动态属性未能准确识别this ## 1.0.6 -- 修复未能准确识别非类变量this -- 修复[#46](https://github.com/thqby/vscode-autohotkey2-lsp/issues/46) + +- 修复未能准确识别非类变量this +- 修复[#46](https://github.com/thqby/vscode-autohotkey2-lsp/issues/46) ## 1.0.5 -- 修复类型推导存在的死循环 -- 修复英文版`ahk2.json`文件存在的错误 -- 修复`switch`中的`default:`着色不正确 -- 修复词法分析中胖箭头函数的局部变量识别错误 + +- 修复类型推导存在的死循环 +- 修复英文版`ahk2.json`文件存在的错误 +- 修复`switch`中的`default:`着色不正确 +- 修复词法分析中胖箭头函数的局部变量识别错误 ## 1.0.4 -- 修复语法高亮的错误 -- 增加对`{prop:val}`对象定义处的属性补全支持 + +- 修复语法高亮的错误 +- 增加对`{prop:val}`对象定义处的属性补全支持 ## 1.0.3 -- 加入英文版头文件([dmtr99](https://github.com/dmtr99)提供)[#45](https://github.com/thqby/vscode-autohotkey2-lsp/issues/45) + +- 加入英文版头文件([dmtr99](https://github.com/dmtr99)提供)[#45](https://github.com/thqby/vscode-autohotkey2-lsp/issues/45) ## 1.0.2 -- 修复[#44](https://github.com/thqby/vscode-autohotkey2-lsp/issues/44) -- 修复`catch Error {`提示为错误 + +- 修复[#44](https://github.com/thqby/vscode-autohotkey2-lsp/issues/44) +- 修复`catch Error {`提示为错误 ## 1.0.0 -- 优化快捷帮助稳定性 -- 增加语义着色对类静态成员的支持 -- 修复`#include *i `中`*i`选项未生效 -- 修复换行符为LF时, 代码格式化存在错误的问题 -- 修复`[(*)=>1]`数组中的匿名函数被识别为错误 + +- 优化快捷帮助稳定性 +- 增加语义着色对类静态成员的支持 +- 修复`#include *i `中`*i`选项未生效 +- 修复换行符为LF时, 代码格式化存在错误的问题 +- 修复`[(*)=>1]`数组中的匿名函数被识别为错误 ## 0.9.3 -- 修复[#43](https://github.com/thqby/vscode-autohotkey2-lsp/issues/43) -- 增加语义着色支持 -- 修复低版本v2获取A_环境变量失败 -- 调整文档过滤器, 插件对临时文件`Untitled`也能生效 -- `#include`增加对`A_LineFile`的解析, 增加对``补全支持 + +- 修复[#43](https://github.com/thqby/vscode-autohotkey2-lsp/issues/43) +- 增加语义着色支持 +- 修复低版本v2获取A\_环境变量失败 +- 调整文档过滤器, 插件对临时文件`Untitled`也能生效 +- `#include`增加对`A_LineFile`的解析, 增加对``补全支持 ## 0.9.2 -- `coc.nvim插件`增加环境设置项, README中增加插件配置说明 + +- `coc.nvim插件`增加环境设置项, README中增加插件配置说明 ## 0.9.1 -- 修复[#40](https://github.com/thqby/vscode-autohotkey2-lsp/issues/40) -- 修复[#41](https://github.com/thqby/vscode-autohotkey2-lsp/issues/41) -- 修复[#42](https://github.com/thqby/vscode-autohotkey2-lsp/issues/42) + +- 修复[#40](https://github.com/thqby/vscode-autohotkey2-lsp/issues/40) +- 修复[#41](https://github.com/thqby/vscode-autohotkey2-lsp/issues/41) +- 修复[#42](https://github.com/thqby/vscode-autohotkey2-lsp/issues/42) ## 0.8.9 -- 修复胖箭头函数的局部变量出现在函数外的bug + +- 修复胖箭头函数的局部变量出现在函数外的bug ## 0.8.8 -- 加入自定义折叠`;{`和`;}` -- 更新AHK_H补全项 [AHK_H beta.1下载](https://github.com/thqby/AutoHotkey_H/releases/tag/v2.0-beta.1) -- 修复switch语句中部分case高亮不正确 -- 修复`catch TypeError, ValueError`高亮不正确 + +- 加入自定义折叠`;{`和`;}` +- 更新AHK_H补全项 [AHK_H beta.1下载](https://github.com/thqby/AutoHotkey_H/releases/tag/v2.0-beta.1) +- 修复switch语句中部分case高亮不正确 +- 修复`catch TypeError, ValueError`高亮不正确 ## 0.8.7 -- 修复一些可能的热键提示为错误 -- 修复函数的参数高亮不正确 -- 修复连续多个热键定义高亮不正确 [#35](https://github.com/thqby/vscode-autohotkey2-lsp/issues/35) + +- 修复一些可能的热键提示为错误 +- 修复函数的参数高亮不正确 +- 修复连续多个热键定义高亮不正确 [#35](https://github.com/thqby/vscode-autohotkey2-lsp/issues/35) ## 0.8.6 -- 修复用户库标准库自动导入异常 -- 修复include可能引发的错误 [#31](https://github.com/thqby/vscode-autohotkey2-lsp/issues/31) -- 支持含特殊符号的变量 [#33](https://github.com/thqby/vscode-autohotkey2-lsp/issues/33) + +- 修复用户库标准库自动导入异常 +- 修复include可能引发的错误 [#31](https://github.com/thqby/vscode-autohotkey2-lsp/issues/31) +- 支持含特殊符号的变量 [#33](https://github.com/thqby/vscode-autohotkey2-lsp/issues/33) ## 0.8.5 -- 调整配置项名, 原设置选项`Path`更名为`InterpreterPath` -- 打开文件夹或工作区时增加保存当前解释器路径 -- 修复单行热键定义`a::global b := 0`的提示错误 + +- 调整配置项名, 原设置选项`Path`更名为`InterpreterPath` +- 打开文件夹或工作区时增加保存当前解释器路径 +- 修复单行热键定义`a::global b := 0`的提示错误 ## 0.8.4 -- 增加遗漏的内置变量 -- 删除废弃的指令 -- 修复属性定义中`ByRef`参数不正确的错误诊断 [#29](https://github.com/thqby/vscode-autohotkey2-lsp/issues/29) -- 增加识别h版的内置变量, 不在大纲中显示 -- 增加设置编译器额外的命令行选项 -- 修复一些赋值语句中保留词作为对象键名被提示为错误 [#32](https://github.com/thqby/vscode-autohotkey2-lsp/issues/32) -- 增加脚本解释器切换 + +- 增加遗漏的内置变量 +- 删除废弃的指令 +- 修复属性定义中`ByRef`参数不正确的错误诊断 [#29](https://github.com/thqby/vscode-autohotkey2-lsp/issues/29) +- 增加识别h版的内置变量, 不在大纲中显示 +- 增加设置编译器额外的命令行选项 +- 修复一些赋值语句中保留词作为对象键名被提示为错误 [#32](https://github.com/thqby/vscode-autohotkey2-lsp/issues/32) +- 增加脚本解释器切换 ## 0.8.3 -- 更新高亮文件 [#24](https://github.com/thqby/vscode-autohotkey2-lsp/issues/24) + +- 更新高亮文件 [#24](https://github.com/thqby/vscode-autohotkey2-lsp/issues/24) ## 0.8.2 -- 诊断继承类的存在 [#19](https://github.com/thqby/vscode-autohotkey2-lsp/issues/19) -- 更新类成员语法高亮 [#20](https://github.com/thqby/vscode-autohotkey2-lsp/issues/20) -- 诊断catch语句格式错误和语法高亮 [#22](https://github.com/thqby/vscode-autohotkey2-lsp/issues/22) + +- 诊断继承类的存在 [#19](https://github.com/thqby/vscode-autohotkey2-lsp/issues/19) +- 更新类成员语法高亮 [#20](https://github.com/thqby/vscode-autohotkey2-lsp/issues/20) +- 诊断catch语句格式错误和语法高亮 [#22](https://github.com/thqby/vscode-autohotkey2-lsp/issues/22) ## 0.8.1 -- 修复行末尾的%被识别为行延续 -- 修复部分对象字面量被识别为错误 [#18](https://github.com/thqby/vscode-autohotkey2-lsp/issues/18) -- 修复setter中的隐藏变量提示缺少默认参数 + +- 修复行末尾的%被识别为行延续 +- 修复部分对象字面量被识别为错误 [#18](https://github.com/thqby/vscode-autohotkey2-lsp/issues/18) +- 修复setter中的隐藏变量提示缺少默认参数 ## 0.8.0 -- 增加检查函数定义中的参数重复 [#12](https://github.com/thqby/vscode-autohotkey2-lsp/issues/12) -- 检查无效的胖箭头函数声明 [#13](https://github.com/thqby/vscode-autohotkey2-lsp/issues/13) -- 修复不正确的可选参数提示 [#14](https://github.com/thqby/vscode-autohotkey2-lsp/issues/14) -- 修复数值识别和高亮问题 [#15](https://github.com/thqby/vscode-autohotkey2-lsp/issues/15) [#16](https://github.com/thqby/vscode-autohotkey2-lsp/issues/16) -- 修复未识别'`s'转义字符 [#17](https://github.com/thqby/vscode-autohotkey2-lsp/issues/17) + +- 增加检查函数定义中的参数重复 [#12](https://github.com/thqby/vscode-autohotkey2-lsp/issues/12) +- 检查无效的胖箭头函数声明 [#13](https://github.com/thqby/vscode-autohotkey2-lsp/issues/13) +- 修复不正确的可选参数提示 [#14](https://github.com/thqby/vscode-autohotkey2-lsp/issues/14) +- 修复数值识别和高亮问题 [#15](https://github.com/thqby/vscode-autohotkey2-lsp/issues/15) [#16](https://github.com/thqby/vscode-autohotkey2-lsp/issues/16) +- 修复未识别'`s'转义字符 [#17](https://github.com/thqby/vscode-autohotkey2-lsp/issues/17) ## 0.7.9 -- 修复h版#dllimport函数选择范围不正确, 并增加类型提示 -- 支持a136版的行延续 -- 修复一些代码格式化问题 -- 诊断与内置类/函数的冲突 + +- 修复h版#dllimport函数选择范围不正确, 并增加类型提示 +- 支持a136版的行延续 +- 修复一些代码格式化问题 +- 诊断与内置类/函数的冲突 ## 0.7.8 -- 同步a137 -- 修复字符串延续bug + +- 同步a137 +- 修复字符串延续bug ## 0.7.7 -- 增加解析字符串延续段`(\n'str1\nstr2'\n)` -- 更新语法高亮文件 + +- 增加解析字符串延续段`(\n'str1\nstr2'\n)` +- 更新语法高亮文件 ## 0.7.6 -- 增加ahk_h补全项 + +- 增加ahk_h补全项 ## 0.7.5 -- 修复格式化错误 [#11](https://github.com/thqby/vscode-autohotkey2-lsp/issues/11) -- 修复悬浮提示等不能正常显示与内置函数同名的用户函数 + +- 修复格式化错误 [#11](https://github.com/thqby/vscode-autohotkey2-lsp/issues/11) +- 修复悬浮提示等不能正常显示与内置函数同名的用户函数 ## 0.7.4 -- 取消粘贴/键入时自动格式化(editor.formatOnPaste,editor.formatOnType中设置启用) -- 修复无法正确识别某些字符串('string ;comment'...) -- 修复格式化未能识别设置的缩进格式 + +- 取消粘贴/键入时自动格式化(editor.formatOnPaste,editor.formatOnType中设置启用) +- 修复无法正确识别某些字符串('string ;comment'...) +- 修复格式化未能识别设置的缩进格式 ## 0.7.3 -- 粘贴格式化将在字符串/备注中不生效 [#10](https://github.com/thqby/vscode-autohotkey2-lsp/issues/10) -- 修复备注被错误的关联 + +- 粘贴格式化将在字符串/备注中不生效 [#10](https://github.com/thqby/vscode-autohotkey2-lsp/issues/10) +- 修复备注被错误的关联 ## 0.7.2 -- 增加换行时自动缩进(if/while/loop ...) [#9](https://github.com/thqby/vscode-autohotkey2-lsp/issues/9) -- 变量上一行的注释将对多个变量生效(;...\na:=1, b:=2) [#8](https://github.com/thqby/vscode-autohotkey2-lsp/issues/8#issuecomment-848663235) + +- 增加换行时自动缩进(if/while/loop ...) [#9](https://github.com/thqby/vscode-autohotkey2-lsp/issues/9) +- 变量上一行的注释将对多个变量生效(;...\na:=1, b:=2) [#8](https://github.com/thqby/vscode-autohotkey2-lsp/issues/8#issuecomment-848663235) ## 0.7.1 -- 修复变量的注释错乱问题 [#8](https://github.com/thqby/vscode-autohotkey2-lsp/issues/8) -- 修复getter/setter中函数无法显示参数提示 -- 注释支持多行格式的(;...\n;...) -- 修复部分class被识别为关键字 + +- 修复变量的注释错乱问题 [#8](https://github.com/thqby/vscode-autohotkey2-lsp/issues/8) +- 修复getter/setter中函数无法显示参数提示 +- 注释支持多行格式的(;...\n;...) +- 修复部分class被识别为关键字 ## 0.7.0 -- 修复bug[#4](https://github.com/thqby/vscode-autohotkey2-lsp/issues/4) -- 修复对象字面量中含有in,and等提示为无效[#7](https://github.com/thqby/vscode-autohotkey2-lsp/issues/7) -- 字符串/备注中不在触发悬浮提示/定义跳转 -- 其他bug + +- 修复bug[#4](https://github.com/thqby/vscode-autohotkey2-lsp/issues/4) +- 修复对象字面量中含有in,and等提示为无效[#7](https://github.com/thqby/vscode-autohotkey2-lsp/issues/7) +- 字符串/备注中不在触发悬浮提示/定义跳转 +- 其他bug ## 0.6.9 -- 修复悬浮提示/自动补全功能存在堆栈溢出的bug [#3](https://github.com/thqby/vscode-autohotkey2-lsp/issues/3) -- 修复字符串延长段未能正确地结束 [#4](https://github.com/thqby/vscode-autohotkey2-lsp/issues/4) -- 修复部分关键字被标记为错误 [#5](https://github.com/thqby/vscode-autohotkey2-lsp/issues/5) -- 减少.触发的自动补全 [#6](https://github.com/thqby/vscode-autohotkey2-lsp/issues/6) -- 更新高亮文件 + +- 修复悬浮提示/自动补全功能存在堆栈溢出的bug [#3](https://github.com/thqby/vscode-autohotkey2-lsp/issues/3) +- 修复字符串延长段未能正确地结束 [#4](https://github.com/thqby/vscode-autohotkey2-lsp/issues/4) +- 修复部分关键字被标记为错误 [#5](https://github.com/thqby/vscode-autohotkey2-lsp/issues/5) +- 减少.触发的自动补全 [#6](https://github.com/thqby/vscode-autohotkey2-lsp/issues/6) +- 更新高亮文件 ## 0.6.8 -- 修复继承类的构造函数参数提示错误 + +- 修复继承类的构造函数参数提示错误 ## 0.6.7 -- 修复继承内置类时, 类型推导错误的问题 -- 修复动态属性getter参数多一个的问题 -- 修复在动态属性中参数提示无法触发 -- 修复快捷帮助偶尔弹出ahk错误 + +- 修复继承内置类时, 类型推导错误的问题 +- 修复动态属性getter参数多一个的问题 +- 修复在动态属性中参数提示无法触发 +- 修复快捷帮助偶尔弹出ahk错误 ## 0.6.6 -- 修复codeinchinese.chineseinputassistant插件(中文代码快速补全)的补全功能失效问题 -- 修复在函数名/方法名处无法生成注释模板 + +- 修复codeinchinese.chineseinputassistant插件(中文代码快速补全)的补全功能失效问题 +- 修复在函数名/方法名处无法生成注释模板 ## 0.6.5 -- 修复函数定义参数值为unset时错误的错误诊断 + +- 修复函数定义参数值为unset时错误的错误诊断 ## 0.6.4 -- 同步a133 -- 增加一些设置选项 -- 增加;TODO:标记 + +- 同步a133 +- 增加一些设置选项 +- 增加;TODO:标记 ## 0.6.2 -- 增加自定义折叠;#region/;#endregion -- 修复部分错误诊断问题 -- 修复类动态属性无法折叠的问题 + +- 增加自定义折叠;#region/;#endregion +- 修复部分错误诊断问题 +- 修复类动态属性无法折叠的问题 ## 0.6.1 -- 同步a131 + +- 同步a131 ## 0.6.0 -- 修复函数调用[]()和()()代码格式化错误地插入空格 -- 修复类的属性定义错误的识别为其他类型的同名变量 + +- 修复函数调用[]()和()()代码格式化错误地插入空格 +- 修复类的属性定义错误的识别为其他类型的同名变量 ## 0.5.9 -- 大纲中移除函数、方法的参数 -- 修复部分补全项丢失 + +- 大纲中移除函数、方法的参数 +- 修复部分补全项丢失 ## 0.5.8 -- 增加a130补全项 + +- 增加a130补全项 ## 0.5.7 -- 增加标签重命名和重定义错误诊断 + +- 增加标签重命名和重定义错误诊断 ## 0.5.6 -- 修复闭包函数内跳转到定义、查找所有引用、符号重命名等不正确的bug + +- 修复闭包函数内跳转到定义、查找所有引用、符号重命名等不正确的bug ## 0.5.4 -- 修复编译脚本在目标exe文件不存在时失败 + +- 修复编译脚本在目标exe文件不存在时失败 ## 0.5.3 -- 修复代码块折叠错误的bug -- 修复代码格式化时, 空{}换行的bug + +- 修复代码块折叠错误的bug +- 修复代码格式化时, 空{}换行的bug ## 0.5.2 -- 增加遗漏的函数补全 -- 增加内置函数参数提示信息 -- 修复一些bug + +- 增加遗漏的函数补全 +- 增加内置函数参数提示信息 +- 修复一些bug ## 0.5.0 -- 语法解析同步a129 -- 增加多文件符号重定义错误诊断 + +- 语法解析同步a129 +- 增加多文件符号重定义错误诊断 ## 0.4.8 (ahk version <= a127) -- 修复类型推导的bug -- 增加参数提示参数说明(@param 参数 说明)抽取显示 -- 修复类中的单行方法被识别为函数的bug + +- 修复类型推导的bug +- 增加参数提示参数说明(@param 参数 说明)抽取显示 +- 修复类中的单行方法被识别为函数的bug ## 0.4.6 -- 修复一些bug + +- 修复一些bug ## 0.4.4 -- 增加插件多语言国际化支持(中文,English) -- 增加对AutoHotkey_H版的补全支持 -- 增加库函数自动include + +- 增加插件多语言国际化支持(中文,English) +- 增加对AutoHotkey_H版的补全支持 +- 增加库函数自动include ## 0.4.3 -- 修复一些bug -- 增加debug聚合,一个配置使用其他已安装的debug插件 -- 修复代码格式化后无括号函数调用省略参数时,前的空格丢失 -- 增加脚本编译功能 + +- 修复一些bug +- 增加debug聚合,一个配置使用其他已安装的debug插件 +- 修复代码格式化后无括号函数调用省略参数时,前的空格丢失 +- 增加脚本编译功能 ## 0.4.2 -- 修复一些bug + +- 修复一些bug ## 0.4.1 -- 修复类型推导的一些bug -- 增加自定义函数的类型推导 +- 修复类型推导的一些bug +- 增加自定义函数的类型推导 ## 0.4.0 -- 增加简单类型推导,提供相关方法、属性补全 -- 增加方法参数提示、定义跳转等支持 -- 增加颜色选择器功能 -- 增加文件保存时对当前文件信息头(/* ... */)中的版本号、日期自动更新 -- 增加查找所用引用和符号重命名(支持变量/函数) +- 增加简单类型推导,提供相关方法、属性补全 +- 增加方法参数提示、定义跳转等支持 +- 增加颜色选择器功能 +- 增加文件保存时对当前文件信息头(/_ ... _/)中的版本号、日期自动更新 +- 增加查找所用引用和符号重命名(支持变量/函数) ## 0.3.0 -- 修复代码格式化的一些bug -- 修复语法解析的一些bug,并增加了一些错误提示 -- 增加代码运行功能(支持运行选择部分的代码) -- 增加快速打开帮助功能(AutoHotkey.exe目录下的chm文件),并搜索关键词 \ No newline at end of file +- 修复代码格式化的一些bug +- 修复语法解析的一些bug,并增加了一些错误提示 +- 增加代码运行功能(支持运行选择部分的代码) +- 增加快速打开帮助功能(AutoHotkey.exe目录下的chm文件),并搜索关键词 diff --git a/README.md b/README.md index a3ca609e..02e0445e 100644 --- a/README.md +++ b/README.md @@ -11,33 +11,33 @@ AutoHotkey v2 Language support for VS Code, features realization based on v2 syntax analysis. Supports running on the Web, such as `Chrome/Edge`. https://vscode.dev or https://github.dev/github/dev -- [AutoHotkey v2 Language Support](#autohotkey-v2-language-support) - - [Language Features](#language-features) - - [Rename Symbol](#rename-symbol) - - [Diagnostics](#diagnostics) - - [IntelliSense](#intellisense) - - [Signature](#signature) - - [Document Symbol](#document-symbol) - - [Semantic Highlight](#semantic-highlight) - - [Tags](#tags) - - [Document Color](#document-color) - - [Hover](#hover) - - [Goto Definition](#goto-definition) - - [Find All References](#find-all-references) - - [CodeFormat](#codeformat) - - [Custom folding](#custom-folding) - - [Context Menu](#context-menu) - - [Quick Help](#quick-help) - - [Run Script](#run-script) - - [Run Selected Script](#run-selected-script) - - [Compile Script](#compile-script) - - [Debug Script](#debug-script) - - [Generate Comment](#generate-comment) - - [Use in other editors](#use-in-other-editors) - - [Sublime Text4](#sublime-text4) - - [Vim and Neovim](#vim-and-neovim) - - [Emacs](#Emacs) - - [Use in Web Browser](#use-in-web-browser) +- [AutoHotkey v2 Language Support](#autohotkey-v2-language-support) + - [Language Features](#language-features) + - [Rename Symbol](#rename-symbol) + - [Diagnostics](#diagnostics) + - [IntelliSense](#intellisense) + - [Signature](#signature) + - [Document Symbol](#document-symbol) + - [Semantic Highlight](#semantic-highlight) + - [Tags](#tags) + - [Document Color](#document-color) + - [Hover](#hover) + - [Goto Definition](#goto-definition) + - [Find All References](#find-all-references) + - [CodeFormat](#codeformat) + - [Custom folding](#custom-folding) + - [Context Menu](#context-menu) + - [Quick Help](#quick-help) + - [Run Script](#run-script) + - [Run Selected Script](#run-selected-script) + - [Compile Script](#compile-script) + - [Debug Script](#debug-script) + - [Generate Comment](#generate-comment) + - [Use in other editors](#use-in-other-editors) + - [Sublime Text4](#sublime-text4) + - [Vim and Neovim](#vim-and-neovim) + - [Emacs](#Emacs) + - [Use in Web Browser](#use-in-web-browser) ## Language Features @@ -140,10 +140,10 @@ See all the source code locations where a certain variable/function is being use usage: -- Right-click the popup menu and click "Format document". -- Press `Shift+Alt+F`. -- Supports formatting code blocks when typing '}', formatting lines and indenting lines when typing '\n'. (`editor.formatOnType` needs to be enabled) -- Supports the use of formatting instructions `;@format array_style: collapse, object_style: expand` to change the object style of different blocks +- Right-click the popup menu and click "Format document". +- Press `Shift+Alt+F`. +- Supports formatting code blocks when typing '}', formatting lines and indenting lines when typing '\n'. (`editor.formatOnType` needs to be enabled) +- Supports the use of formatting instructions `;@format array_style: collapse, object_style: expand` to change the object style of different blocks ![codeFormat](./pic/codeFormat.gif) @@ -199,87 +199,89 @@ node install.js ### Sublime Text4 -- `Package Control: Install Package`, and install [Sublime LSP](https://github.com/sublimelsp/LSP) plug-in. -- `Preferences: LSP Settings`, add lsp configuration, language selector, and syntax highlighting. This is a simple example [syntax highlighting](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), save the file in a similar path `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax`. +- `Package Control: Install Package`, and install [Sublime LSP](https://github.com/sublimelsp/LSP) plug-in. +- `Preferences: LSP Settings`, add lsp configuration, language selector, and syntax highlighting. This is a simple example [syntax highlighting](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), save the file in a similar path `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax`. ```json { - "clients": { - "lsp-ahk2": { - "enabled": true, - "command": [ - "node", - "/server/dist/server.js", - "--stdio" - ], // Update the path of node.exe(maybe it's already in PATH, so you don't need to set it) and the folder of vscode-autohotkey2-lsp - "selector": "source.ahk2", // Same as scope in AutoHotkey2.sublime-syntax - "schemes": ["file", "buffer", "res"], - "initializationOptions": { - "locale": "en-us", // or "zh-cn" - "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" - "CommentTags": "^;;\\s*(?.+)", - "CompleteFunctionParens": false, - "Diagnostics": { - "ClassStaticMemberCheck": true, - "ParamsCheck": true - }, - "ActionWhenV1IsDetected": "Continue", - "FormatOptions": { - "array_style": "none", // or "collapse" or "expand" - "break_chained_methods": false, - "ignore_comment": false, - "indent_string": "\t", - "max_preserve_newlines": 2, - "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" - "object_style": "none", // or "collapse" or "expand" - "preserve_newlines": true, - "space_after_double_colon": true, - "space_before_conditional": true, - "space_in_empty_paren": false, - "space_in_other": true, - "space_in_paren": false, - "wrap_line_length": 0 - }, - "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - "WorkingDirs": [], - "SymbolFoldingFromOpenBrace": false - } - } - }, - "semantic_highlighting": true + "clients": { + "lsp-ahk2": { + "enabled": true, + "command": [ + "node", + "/server/dist/server.js", + "--stdio" + ], // Update the path of node.exe(maybe it's already in PATH, so you don't need to set it) and the folder of vscode-autohotkey2-lsp + "selector": "source.ahk2", // Same as scope in AutoHotkey2.sublime-syntax + "schemes": ["file", "buffer", "res"], + "initializationOptions": { + "locale": "en-us", // or "zh-cn" + "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" + "CommentTags": "^;;\\s*(?.+)", + "CompleteFunctionParens": false, + "Diagnostics": { + "ClassStaticMemberCheck": true, + "ParamsCheck": true + }, + "ActionWhenV1IsDetected": "Continue", + "FormatOptions": { + "array_style": "none", // or "collapse" or "expand" + "break_chained_methods": false, + "ignore_comment": false, + "indent_string": "\t", + "max_preserve_newlines": 2, + "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" + "object_style": "none", // or "collapse" or "expand" + "preserve_newlines": true, + "space_after_double_colon": true, + "space_before_conditional": true, + "space_in_empty_paren": false, + "space_in_other": true, + "space_in_paren": false, + "wrap_line_length": 0 + }, + "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + "WorkingDirs": [], + "SymbolFoldingFromOpenBrace": false + } + } + }, + "semantic_highlighting": true } ``` ### Vim and Neovim #### COC -- Download [coc.nvim plugin](https://github.com/neoclide/coc.nvim). + +- Download [coc.nvim plugin](https://github.com/neoclide/coc.nvim). ```bat cd $VIMRUNTIME\plugin git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 ``` -- Open (n)vim and enter the command `:CocConfig` to enter the `coc.nvim` configuration file to add configuration information. +- Open (n)vim and enter the command `:CocConfig` to enter the `coc.nvim` configuration file to add configuration information. ```json { - "languageserver": { - "lsp-ahk2": { - "module": "/server/dist/server.js", - "filetypes": ["autohotkey"], - "args": ["--node-ipc"], - "initializationOptions": { - // Same as initializationOptions for Sublime Text4 - } - } - } + "languageserver": { + "lsp-ahk2": { + "module": "/server/dist/server.js", + "filetypes": ["autohotkey"], + "args": ["--node-ipc"], + "initializationOptions": { + // Same as initializationOptions for Sublime Text4 + } + } + } } ``` #### nvim-lspconfig -- Download [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). -- Add the following to your NVIM configuration (init.lua e.g.). Ensure that `cmd` points to the path of your vscode-autohotkey2-lsp installation and `InterpreterPath` points to your AHK exe. + +- Download [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). +- Add the following to your NVIM configuration (init.lua e.g.). Ensure that `cmd` points to the path of your vscode-autohotkey2-lsp installation and `InterpreterPath` points to your AHK exe. ```lua local function custom_attach(client, bufnr) @@ -321,9 +323,10 @@ nvim_lsp.ahk2.setup({}) ### Emacs #### Eglot -- Add the following lines to your emacs config file -``` emacs-lisp +- Add the following lines to your emacs config file + +```emacs-lisp (add-to-list 'eglot-server-programs '(ahk-mode "node" "/server/dist/server.js" "--stdio")) ``` diff --git a/README.zh-CN.md b/README.zh-CN.md index 04572b51..968fea42 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -11,33 +11,33 @@ AutoHotkey v2 语言支持 for VS Code, 功能实现基于 v2 语法分析。 支持在`Chrome/Edge`等浏览器中使用 https://vscode.dev 或 https://github.dev/github/dev -- [AutoHotkey v2 语言支持](#autohotkey-v2-语言支持) - - [语言特性](#语言特性) - - [重命名符号](#重命名符号) - - [错误诊断](#错误诊断) - - [智能感知](#智能感知) - - [智能提示](#智能提示) - - [大纲](#大纲) - - [语义高亮](#语义高亮) - - [代码标记](#代码标记) - - [颜色提示](#颜色提示) - - [悬停提示](#悬停提示) - - [转到定义](#转到定义) - - [查找所有引用](#查找所有引用) - - [代码格式化](#代码格式化) - - [自定义折叠](#自定义折叠) - - [上下文菜单](#上下文菜单) - - [快速帮助](#快速帮助) - - [运行脚本](#运行脚本) - - [运行选定的脚本](#运行选定的脚本) - - [编译脚本](#编译脚本) - - [调试脚本](#调试脚本) - - [生成注释](#生成注释) - - [在其他编辑器中使用](#在其他编辑器中使用) - - [Sublime Text 4](#sublime-text-4) - - [Vim 和 Neovim](#vim-和-neovim) - - [Emacs](#Emacs) - - [在 Web 浏览器中使用](#在-web-浏览器中使用) +- [AutoHotkey v2 语言支持](#autohotkey-v2-语言支持) + - [语言特性](#语言特性) + - [重命名符号](#重命名符号) + - [错误诊断](#错误诊断) + - [智能感知](#智能感知) + - [智能提示](#智能提示) + - [大纲](#大纲) + - [语义高亮](#语义高亮) + - [代码标记](#代码标记) + - [颜色提示](#颜色提示) + - [悬停提示](#悬停提示) + - [转到定义](#转到定义) + - [查找所有引用](#查找所有引用) + - [代码格式化](#代码格式化) + - [自定义折叠](#自定义折叠) + - [上下文菜单](#上下文菜单) + - [快速帮助](#快速帮助) + - [运行脚本](#运行脚本) + - [运行选定的脚本](#运行选定的脚本) + - [编译脚本](#编译脚本) + - [调试脚本](#调试脚本) + - [生成注释](#生成注释) + - [在其他编辑器中使用](#在其他编辑器中使用) + - [Sublime Text 4](#sublime-text-4) + - [Vim 和 Neovim](#vim-和-neovim) + - [Emacs](#Emacs) + - [在 Web 浏览器中使用](#在-web-浏览器中使用) ## 语言特性 @@ -137,10 +137,10 @@ class abc { 用法: -- 右键弹出菜单然后点击 格式化文档。 -- 或按 `Shift+Alt+F`。 -- 支持在键入`}`时格式化代码块,在代码行结束处键入`\n`时格式化行并缩进。支持在代码区(非注释、字符串)输入中文标点时替换为英文标点。 (需要开启`editor.format OnType`) -- 支持使用格式化指令`;@format array_style: collapse, object_style: expand`改变不同块的对象样式 +- 右键弹出菜单然后点击 格式化文档。 +- 或按 `Shift+Alt+F`。 +- 支持在键入`}`时格式化代码块,在代码行结束处键入`\n`时格式化行并缩进。支持在代码区(非注释、字符串)输入中文标点时替换为英文标点。 (需要开启`editor.format OnType`) +- 支持使用格式化指令`;@format array_style: collapse, object_style: expand`改变不同块的对象样式 ![codeFormat](./pic/codeFormat.gif) @@ -196,87 +196,89 @@ node install.js ### Sublime Text 4 -- `Package Control: Install Package`, 安装[Sublime LSP](https://github.com/sublimelsp/LSP)插件 -- `Preferences: LSP Settings`, 增加 lsp 配置、语言选择器和语法高亮. 这是一个简单的[语法高亮示例](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), 存放在类似路径下 `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax` +- `Package Control: Install Package`, 安装[Sublime LSP](https://github.com/sublimelsp/LSP)插件 +- `Preferences: LSP Settings`, 增加 lsp 配置、语言选择器和语法高亮. 这是一个简单的[语法高亮示例](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), 存放在类似路径下 `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax` ```json { - "clients": { - "lsp-ahk2": { - "enabled": true, - "command": [ - "node", - "/server/dist/server.js", - "--stdio" - ], // 更新node.exe的路径(可能已经在环境变量中,所以你不需要设置)和vscode-autohotkey2-lsp的文件夹 - "selector": "source.ahk2", // 与AutoHotkey2.sublime-syntax中的scope相同 - "schemes": ["file", "buffer", "res"], - "initializationOptions": { - "locale": "en-us", // or "zh-cn" - "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" - "CommentTags": "^;;\\s*(?.+)", - "CompleteFunctionParens": false, - "Diagnostics": { - "ClassStaticMemberCheck": true, - "ParamsCheck": true - }, - "ActionWhenV1IsDetected": "Continue", - "FormatOptions": { - "array_style": "none", // or "collapse" or "expand" - "break_chained_methods": false, - "ignore_comment": false, - "indent_string": "\t", - "max_preserve_newlines": 2, - "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" - "object_style": "none", // or "collapse" or "expand" - "preserve_newlines": true, - "space_after_double_colon": true, - "space_before_conditional": true, - "space_in_empty_paren": false, - "space_in_other": true, - "space_in_paren": false, - "wrap_line_length": 0 - }, - "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - "WorkingDirs": [], - "SymbolFoldingFromOpenBrace": false - } - } - }, - "semantic_highlighting": true + "clients": { + "lsp-ahk2": { + "enabled": true, + "command": [ + "node", + "/server/dist/server.js", + "--stdio" + ], // 更新node.exe的路径(可能已经在环境变量中,所以你不需要设置)和vscode-autohotkey2-lsp的文件夹 + "selector": "source.ahk2", // 与AutoHotkey2.sublime-syntax中的scope相同 + "schemes": ["file", "buffer", "res"], + "initializationOptions": { + "locale": "en-us", // or "zh-cn" + "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" + "CommentTags": "^;;\\s*(?.+)", + "CompleteFunctionParens": false, + "Diagnostics": { + "ClassStaticMemberCheck": true, + "ParamsCheck": true + }, + "ActionWhenV1IsDetected": "Continue", + "FormatOptions": { + "array_style": "none", // or "collapse" or "expand" + "break_chained_methods": false, + "ignore_comment": false, + "indent_string": "\t", + "max_preserve_newlines": 2, + "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" + "object_style": "none", // or "collapse" or "expand" + "preserve_newlines": true, + "space_after_double_colon": true, + "space_before_conditional": true, + "space_in_empty_paren": false, + "space_in_other": true, + "space_in_paren": false, + "wrap_line_length": 0 + }, + "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + "WorkingDirs": [], + "SymbolFoldingFromOpenBrace": false + } + } + }, + "semantic_highlighting": true } ``` ### Vim 和 Neovim #### COC -- 下载[coc.nvim 插件](https://github.com/neoclide/coc.nvim)。 + +- 下载[coc.nvim 插件](https://github.com/neoclide/coc.nvim)。 ```bat cd $VIMRUNTIME\plugin git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 ``` -- 打开(n)vim, 输入命令 `:CocConfig` 进入`coc.nvim`配置文件增加配置信息。 +- 打开(n)vim, 输入命令 `:CocConfig` 进入`coc.nvim`配置文件增加配置信息。 ```json { - "languageserver": { - "lsp-ahk2": { - "module": "/server/dist/server.js", - "filetypes": ["autohotkey"], - "args": ["--node-ipc"], - "initializationOptions": { - // Same as initializationOptions for Sublime Text4 - } - } - } + "languageserver": { + "lsp-ahk2": { + "module": "/server/dist/server.js", + "filetypes": ["autohotkey"], + "args": ["--node-ipc"], + "initializationOptions": { + // Same as initializationOptions for Sublime Text4 + } + } + } } ``` #### nvim-lspconfig -- 下载[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)。 -- 将以下内容添加到您的NVIM配置中(init.lua 等). 确定`cmd`指向vscode-autohotkey2-lsp的安装路径,`InterpreterPath`指向AHK exe. + +- 下载[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)。 +- 将以下内容添加到您的NVIM配置中(init.lua 等). 确定`cmd`指向vscode-autohotkey2-lsp的安装路径,`InterpreterPath`指向AHK exe. ```lua local function custom_attach(client, bufnr) @@ -318,9 +320,10 @@ nvim_lsp.ahk2.setup({}) ### Emacs #### Eglot -- 将以下内容添加到您的emacs配置文件中 -``` emacs-lisp +- 将以下内容添加到您的emacs配置文件中 + +```emacs-lisp (add-to-list 'eglot-server-programs '(ahk-mode "node" "/server/dist/server.js" "--stdio")) ``` diff --git a/ahk2.configuration.json b/ahk2.configuration.json index 6c0f8b1a..bfbcf12b 100644 --- a/ahk2.configuration.json +++ b/ahk2.configuration.json @@ -1,90 +1,42 @@ { "comments": { "lineComment": ";", - "blockComment": [ - "/*", - "*/" - ] + "blockComment": ["/*", "*/"] }, "brackets": [ - [ - "{", - "}" - ], - [ - "[", - "]" - ], - [ - "(", - ")" - ] + ["{", "}"], + ["[", "]"], + ["(", ")"] ], "autoClosingPairs": [ - [ - "{", - "}" - ], - [ - "[", - "]" - ], - [ - "(", - ")" - ], - [ - "%", - "%" - ], + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["%", "%"], { "open": "\"", "close": "\"", - "notIn": [ - "string" - ] + "notIn": ["string"] }, { "open": "'", "close": "'", - "notIn": [ - "string" - ] + "notIn": ["string"] }, { "open": "/**", "close": " */", - "notIn": [ - "string" - ] + "notIn": ["string"] } ], "autoCloseBefore": ":.,}])>'\" \n\t", "surroundingPairs": [ - [ - "{", - "}" - ], - [ - "[", - "]" - ], - [ - "(", - ")" - ], - [ - "\"", - "\"" - ], - [ - "'", - "'" - ], - [ - "%", - "%" - ] + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"], + ["%", "%"] ], "indentationRules": { "increaseIndentPattern": "^((?!;).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$", @@ -164,4 +116,4 @@ } } ] -} \ No newline at end of file +} diff --git a/eslint.config.mjs b/eslint.config.mjs index fc24cdc2..7dc2a7b8 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,33 +1,41 @@ -import globals from "globals"; -import pluginJs from "@eslint/js"; -import tseslint from "typescript-eslint"; +import globals from 'globals'; +import pluginJs from '@eslint/js'; +import tseslint from 'typescript-eslint'; /** @type {typeof tseslint.configs.recommended} */ export default [ - { - languageOptions: { - globals: { - ...globals.browser, - ...globals.node - } - } - }, - pluginJs.configs.recommended, - ...tseslint.configs.recommended, - { - ignores: ['**/*.js', '**/*.d.ts', '**/.vscode-test-web/*', '**/.vscode-test/*'], - }, - { - rules: { - 'no-control-regex': 'off', - 'no-empty': ['error', { allowEmptyCatch: true }], - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': ['error', { - argsIgnorePattern: '^_', - varsIgnorePattern: '^_', - caughtErrors: 'none', - ignoreRestSiblings: true - }], - } - } -]; \ No newline at end of file + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + }, + }, + }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + ignores: [ + '**/*.js', + '**/*.d.ts', + '**/.vscode-test-web/*', + '**/.vscode-test/*', + ], + }, + { + rules: { + 'no-control-regex': 'off', + 'no-empty': ['error', { allowEmptyCatch: true }], + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrors: 'none', + ignoreRestSiblings: true, + }, + ], + }, + }, +]; diff --git a/package-lock.json b/package-lock.json index 0f647b30..d23e5b7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "globals": "^15.4.0", "mocha": "^10.7.0", "path-browserify": "^1.0.1", + "prettier": "3.3.3", "sinon": "^18.0.0", "sort-package-json": "^2.10.0", "ts-loader": "^9.4.0", @@ -6819,6 +6820,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", diff --git a/package.json b/package.json index d2137c87..2fc01d91 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,11 @@ "compile-test": "cd client && tsc", "compile-test//": "Compile test files", "compile//": "Compile the extension for packaging and publishing", - "eslint": "eslint --fix", + "eslint": "npm run eslint:files -- client server && echo No ESLint problems", + "eslint:files": "eslint --max-warnings=0", + "eslint:fix": "npm run eslint:files -- client server --fix", + "format": "prettier --check .", + "format:fix": "prettier --write .", "package": "vsce package", "patch": "npm version patch", "publish": "vsce publish", @@ -639,6 +643,7 @@ "globals": "^15.4.0", "mocha": "^10.7.0", "path-browserify": "^1.0.1", + "prettier": "3.3.3", "sinon": "^18.0.0", "sort-package-json": "^2.10.0", "ts-loader": "^9.4.0", diff --git a/package.nls.json b/package.nls.json index 5a5fa2ef..f5c70294 100644 --- a/package.nls.json +++ b/package.nls.json @@ -32,4 +32,4 @@ "ahk2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", "ahk2.updateversioninfo": "Update File Version Info", "ahk2.workingdirs": "Sets the working directory for the script" -} \ No newline at end of file +} diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index 9ee14368..572acbae 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -108,4 +108,4 @@ "setting.getenverr": "获取环境变量失败", "setting.uialimit": "由于安全限制, UIA可执行文件不允许重定向stdin/stdout, 因此依赖于此的一些功能将无法工作", "setting.versionerr": "当前AutoHotkey.exe不是v2版本, 无法获得正确的语法解析、补全等功能" -} \ No newline at end of file +} diff --git a/server/cli/cli.ts b/server/cli/cli.ts index 66ad1631..35d6da97 100644 --- a/server/cli/cli.ts +++ b/server/cli/cli.ts @@ -3,18 +3,16 @@ import { Lexer } from '../src/Lexer'; function main() { const options: { [k: string]: string } = {}; - process.argv.slice(2).forEach(s => { + process.argv.slice(2).forEach((s) => { const arr = s.split('='); options[arr[0]] = arr[1]; }); let path: string = options.path ?? ''; path = path.replace(/^(['"])(.*)\1$/, '$2'); - if (!path) - return; + if (!path) return; try { const td = openFile(path, false); - if (!td) - return; + if (!td) return; const sc = new Lexer(td).beautify({}); console.log(sc); } catch (e) { @@ -22,4 +20,4 @@ function main() { } } -main() \ No newline at end of file +main(); diff --git a/server/src/Lexer.ts b/server/src/Lexer.ts index 1e36db90..ab7c8cd7 100644 --- a/server/src/Lexer.ts +++ b/server/src/Lexer.ts @@ -6442,7 +6442,7 @@ export class Lexer { } if (l <= r && it) return (this.tokens[it.start] ?? ((it = this.tokens[it.previous!])?.data - && { ...it.data as {}, previous_token: it, type: '' })) as Token; + && { ...it.data, previous_token: it, type: '' })) as Token; } } diff --git a/server/src/common.ts b/server/src/common.ts index 05f1a482..7e735626 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -253,6 +253,7 @@ export function initahk2cache() { export function loadahk2(filename = 'ahk2', d = 3) { let path: string | undefined; + // todo get this working with AHK++ const file = `${rootdir}/syntaxes/<>/${filename}`; if (isBrowser) { const td = openFile(file + '.d.ahk'); diff --git a/server/src/server.ts b/server/src/server.ts index 4fb96954..b8a2c5b1 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,20 +1,69 @@ import { resolve } from 'path'; import { TextDocument } from 'vscode-languageserver-textdocument'; import { - createConnection, DidChangeConfigurationNotification, InitializeResult, - ProposedFeatures, SymbolKind, TextDocuments, TextDocumentSyncKind + createConnection, + DidChangeConfigurationNotification, + InitializeResult, + ProposedFeatures, + SymbolKind, + TextDocuments, + TextDocumentSyncKind, } from 'vscode-languageserver/node'; import { URI } from 'vscode-uri'; import { get_ahkProvider } from './ahkProvider'; import { - a_vars, AHKLSSettings, ahkpath_cur, chinese_punctuations, clearLibfuns, codeActionProvider, - colorPresentation, colorProvider, commands, completionProvider, defintionProvider, - documentFormatting, enum_ahkfiles, executeCommandProvider, exportSymbols, extsettings, hoverProvider, - initahk2cache, isahk2_h, Lexer, lexers, libdirs, libfuncs, loadahk2, loadlocalize, openFile, - parse_include, prepareRename, rangeFormatting, referenceProvider, renameProvider, SemanticTokenModifiers, - semanticTokensOnFull, semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, set_ahkpath, set_Connection, - set_dirname, set_locale, set_version, set_WorkspaceFolders, setting, signatureProvider, sleep, symbolProvider, - traverse_include, typeFormatting, update_settings, utils, winapis, workspaceSymbolProvider + a_vars, + AHKLSSettings, + ahkpath_cur, + chinese_punctuations, + clearLibfuns, + codeActionProvider, + colorPresentation, + colorProvider, + commands, + completionProvider, + defintionProvider, + documentFormatting, + enum_ahkfiles, + executeCommandProvider, + exportSymbols, + extsettings, + hoverProvider, + initahk2cache, + isahk2_h, + Lexer, + lexers, + libdirs, + libfuncs, + loadahk2, + loadlocalize, + openFile, + parse_include, + prepareRename, + rangeFormatting, + referenceProvider, + renameProvider, + SemanticTokenModifiers, + semanticTokensOnFull, + semanticTokensOnRange, + SemanticTokenTypes, + set_ahk_h, + set_ahkpath, + set_Connection, + set_dirname, + set_locale, + set_version, + set_WorkspaceFolders, + setting, + signatureProvider, + sleep, + symbolProvider, + traverse_include, + typeFormatting, + update_settings, + utils, + winapis, + workspaceSymbolProvider, } from './common'; import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; import { resolvePath, runscript } from './scriptrunner'; @@ -24,13 +73,14 @@ const languageServer = 'ahk2-language-server'; const documents = new TextDocuments(TextDocument); const connection = set_Connection(createConnection(ProposedFeatures.all)); const workspaceFolders = new Set(); -let hasConfigurationCapability = false, hasWorkspaceFolderCapability = false; +let hasConfigurationCapability = false, + hasWorkspaceFolderCapability = false; let uri_switch_to_ahk2 = ''; commands['ahk2.resetinterpreterpath'] = (args: string[]) => - setInterpreter((args[0]).replace(/^[A-Z]:/, m => m.toLowerCase())); + setInterpreter(args[0].replace(/^[A-Z]:/, (m) => m.toLowerCase())); -connection.onInitialize(async params => { +connection.onInitialize(async (params) => { const capabilities = params.capabilities; hasConfigurationCapability = !!( capabilities.workspace && !!capabilities.workspace.configuration @@ -46,20 +96,26 @@ connection.onInitialize(async params => { capabilities: { textDocumentSync: { change: TextDocumentSyncKind.Incremental, - openClose: true + openClose: true, }, completionProvider: { resolveProvider: false, - triggerCharacters: ['.', '#', '*', '@'] + triggerCharacters: ['.', '#', '*', '@'], }, signatureHelpProvider: { - triggerCharacters: ['(', ',', ' '] + triggerCharacters: ['(', ',', ' '], }, documentSymbolProvider: true, definitionProvider: true, documentFormattingProvider: true, documentRangeFormattingProvider: true, - documentOnTypeFormattingProvider: { firstTriggerCharacter: '}', moreTriggerCharacter: ['\n', ...Object.keys(chinese_punctuations)] }, + documentOnTypeFormattingProvider: { + firstTriggerCharacter: '}', + moreTriggerCharacter: [ + '\n', + ...Object.keys(chinese_punctuations), + ], + }, executeCommandProvider: { commands: Object.keys(commands) }, hoverProvider: true, foldingRangeProvider: true, @@ -69,24 +125,36 @@ connection.onInitialize(async params => { referencesProvider: { workDoneProgress: true }, semanticTokensProvider: { legend: { - tokenTypes: Object.values(SemanticTokenTypes).filter(t => typeof t === 'string') as string[], - tokenModifiers: Object.values(SemanticTokenModifiers).filter(t => typeof t === 'string') as string[] + tokenTypes: Object.values(SemanticTokenTypes).filter( + (t) => typeof t === 'string', + ) as string[], + tokenModifiers: Object.values( + SemanticTokenModifiers, + ).filter((t) => typeof t === 'string') as string[], }, full: true, - range: true + range: true, }, - workspaceSymbolProvider: true - } + workspaceSymbolProvider: true, + }, }; if (hasWorkspaceFolderCapability) { - params.workspaceFolders?.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); - result.capabilities.workspace = { workspaceFolders: { supported: true } }; + params.workspaceFolders?.forEach((it) => + workspaceFolders.add(it.uri.toLowerCase() + '/'), + ); + result.capabilities.workspace = { + workspaceFolders: { supported: true }, + }; } let configs: AHKLSSettings | undefined; const env = process.env; if (env.AHK2_LS_CONFIG) - try { configs = JSON.parse(env.AHK2_LS_CONFIG); } catch { } + try { + configs = JSON.parse(env.AHK2_LS_CONFIG); + } catch { + /* do nothing */ + } if (params.initializationOptions) configs = Object.assign(configs ?? {}, params.initializationOptions); set_dirname(resolve(__dirname, '../..')); @@ -96,9 +164,12 @@ connection.onInitialize(async params => { utils.get_ahkProvider = get_ahkProvider; loadlocalize(); initahk2cache(); - if (configs) - update_settings(configs); - if (!(await setInterpreter(resolvePath(extsettings.InterpreterPath ??= '')))) + if (configs) update_settings(configs); + if ( + !(await setInterpreter( + resolvePath((extsettings.InterpreterPath ??= '')), + )) + ) patherr(setting.ahkpatherr()); set_WorkspaceFolders(workspaceFolders); loadahk2(); @@ -111,63 +182,90 @@ connection.onInitialized(() => { connection.client.register(DidChangeConfigurationNotification.type); } if (hasWorkspaceFolderCapability) { - connection.workspace.onDidChangeWorkspaceFolders(event => { - event.removed.forEach(it => workspaceFolders.delete(it.uri.toLowerCase() + '/')); - event.added.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); + connection.workspace.onDidChangeWorkspaceFolders((event) => { + event.removed.forEach((it) => + workspaceFolders.delete(it.uri.toLowerCase() + '/'), + ); + event.added.forEach((it) => + workspaceFolders.add(it.uri.toLowerCase() + '/'), + ); set_WorkspaceFolders(workspaceFolders); }); } - getDllExport(['user32', 'kernel32', 'comctl32', 'gdi32'].map(name => `C:\\Windows\\System32\\${name}.dll`)) - .then(val => winapis.push(...val)); + getDllExport( + ['user32', 'kernel32', 'comctl32', 'gdi32'].map( + (name) => `C:\\Windows\\System32\\${name}.dll`, + ), + ).then((val) => winapis.push(...val)); }); -connection.onDidChangeConfiguration(async change => { +connection.onDidChangeConfiguration(async (change) => { let newset: AHKLSSettings | undefined = change?.settings; if (hasConfigurationCapability && !newset) + // todo AutoHotkey2 config is provided by the ahk2 package.json newset = await connection.workspace.getConfiguration('AutoHotkey2'); if (!newset) { - connection.window.showWarningMessage('Failed to obtain the configuration'); + connection.window.showWarningMessage( + 'Failed to obtain the configuration', + ); return; } const { AutoLibInclude, InterpreterPath, Syntaxes } = extsettings; update_settings(newset); set_WorkspaceFolders(workspaceFolders); if (InterpreterPath !== extsettings.InterpreterPath) { - if (await setInterpreter(resolvePath(extsettings.InterpreterPath ??= ''))) - connection.sendRequest('ahk2.updateStatusBar', [extsettings.InterpreterPath]); + if ( + await setInterpreter( + resolvePath((extsettings.InterpreterPath ??= '')), + ) + ) + connection.sendRequest('ahk2.updateStatusBar', [ + extsettings.InterpreterPath, + ]); } if (AutoLibInclude !== extsettings.AutoLibInclude) { - if ((extsettings.AutoLibInclude > 1) && (AutoLibInclude <= 1)) + if (extsettings.AutoLibInclude > 1 && AutoLibInclude <= 1) parseuserlibs(); - if ((extsettings.AutoLibInclude & 1) && !(AutoLibInclude & 1)) - documents.all().forEach(e => parseproject(e.uri.toLowerCase())); + if (extsettings.AutoLibInclude & 1 && !(AutoLibInclude & 1)) + documents.all().forEach((e) => parseproject(e.uri.toLowerCase())); } if (Syntaxes !== extsettings.Syntaxes) { - initahk2cache(), loadahk2(); - if (isahk2_h) - loadahk2('ahk_h'), loadahk2('winapi', 4); + initahk2cache(); + loadahk2(); + if (isahk2_h) { + loadahk2('ahk_h'); + loadahk2('winapi', 4); + } } }); -documents.onDidOpen(e => { +documents.onDidOpen((e) => { const to_ahk2 = uri_switch_to_ahk2 === e.document.uri; const uri = e.document.uri.toLowerCase(); let doc = lexers[uri]; if (doc) doc.document = e.document; else { lexers[uri] = doc = new Lexer(e.document); - Object.defineProperty(doc.include = {}, '', { value: '', enumerable: false }); + Object.defineProperty((doc.include = {}), '', { + value: '', + enumerable: false, + }); } doc.actived = true; - if (to_ahk2) - doc.actionwhenv1 = 'Continue'; + if (to_ahk2) doc.actionwhenv1 = 'Continue'; if (extsettings.AutoLibInclude & 1) - parseproject(uri).then(() => doc.last_diags && - Object.keys(doc.included).length && doc.update()); + parseproject(uri).then( + () => + doc.last_diags && + Object.keys(doc.included).length && + doc.update(), + ); }); -documents.onDidClose(e => lexers[e.document.uri.toLowerCase()]?.close()); -documents.onDidChangeContent(e => lexers[e.document.uri.toLowerCase()].update()); +documents.onDidClose((e) => lexers[e.document.uri.toLowerCase()]?.close()); +documents.onDidChangeContent((e) => + lexers[e.document.uri.toLowerCase()].update(), +); connection.onCodeAction(codeActionProvider); connection.onCompletion(completionProvider); @@ -178,7 +276,9 @@ connection.onDocumentFormatting(documentFormatting); connection.onDocumentRangeFormatting(rangeFormatting); connection.onDocumentOnTypeFormatting(typeFormatting); connection.onDocumentSymbol(symbolProvider); -connection.onFoldingRanges(params => lexers[params.textDocument.uri.toLowerCase()].foldingranges); +connection.onFoldingRanges( + (params) => lexers[params.textDocument.uri.toLowerCase()].foldingranges, +); connection.onHover(hoverProvider); connection.onPrepareRename(prepareRename); connection.onReferences(referenceProvider); @@ -190,36 +290,47 @@ connection.languages.semanticTokens.on(semanticTokensOnFull); connection.languages.semanticTokens.onRange(semanticTokensOnRange); connection.onRequest('ahk2.exportSymbols', (uri: string) => exportSymbols(uri)); connection.onRequest('ahk2.getAHKversion', getAHKversion); -connection.onRequest('ahk2.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); +connection.onRequest('ahk2.getContent', (uri: string) => + lexers[uri.toLowerCase()]?.document.getText(), +); connection.onRequest('ahk2.getVersionInfo', (uri: string) => { const doc = lexers[uri.toLowerCase()]; if (doc) { const tk = doc.get_token(0); - if ((tk.type === 'TK_BLOCK_COMMENT' || tk.type === '') && tk.content.match(/^\s*[;*]?\s*@(date|version)\b/im)) { + if ( + (tk.type === 'TK_BLOCK_COMMENT' || tk.type === '') && + tk.content.match(/^\s*[;*]?\s*@(date|version)\b/im) + ) { return { uri: uri, content: tk.content, range: { start: doc.document.positionAt(tk.offset), - end: doc.document.positionAt(tk.offset + tk.length) - } + end: doc.document.positionAt(tk.offset + tk.length), + }, }; } } return null; }); -connection.onNotification('onDidCloseTextDocument', (params: { uri: string, id: string }) => { - if (params.id === 'ahk2') - lexers[params.uri.toLowerCase()]?.close(true); - else uri_switch_to_ahk2 = params.uri; -}); +connection.onNotification( + 'onDidCloseTextDocument', + (params: { uri: string; id: string }) => { + if (params.id === 'ahk2') lexers[params.uri.toLowerCase()]?.close(true); + else uri_switch_to_ahk2 = params.uri; + }, +); documents.listen(connection); connection.listen(); async function patherr(msg: string) { if (!extsettings.commands?.includes('ahk2.executeCommand')) return connection.window.showErrorMessage(msg); - if (await connection.window.showErrorMessage(msg, { title: 'Select Interpreter' })) + if ( + await connection.window.showErrorMessage(msg, { + title: 'Select Interpreter', + }) + ) connection.sendRequest('ahk2.executeCommand', ['ahk2.setinterpreter']); } @@ -235,59 +346,76 @@ async function initpathenv(samefolder = false, retry = true): Promise { FileAppend2(text, file, encode) { FileAppend %text%, %file%, %encode% }`; - let fail = 0, data = runscript(script); + let fail = 0, + data = runscript(script); if (data === undefined) { - if (retry) - return initpathenv(samefolder, false); + if (retry) return initpathenv(samefolder, false); patherr(setting.ahkpatherr()); return false; } if (!(data = data.trim())) { const path = ahkpath_cur; if ((await getAHKversion([path]))[0].endsWith('[UIAccess]')) { - let ret = false, n = path.replace(/_uia\.exe$/i, '.exe'); + let ret = false, + n = path.replace(/_uia\.exe$/i, '.exe'); fail = 2; - if (path !== n && (n = resolvePath(n, true)) && !(await getAHKversion([n]))[0].endsWith('[UIAccess]')) { + if ( + path !== n && + (n = resolvePath(n, true)) && + !(await getAHKversion([n]))[0].endsWith('[UIAccess]') + ) { set_ahkpath(n); - if ((ret = await initpathenv(samefolder))) - fail = 0; + if ((ret = await initpathenv(samefolder))) fail = 0; set_ahkpath(path); } - fail && connection.window.showWarningMessage(setting.uialimit()); + if (fail) connection.window.showWarningMessage(setting.uialimit()); await update_rcdata(); - if (ret) - return true; + if (ret) return true; } else fail = 1; - if (fail !== 2 && retry) - return initpathenv(samefolder, false); + if (fail !== 2 && retry) return initpathenv(samefolder, false); if (!a_vars.mydocuments) connection.window.showErrorMessage(setting.getenverr()); return false; } - Object.assign(a_vars, Object.fromEntries(data.replace(/\t[A-Z]:\\/g, m => m.toLowerCase()).split('|').map(l => l.split('\t')))); + Object.assign( + a_vars, + Object.fromEntries( + data + .replace(/\t[A-Z]:\\/g, (m) => m.toLowerCase()) + .split('|') + .map((l) => l.split('\t')), + ), + ); a_vars.ahkpath = ahkpath_cur; - set_version(a_vars.ahkversion ??= '2.0.0'); - if (a_vars.ahkversion.startsWith('1.')) - patherr(setting.versionerr()); + set_version((a_vars.ahkversion ??= '2.0.0')); + if (a_vars.ahkversion.startsWith('1.')) patherr(setting.versionerr()); if (!samefolder || !libdirs.length) { libdirs.length = 0; - libdirs.push(a_vars.mydocuments + '\\AutoHotkey\\Lib\\', - a_vars.ahkpath.replace(/[^\\/]+$/, 'Lib\\')); + libdirs.push( + a_vars.mydocuments + '\\AutoHotkey\\Lib\\', + a_vars.ahkpath.replace(/[^\\/]+$/, 'Lib\\'), + ); let lb; - for (lb of Object.values(libfuncs)) - lb.islib = inlibdirs(lb.fsPath); + for (lb of Object.values(libfuncs)) lb.islib = inlibdirs(lb.fsPath); } a_vars.h = (a_vars.h ?? '0').slice(0, 1); if (a_vars.h === '1') { - if (!isahk2_h) - set_ahk_h(true), samefolder = false, loadahk2('ahk2_h'), loadahk2('winapi', 4); + if (!isahk2_h) { + set_ahk_h(true); + samefolder = false; + loadahk2('ahk2_h'); + loadahk2('winapi', 4); + } } else { - if (isahk2_h) - set_ahk_h(false), samefolder = false, initahk2cache(), loadahk2(); + if (isahk2_h) { + set_ahk_h(false); + samefolder = false; + initahk2cache(); + loadahk2(); + } } await update_rcdata(); - if (samefolder) - return true; + if (samefolder) return true; for (const uri in lexers) { const doc = lexers[uri]; if (!doc.d) { @@ -297,33 +425,46 @@ async function initpathenv(samefolder = false, retry = true): Promise { } } clearLibfuns(); - if (extsettings.AutoLibInclude > 1) - parseuserlibs(); + if (extsettings.AutoLibInclude > 1) parseuserlibs(); return true; async function update_rcdata() { const pe = new PEFile(ahkpath_cur); try { const rc = await pe.getResource(RESOURCE_TYPE.RCDATA); curPERCDATA = rc; - } catch (e) { } - finally { pe.close(); } + } catch (e) { + console.error(e); + } finally { + pe.close(); + } } } function get_lib_symbols(lex: Lexer) { return Object.assign( - Object.values(lex.declaration).filter(it => it.kind === SymbolKind.Class || it.kind === SymbolKind.Function), - { fsPath: lex.fsPath, islib: inlibdirs(lex.fsPath) } + Object.values(lex.declaration).filter( + (it) => + it.kind === SymbolKind.Class || it.kind === SymbolKind.Function, + ), + { fsPath: lex.fsPath, islib: inlibdirs(lex.fsPath) }, ); } async function parseuserlibs() { - let dir: string, path: string, uri: string, d: Lexer, t: TextDocument | undefined; + let dir: string, + path: string, + uri: string, + d: Lexer, + t: TextDocument | undefined; for (dir of libdirs) for await (path of enum_ahkfiles(dir)) { - if (!libfuncs[uri = URI.file(path).toString().toLowerCase()]) { + if (!libfuncs[(uri = URI.file(path).toString().toLowerCase())]) { if (!(d = lexers[uri])) - if (!(t = openFile(path)) || (d = new Lexer(t)).d || (d.parseScript(), d.maybev1)) + if ( + !(t = openFile(path)) || + (d = new Lexer(t)).d || + (d.parseScript(), d.maybev1) + ) continue; libfuncs[uri] = get_lib_symbols(d); await sleep(50); @@ -334,55 +475,60 @@ async function parseuserlibs() { function inlibdirs(path: string) { path = path.toLowerCase(); for (const p of libdirs) { - if (path.startsWith(p.toLowerCase())) - return true; + if (path.startsWith(p.toLowerCase())) return true; } return false; } async function changeInterpreter(oldpath: string, newpath: string) { - const samefolder = !!oldpath && resolve(oldpath, '..').toLowerCase() === resolve(newpath, '..').toLowerCase(); - if (!(await initpathenv(samefolder))) - return false; - if (samefolder) - return true; - documents.all().forEach(td => { + const samefolder = + !!oldpath && + resolve(oldpath, '..').toLowerCase() === + resolve(newpath, '..').toLowerCase(); + if (!(await initpathenv(samefolder))) return false; + if (samefolder) return true; + documents.all().forEach((td) => { const doc = lexers[td.uri.toLowerCase()]; if (!doc) return; doc.initLibDirs(doc.scriptdir); - if (extsettings.AutoLibInclude & 1) - parseproject(doc.uri); + if (extsettings.AutoLibInclude & 1) parseproject(doc.uri); }); return true; } async function setInterpreter(path: string) { const old = ahkpath_cur; - if (!path || path.toLowerCase() === old.toLowerCase()) - return false; + if (!path || path.toLowerCase() === old.toLowerCase()) return false; set_ahkpath(path); - if (!(await changeInterpreter(old, path))) - set_ahkpath(old); + if (!(await changeInterpreter(old, path))) set_ahkpath(old); return true; } async function parseproject(uri: string) { let lex = lexers[uri]; - if (!lex || !uri.startsWith('file:')) - return; - !lex.d && (libfuncs[uri] ??= get_lib_symbols(lex)); - let searchdir = lex.workspaceFolder, workspace = false, path: string, t: TextDocument | undefined; - if (searchdir) - searchdir = URI.parse(searchdir).fsPath, workspace = true; - else - searchdir = lex.scriptdir + '\\lib'; + if (!lex || !uri.startsWith('file:')) return; + if (!lex.d) { + libfuncs[uri] ??= get_lib_symbols(lex); + } + let searchdir = lex.workspaceFolder, + workspace = false, + path: string, + t: TextDocument | undefined; + if (searchdir) { + searchdir = URI.parse(searchdir).fsPath; + workspace = true; + } else searchdir = lex.scriptdir + '\\lib'; for await (path of enum_ahkfiles(searchdir)) { - if (!libfuncs[uri = URI.file(path).toString().toLowerCase()]) { + if (!libfuncs[(uri = URI.file(path).toString().toLowerCase())]) { if (!(lex = lexers[uri])) { - if (!(t = openFile(path)) || (lex = new Lexer(t)).d || (lex.parseScript(), lex.maybev1)) + if ( + !(t = openFile(path)) || + (lex = new Lexer(t)).d || + (lex.parseScript(), lex.maybev1) + ) continue; if (workspace) { - parse_include(lexers[uri] = lex, lex.scriptdir); + parse_include((lexers[uri] = lex), lex.scriptdir); traverse_include(lex); } } @@ -393,34 +539,55 @@ async function parseproject(uri: string) { } async function getAHKversion(params: string[]) { - return Promise.all(params.map(async path => { - let pe: PEFile | undefined; - try { - pe = new PEFile(path); - const props = (await pe.getResource(RESOURCE_TYPE.VERSION))[0].StringTable[0]; - if (props.ProductName?.toLowerCase().startsWith('autohotkey')) { - const is_bit64 = await pe.is_bit64; - const m = (await pe.getResource(RESOURCE_TYPE.MANIFEST))[0]?.replace(//g, '') ?? ''; - let version = `${props.ProductName} ${props.ProductVersion ?? 'unknown version'} ${is_bit64 ? '64' : '32'} bit`; - if (m.includes('uiAccess="true"')) - version += ' [UIAccess]'; - return version; + return Promise.all( + params.map(async (path) => { + let pe: PEFile | undefined; + try { + pe = new PEFile(path); + const props = (await pe.getResource(RESOURCE_TYPE.VERSION))[0] + .StringTable[0]; + if (props.ProductName?.toLowerCase().startsWith('autohotkey')) { + const is_bit64 = await pe.is_bit64; + const m = + ( + await pe.getResource(RESOURCE_TYPE.MANIFEST) + )[0]?.replace(//g, '') ?? ''; + let version = `${props.ProductName} ${ + props.ProductVersion ?? 'unknown version' + } ${is_bit64 ? '64' : '32'} bit`; + if (m.includes('uiAccess="true"')) version += ' [UIAccess]'; + return version; + } + } catch (e) { + console.error(e); + } finally { + pe?.close(); } - } catch (e) { } - finally { pe?.close(); } - return 'unknown version'; - })); + return 'unknown version'; + }), + ); } async function getDllExport(paths: string[] | Set, onlyone = false) { const funcs: { [name: string]: true } = {}; for (const path of paths) { - const pe = await searchAndOpenPEFile(path, a_vars.is64bit === '1' ? true : a_vars.is64bit === '0' ? false : undefined); + const pe = await searchAndOpenPEFile( + path, + a_vars.is64bit === '1' + ? true + : a_vars.is64bit === '0' + ? false + : undefined, + ); if (!pe) continue; try { - (await pe.getExport())?.Functions.forEach((it) => funcs[it.Name] = true); + (await pe.getExport())?.Functions.forEach( + (it) => (funcs[it.Name] = true), + ); if (onlyone) break; - } finally { pe.close(); } + } finally { + pe.close(); + } } delete funcs['']; return Object.keys(funcs); @@ -430,19 +597,26 @@ let curPERCDATA: { [key: string]: Buffer } | undefined = undefined; function getRCDATA(name?: string) { const exe = resolvePath(ahkpath_cur, true); if (!exe) return; - if (!name) return { uri: '', path: '', paths: Object.keys(curPERCDATA ?? {}) }; + if (!name) + return { uri: '', path: '', paths: Object.keys(curPERCDATA ?? {}) }; const path = `${exe.toLowerCase()}:${name}`; const uri = URI.from({ scheme: 'ahkres', path }).toString().toLowerCase(); - if (lexers[uri]) - return { uri, path }; - if (!name || !curPERCDATA) - return; + if (lexers[uri]) return { uri, path }; + if (!name || !curPERCDATA) return; const data = curPERCDATA[name]; - if (!data) - return; + if (!data) return; try { - const doc = lexers[uri] = new Lexer(TextDocument.create(uri, 'ahk2', -10, new TextDecoder('utf8', { fatal: true }).decode(data))); + const doc = (lexers[uri] = new Lexer( + TextDocument.create( + uri, + 'ahk2', + -10, + new TextDecoder('utf8', { fatal: true }).decode(data), + ), + )); doc.parseScript(); return { uri, path }; - } catch { delete curPERCDATA[name]; } -} \ No newline at end of file + } catch { + delete curPERCDATA[name]; + } +} diff --git a/syntaxes/ahk2-output.tmLanguage.json b/syntaxes/ahk2-output.tmLanguage.json index 8d63ebd9..b29ae0e2 100644 --- a/syntaxes/ahk2-output.tmLanguage.json +++ b/syntaxes/ahk2-output.tmLanguage.json @@ -1,113 +1,113 @@ { - "name": "ahk2-output", - "scopeName": "ahk2.output", - "patterns": [ - { - "include": "#url" - }, - { - "captures": { - "1": { - "name": "token.info-token" - }, - "2": { - "name": "string" - } - }, - "match": "^(\\[Running\\])(.*)$", - "name": "ahk2.running" - }, - { - "captures": { - "1": { - "name": "token.info-token" - }, - "2": { - "name": "string" - }, - "3": { - "name": "token.debug-token" - }, - "4": { - "name": "token.error-token" - }, - "5": { - "name": "string" - }, - "6": { - "name": "constant.numeric" - }, - "7": { - "name": "string" - } - }, - "match": "^(\\[Done\\])(.+)(?:(code=0)|(code=\\d+))([^\\d]+)(\\d+(?:\\.\\d+)?)([^\\d]+)$", - "name": "ahk2.done" - }, - { - "match": "\\d{1,3}(\\.\\d{1,3}){3}(:\\d+)", - "name": "constant.numeric" - }, - { - "match": "^(?i:(\\[error\\])|(\\[info\\])|(\\[warn\\]))(.*)", - "captures": { - "1": { - "name": "token.error-token" - }, - "2": { - "name": "token.info-token" - }, - "3": { - "name": "token.warn-token" - } - }, - "name": "ahk2.log" - }, - { - "include": "#numbers" - }, - { - "include": "#operators" - }, - { - "include": "#string" - } - ], - "repository": { - "url": { - "match": "\\b((?i:(https?|ws)://\\S+))\\b", - "name": "string.url" - }, - "numbers": { - "match": "\\b(\\d+(?:\\.\\d+)?|0[xX][\\da-fA-F]+)\\b", - "name": "constant.numeric" - }, - "operators": { - "patterns": [ - { - "match": "&=|\\^=|<<=|>>=|\\|=|\\.=|\\+=|-=|\\*=|(?>|!=|<=|>=|=?=|<|>|&&|!|\\|\\||&|\\||\\^|~|:=|\\*|/|-|\\+", - "name": "keyword.operator" - } - ] - }, - "string": { - "patterns": [ - { - "begin": "(['\"])(?=.*\\1)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin" - } - }, - "end": "(\\1)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end" - } - }, - "name": "string.quoted" - } - ] - } - } -} \ No newline at end of file + "name": "ahk2-output", + "scopeName": "ahk2.output", + "patterns": [ + { + "include": "#url" + }, + { + "captures": { + "1": { + "name": "token.info-token" + }, + "2": { + "name": "string" + } + }, + "match": "^(\\[Running\\])(.*)$", + "name": "ahk2.running" + }, + { + "captures": { + "1": { + "name": "token.info-token" + }, + "2": { + "name": "string" + }, + "3": { + "name": "token.debug-token" + }, + "4": { + "name": "token.error-token" + }, + "5": { + "name": "string" + }, + "6": { + "name": "constant.numeric" + }, + "7": { + "name": "string" + } + }, + "match": "^(\\[Done\\])(.+)(?:(code=0)|(code=\\d+))([^\\d]+)(\\d+(?:\\.\\d+)?)([^\\d]+)$", + "name": "ahk2.done" + }, + { + "match": "\\d{1,3}(\\.\\d{1,3}){3}(:\\d+)", + "name": "constant.numeric" + }, + { + "match": "^(?i:(\\[error\\])|(\\[info\\])|(\\[warn\\]))(.*)", + "captures": { + "1": { + "name": "token.error-token" + }, + "2": { + "name": "token.info-token" + }, + "3": { + "name": "token.warn-token" + } + }, + "name": "ahk2.log" + }, + { + "include": "#numbers" + }, + { + "include": "#operators" + }, + { + "include": "#string" + } + ], + "repository": { + "url": { + "match": "\\b((?i:(https?|ws)://\\S+))\\b", + "name": "string.url" + }, + "numbers": { + "match": "\\b(\\d+(?:\\.\\d+)?|0[xX][\\da-fA-F]+)\\b", + "name": "constant.numeric" + }, + "operators": { + "patterns": [ + { + "match": "&=|\\^=|<<=|>>=|\\|=|\\.=|\\+=|-=|\\*=|(?>|!=|<=|>=|=?=|<|>|&&|!|\\|\\||&|\\||\\^|~|:=|\\*|/|-|\\+", + "name": "keyword.operator" + } + ] + }, + "string": { + "patterns": [ + { + "begin": "(['\"])(?=.*\\1)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.begin" + } + }, + "end": "(\\1)", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end" + } + }, + "name": "string.quoted" + } + ] + } + } +} diff --git a/syntaxes/ahk2.json b/syntaxes/ahk2.json index b8eda147..9d23f298 100644 --- a/syntaxes/ahk2.json +++ b/syntaxes/ahk2.json @@ -1010,4 +1010,4 @@ "body": "XButton2" } ] -} \ No newline at end of file +} diff --git a/syntaxes/ahk2.tmLanguage.json b/syntaxes/ahk2.tmLanguage.json index c9e2c688..e7697c49 100644 --- a/syntaxes/ahk2.tmLanguage.json +++ b/syntaxes/ahk2.tmLanguage.json @@ -1,2361 +1,2361 @@ { - "name": "autohotkey2", - "scopeName": "source.ahk2", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "include": "#hotkey_hotstring" - }, - { - "include": "#switch_statement" - }, - { - "include": "#object_property" - }, - { - "include": "#reserved" - }, - { - "include": "#numbers" - }, - { - "include": "#operators" - }, - { - "include": "#strings" - }, - { - "include": "#pre_definition" - }, - { - "include": "#class_block" - }, - { - "include": "#block" - }, - { - "include": "#continuation_section" - }, - { - "include": "#parens" - }, - { - "include": "#function_call" - }, - { - "include": "#property" - }, - { - "include": "#variables" - } - ], - "repository": { - "block": { - "patterns": [ - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.ahk2" - } - }, - "patterns": [ - { - "include": "#block_innards" - } - ] - } - ] - }, - "block_innards": { - "patterns": [ - { - "include": "#object_property" - }, - { - "name": "meta.initialization.ahk2", - "begin": "(?x)\n(?:\n (?:\n\t(?=[ \t])(?=+!]+ | \\(\\) | \\[\\]))\n)\n[ \t]*(\\() # opening bracket", - "beginCaptures": { - "1": { - "name": "variable.other.ahk2" - }, - "2": { - "name": "punctuation.section.parens.begin.bracket.round.initialization.ahk2" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.section.parens.end.bracket.round.initialization.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.ahk2" - } - }, - "patterns": [ - { - "include": "#block_innards" - } - ] - }, - { - "include": "$base" - } - ] - }, - "case_statement": { - "name": "meta.conditional.case.ahk2", - "begin": "(?<=^[ \t]*\\{?[ \t]*)((?i:case))(?!\\w)", - "beginCaptures": { - "1": { - "name": "keyword.control.case.ahk2" - } - }, - "end": "(:)", - "endCaptures": { - "1": { - "name": "punctuation.separator.colon.case.ahk2" - } - }, - "patterns": [ - { - "include": "#strings" - }, - { - "include": "#numbers" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "\\.(?=\\w)", - "name": "punctuation.accessor.ahk2" - }, - { - "include": "#function_call" - }, - { - "match": "{", - "name": "punctuation.section.block.begin.ahk2" - }, - { - "match": "}", - "name": "punctuation.section.block.end.ahk2" - }, - { - "match": "\\[|\\(", - "name": "punctuation.section.parens.begin.ahk2" - }, - { - "match": "\\]|\\)", - "name": "punctuation.section.parens.end.ahk2" - }, - { - "include": "#operators" - }, - { - "include": "#variables" - }, - { - "include": "#comments" - } - ] - }, - "class_block": { - "name": "meta.block.class.ahk2", - "begin": "(^|(?<=^[ \t]*\\*/))[ \t]*((?i:class))[ \t]+(\\$?\\w+(\\.\\w+)*)", - "beginCaptures": { - "2": { - "name": "storage.type.class.ahk2" - }, - "3": { - "name": "entity.name.type.class.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.class.end.ahk2" - } - }, - "patterns": [ - { - "begin": "\\G(?!\\{)", - "end": "(?=\\{)", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "\\G[ \t]*(<)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.begin.ahk2" - } - }, - "end": ">", - "endCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.end.ahk2" - } - }, - "patterns": [ - { - "match": "\\w+", - "name": "entity.name.type.parameter" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "=", - "name": "keyword.operator.assignment.ahk2" - }, - { - "match": "\\.", - "name": "punctuation.accessor.ahk2" - }, - { - "match": "\\|", - "name": "keyword.operator.ahk2" - } - ] - }, - { - "match": "\\b((?i:extends))([ \t]+([\\w.]+))?", - "captures": { - "1": { - "name": "storage.modifier.ahk2" - }, - "3": { - "patterns": [ - { - "match": "\\.(?=\\w)", - "name": "punctuation.accessor.ahk2" - }, - { - "include": "#default_classes" - }, - { - "match": "\\b[^.]+\\b", - "name": "entity.name.type.class.ahk2" - } - ] - } - } - } - ] - }, - { - "begin": "\\{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.class.begin.ahk2" - } - }, - "end": "(?=})", - "name": "meta.block.class.body.ahk2", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "match": "(?<=^[ \t]*)(?i:static)(?=[ \t]+\\w)", - "name": "storage.modifier.ahk2" - }, - { - "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)[ \t]*(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "patterns": [ - { - "match": "\\b(?i:__item)\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "variable.other.property.ahk2" - }, - "2": { - "name": "storage.type.function.arrow.ahk2" - }, - "4": { - "name": "comment.line.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.block.prototype.body.ahk2", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - { - "match": "(?<=(^[ \t]*(?i:static[ \t]+)?|,[ \t]*))\\w+(?=[ \t]*:=)", - "captures": { - "0": { - "patterns": [ - { - "match": "\\b(?i:__item)\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "variable.other.property.ahk2" - } - } - }, - { - "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)(?=\\()", - "beginCaptures": { - "1": { - "patterns": [ - { - "match": "\\b(__(?i:new|init|enum|get|call|set|delete))\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "entity.name.function.method.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.block.method.ahk2", - "patterns": [ - { - "begin": "\\G\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.ahk2" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.method.begin.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.method.end.ahk2" - } - }, - "name": "meta.block.method.body.ahk2", - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.block.method.body.ahk2", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - } - ] - }, - { - "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)\\b\\w+\\b(?=(\\[|[ \t]*\\{?([ \t];.*)?\\n))", - "beginCaptures": { - "0": { - "patterns": [ - { - "match": "\\b(?i:__item)\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "variable.other.property.ahk2" - } - }, - "name": "meta.block.property.ahk2", - "end": "(?=\\n)", - "endCaptures": { - "1": { - "name": "punctuation.definition.block.property.end.ahk2" - } - }, - "patterns": [ - { - "begin": "\\G\\[", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.ahk2" - } - }, - "end": "\\]", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.property.begin.ahk2" - } - }, - "end": "(?=})", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.property.end.ahk2" - } - }, - "name": "meta.block.property.body.ahk2", - "patterns": [ - { - "begin": "(?<=^[ \t]*)(?i:set)\\b", - "beginCaptures": { - "0": { - "name": "storage.type.setter.ahk2" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.property.setter.begin.ahk2" - } - }, - "name": "meta.block.property.setter.body.ahk2", - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.property.setter.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "name": "meta.block.property.setter.body.ahk2", - "end": "(?=\\n)", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - } - ] - }, - { - "begin": "(?<=^[ \t]*)(?i:get)\\b", - "beginCaptures": { - "0": { - "name": "storage.type.getter.ahk2" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.property.getter.begin.ahk2" - } - }, - "name": "meta.block.property.getter.body.ahk2", - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.property.getter.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "name": "meta.block.property.getter.body.ahk2", - "end": "(?=\\n)", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - } - ] - }, - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "name": "meta.block.property.getter.body.ahk2", - "end": "(?=\\n)", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - { - "include": "#variables" - } - ] - }, - { - "include": "#class_block" - }, - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - } - ] - }, - "comments": { - "patterns": [ - { - "name": "comment.block.jsdoc.ahk2", - "begin": "^[ \t]*(\\/\\*\\*)(?!\\/)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.begin.ahk2" - } - }, - "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.comment.end.ahk2" - } - }, - "patterns": [ - { - "include": "#docblock" - } - ] - }, - { - "name": "comment.block.ahk2", - "begin": "(?<=^[ \t]*)(\\/\\*)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.begin.ahk2" - } - }, - "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.comment.end.ahk2" - } - } - }, - { - "name": "comment.line.ahk2", - "match": "(?<=(^[ \t]*|[ \t]))(;.*)" - } - ] - }, - "compiler_directive": { - "patterns": [ - { - "name": "comment.block.ahk2", - "begin": "^[ \t]*(\\/\\*)((?i:@ahk2exe-keep))", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.begin.ahk2" - }, - "2": { - "name": "keyword.control.directive.conditional.ahk2" - } - }, - "end": "^[ \t]*(\\*\\/)", - "endCaptures": { - "1": { - "name": "punctuation.definition.comment.end.ahk2" - } - } - }, - { - "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-ignore(begin|end))", - "name": "keyword.control.directive.ahk2" - }, - { - "begin": "^[ \t]*(;[ \t]*@(?i:ahk2exe-let))\\b", - "beginCaptures": { - "0": { - "name": "keyword.control.directive.ahk2" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "include": "#strings" - }, - { - "include": "#numbers" - }, - { - "match": "\\b([_[:alpha:]][_[:alnum:]]*)(?=[ \t]*=)", - "name": "constant.language.ahk2" - }, - { - "match": "=", - "name": "keyword.operator.assignment.ahk2" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - } - ] - }, - { - "begin": "^[ \t]*((;[ \t]*@)(?i:include))\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.preprocessor.include.ahk2", - "patterns": [ - { - "begin": "[^ \t;]", - "end": "(?=(?:[ \t]+;))|(?=\\n)", - "name": "string.literal.include.ahk2" - }, - { - "match": "(?:[ \t]+);.*", - "name": "comment.line.ahk2" - } - ] - }, - { - "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-\\w+)\\b([ \t].*)?", - "name": "keyword.control.directive.ahk2", - "captures": { - "1": { - "name": "string.literal.ahk2" - } - } - }, - { - "match": "(?<=^|[ \t]);[ \t]*@(?:[\\w\\-]+)\\b([ \t]+(.*))?", - "name": "keyword.control.directive.ahk2", - "captures": { - "2": { - "name": "comment.line.ahk2" - } - } - } - ] - }, - "conditional_context": { - "patterns": [ - { - "include": "$self" - }, - { - "include": "#block_innards" - } - ] - }, - "continuation_section": { - "name": "meta.parens.continuation_section.ahk2", - "begin": "(?<=^[ \t]*)(\\()((((?i:join)[^ \t]*|[^ \t();]+)(?=[ \t]|$)|[ \t]+)*)((?<=[ \t]);.*)?$", - "beginCaptures": { - "1": { - "name": "punctuation.section.parens.begin.ahk2" - }, - "2": { - "patterns": [ - { - "match": "(?<=[ \t]|^[ \t]*\\()(?i:c(om(ments?)?)?|[lr]trim0?|`|join(`s|[^ \t]){0,15})(?=[ \t]|$)", - "name": "string.options.ahk2 markup.italic" - }, - { - "match": "[^ \t]+", - "name": "invalid.options.ahk2 markup.strikethrough" - } - ] - }, - "5": { - "name": "comment.line.ahk2" - } - }, - "end": "^[ \t]*(\\))", - "endCaptures": { - "1": { - "name": "punctuation.section.parens.end.ahk2" - } - }, - "patterns": [ - { - "include": "#continuation_section_innards" - } - ] - }, - "continuation_section_innards": { - "patterns": [ - { - "begin": "('|\")", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin.ahk2" - } - }, - "end": "(\\1)|(?=^[ \t]*\\))", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.ahk2" - } - }, - "name": "string.continuation_section_innards.ahk2", - "patterns": [ - { - "include": "#string_escaped_char" - } - ] - }, - { - "include": "#variables" - }, - { - "match": "{", - "name": "punctuation.section.block.begin.ahk2" - }, - { - "match": "}", - "name": "punctuation.section.block.end.ahk2" - }, - { - "match": "\\[", - "name": "punctuation.section.parens.begin.ahk2" - }, - { - "match": "\\]", - "name": "punctuation.section.parens.end.ahk2" - }, - { - "include": "#parens" - }, - { - "include": "$base" - } - ] - }, - "default_classes": { - "patterns": [ - { - "begin": "(?*/]\n (?:[^@<>*/]|\\*[^/])*\n)\n(?:\n \\s*\n (<)\n ([^>\\s]+)\n (>)\n)?", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - }, - "4": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "5": { - "name": "constant.other.email.link.underline.jsdoc" - }, - "6": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)borrows) \\s+\n((?:[^@\\s*/]|\\*[^/])+) # \n\\s+ (as) \\s+ # as\n((?:[^@\\s*/]|\\*[^/])+) # ", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - }, - "4": { - "name": "keyword.operator.control.jsdoc" - }, - "5": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "name": "meta.embedded.ahk2 meta.example.jsdoc", - "begin": "((@)example)\\s+", - "end": "(?=@|\\*+/)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "patterns": [ - { - "match": "^\\s*\\*\\s+", - "name": "comment.block.ahk2" - }, - { - "contentName": "constant.other.description.jsdoc", - "begin": "\\G(<)caption(>)", - "beginCaptures": { - "0": { - "name": "entity.name.tag.inline.jsdoc" - }, - "1": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - }, - "end": "()|(?=\\*/)", - "endCaptures": { - "0": { - "name": "entity.name.tag.inline.jsdoc" - }, - "1": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - }, - "patterns": [ - { - "match": "^\\s*\\*\\s", - "name": "comment.block.ahk2" - } - ] - }, - { - "include": "$base" - } - ] - }, - { - "name": "meta.overload.ahk2", - "begin": "((@)overload)\\s+", - "end": "(?=\\n|^\\s*\\*)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "match": "(?x) ((@)kind) \\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\b", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "constant.language.symbol-type.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)see)\n\\s+\n(?:\n # URL\n (\n (?=https?://)\n (?:[^\\s*]|\\*[^/])+\n )\n |\n # JSDoc namepath\n (\n (?!\n # Avoid matching bare URIs (also acceptable as links)\n https?://\n |\n # Avoid matching {@inline tags}; we match those below\n (?:\\[[^\\[\\]]*\\])? # Possible description [preceding]{@tag}\n {@(?:link|linkcode|linkplain|tutorial)\\b\n )\n # Matched namepath\n (?:[^@\\s*/]|\\*[^/])+\n )\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.link.underline.jsdoc" - }, - "4": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)template)\n\\s+\n# One or more valid identifiers\n(\n [A-Za-z_$] # First character: non-numeric word character\n [\\w$.\\[\\]]* # Rest of identifier\n (?: # Possible list of additional identifiers\n \\s* , \\s*\n [A-Za-z_$]\n [\\w$.\\[\\]]*\n )*\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - } - } - }, - { - "begin": "((@)typedef)\\s+(?={)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", - "patterns": [ - { - "include": "#jsdoctype" - }, - { - "name": "entity.name.type.instance.jsdoc", - "match": "(?:[^@\\s*/]|\\*[^/])+" - } - ] - }, - { - "begin": "((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\s+(?=[\\[{]|(?!\\d)\\w)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]\\w])", - "patterns": [ - { - "include": "#jsdoctype" - }, - { - "name": "variable.other.jsdoc", - "match": "((?!\\d)\\w[\\w.\\[\\]]*)" - }, - { - "name": "variable.other.jsdoc", - "match": "(?x)\n(\\[)\\s*\n\\w+\n(?:\n (?:\\[\\])? # Foo[ ].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [\\w$]+\n)*\n(?:\n \\s*\n (=) # [foo=bar] Default parameter value\n \\s*\n (\n # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\n (?>\n \"(?:(?:\\*(?!/))|(?:\\\\(?!\"))|[^*\\\\])*?\" | # [foo=\"bar\"] Double-quoted\n '(?:(?:\\*(?!/))|(?:\\\\(?!'))|[^*\\\\])*?' | # [foo='bar'] Single-quoted\n \\[ (?:(?:\\*(?!/))|[^*])*? \\] | # [foo=[1,2]] Array literal\n (?:(?:\\*(?!/))|\\s(?!\\s*\\])|\\[.*?(?:\\]|(?=\\*/))|[^*\\s\\[\\]])* # Everything else\n )*\n )\n)?\n\\s*(?:(\\])((?:[^*\\s]|\\*[^\\s/])+)?|(?=\\*/))", - "captures": { - "1": { - "name": "punctuation.definition.optional-value.begin.bracket.square.jsdoc" - }, - "2": { - "name": "keyword.operator.assignment.jsdoc" - }, - "3": { - "name": "meta.embedded.ahk2" - }, - "4": { - "name": "punctuation.definition.optional-value.end.bracket.square.jsdoc" - }, - "5": { - "name": "invalid.illegal.syntax.jsdoc" - } - } - } - ] - }, - { - "begin": "(?x)\n(\n (@)\n (?:define|enum|exception|export|extends|lends|implements|modifies\n |namespace|private|protected|returns?|suppress|this|throws|type\n |yields?)\n)\n\\s+(?={)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", - "patterns": [ - { - "include": "#jsdoctype" - } - ] - }, - { - "match": "((@)method)\\b\\s*((\\w|[^\\x00-\\x7f])+)?", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.function.method.ahk2" - } - } - }, - { - "match": "(?x)\n(\n (@)\n (?:alias|augments|callback|constructs|emits|event|fires|exports?\n |extends|external|function|func|host|lends|listens|interface|memberof!?\n |module|mixes|mixin|name|requires|see|this|typedef|uses)\n)\n\\s+\n(\n (?:\n [^{}@\\s*] | \\*[^/]\n )+\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "contentName": "variable.other.jsdoc", - "begin": "((@)(?:default(?:value)?|license|version))\\s+(([''\"]))", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - }, - "4": { - "name": "punctuation.definition.string.begin.jsdoc" - } - }, - "end": "(\\3)|(?=$|\\*/)", - "endCaptures": { - "0": { - "name": "variable.other.jsdoc" - }, - "1": { - "name": "punctuation.definition.string.end.jsdoc" - } - } - }, - { - "match": "((@)(?:default(?:value)?|license|tutorial|variation|version))\\s+([^\\s*]+)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - } - } - }, - { - "name": "storage.type.class.jsdoc", - "match": "(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\b", - "captures": { - "1": { - "name": "punctuation.definition.block.tag.jsdoc" - } - } - }, - { - "include": "#inline-tags" - }, - { - "match": "((@)(?:[_$[:alpha:]][_$[:alnum:]]*))(?=\\s+)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - } - } - ] - }, - "function_call": { - "match": "([_[:alpha:]][[:alnum:]_]*+)(?=\\()", - "captures": { - "1": { - "name": "entity.name.function.ahk2", - "patterns": [ - { - "match": "(?<=\\.).+", - "name": "entity.name.function.method.ahk2" - }, - { - "include": "#variables_language" - } - ] - } - } - }, - "function_call_notparens": { - "patterns": [ - { - "match": "(?<=^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\b(?>=|\\?|\\{))|$))", - "name": "entity.name.function.ahk2", - "captures": { - "0": { - "patterns": [ - { - "include": "#function_defaultLibrary" - } - ] - } - } - }, - { - "match": "(?<=(^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\.)+)([[:alpha:]_][[:alnum:]_]*\\b)(?=$|[ \t]((?!([ \t]*[+\\-*/^&:.|]?=|<<=|>>=|\\?|\\{))|$))", - "name": "entity.name.function.method.ahk2" - } - ] - }, - "function_defaultLibrary": { - "patterns": [ - { - "match": "(?$~*!+#^]*?)(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))|~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+)[ \t]+&[ \t]+~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))([ \t]+up)?)(::)", - "beginCaptures": { - "1": { - "name": "hotkey.ahk2", - "patterns": [ - { - "match": "(?<=[ \t])&(?=[ \t]+[^ \t]+(?i:[ \t]+up)?$)", - "name": "keyword.operator.ahk2" - }, - { - "match": "(?<=(&[ \t]+|^[ \t]*))([<>$~*!+#^]*?)(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+|`[;{]|[\\x21-\\x3A\\x3C-\\x7E]|(?<=[^ \t]);)(?=([ \t]|$))", - "name": "keyword.keys.ahk2" - } - ] - }, - "7": { - "name": "keyword.keys.up.ahk2" - }, - "8": { - "name": "punctuation.definition.colon" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "match": "(?<=\\G[ \t]*)((?i:alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab)\\b|([<>]?[!+#^]){0,4}(`[{;]|(?<=\\G);|[^{;]|(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))(?=([ \t]+;.*|[ \t]*)\\n))", - "name": "keyword.keys.ahk2" - }, - { - "include": "$base" - } - ] - }, - { - "match": "(?<=^[ \t]*\\{?[ \t]*)(\\w+)(:)(?=[ \t]*([ \t];.*)?$)", - "captures": { - "1": { - "name": "entity.name.label.ahk2" - }, - "2": { - "name": "punctuation.definition.colon" - } - } - } - ] - }, - "hotstring_execute": { - "match": "^[ \t]*(:)([^:]*)(:)((`.|[^`])*?)(::)", - "captures": { - "1": { - "name": "punctuation.definition.colon" - }, - "2": { - "patterns": [ - { - "match": "(?i:(s[ipe]|[*?borstz]0?|c[01]?|k-1|[kp]\\d+|x1?))", - "name": "string.options.ahk2 markup.italic" - }, - { - "match": "[^ \t]", - "name": "invalid.options.ahk2 markup.strikethrough" - } - ] - }, - "3": { - "name": "punctuation.definition.colon" - }, - "4": { - "name": "keyword.keys.ahk2 markup.underline" - }, - "6": { - "name": "punctuation.definition.colon" - } - }, - "name": "hotstring.ahk2" - }, - "inline-tags": { - "patterns": [ - { - "name": "constant.other.description.jsdoc", - "match": "(\\[)[^\\]]+(\\])(?={@(?:link|linkcode|linkplain|tutorial))", - "captures": { - "1": { - "name": "punctuation.definition.bracket.square.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.square.end.jsdoc" - } - } - }, - { - "name": "entity.name.type.instance.jsdoc", - "begin": "({)((@)(?:link(?:code|plain)?|tutorial))\\s*", - "beginCaptures": { - "1": { - "name": "punctuation.definition.bracket.curly.begin.jsdoc" - }, - "2": { - "name": "storage.type.class.jsdoc" - }, - "3": { - "name": "punctuation.definition.inline.tag.jsdoc" - } - }, - "end": "}|(?=\\*/)", - "endCaptures": { - "0": { - "name": "punctuation.definition.bracket.curly.end.jsdoc" - } - }, - "patterns": [ - { - "match": "\\G((?=https?://)(?:[^|}\\s*]|\\*[/])+)(\\|)?", - "captures": { - "1": { - "name": "variable.other.link.underline.jsdoc" - }, - "2": { - "name": "punctuation.separator.pipe.jsdoc" - } - } - }, - { - "match": "\\G((?:[^{}@\\s|*]|\\*[^/])+)(\\|)?", - "captures": { - "1": { - "name": "variable.other.description.jsdoc" - }, - "2": { - "name": "punctuation.separator.pipe.jsdoc" - } - } - } - ] - } - ] - }, - "brackets": { - "patterns": [ - { - "match": "^\\s*\\*\\s+", - "name": "comment.block.ahk2" - }, - { - "match": "(['\"])(`\\1|.(??:=.&|^]+|[~+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or)))[ \t]*([ \t];.*)?\\n", - "beginCaptures": { - "1": { - "patterns": [ - { - "include": "#operators" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "=>", - "name": "storage.type.function.arrow.ahk2" - } - ] - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "end": "(?!([*/<>?:=.]+|[+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or))))[ \t]*([ \t];.*)?(?=\\n)|(?<=^[ \t]*(?i:class|static|if|try|loop|while)[ \t]+\\w+)", - "endCaptures": { - "3": { - "name": "comment.line.ahk2" - } - }, - "patterns": [ - { - "match": "(?<=^[ \t]*)\\w+(?=(\\n|[ \t]))", - "captures": { - "0": { - "patterns": [ - { - "include": "#variables" - } - ] - } - } - }, - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - "numbers": { - "match": "(?", - "name": "storage.type.function.arrow.ahk2" - }, - { - "match": "\\.=|\\+=|-=|\\*=|/?/=", - "name": "keyword.operator.assignment.compound.ahk2" - }, - { - "match": "&=|\\^=|<<=|>>>=|>>=|\\|=", - "name": "keyword.operator.assignment.compound.bitwise.ahk2" - }, - { - "match": "<<|>>>|>>", - "name": "keyword.operator.bitwise.shift.ahk2" - }, - { - "match": "!=|<=|>=|=?=|<|>", - "name": "keyword.operator.comparison.ahk2" - }, - { - "match": "~=", - "name": "keyword.operator.regexp.ahk2" - }, - { - "match": "\\?\\?|&&|!|\\|\\|", - "name": "keyword.operator.logical.ahk2" - }, - { - "match": "&|\\||\\^|~", - "name": "keyword.operator.ahk2" - }, - { - "match": ":=", - "name": "keyword.operator.assignment.ahk2" - }, - { - "match": "\\.(?=\\w)", - "name": "punctuation.accessor.ahk2" - }, - { - "match": "\\*|/|-|\\+|\\.", - "name": "keyword.operator.ahk2" - }, - { - "match": "%", - "name": "punctuation.parens.percent.ahk2" - }, - { - "match": "\\[", - "name": "punctuation.square.begin.ahk2" - }, - { - "match": "\\]", - "name": "punctuation.square.end.ahk2" - }, - { - "match": "\\?(?=[ \t]*[,)\\]}])", - "name": "keyword.operator.optional.ahk2" - }, - { - "match": "\\?|:(?!\\:)", - "name": "keyword.operator.ternary.ahk2" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - } - ] - }, - "parens": { - "name": "meta.parens.ahk2", - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "punctuation.section.parens.begin.bracket.round.ahk2" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.section.parens.end.bracket.round.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - "property": { - "patterns": [ - { - "name": "variable.other.property.ahk2", - "match": "\\b(?<=\\.)[_[:alnum:]]+\\b" - } - ] - }, - "pre_definition": { - "patterns": [ - { - "begin": "^[ \t]*((#)(?i:dllload|hotstring|include(again)?|mapcasesense|requires|errorstdout|definedefault(array|map|object)value|windowclass(gui|main)|singleinstance|targetcontrolerror|targetwindowerror))\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - }, - "end": "\\n", - "name": "meta.preprocessor.ahk2", - "patterns": [ - { - "match": "[^ \t;].*?(?=([ \t]+;|[ \t]*\\n))", - "name": "string.literal.ahk2" - }, - { - "match": "(?<=[ \t]);.*", - "name": "comment.line.ahk2" - } - ] - }, - { - "begin": "^[ \t]*((#)(?i:warn))\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - }, - "end": "\\n", - "name": "meta.preprocessor.ahk2", - "patterns": [ - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "\\w+", - "name": "string.literal.ahk2" - }, - { - "match": "(?<=[ \t]);.*", - "name": "comment.line.ahk2" - } - ] - }, - { - "match": "^[ \t]*((#)(?i:clipboardtimeout|criticalobject(sleeptime|timeout)|hotif|hotiftimeout|inputlevel|initexec|maxthreads|maxthreadsbuffer|maxthreadsperhotkey|notrayicon|suspendexempt|usehook|usestdlib|warn|warncontinuableexception|winactivateforce))\\b", - "captures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - } - }, - { - "begin": "^[ \t]*((#)(?i:dllimport))([ \t]+(\\w+)[ \t]*(,?))?", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - }, - "4": { - "name": "entity.name.function.ahk2" - }, - "5": { - "name": "punctuation.separator.comma.ahk2" - } - }, - "end": "\\n", - "name": "meta.preprocessor.ahk2", - "patterns": [ - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "[^,\\n\\r]+", - "name": "string.literal.ahk2" - } - ] - } - ] - }, - "reserved": { - "patterns": [ - { - "match": "(?(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))(\\()", - "beginCaptures": { - "1": { - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - } - ] - }, - "2": { - "name": "comment.block.ahk2 punctuation.definition.comment.begin.ahk2" - }, - "3": { - "name": "comment.block.ahk2" - }, - "4": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.ahk2 punctuation.definition.comment.end.ahk2" - }, - { - "match": "\\*", - "name": "comment.block.ahk2" - } - ] - }, - "5": { - "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.ahk2" - } - }, - "end": "(\\))", - "endCaptures": { - "1": { - "name": "punctuation.section.parens.end.bracket.round.conditional.switch.ahk2" - } - }, - "patterns": [ - { - "include": "#conditional_context" - } - ] - }, - "switch_statement": { - "name": "meta.block.switch.ahk2", - "begin": "(((?>(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))((?\\[\\]=]))", - "patterns": [ - { - "name": "meta.head.switch.ahk2", - "begin": "\\G ?", - "end": "(?=+!]+ | \\(\\) | \\[\\]))\n)\n[ \t]*(\\() # opening bracket", + "beginCaptures": { + "1": { + "name": "variable.other.ahk2" + }, + "2": { + "name": "punctuation.section.parens.begin.bracket.round.initialization.ahk2" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.initialization.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.ahk2" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.ahk2" + } + }, + "patterns": [ + { + "include": "#block_innards" + } + ] + }, + { + "include": "$base" + } + ] + }, + "case_statement": { + "name": "meta.conditional.case.ahk2", + "begin": "(?<=^[ \t]*\\{?[ \t]*)((?i:case))(?!\\w)", + "beginCaptures": { + "1": { + "name": "keyword.control.case.ahk2" + } + }, + "end": "(:)", + "endCaptures": { + "1": { + "name": "punctuation.separator.colon.case.ahk2" + } + }, + "patterns": [ + { + "include": "#strings" + }, + { + "include": "#numbers" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "\\.(?=\\w)", + "name": "punctuation.accessor.ahk2" + }, + { + "include": "#function_call" + }, + { + "match": "{", + "name": "punctuation.section.block.begin.ahk2" + }, + { + "match": "}", + "name": "punctuation.section.block.end.ahk2" + }, + { + "match": "\\[|\\(", + "name": "punctuation.section.parens.begin.ahk2" + }, + { + "match": "\\]|\\)", + "name": "punctuation.section.parens.end.ahk2" + }, + { + "include": "#operators" + }, + { + "include": "#variables" + }, + { + "include": "#comments" + } + ] + }, + "class_block": { + "name": "meta.block.class.ahk2", + "begin": "(^|(?<=^[ \t]*\\*/))[ \t]*((?i:class))[ \t]+(\\$?\\w+(\\.\\w+)*)", + "beginCaptures": { + "2": { + "name": "storage.type.class.ahk2" + }, + "3": { + "name": "entity.name.type.class.ahk2" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.class.end.ahk2" + } + }, + "patterns": [ + { + "begin": "\\G(?!\\{)", + "end": "(?=\\{)", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "\\G[ \t]*(<)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.typeparameters.begin.ahk2" + } + }, + "end": ">", + "endCaptures": { + "0": { + "name": "punctuation.definition.typeparameters.end.ahk2" + } + }, + "patterns": [ + { + "match": "\\w+", + "name": "entity.name.type.parameter" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "=", + "name": "keyword.operator.assignment.ahk2" + }, + { + "match": "\\.", + "name": "punctuation.accessor.ahk2" + }, + { + "match": "\\|", + "name": "keyword.operator.ahk2" + } + ] + }, + { + "match": "\\b((?i:extends))([ \t]+([\\w.]+))?", + "captures": { + "1": { + "name": "storage.modifier.ahk2" + }, + "3": { + "patterns": [ + { + "match": "\\.(?=\\w)", + "name": "punctuation.accessor.ahk2" + }, + { + "include": "#default_classes" + }, + { + "match": "\\b[^.]+\\b", + "name": "entity.name.type.class.ahk2" + } + ] + } + } + } + ] + }, + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.class.begin.ahk2" + } + }, + "end": "(?=})", + "name": "meta.block.class.body.ahk2", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "match": "(?<=^[ \t]*)(?i:static)(?=[ \t]+\\w)", + "name": "storage.modifier.ahk2" + }, + { + "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)[ \t]*(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "patterns": [ + { + "match": "\\b(?i:__item)\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "variable.other.property.ahk2" + }, + "2": { + "name": "storage.type.function.arrow.ahk2" + }, + "4": { + "name": "comment.line.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.block.prototype.body.ahk2", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + { + "match": "(?<=(^[ \t]*(?i:static[ \t]+)?|,[ \t]*))\\w+(?=[ \t]*:=)", + "captures": { + "0": { + "patterns": [ + { + "match": "\\b(?i:__item)\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "variable.other.property.ahk2" + } + } + }, + { + "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)(?=\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "match": "\\b(__(?i:new|init|enum|get|call|set|delete))\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "entity.name.function.method.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.block.method.ahk2", + "patterns": [ + { + "begin": "\\G\\(", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.ahk2" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.method.begin.ahk2" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.method.end.ahk2" + } + }, + "name": "meta.block.method.body.ahk2", + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.block.method.body.ahk2", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + } + ] + }, + { + "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)\\b\\w+\\b(?=(\\[|[ \t]*\\{?([ \t];.*)?\\n))", + "beginCaptures": { + "0": { + "patterns": [ + { + "match": "\\b(?i:__item)\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "variable.other.property.ahk2" + } + }, + "name": "meta.block.property.ahk2", + "end": "(?=\\n)", + "endCaptures": { + "1": { + "name": "punctuation.definition.block.property.end.ahk2" + } + }, + "patterns": [ + { + "begin": "\\G\\[", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.ahk2" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.property.begin.ahk2" + } + }, + "end": "(?=})", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.property.end.ahk2" + } + }, + "name": "meta.block.property.body.ahk2", + "patterns": [ + { + "begin": "(?<=^[ \t]*)(?i:set)\\b", + "beginCaptures": { + "0": { + "name": "storage.type.setter.ahk2" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.property.setter.begin.ahk2" + } + }, + "name": "meta.block.property.setter.body.ahk2", + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.property.setter.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "name": "meta.block.property.setter.body.ahk2", + "end": "(?=\\n)", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + } + ] + }, + { + "begin": "(?<=^[ \t]*)(?i:get)\\b", + "beginCaptures": { + "0": { + "name": "storage.type.getter.ahk2" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.property.getter.begin.ahk2" + } + }, + "name": "meta.block.property.getter.body.ahk2", + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.property.getter.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "name": "meta.block.property.getter.body.ahk2", + "end": "(?=\\n)", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "name": "meta.block.property.getter.body.ahk2", + "end": "(?=\\n)", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + { + "include": "#variables" + } + ] + }, + { + "include": "#class_block" + }, + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + } + ] + }, + "comments": { + "patterns": [ + { + "name": "comment.block.jsdoc.ahk2", + "begin": "^[ \t]*(\\/\\*\\*)(?!\\/)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.ahk2" + } + }, + "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.ahk2" + } + }, + "patterns": [ + { + "include": "#docblock" + } + ] + }, + { + "name": "comment.block.ahk2", + "begin": "(?<=^[ \t]*)(\\/\\*)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.ahk2" + } + }, + "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.ahk2" + } + } + }, + { + "name": "comment.line.ahk2", + "match": "(?<=(^[ \t]*|[ \t]))(;.*)" + } + ] + }, + "compiler_directive": { + "patterns": [ + { + "name": "comment.block.ahk2", + "begin": "^[ \t]*(\\/\\*)((?i:@ahk2exe-keep))", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.ahk2" + }, + "2": { + "name": "keyword.control.directive.conditional.ahk2" + } + }, + "end": "^[ \t]*(\\*\\/)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.ahk2" + } + } + }, + { + "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-ignore(begin|end))", + "name": "keyword.control.directive.ahk2" + }, + { + "begin": "^[ \t]*(;[ \t]*@(?i:ahk2exe-let))\\b", + "beginCaptures": { + "0": { + "name": "keyword.control.directive.ahk2" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "include": "#strings" + }, + { + "include": "#numbers" + }, + { + "match": "\\b([_[:alpha:]][_[:alnum:]]*)(?=[ \t]*=)", + "name": "constant.language.ahk2" + }, + { + "match": "=", + "name": "keyword.operator.assignment.ahk2" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + } + ] + }, + { + "begin": "^[ \t]*((;[ \t]*@)(?i:include))\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.preprocessor.include.ahk2", + "patterns": [ + { + "begin": "[^ \t;]", + "end": "(?=(?:[ \t]+;))|(?=\\n)", + "name": "string.literal.include.ahk2" + }, + { + "match": "(?:[ \t]+);.*", + "name": "comment.line.ahk2" + } + ] + }, + { + "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-\\w+)\\b([ \t].*)?", + "name": "keyword.control.directive.ahk2", + "captures": { + "1": { + "name": "string.literal.ahk2" + } + } + }, + { + "match": "(?<=^|[ \t]);[ \t]*@(?:[\\w\\-]+)\\b([ \t]+(.*))?", + "name": "keyword.control.directive.ahk2", + "captures": { + "2": { + "name": "comment.line.ahk2" + } + } + } + ] + }, + "conditional_context": { + "patterns": [ + { + "include": "$self" + }, + { + "include": "#block_innards" + } + ] + }, + "continuation_section": { + "name": "meta.parens.continuation_section.ahk2", + "begin": "(?<=^[ \t]*)(\\()((((?i:join)[^ \t]*|[^ \t();]+)(?=[ \t]|$)|[ \t]+)*)((?<=[ \t]);.*)?$", + "beginCaptures": { + "1": { + "name": "punctuation.section.parens.begin.ahk2" + }, + "2": { + "patterns": [ + { + "match": "(?<=[ \t]|^[ \t]*\\()(?i:c(om(ments?)?)?|[lr]trim0?|`|join(`s|[^ \t]){0,15})(?=[ \t]|$)", + "name": "string.options.ahk2 markup.italic" + }, + { + "match": "[^ \t]+", + "name": "invalid.options.ahk2 markup.strikethrough" + } + ] + }, + "5": { + "name": "comment.line.ahk2" + } + }, + "end": "^[ \t]*(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.ahk2" + } + }, + "patterns": [ + { + "include": "#continuation_section_innards" + } + ] + }, + "continuation_section_innards": { + "patterns": [ + { + "begin": "('|\")", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.begin.ahk2" + } + }, + "end": "(\\1)|(?=^[ \t]*\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.ahk2" + } + }, + "name": "string.continuation_section_innards.ahk2", + "patterns": [ + { + "include": "#string_escaped_char" + } + ] + }, + { + "include": "#variables" + }, + { + "match": "{", + "name": "punctuation.section.block.begin.ahk2" + }, + { + "match": "}", + "name": "punctuation.section.block.end.ahk2" + }, + { + "match": "\\[", + "name": "punctuation.section.parens.begin.ahk2" + }, + { + "match": "\\]", + "name": "punctuation.section.parens.end.ahk2" + }, + { + "include": "#parens" + }, + { + "include": "$base" + } + ] + }, + "default_classes": { + "patterns": [ + { + "begin": "(?*/]\n (?:[^@<>*/]|\\*[^/])*\n)\n(?:\n \\s*\n (<)\n ([^>\\s]+)\n (>)\n)?", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.type.instance.jsdoc" + }, + "4": { + "name": "punctuation.definition.bracket.angle.begin.jsdoc" + }, + "5": { + "name": "constant.other.email.link.underline.jsdoc" + }, + "6": { + "name": "punctuation.definition.bracket.angle.end.jsdoc" + } + } + }, + { + "match": "(?x)\n((@)borrows) \\s+\n((?:[^@\\s*/]|\\*[^/])+) # \n\\s+ (as) \\s+ # as\n((?:[^@\\s*/]|\\*[^/])+) # ", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.type.instance.jsdoc" + }, + "4": { + "name": "keyword.operator.control.jsdoc" + }, + "5": { + "name": "entity.name.type.instance.jsdoc" + } + } + }, + { + "name": "meta.embedded.ahk2 meta.example.jsdoc", + "begin": "((@)example)\\s+", + "end": "(?=@|\\*+/)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "patterns": [ + { + "match": "^\\s*\\*\\s+", + "name": "comment.block.ahk2" + }, + { + "contentName": "constant.other.description.jsdoc", + "begin": "\\G(<)caption(>)", + "beginCaptures": { + "0": { + "name": "entity.name.tag.inline.jsdoc" + }, + "1": { + "name": "punctuation.definition.bracket.angle.begin.jsdoc" + }, + "2": { + "name": "punctuation.definition.bracket.angle.end.jsdoc" + } + }, + "end": "()|(?=\\*/)", + "endCaptures": { + "0": { + "name": "entity.name.tag.inline.jsdoc" + }, + "1": { + "name": "punctuation.definition.bracket.angle.begin.jsdoc" + }, + "2": { + "name": "punctuation.definition.bracket.angle.end.jsdoc" + } + }, + "patterns": [ + { + "match": "^\\s*\\*\\s", + "name": "comment.block.ahk2" + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "name": "meta.overload.ahk2", + "begin": "((@)overload)\\s+", + "end": "(?=\\n|^\\s*\\*)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "match": "(?x) ((@)kind) \\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\b", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "constant.language.symbol-type.jsdoc" + } + } + }, + { + "match": "(?x)\n((@)see)\n\\s+\n(?:\n # URL\n (\n (?=https?://)\n (?:[^\\s*]|\\*[^/])+\n )\n |\n # JSDoc namepath\n (\n (?!\n # Avoid matching bare URIs (also acceptable as links)\n https?://\n |\n # Avoid matching {@inline tags}; we match those below\n (?:\\[[^\\[\\]]*\\])? # Possible description [preceding]{@tag}\n {@(?:link|linkcode|linkplain|tutorial)\\b\n )\n # Matched namepath\n (?:[^@\\s*/]|\\*[^/])+\n )\n)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.link.underline.jsdoc" + }, + "4": { + "name": "entity.name.type.instance.jsdoc" + } + } + }, + { + "match": "(?x)\n((@)template)\n\\s+\n# One or more valid identifiers\n(\n [A-Za-z_$] # First character: non-numeric word character\n [\\w$.\\[\\]]* # Rest of identifier\n (?: # Possible list of additional identifiers\n \\s* , \\s*\n [A-Za-z_$]\n [\\w$.\\[\\]]*\n )*\n)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.jsdoc" + } + } + }, + { + "begin": "((@)typedef)\\s+(?={)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", + "patterns": [ + { + "include": "#jsdoctype" + }, + { + "name": "entity.name.type.instance.jsdoc", + "match": "(?:[^@\\s*/]|\\*[^/])+" + } + ] + }, + { + "begin": "((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\s+(?=[\\[{]|(?!\\d)\\w)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "end": "(?=\\s|\\*/|[^{}\\[\\]\\w])", + "patterns": [ + { + "include": "#jsdoctype" + }, + { + "name": "variable.other.jsdoc", + "match": "((?!\\d)\\w[\\w.\\[\\]]*)" + }, + { + "name": "variable.other.jsdoc", + "match": "(?x)\n(\\[)\\s*\n\\w+\n(?:\n (?:\\[\\])? # Foo[ ].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [\\w$]+\n)*\n(?:\n \\s*\n (=) # [foo=bar] Default parameter value\n \\s*\n (\n # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\n (?>\n \"(?:(?:\\*(?!/))|(?:\\\\(?!\"))|[^*\\\\])*?\" | # [foo=\"bar\"] Double-quoted\n '(?:(?:\\*(?!/))|(?:\\\\(?!'))|[^*\\\\])*?' | # [foo='bar'] Single-quoted\n \\[ (?:(?:\\*(?!/))|[^*])*? \\] | # [foo=[1,2]] Array literal\n (?:(?:\\*(?!/))|\\s(?!\\s*\\])|\\[.*?(?:\\]|(?=\\*/))|[^*\\s\\[\\]])* # Everything else\n )*\n )\n)?\n\\s*(?:(\\])((?:[^*\\s]|\\*[^\\s/])+)?|(?=\\*/))", + "captures": { + "1": { + "name": "punctuation.definition.optional-value.begin.bracket.square.jsdoc" + }, + "2": { + "name": "keyword.operator.assignment.jsdoc" + }, + "3": { + "name": "meta.embedded.ahk2" + }, + "4": { + "name": "punctuation.definition.optional-value.end.bracket.square.jsdoc" + }, + "5": { + "name": "invalid.illegal.syntax.jsdoc" + } + } + } + ] + }, + { + "begin": "(?x)\n(\n (@)\n (?:define|enum|exception|export|extends|lends|implements|modifies\n |namespace|private|protected|returns?|suppress|this|throws|type\n |yields?)\n)\n\\s+(?={)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", + "patterns": [ + { + "include": "#jsdoctype" + } + ] + }, + { + "match": "((@)method)\\b\\s*((\\w|[^\\x00-\\x7f])+)?", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.function.method.ahk2" + } + } + }, + { + "match": "(?x)\n(\n (@)\n (?:alias|augments|callback|constructs|emits|event|fires|exports?\n |extends|external|function|func|host|lends|listens|interface|memberof!?\n |module|mixes|mixin|name|requires|see|this|typedef|uses)\n)\n\\s+\n(\n (?:\n [^{}@\\s*] | \\*[^/]\n )+\n)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.type.instance.jsdoc" + } + } + }, + { + "contentName": "variable.other.jsdoc", + "begin": "((@)(?:default(?:value)?|license|version))\\s+(([''\"]))", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.jsdoc" + }, + "4": { + "name": "punctuation.definition.string.begin.jsdoc" + } + }, + "end": "(\\3)|(?=$|\\*/)", + "endCaptures": { + "0": { + "name": "variable.other.jsdoc" + }, + "1": { + "name": "punctuation.definition.string.end.jsdoc" + } + } + }, + { + "match": "((@)(?:default(?:value)?|license|tutorial|variation|version))\\s+([^\\s*]+)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.jsdoc" + } + } + }, + { + "name": "storage.type.class.jsdoc", + "match": "(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\b", + "captures": { + "1": { + "name": "punctuation.definition.block.tag.jsdoc" + } + } + }, + { + "include": "#inline-tags" + }, + { + "match": "((@)(?:[_$[:alpha:]][_$[:alnum:]]*))(?=\\s+)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + } + } + ] + }, + "function_call": { + "match": "([_[:alpha:]][[:alnum:]_]*+)(?=\\()", + "captures": { + "1": { + "name": "entity.name.function.ahk2", + "patterns": [ + { + "match": "(?<=\\.).+", + "name": "entity.name.function.method.ahk2" + }, + { + "include": "#variables_language" + } + ] + } + } + }, + "function_call_notparens": { + "patterns": [ + { + "match": "(?<=^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\b(?>=|\\?|\\{))|$))", + "name": "entity.name.function.ahk2", + "captures": { + "0": { + "patterns": [ + { + "include": "#function_defaultLibrary" + } + ] + } + } + }, + { + "match": "(?<=(^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\.)+)([[:alpha:]_][[:alnum:]_]*\\b)(?=$|[ \t]((?!([ \t]*[+\\-*/^&:.|]?=|<<=|>>=|\\?|\\{))|$))", + "name": "entity.name.function.method.ahk2" + } + ] + }, + "function_defaultLibrary": { + "patterns": [ + { + "match": "(?$~*!+#^]*?)(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))|~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+)[ \t]+&[ \t]+~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))([ \t]+up)?)(::)", + "beginCaptures": { + "1": { + "name": "hotkey.ahk2", + "patterns": [ + { + "match": "(?<=[ \t])&(?=[ \t]+[^ \t]+(?i:[ \t]+up)?$)", + "name": "keyword.operator.ahk2" + }, + { + "match": "(?<=(&[ \t]+|^[ \t]*))([<>$~*!+#^]*?)(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+|`[;{]|[\\x21-\\x3A\\x3C-\\x7E]|(?<=[^ \t]);)(?=([ \t]|$))", + "name": "keyword.keys.ahk2" + } + ] + }, + "7": { + "name": "keyword.keys.up.ahk2" + }, + "8": { + "name": "punctuation.definition.colon" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "match": "(?<=\\G[ \t]*)((?i:alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab)\\b|([<>]?[!+#^]){0,4}(`[{;]|(?<=\\G);|[^{;]|(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))(?=([ \t]+;.*|[ \t]*)\\n))", + "name": "keyword.keys.ahk2" + }, + { + "include": "$base" + } + ] + }, + { + "match": "(?<=^[ \t]*\\{?[ \t]*)(\\w+)(:)(?=[ \t]*([ \t];.*)?$)", + "captures": { + "1": { + "name": "entity.name.label.ahk2" + }, + "2": { + "name": "punctuation.definition.colon" + } + } + } + ] + }, + "hotstring_execute": { + "match": "^[ \t]*(:)([^:]*)(:)((`.|[^`])*?)(::)", + "captures": { + "1": { + "name": "punctuation.definition.colon" + }, + "2": { + "patterns": [ + { + "match": "(?i:(s[ipe]|[*?borstz]0?|c[01]?|k-1|[kp]\\d+|x1?))", + "name": "string.options.ahk2 markup.italic" + }, + { + "match": "[^ \t]", + "name": "invalid.options.ahk2 markup.strikethrough" + } + ] + }, + "3": { + "name": "punctuation.definition.colon" + }, + "4": { + "name": "keyword.keys.ahk2 markup.underline" + }, + "6": { + "name": "punctuation.definition.colon" + } + }, + "name": "hotstring.ahk2" + }, + "inline-tags": { + "patterns": [ + { + "name": "constant.other.description.jsdoc", + "match": "(\\[)[^\\]]+(\\])(?={@(?:link|linkcode|linkplain|tutorial))", + "captures": { + "1": { + "name": "punctuation.definition.bracket.square.begin.jsdoc" + }, + "2": { + "name": "punctuation.definition.bracket.square.end.jsdoc" + } + } + }, + { + "name": "entity.name.type.instance.jsdoc", + "begin": "({)((@)(?:link(?:code|plain)?|tutorial))\\s*", + "beginCaptures": { + "1": { + "name": "punctuation.definition.bracket.curly.begin.jsdoc" + }, + "2": { + "name": "storage.type.class.jsdoc" + }, + "3": { + "name": "punctuation.definition.inline.tag.jsdoc" + } + }, + "end": "}|(?=\\*/)", + "endCaptures": { + "0": { + "name": "punctuation.definition.bracket.curly.end.jsdoc" + } + }, + "patterns": [ + { + "match": "\\G((?=https?://)(?:[^|}\\s*]|\\*[/])+)(\\|)?", + "captures": { + "1": { + "name": "variable.other.link.underline.jsdoc" + }, + "2": { + "name": "punctuation.separator.pipe.jsdoc" + } + } + }, + { + "match": "\\G((?:[^{}@\\s|*]|\\*[^/])+)(\\|)?", + "captures": { + "1": { + "name": "variable.other.description.jsdoc" + }, + "2": { + "name": "punctuation.separator.pipe.jsdoc" + } + } + } + ] + } + ] + }, + "brackets": { + "patterns": [ + { + "match": "^\\s*\\*\\s+", + "name": "comment.block.ahk2" + }, + { + "match": "(['\"])(`\\1|.(??:=.&|^]+|[~+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or)))[ \t]*([ \t];.*)?\\n", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#operators" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "=>", + "name": "storage.type.function.arrow.ahk2" + } + ] + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "end": "(?!([*/<>?:=.]+|[+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or))))[ \t]*([ \t];.*)?(?=\\n)|(?<=^[ \t]*(?i:class|static|if|try|loop|while)[ \t]+\\w+)", + "endCaptures": { + "3": { + "name": "comment.line.ahk2" + } + }, + "patterns": [ + { + "match": "(?<=^[ \t]*)\\w+(?=(\\n|[ \t]))", + "captures": { + "0": { + "patterns": [ + { + "include": "#variables" + } + ] + } + } + }, + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + "numbers": { + "match": "(?", + "name": "storage.type.function.arrow.ahk2" + }, + { + "match": "\\.=|\\+=|-=|\\*=|/?/=", + "name": "keyword.operator.assignment.compound.ahk2" + }, + { + "match": "&=|\\^=|<<=|>>>=|>>=|\\|=", + "name": "keyword.operator.assignment.compound.bitwise.ahk2" + }, + { + "match": "<<|>>>|>>", + "name": "keyword.operator.bitwise.shift.ahk2" + }, + { + "match": "!=|<=|>=|=?=|<|>", + "name": "keyword.operator.comparison.ahk2" + }, + { + "match": "~=", + "name": "keyword.operator.regexp.ahk2" + }, + { + "match": "\\?\\?|&&|!|\\|\\|", + "name": "keyword.operator.logical.ahk2" + }, + { + "match": "&|\\||\\^|~", + "name": "keyword.operator.ahk2" + }, + { + "match": ":=", + "name": "keyword.operator.assignment.ahk2" + }, + { + "match": "\\.(?=\\w)", + "name": "punctuation.accessor.ahk2" + }, + { + "match": "\\*|/|-|\\+|\\.", + "name": "keyword.operator.ahk2" + }, + { + "match": "%", + "name": "punctuation.parens.percent.ahk2" + }, + { + "match": "\\[", + "name": "punctuation.square.begin.ahk2" + }, + { + "match": "\\]", + "name": "punctuation.square.end.ahk2" + }, + { + "match": "\\?(?=[ \t]*[,)\\]}])", + "name": "keyword.operator.optional.ahk2" + }, + { + "match": "\\?|:(?!\\:)", + "name": "keyword.operator.ternary.ahk2" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + } + ] + }, + "parens": { + "name": "meta.parens.ahk2", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.ahk2" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + "property": { + "patterns": [ + { + "name": "variable.other.property.ahk2", + "match": "\\b(?<=\\.)[_[:alnum:]]+\\b" + } + ] + }, + "pre_definition": { + "patterns": [ + { + "begin": "^[ \t]*((#)(?i:dllload|hotstring|include(again)?|mapcasesense|requires|errorstdout|definedefault(array|map|object)value|windowclass(gui|main)|singleinstance|targetcontrolerror|targetwindowerror))\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + }, + "end": "\\n", + "name": "meta.preprocessor.ahk2", + "patterns": [ + { + "match": "[^ \t;].*?(?=([ \t]+;|[ \t]*\\n))", + "name": "string.literal.ahk2" + }, + { + "match": "(?<=[ \t]);.*", + "name": "comment.line.ahk2" + } + ] + }, + { + "begin": "^[ \t]*((#)(?i:warn))\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + }, + "end": "\\n", + "name": "meta.preprocessor.ahk2", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "\\w+", + "name": "string.literal.ahk2" + }, + { + "match": "(?<=[ \t]);.*", + "name": "comment.line.ahk2" + } + ] + }, + { + "match": "^[ \t]*((#)(?i:clipboardtimeout|criticalobject(sleeptime|timeout)|hotif|hotiftimeout|inputlevel|initexec|maxthreads|maxthreadsbuffer|maxthreadsperhotkey|notrayicon|suspendexempt|usehook|usestdlib|warn|warncontinuableexception|winactivateforce))\\b", + "captures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + } + }, + { + "begin": "^[ \t]*((#)(?i:dllimport))([ \t]+(\\w+)[ \t]*(,?))?", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + }, + "4": { + "name": "entity.name.function.ahk2" + }, + "5": { + "name": "punctuation.separator.comma.ahk2" + } + }, + "end": "\\n", + "name": "meta.preprocessor.ahk2", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "[^,\\n\\r]+", + "name": "string.literal.ahk2" + } + ] + } + ] + }, + "reserved": { + "patterns": [ + { + "match": "(?(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + } + ] + }, + "2": { + "name": "comment.block.ahk2 punctuation.definition.comment.begin.ahk2" + }, + "3": { + "name": "comment.block.ahk2" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.ahk2 punctuation.definition.comment.end.ahk2" + }, + { + "match": "\\*", + "name": "comment.block.ahk2" + } + ] + }, + "5": { + "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.ahk2" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.conditional.switch.ahk2" + } + }, + "patterns": [ + { + "include": "#conditional_context" + } + ] + }, + "switch_statement": { + "name": "meta.block.switch.ahk2", + "begin": "(((?>(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))((?\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.switch.ahk2", + "begin": "\\G ?", + "end": "(?= minPos && --bufferPosition >= 0) { - if (buffer.length - bufferPosition >= 4 && buffer[bufferPosition] === op.firstByte) { + if ( + buffer.length - bufferPosition >= 4 && + buffer[bufferPosition] === op.firstByte + ) { // quick check first signature byte if (buffer.readUInt32LE(bufferPosition) === op.sig) { op.lastBufferPosition = bufferPosition; @@ -184,7 +192,10 @@ class StreamZip extends events.EventEmitter { } function readCentralDirectory() { - const totalReadLength = Math.min(consts.ENDHDR + consts.MAXFILECOMMENT, fileSize); + const totalReadLength = Math.min( + consts.ENDHDR + consts.MAXFILECOMMENT, + fileSize, + ); op = { win: new FileWindowBuffer(fd), totalReadLength, @@ -195,7 +206,11 @@ class StreamZip extends events.EventEmitter { sig: consts.ENDSIG, complete: readCentralDirectoryComplete, }; - op.win.read(fileSize - op.chunkSize, op.chunkSize, readUntilFoundCallback); + op.win.read( + fileSize - op.chunkSize, + op.chunkSize, + readUntilFoundCallback, + ); } function readCentralDirectoryComplete() { @@ -209,7 +224,9 @@ class StreamZip extends events.EventEmitter { that.comment = buffer .slice( pos + consts.ENDHDR, - pos + consts.ENDHDR + centralDirectory.commentLength + pos + + consts.ENDHDR + + centralDirectory.commentLength, ) .toString(); } else { @@ -219,7 +236,8 @@ class StreamZip extends events.EventEmitter { that.centralDirectory = centralDirectory; if ( (centralDirectory.volumeEntries === consts.EF_ZIP64_OR_16 && - centralDirectory.totalEntries === consts.EF_ZIP64_OR_16) || + centralDirectory.totalEntries === + consts.EF_ZIP64_OR_16) || centralDirectory.size === consts.EF_ZIP64_OR_32 || centralDirectory.offset === consts.EF_ZIP64_OR_32 ) { @@ -249,7 +267,11 @@ class StreamZip extends events.EventEmitter { sig: consts.ENDL64SIG, complete: readZip64CentralDirectoryLocatorComplete, }; - op.win.read(op.lastPos - op.chunkSize, op.chunkSize, readUntilFoundCallback); + op.win.read( + op.lastPos - op.chunkSize, + op.chunkSize, + readUntilFoundCallback, + ); } } @@ -257,7 +279,10 @@ class StreamZip extends events.EventEmitter { const buffer = op.win.buffer; const locHeader = new CentralDirectoryLoc64Header(); locHeader.read( - buffer.slice(op.lastBufferPosition, op.lastBufferPosition + consts.ENDL64HDR) + buffer.slice( + op.lastBufferPosition, + op.lastBufferPosition + consts.ENDL64HDR, + ), ); const readLength = fileSize - locHeader.headerOffset; op = { @@ -270,13 +295,22 @@ class StreamZip extends events.EventEmitter { sig: consts.END64SIG, complete: readZip64CentralDirectoryComplete, }; - op.win.read(fileSize - op.chunkSize, op.chunkSize, readUntilFoundCallback); + op.win.read( + fileSize - op.chunkSize, + op.chunkSize, + readUntilFoundCallback, + ); } function readZip64CentralDirectoryComplete() { const buffer = op.win.buffer; const zip64cd = new CentralDirectoryZip64Header(); - zip64cd.read(buffer.slice(op.lastBufferPosition, op.lastBufferPosition + consts.END64HDR)); + zip64cd.read( + buffer.slice( + op.lastBufferPosition, + op.lastBufferPosition + consts.END64HDR, + ), + ); that.centralDirectory.volumeEntries = zip64cd.volumeEntries; that.centralDirectory.totalEntries = zip64cd.totalEntries; that.centralDirectory.size = zip64cd.size; @@ -293,12 +327,19 @@ class StreamZip extends events.EventEmitter { chunkSize, entriesLeft: centralDirectory.volumeEntries, }; - op.win.read(op.pos, Math.min(chunkSize, fileSize - op.pos), readEntriesCallback); + op.win.read( + op.pos, + Math.min(chunkSize, fileSize - op.pos), + readEntriesCallback, + ); } function readEntriesCallback(err, bytesRead) { if (err || !bytesRead) { - return that.emit('error', err || new Error('Entries read error')); + return that.emit( + 'error', + err || new Error('Entries read error'), + ); } let bufferPos = op.pos - op.win.position; let entry = op.entry; @@ -314,10 +355,17 @@ class StreamZip extends events.EventEmitter { op.pos += consts.CENHDR; bufferPos += consts.CENHDR; } - const entryHeaderSize = entry.fnameLen + entry.extraLen + entry.comLen; - const advanceBytes = entryHeaderSize + (op.entriesLeft > 1 ? consts.CENHDR : 0); + const entryHeaderSize = + entry.fnameLen + entry.extraLen + entry.comLen; + const advanceBytes = + entryHeaderSize + + (op.entriesLeft > 1 ? consts.CENHDR : 0); if (bufferLength - bufferPos < advanceBytes) { - op.win.moveRight(chunkSize, readEntriesCallback, bufferPos); + op.win.moveRight( + chunkSize, + readEntriesCallback, + bufferPos, + ); op.move = true; return; } @@ -370,22 +418,34 @@ class StreamZip extends events.EventEmitter { return callback(err); } const offset = dataOffset(entry); - let entryStream = new EntryDataReaderStream(fd, offset, entry.compressedSize); + let entryStream = new EntryDataReaderStream( + fd, + offset, + entry.compressedSize, + ); if (entry.method === consts.STORED) { // nothing to do } else if (entry.method === consts.DEFLATED) { entryStream = entryStream.pipe(zlib.createInflateRaw()); } else { - return callback(new Error('Unknown compression method: ' + entry.method)); + return callback( + new Error( + 'Unknown compression method: ' + entry.method, + ), + ); } if (canVerifyCrc(entry)) { entryStream = entryStream.pipe( - new EntryVerifyStream(entryStream, entry.crc, entry.size) + new EntryVerifyStream( + entryStream, + entry.crc, + entry.size, + ), ); } callback(null, entryStream); }, - false + false, ); }; @@ -397,21 +457,31 @@ class StreamZip extends events.EventEmitter { err = e; entry = en; }, - true + true, ); if (err) { throw err; } let data = Buffer.alloc(entry.compressedSize); - new BufRead(fd, data, 0, entry.compressedSize, dataOffset(entry), (e) => { - err = e; - }).read(true); + new BufRead( + fd, + data, + 0, + entry.compressedSize, + dataOffset(entry), + (e) => { + err = e; + }, + ).read(true); if (err) { throw err; } if (entry.method === consts.STORED) { // nothing to do - } else if (entry.method === consts.DEFLATED || entry.method === consts.ENHANCED_DEFLATED) { + } else if ( + entry.method === consts.DEFLATED || + entry.method === consts.ENHANCED_DEFLATED + ) { data = zlib.inflateRawSync(data); } else { throw new Error('Unknown compression method: ' + entry.method); @@ -459,7 +529,9 @@ class StreamZip extends events.EventEmitter { }; function dataOffset(entry) { - return entry.offset + consts.LOCHDR + entry.fnameLen + entry.extraLen; + return ( + entry.offset + consts.LOCHDR + entry.fnameLen + entry.extraLen + ); } function canVerifyCrc(entry) { @@ -519,17 +591,32 @@ class StreamZip extends events.EventEmitter { }); } - function extractFiles(baseDir, baseRelPath, files, callback, extractedCount) { + function extractFiles( + baseDir, + baseRelPath, + files, + callback, + extractedCount, + ) { if (!files.length) { return callback(null, extractedCount); } const file = files.shift(); - const targetPath = path.join(baseDir, file.name.replace(baseRelPath, '')); + const targetPath = path.join( + baseDir, + file.name.replace(baseRelPath, ''), + ); extract(file, targetPath, (err) => { if (err) { return callback(err, extractedCount); } - extractFiles(baseDir, baseRelPath, files, callback, extractedCount + 1); + extractFiles( + baseDir, + baseRelPath, + files, + callback, + extractedCount + 1, + ); }); } @@ -540,7 +627,10 @@ class StreamZip extends events.EventEmitter { if (entry) { entryName = entry.name; } else { - if (entryName.length && entryName[entryName.length - 1] !== '/') { + if ( + entryName.length && + entryName[entryName.length - 1] !== '/' + ) { entryName += '/'; } } @@ -556,8 +646,7 @@ class StreamZip extends events.EventEmitter { ) { let relPath = e.replace(entryName, ''); const childEntry = entries[e]; - if (filter && !filter(childEntry)) - continue; + if (filter && !filter(childEntry)) continue; if (childEntry.isFile) { files.push(childEntry); relPath = path.dirname(relPath); @@ -590,7 +679,13 @@ class StreamZip extends events.EventEmitter { if (err) { callback(err); } else { - extractFiles(outPath, entryName, files, callback, 0); + extractFiles( + outPath, + entryName, + files, + callback, + 0, + ); } }); } else { @@ -599,7 +694,11 @@ class StreamZip extends events.EventEmitter { } else { fs.stat(outPath, (err, stat) => { if (stat && stat.isDirectory()) { - extract(entry, path.join(outPath, path.basename(entry.name)), callback); + extract( + entry, + path.join(outPath, path.basename(entry.name)), + callback, + ); } else { extract(entry, outPath, callback); } @@ -630,12 +729,15 @@ class StreamZip extends events.EventEmitter { return originalEmit.call(this, ...args); } }; - }; + } } class CentralDirectoryHeader { read(data) { - if (data.length !== consts.ENDHDR || data.readUInt32LE(0) !== consts.ENDSIG) { + if ( + data.length !== consts.ENDHDR || + data.readUInt32LE(0) !== consts.ENDSIG + ) { throw new Error('Invalid central directory'); } // number of entries on this volume @@ -653,7 +755,10 @@ class CentralDirectoryHeader { class CentralDirectoryLoc64Header { read(data) { - if (data.length !== consts.ENDL64HDR || data.readUInt32LE(0) !== consts.ENDL64SIG) { + if ( + data.length !== consts.ENDL64HDR || + data.readUInt32LE(0) !== consts.ENDL64SIG + ) { throw new Error('Invalid zip64 central directory locator'); } // ZIP64 EOCD header offset @@ -663,7 +768,10 @@ class CentralDirectoryLoc64Header { class CentralDirectoryZip64Header { read(data) { - if (data.length !== consts.END64HDR || data.readUInt32LE(0) !== consts.END64SIG) { + if ( + data.length !== consts.END64HDR || + data.readUInt32LE(0) !== consts.END64SIG + ) { throw new Error('Invalid central directory'); } // number of entries on this volume @@ -680,7 +788,10 @@ class CentralDirectoryZip64Header { class ZipEntry { readHeader(data, offset) { // data should be 46 bytes and start with "PK 01 02" - if (data.length < offset + consts.CENHDR || data.readUInt32LE(offset) !== consts.CENSIG) { + if ( + data.length < offset + consts.CENHDR || + data.readUInt32LE(offset) !== consts.CENSIG + ) { throw new Error('Invalid entry header'); } // version made by @@ -764,7 +875,9 @@ class ZipEntry { this.readExtra(data, offset); offset += this.extraLen; } - this.comment = this.comLen ? data.slice(offset, offset + this.comLen).toString() : null; + this.comment = this.comLen + ? data.slice(offset, offset + this.comLen).toString() + : null; } validateName() { @@ -838,7 +951,7 @@ class BufRead { let bytesRead = this.fd.copy( this.buffer, this.offset + this.bytesRead, - this.position + this.bytesRead + this.position + this.bytesRead, ); this.readCallback(sync, err, !sync || err ? bytesRead : null); } @@ -876,7 +989,14 @@ class FileWindowBuffer { this.buffer = Buffer.alloc(length); } this.position = pos; - this.fsOp = new BufRead(this.fd, this.buffer, 0, length, this.position, callback).read(); + this.fsOp = new BufRead( + this.fd, + this.buffer, + 0, + length, + this.position, + callback, + ).read(); } expandLeft(length, callback) { @@ -886,7 +1006,14 @@ class FileWindowBuffer { if (this.position < 0) { this.position = 0; } - this.fsOp = new BufRead(this.fd, this.buffer, 0, length, this.position, callback).read(); + this.fsOp = new BufRead( + this.fd, + this.buffer, + 0, + length, + this.position, + callback, + ).read(); } expandRight(length, callback) { @@ -899,7 +1026,7 @@ class FileWindowBuffer { offset, length, this.position + offset, - callback + callback, ).read(); } @@ -917,7 +1044,7 @@ class FileWindowBuffer { this.buffer.length - shift, shift, this.position + this.buffer.length - shift, - callback + callback, ).read(); } } @@ -934,7 +1061,11 @@ class EntryDataReaderStream extends stream.Readable { _read(n) { const buffer = Buffer.alloc(Math.min(n, this.length - this.pos)); if (buffer.length) { - this.readCallback(undefined, this.fd.copy(buffer, 0, this.offset + this.pos), buffer); + this.readCallback( + undefined, + this.fd.copy(buffer, 0, this.offset + this.pos), + buffer, + ); } else { this.push(null); } @@ -1016,7 +1147,7 @@ class CrcVerify { const b = Buffer.alloc(4); for (let n = 0; n < 256; n++) { let c = n; - for (let k = 8; --k >= 0;) { + for (let k = 8; --k >= 0; ) { if ((c & 1) !== 0) { c = 0xedb88320 ^ (c >>> 1); } else { @@ -1046,7 +1177,11 @@ function parseZipTime(timebytes, datebytes) { M: parseInt(datebits.slice(7, 11).join(''), 2), D: parseInt(datebits.slice(11, 16).join(''), 2), }; - const dt_str = [mt.Y, mt.M, mt.D].join('-') + ' ' + [mt.h, mt.m, mt.s].join(':') + ' GMT+0'; + const dt_str = + [mt.Y, mt.M, mt.D].join('-') + + ' ' + + [mt.h, mt.m, mt.s].join(':') + + ' GMT+0'; return new Date(dt_str).getTime(); } @@ -1059,25 +1194,33 @@ function toBits(dec, size) { } function readUInt64LE(buffer, offset) { - return buffer.readUInt32LE(offset + 4) * 0x0000000100000000 + buffer.readUInt32LE(offset); + return ( + buffer.readUInt32LE(offset + 4) * 0x0000000100000000 + + buffer.readUInt32LE(offset) + ); } - const https = require('https'); function https_request(url, data, headers) { return new Promise((resolve, reject) => { - let req = https.request(url, { method: data ? 'POST' : 'GET', headers }, + let req = https.request( + url, + { method: data ? 'POST' : 'GET', headers }, (msg) => { let body = Buffer.alloc(0); let isgzip = msg.headers['content-encoding'] === 'gzip'; - msg.on('data', (chunk) => body = Buffer.concat([body, chunk])); + msg.on( + 'data', + (chunk) => (body = Buffer.concat([body, chunk])), + ); msg.on('end', () => { if (isgzip) - zlib.gunzip(body, (err, buf) => resolve(err ? body : buf)); - else - resolve(body) + zlib.gunzip(body, (err, buf) => + resolve(err ? body : buf), + ); + else resolve(body); }); - } + }, ); data && req.write(data); req.end(); @@ -1092,61 +1235,91 @@ function get_latest_ahk2lsp() { '{"assetTypes":null,"filters":[{"criteria":[{"filterType":7,"value":"thqby.vscode-autohotkey2-lsp"}],"direction":2,"pageSize":100,"pageNumber":1,"sortBy":0,"sortOrder":0,"pagingToken":null}],"flags":2151}', { 'content-type': 'application/json', - 'accept': 'application/json;api-version=7.1-preview.1;excludeUrls=true', - } - ).catch(err => console.error(err)).then(info => { - let ext = JSON.parse(info).results[0].extensions[0].versions[0]; - let version = ext.version; - fs.readFile('./package.json', (err, buf) => { - let update = !buf; - if (buf) { - try { - let curver = JSON.parse(buf).version.split('.'), ver = version.split('.'); - for (let n in curver) { - if (parseInt(curver[n]) < parseInt(ver[n])) { - update = true; - break; + accept: 'application/json;api-version=7.1-preview.1;excludeUrls=true', + }, + ) + .catch((err) => console.error(err)) + .then((info) => { + let ext = JSON.parse(info).results[0].extensions[0].versions[0]; + let version = ext.version; + fs.readFile('./package.json', (err, buf) => { + let update = !buf; + if (buf) { + try { + let curver = JSON.parse(buf).version.split('.'), + ver = version.split('.'); + for (let n in curver) { + if (parseInt(curver[n]) < parseInt(ver[n])) { + update = true; + break; + } } + } catch (e) { + update = true; } - } catch (e) { update = true; } - } - if (update) - download_ahk2lsp(); - else - console.log(`thqby.vscode-autohotkey2-lsp v${version} is the latest version.`); - - function download_ahk2lsp(url) { - https_request(url ?? `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/thqby/vsextensions/vscode-autohotkey2-lsp/${version}/vspackage`) - .then(buffer => { - if (buffer[0] === 123) { - if (!url) { - for (let f of ext.files) - if (f.assetType.endsWith('.VSIXPackage')) - return download_ahk2lsp(f.source); + } + if (update) download_ahk2lsp(); + else + console.log( + `thqby.vscode-autohotkey2-lsp v${version} is the latest version.`, + ); + + function download_ahk2lsp(url) { + https_request( + url ?? + `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/thqby/vsextensions/vscode-autohotkey2-lsp/${version}/vspackage`, + ) + .then((buffer) => { + if (buffer[0] === 123) { + if (!url) { + for (let f of ext.files) + if ( + f.assetType.endsWith('.VSIXPackage') + ) + return download_ahk2lsp(f.source); + } + return console.error(buffer.toString()); } - return console.error(buffer.toString()); - } - let zip = new StreamZip({ buffer }); - let extract_count = 0, has_extract_count = 0; - zip.on('ready', () => zip.extract('extension/', './', err => err && console.error(err), (entry) => { - let name = entry.name.toLowerCase(); - if (name.includes('/client/') || name.includes('/browser')) - return false; - if (name.endsWith('/ahk2.configuration.json') || name.endsWith('.png') || name.endsWith('.tmlanguage.json')) - return false; - extract_count++; - return true; - })); - zip.on('error', err => console.error(err)); - zip.on('extract', (entry, outPath) => { - if (++has_extract_count === extract_count) - console.log(`thqby.vscode-autohotkey2-lsp v${version} has been installed.`); - }); - }) - .catch(err => console.error(err)); - } + let zip = new StreamZip({ buffer }); + let extract_count = 0, + has_extract_count = 0; + zip.on('ready', () => + zip.extract( + 'extension/', + './', + (err) => err && console.error(err), + (entry) => { + let name = entry.name.toLowerCase(); + if ( + name.includes('/client/') || + name.includes('/browser') + ) + return false; + if ( + name.endsWith( + '/ahk2.configuration.json', + ) || + name.endsWith('.png') || + name.endsWith('.tmlanguage.json') + ) + return false; + extract_count++; + return true; + }, + ), + ); + zip.on('error', (err) => console.error(err)); + zip.on('extract', (entry, outPath) => { + if (++has_extract_count === extract_count) + console.log( + `thqby.vscode-autohotkey2-lsp v${version} has been installed.`, + ); + }); + }) + .catch((err) => console.error(err)); + } + }); }); - }); } -get_latest_ahk2lsp() \ No newline at end of file +get_latest_ahk2lsp(); diff --git a/tsconfig.json b/tsconfig.json index 737f49b4..f1057913 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,17 +6,9 @@ "outDir": "out", "rootDir": "src", "sourceMap": true, - "composite": true, + "composite": true }, - "include": [ - "src" - ], - "exclude": [ - "node_modules", - ".vscode-test" - ], - "references": [ - { "path": "./client" }, - { "path": "./server" } - ] -} \ No newline at end of file + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"], + "references": [{ "path": "./client" }, { "path": "./server" }] +} diff --git a/webpack.config.cli.js b/webpack.config.cli.js index 301dd0de..5b13444a 100644 --- a/webpack.config.cli.js +++ b/webpack.config.cli.js @@ -17,7 +17,7 @@ const nodeCLIConfig = /** @type WebpackConfig */ { mode: 'none', target: 'node', entry: { - cli: './cli/cli.ts' + cli: './cli/cli.ts', }, output: { filename: '[name].js', @@ -27,7 +27,7 @@ const nodeCLIConfig = /** @type WebpackConfig */ { resolve: { mainFields: ['module', 'main'], extensions: ['.ts', '.js'], // support ts-files and js-files - alias: {} + alias: {}, }, module: { rules: [ @@ -50,4 +50,4 @@ const nodeCLIConfig = /** @type WebpackConfig */ { }, devtool: 'source-map', }; -module.exports = [nodeCLIConfig]; \ No newline at end of file +module.exports = [nodeCLIConfig]; diff --git a/webpack.config.js b/webpack.config.js index 550cc62a..b16ec9db 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -26,7 +26,7 @@ const nodeClientConfig = /** @type WebpackConfig */ { resolve: { mainFields: ['module', 'main'], extensions: ['.ts', '.js'], // support ts-files and js-files - alias: {} + alias: {}, }, module: { rules: [ @@ -47,6 +47,7 @@ const nodeClientConfig = /** @type WebpackConfig */ { performance: { hints: false, }, + // todo minify production build devtool: 'source-map', }; @@ -55,7 +56,7 @@ const nodeServerConfig = /** @type WebpackConfig */ { mode: 'none', target: 'node', entry: { - server: './src/server.ts' + server: './src/server.ts', }, output: { filename: '[name].js', @@ -65,7 +66,7 @@ const nodeServerConfig = /** @type WebpackConfig */ { resolve: { mainFields: ['module', 'main'], extensions: ['.ts', '.js'], // support ts-files and js-files - alias: {} + alias: {}, }, module: { rules: [ @@ -136,7 +137,7 @@ const browserServerConfig = /** @type WebpackConfig */ { mode: 'none', target: 'webworker', // web extensions run in a webworker context entry: { - browserServerMain: './src/browserServerMain.ts' + browserServerMain: './src/browserServerMain.ts', }, output: { filename: '[name].js', @@ -151,8 +152,8 @@ const browserServerConfig = /** @type WebpackConfig */ { fallback: { fs: false, child_process: false, - path: require.resolve("path-browserify"), - process: false + path: require.resolve('path-browserify'), + process: false, }, }, module: { @@ -174,7 +175,12 @@ const browserServerConfig = /** @type WebpackConfig */ { performance: { hints: false, }, - devtool: 'source-map' + devtool: 'source-map', }; -module.exports = [nodeClientConfig, nodeServerConfig, browserClientConfig, browserServerConfig]; \ No newline at end of file +module.exports = [ + nodeClientConfig, + nodeServerConfig, + browserClientConfig, + browserServerConfig, +]; From f7548c03dbfc5f697a71c66a48846c2198c322f7 Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Wed, 21 Aug 2024 23:41:48 -0700 Subject: [PATCH 12/60] Document todo removal of ahk2.help --- client/src/extension.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/extension.ts b/client/src/extension.ts index 066bdf7f..54588d98 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -196,6 +196,7 @@ export async function activate(context: ExtensionContext) { context.subscriptions.push( ahkStatusBarItem, ahkLanguageStatusItem, outputchannel, extensions.onDidChange(update_extensions_info), + // todo remove this, AHK++ already has it commands.registerTextEditorCommand('ahk2.help', quickHelp), commands.registerTextEditorCommand('ahk2.compile', compileScript), commands.registerTextEditorCommand('ahk2.run', textEditor => runScript(textEditor)), From d665c1c9ddd50f3b7390c8632c5fec553fa762d6 Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Thu, 22 Aug 2024 18:25:47 -0700 Subject: [PATCH 13/60] Simplify repo validation - Remove unused external tests - Remove packaging --- client/src/{test => }/extension.test.ts | 2 +- client/src/test/formattingProvider.test.ts | 90 ---------------------- client/src/test/samples/0-format.in.ahk2 | 4 - client/src/test/samples/0-format.out.ahk2 | 4 - package.json | 2 +- 5 files changed, 2 insertions(+), 100 deletions(-) rename client/src/{test => }/extension.test.ts (93%) delete mode 100644 client/src/test/formattingProvider.test.ts delete mode 100644 client/src/test/samples/0-format.in.ahk2 delete mode 100644 client/src/test/samples/0-format.out.ahk2 diff --git a/client/src/test/extension.test.ts b/client/src/extension.test.ts similarity index 93% rename from client/src/test/extension.test.ts rename to client/src/extension.test.ts index d32135e6..bb4390b6 100644 --- a/client/src/test/extension.test.ts +++ b/client/src/extension.test.ts @@ -1,7 +1,7 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; import * as fs from 'fs'; -import { resolvePath } from '../extension'; +import { resolvePath } from './extension'; suite('resolvePath', () => { let lstatSyncStub: sinon.SinonStub; diff --git a/client/src/test/formattingProvider.test.ts b/client/src/test/formattingProvider.test.ts deleted file mode 100644 index 69694f44..00000000 --- a/client/src/test/formattingProvider.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { getDocument, sleep } from '../test/utils'; -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as vscode from 'vscode'; - -const inFilenameSuffix = '.in.ahk2'; -const outFilenameSuffix = '.out.ahk2'; -interface FormatTest { - /** Name of the file, excluding the suffix (@see inFilenameSuffix, @see outFilenameSuffix) */ - filenameRoot: string; -} - -// Currently in `out` folder, need to get back to main `src` folder -// * this path changes if you import from the server folder -const filesParentPath = path.join( - __dirname, // client/dist/test - '..', // client/dist - '..', // client - 'src', // client/src - 'test', // client/src/test - 'samples', // client/src/test/samples -); - -suite('External formatter', () => { - const externalFormatTests: FormatTest[] = [{ filenameRoot: '0-format' }]; - - externalFormatTests.forEach((formatTest) => { - test(`${formatTest.filenameRoot} external format`, async () => { - // Arrange - const inFilename = formatTest.filenameRoot + inFilenameSuffix; - const outFilename = formatTest.filenameRoot + outFilenameSuffix; - const outFileString = fs - .readFileSync(path.join(filesParentPath, outFilename)) - .toString(); - const unformattedSampleFile = await getDocument( - path.join(filesParentPath, inFilename), - ); - const originalText = unformattedSampleFile.getText(); - const textEditor = await vscode.window.showTextDocument( - unformattedSampleFile, - ); - let eventFired = false; - const formattingPromise = new Promise((resolve) => { - const disposable = vscode.workspace.onDidChangeTextDocument( - (event) => { - if (event.document === textEditor.document) { - eventFired = true; - disposable.dispose(); - resolve(); - } - }, - ); - }); - - // Act - while (!eventFired) { - await vscode.commands.executeCommand( - 'editor.action.formatDocument', - ); - await sleep(50); - } - await formattingPromise; - - // Assert - assert.strictEqual(textEditor.document.getText(), outFileString); - - // Teardown - revert the file to its original state - const lastLineIndex = unformattedSampleFile.lineCount - 1; - const lastLineLength = - unformattedSampleFile.lineAt(lastLineIndex).text.length; - const fullDocumentRange = unformattedSampleFile.validateRange( - new vscode.Range( - new vscode.Position(0, 0), - new vscode.Position(lastLineIndex + 1, lastLineLength + 1), // + 1 to ensure full coverage - ), - ); - - // editing the file also saves the file - await textEditor.edit((editBuilder) => - editBuilder.replace(fullDocumentRange, originalText), - ); - - // Close opened file - await vscode.commands.executeCommand( - 'workbench.action.closeActiveEditor', - ); - }); - }); -}); diff --git a/client/src/test/samples/0-format.in.ahk2 b/client/src/test/samples/0-format.in.ahk2 deleted file mode 100644 index 7daa338b..00000000 --- a/client/src/test/samples/0-format.in.ahk2 +++ /dev/null @@ -1,4 +0,0 @@ -#Requires AutoHotkey v2 - -; This is a comment - MsgBox("Hello, world!") \ No newline at end of file diff --git a/client/src/test/samples/0-format.out.ahk2 b/client/src/test/samples/0-format.out.ahk2 deleted file mode 100644 index ea097373..00000000 --- a/client/src/test/samples/0-format.out.ahk2 +++ /dev/null @@ -1,4 +0,0 @@ -#Requires AutoHotkey v2 - -; This is a comment -MsgBox("Hello, world!") \ No newline at end of file diff --git a/package.json b/package.json index 2fc01d91..6d8aa163 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "test": "cd client && vscode-test", "test-grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", "test//": "Run tests", - "validate": "npm run clean && npm run vscode:prepublish && npm run test-grammar && npm run test && npm run package", + "validate": "npm run clean && npm run test-grammar && npm run test", "vscode:prepublish": "npm run build", "watch": "tsc -b -w", "watch-web": "webpack --watch" From 41b1309a3ff3f5186ff730f18e6a77fa7a10ff09 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 27 Aug 2024 18:00:51 -0700 Subject: [PATCH 14/60] Changes for AHK++ 5.1.1 (#12) --- .vscode/launch.json | 7 +++++-- .vscode/tasks.json | 19 ------------------- package.json | 4 ++-- server/src/common.ts | 6 ++++-- 4 files changed, 11 insertions(+), 25 deletions(-) delete mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json index 299a2681..528abe84 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,7 +12,7 @@ "--extensionDevelopmentKind=web" ], "outFiles": ["${workspaceFolder}/client/dist/**/*.js"], - "preLaunchTask": "npm: watch-web" + "preLaunchTask": "npm: build:watch" }, { "type": "extensionHost", @@ -20,7 +20,10 @@ "name": "Launch Client", "runtimeExecutable": "${execPath}", "args": ["--extensionDevelopmentPath=${workspaceRoot}"], - "env": { "VSCODE_AHK_SERVER_PATH": "server/dist/server.js" }, + "env": { + "VSCODE_AHK_SERVER_PATH": "server/dist/server.js", + "SYNTAXES_PATH": "syntaxes" + }, "outFiles": ["${workspaceRoot}/client/dist/**/*.js"], "preLaunchTask": "npm: build:dev" }, diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 9c72b15c..00000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "watch-web", - "group": "build", - "isBackground": true, - "problemMatcher": ["$ts-webpack-watch"] - }, - { - "type": "npm", - "script": "watch", - "group": "build", - "isBackground": true, - "problemMatcher": ["$tsc-watch"] - } - ] -} diff --git a/package.json b/package.json index 6d8aa163..36c1ed85 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "build": "webpack --mode production --devtool hidden-source-map", "prebuild:dev": "npm run clean", "build:dev": "webpack", + "build:watch": "webpack --watch", "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", "clean": "del-cli client/dist server/dist/*.js*", "clean//": "Remove both the compiled extension and compiled test files", @@ -58,8 +59,7 @@ "test//": "Run tests", "validate": "npm run clean && npm run test-grammar && npm run test", "vscode:prepublish": "npm run build", - "watch": "tsc -b -w", - "watch-web": "webpack --watch" + "watch": "tsc -b -w" }, "contributes": { "breakpoints": [ diff --git a/server/src/common.ts b/server/src/common.ts index 7e735626..b4933cc3 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -251,10 +251,12 @@ export function initahk2cache() { }; } +/** Loads IntelliSense hover text */ +// (proven by skipping this func and seeing the results) export function loadahk2(filename = 'ahk2', d = 3) { let path: string | undefined; - // todo get this working with AHK++ - const file = `${rootdir}/syntaxes/<>/${filename}`; + const syntaxesPath = process.env.SYNTAXES_PATH || 'syntaxes'; + const file = `${rootdir}/${syntaxesPath}/<>/${filename}`; if (isBrowser) { const td = openFile(file + '.d.ahk'); if (td) { From 289244990f1a6c836417936dd7cf140c68089847 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 27 Aug 2024 18:57:27 -0700 Subject: [PATCH 15/60] Build with ESBuild (#13) --- build.mjs | 30 +++ package-lock.json | 559 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 26 +-- 3 files changed, 594 insertions(+), 21 deletions(-) create mode 100644 build.mjs diff --git a/build.mjs b/build.mjs new file mode 100644 index 00000000..cfc8d003 --- /dev/null +++ b/build.mjs @@ -0,0 +1,30 @@ +import { build } from 'esbuild'; +import path from 'path'; + +const isProd = process.argv.indexOf('--mode=production') >= 0; + +// Node server +// https://esbuild.github.io/api +build({ + entryPoints: [path.join('./server/src/server.ts')], + bundle: true, + outfile: path.join('./server/dist/server.js'), + external: ['vscode'], + format: 'cjs', + platform: 'node', + minify: isProd, + sourcemap: !isProd, +}); + +// Node client (not necessary for AHK++, but super fast) +// https://esbuild.github.io/api +build({ + entryPoints: [path.join('./client/src/extension.ts')], + bundle: true, + outfile: path.join('./client/dist/extension.js'), + external: ['vscode'], + format: 'cjs', + platform: 'node', + minify: isProd, + sourcemap: !isProd, +}); diff --git a/package-lock.json b/package-lock.json index d23e5b7d..79129b02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,8 +22,9 @@ "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", - "@vscode/vsce": "^2.27.0", + "@vscode/vsce": "^3.0.0", "del-cli": "^5.1.0", + "esbuild": "^0.23.1", "eslint": "^9.4.0", "globals": "^15.4.0", "mocha": "^10.7.0", @@ -322,6 +323,414 @@ "node": ">=10.0.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1159,9 +1568,9 @@ } }, "node_modules/@vscode/vsce": { - "version": "2.27.0", - "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-2.27.0.tgz", - "integrity": "sha512-FFUMBVSyyjjJpWszwqk7d4U3YllY8FdWslbUDMRki1x4ZjA3Z0hmRMfypWrjP9sptbSR9nyPFU4uqjhy2qRB/w==", + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-3.0.0.tgz", + "integrity": "sha512-UKYcC7fcSw6AUK6nlfm8A8WSOA41H3DRAwafCMp9CQpg3K9COAQKkrgQ+dKPhwkFTP7SPZNEiulDpPLwvr5QQQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1173,7 +1582,7 @@ "cockatiel": "^3.1.2", "commander": "^6.2.1", "form-data": "^4.0.0", - "glob": "^7.0.6", + "glob": "^11.0.0", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", "leven": "^3.1.0", @@ -1183,7 +1592,7 @@ "parse-semver": "^1.1.1", "read": "^1.0.7", "semver": "^7.5.2", - "tmp": "^0.2.1", + "tmp": "^0.2.3", "typed-rest-client": "^1.8.4", "url-join": "^4.0.1", "xml2js": "^0.5.0", @@ -1194,7 +1603,7 @@ "vsce": "vsce" }, "engines": { - "node": ">= 16" + "node": ">= 20" }, "optionalDependencies": { "keytar": "^7.7.0" @@ -1345,6 +1754,102 @@ "win32" ] }, + "node_modules/@vscode/vsce/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vscode/vsce/node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/@vscode/vsce/node_modules/lru-cache": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.0.0.tgz", + "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@vscode/vsce/node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -3224,6 +3729,46 @@ "dev": true, "license": "MIT" }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.2.tgz", diff --git a/package.json b/package.json index 36c1ed85..f7b44d79 100644 --- a/package.json +++ b/package.json @@ -28,17 +28,14 @@ "author": "thqby and Mark Wiemer", "publisher": "mark-wiemer", "main": "./client/dist/extension", - "browser": "./client/dist/browserClientMain", "scripts": { - "prebuild": "npm run clean", - "build": "webpack --mode production --devtool hidden-source-map", + "build": "node build.mjs --mode=production", "prebuild:dev": "npm run clean", - "build:dev": "webpack", - "build:watch": "webpack --watch", + "build:dev": "node build.mjs", + "build:old": "webpack", "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", "clean": "del-cli client/dist server/dist/*.js*", "clean//": "Remove both the compiled extension and compiled test files", - "compile": "webpack", "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", "compile-test": "cd client && tsc", "compile-test//": "Compile test files", @@ -48,17 +45,17 @@ "eslint:fix": "npm run eslint:files -- client server --fix", "format": "prettier --check .", "format:fix": "prettier --write .", + "lint": "npm run eslint && npm run sort-package-json", "package": "vsce package", - "patch": "npm version patch", - "publish": "vsce publish", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", - "pretest": "npm run compile-test", - "test": "cd client && vscode-test", + "test": "npm run test-grammar && npm run test-unit", "test-grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", - "test//": "Run tests", - "validate": "npm run clean && npm run test-grammar && npm run test", - "vscode:prepublish": "npm run build", + "pretest-unit": "npm run compile-test", + "test-unit": "cd client && vscode-test", + "test//": "Run unit tests, not grammar tests", + "validate": "npm run lint && npm run test && npm run package", + "vscode:prepublish": "npm run build:old", "watch": "tsc -b -w" }, "contributes": { @@ -637,8 +634,9 @@ "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", - "@vscode/vsce": "^2.27.0", + "@vscode/vsce": "^3.0.0", "del-cli": "^5.1.0", + "esbuild": "^0.23.1", "eslint": "^9.4.0", "globals": "^15.4.0", "mocha": "^10.7.0", From fd70f0e5736876ddbe7e877b0d8d895360fb76a2 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 27 Aug 2024 19:13:12 -0700 Subject: [PATCH 16/60] Remove funding (I'm not thqby!) (#14) --- .github/FUNDING.yml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 508324cc..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,5 +0,0 @@ -# These are supported funding model platforms - -github: thqby -custom: - - https://www.paypal.me/thqby From 5b158274026d32b01b59c1f7ab1edbfa141af2fa Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 27 Aug 2024 19:20:49 -0700 Subject: [PATCH 17/60] Format the test files (#15) --- .prettierignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.prettierignore b/.prettierignore index c33eba81..2e589f88 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,8 +10,6 @@ server/expr_parser/* client/src/browserClientMain.ts client/src/extension.ts -client/src/test/extension.test.ts -client/src/test/formattingProvider.test.ts client/src/test/utils.ts server/src/ahkProvider.ts server/src/browserServerMain.ts From 85bebd393e9871e70aedf354a0a1765711012486 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 27 Aug 2024 19:50:51 -0700 Subject: [PATCH 18/60] Add build workflow (#16) --- .github/workflows/node.js.yml | 32 ++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/node.js.yml diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 00000000..05750265 --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,32 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Build + +on: + push: + branches: ['main'] + pull_request: + branches: ['main'] + workflow_dispatch: + merge_group: + +jobs: + build: + strategy: + matrix: + # AHK is built for Windows only, so we only build on Windows + # As always, if community asks, community shall receive ;) + os: [windows-latest] + node-version: [20.x] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + - run: npm install + - run: npm run validate diff --git a/package.json b/package.json index f7b44d79..3697bacc 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "eslint:fix": "npm run eslint:files -- client server --fix", "format": "prettier --check .", "format:fix": "prettier --write .", - "lint": "npm run eslint && npm run sort-package-json", + "lint": "npm run format && npm run eslint && npm run sort-package-json", "package": "vsce package", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", From 0ac4eb3fc932a60e53cf9cd429e4546c7ee22dce Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 27 Aug 2024 20:14:36 -0700 Subject: [PATCH 19/60] Remove format from validation (#17) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3697bacc..f7b44d79 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "eslint:fix": "npm run eslint:files -- client server --fix", "format": "prettier --check .", "format:fix": "prettier --write .", - "lint": "npm run format && npm run eslint && npm run sort-package-json", + "lint": "npm run eslint && npm run sort-package-json", "package": "vsce package", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", From 4f5fd5a4403f8dfe8c919f194f3ca1608318e39e Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 27 Aug 2024 20:47:07 -0700 Subject: [PATCH 20/60] Remove dupe commands (#18) * Remoe ahk2.debug * Remove debug language * Remove ahk2.compile * Remove ahk2.debug --- client/src/extension.ts | 58 ----------------------------------------- package.json | 38 --------------------------- package.nls.json | 2 -- package.nls.zh-cn.json | 2 -- 4 files changed, 100 deletions(-) diff --git a/client/src/extension.ts b/client/src/extension.ts index 54588d98..ce871681 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -198,12 +198,10 @@ export async function activate(context: ExtensionContext) { extensions.onDidChange(update_extensions_info), // todo remove this, AHK++ already has it commands.registerTextEditorCommand('ahk2.help', quickHelp), - commands.registerTextEditorCommand('ahk2.compile', compileScript), commands.registerTextEditorCommand('ahk2.run', textEditor => runScript(textEditor)), commands.registerTextEditorCommand('ahk2.selection.run', textEditor => runScript(textEditor, true)), commands.registerCommand('ahk2.stop', stopRunningScript), commands.registerCommand('ahk2.setinterpreter', setInterpreter), - commands.registerCommand('ahk2.debug', () => beginDebug(extlist, debugexts)), commands.registerCommand('ahk2.debug.params', () => beginDebug(extlist, debugexts, true)), commands.registerCommand('ahk2.debug.attach', () => beginDebug(extlist, debugexts, false, true)), commands.registerCommand('ahk2.selectsyntaxes', selectSyntaxes), @@ -372,62 +370,6 @@ async function stopRunningScript() { } } -async function compileScript(textEditor: TextEditor) { - let cmd = '', cmdop = workspace.getConfiguration('AutoHotkey2').CompilerCMD as string; - const ws = workspace.getWorkspaceFolder(textEditor.document.uri)?.uri.fsPath ?? ''; - const compilePath = findfile(['Compiler\\Ahk2Exe.exe', '..\\Compiler\\Ahk2Exe.exe'], ws); - const executePath = resolvePath(ahkpath_cur, ws); - if (!compilePath) { - window.showErrorMessage(zhcn ? `"Ahk2Exe.exe"未找到!` : `"Ahk2Exe.exe" was not found!`); - return; - } - if (!executePath) { - const s = ahkpath_cur || 'AutoHotkey.exe'; - window.showErrorMessage(zhcn ? `"${s}"未找到!` : `"${s}" was not found!`); - return; - } - if (textEditor.document.isUntitled || !textEditor.document.uri.toString().startsWith('file:///')) { - window.showErrorMessage(zhcn ? '编译前请先保存脚本' : 'Please save the script before compiling'); - return; - } - commands.executeCommand('workbench.action.files.save'); - const currentPath = textEditor.document.uri.fsPath; - const exePath = currentPath.replace(/\.\w+$/, '.exe'); - try { - if (existsSync(exePath)) - unlinkSync(exePath); - } catch (e) { - window.showErrorMessage((e as Error).message); - return; - } - cmdop = cmdop.replace(/(['"]?)\$\{execPath\}\1/gi, `"${executePath}"`); - if (cmdop.match(/\bahk2exe\w*\.exe/i)) { - cmd = cmdop + ' /in ' + currentPath; - if (!cmd.toLowerCase().includes(' /out ')) - cmd += '/out "' + exePath + '"'; - } else { - cmd = `"${compilePath}" ${cmdop} /in "${currentPath}" `; - if (!cmdop.toLowerCase().includes(' /out ')) - cmd += '/out "' + exePath + '"'; - } - const process = exec(cmd, { cwd: resolve(currentPath, '..') }); - if (process.pid) { - if ((cmd += ' ').toLowerCase().includes(' /gui ')) - return; - outputchannel.show(true); - outputchannel.clear(); - process.on('exit', () => { - if (existsSync(exePath)) - window.showInformationMessage(zhcn ? '编译成功!' : 'Compiled successfully!'); - else - window.showErrorMessage(zhcn ? '编译失败!' : 'Compiled failed!'); - }); - process.stderr?.on('data', (error) => outputchannel.appendLine(error)); - process.stdout?.on('data', (msg) => outputchannel.appendLine(msg)); - } else - window.showErrorMessage(zhcn ? '编译失败!' : 'Compilation failed!'); -} - async function quickHelp(textEditor: TextEditor) { const document = textEditor.document, position = textEditor.selection.active; const range = document.getWordRangeAtPosition(position), line = position.line; diff --git a/package.json b/package.json index f7b44d79..faecad1d 100644 --- a/package.json +++ b/package.json @@ -65,13 +65,6 @@ } ], "commands": [ - { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk2.debug", - "title": "%ahk2.debug%", - "icon": "$(debug)", - "category": "ahk2" - }, { "enablement": "!isWeb", "command": "ahk2.debug.attach", @@ -116,12 +109,6 @@ "icon": "$(stop)", "category": "ahk2" }, - { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk2.compile", - "title": "%ahk2.compile%", - "category": "ahk2" - }, { "enablement": "editorLangId == ahk2 && !isWeb", "command": "ahk2.help", @@ -466,16 +453,6 @@ "key": "ctrl+f5", "when": "editorLangId == ahk2 && !isWeb && editorHasSelection" }, - { - "command": "ahk2.compile", - "key": "ctrl+shift+f5", - "when": "editorLangId == ahk2 && !isWeb" - }, - { - "command": "ahk2.debug", - "key": "f5", - "when": "editorLangId == ahk2 && !isWeb && !inDebugMode" - }, { "command": "ahk2.debug.params", "key": "shift+f5", @@ -523,11 +500,6 @@ ], "menus": { "editor/context": [ - { - "when": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.debug", - "group": "navigation@1" - }, { "when": "editorLangId == ahk2 && !isWeb", "command": "ahk2.debug.attach", @@ -548,11 +520,6 @@ "command": "ahk2.run", "group": "navigation@0" }, - { - "when": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.compile", - "group": "navigation@2" - }, { "when": "editorLangId == ahk2 && !isWeb", "command": "ahk2.help", @@ -584,11 +551,6 @@ "command": "ahk2.stop", "group": "navigation@0", "when": "resourceLangId == ahk2 && ahk2:isRunning && shellExecutionSupported" - }, - { - "command": "ahk2.debug", - "group": "navigation@1", - "when": "resourceLangId == ahk2 && shellExecutionSupported" } ] }, diff --git a/package.nls.json b/package.nls.json index f5c70294..3bed38b5 100644 --- a/package.nls.json +++ b/package.nls.json @@ -2,13 +2,11 @@ "ahk2.actionwhenv1isdetected": "Action when v1 script is detected", "ahk2.autolibinclude": "Provide completion and automatic include from User and Standard library, Local library", "ahk2.commenttags": "A regular expression used to extract named tags from comments and generate module symbols", - "ahk2.compile": "Compile Script", "ahk2.compilercmd": "Compiler command line options. If ahk2exe.exe is not specified, the default path will be used. `${execPath}` is equal to the currently selected AutoHotkey.exe", "ahk2.completefunctionparens": "Parentheses are added to function completion when there is no `(` or `[` on the right; otherwise move the cursor to the right", "ahk2.completioncommitcharacters": "Characters which commit auto completion, such as `.(`", "ahk2.debug.attach": "Attach Running Script", "ahk2.debug.params": "Debug Script with Params", - "ahk2.debug": "Debug Script", "ahk2.debugconfiguration": "Append debugging configuration to the currently started debugger, same as launch.json configuration", "ahk2.description": "Autohotkey2 Language Support using vscode-lsp", "ahk2.diagnostic.full": "Diagnostic full text", diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index 572acbae..515b7785 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -5,13 +5,11 @@ "ahk2.actionwhenv1isdetected": "检测到v1脚本时的行为", "ahk2.autolibinclude": "对用户库和标准库, 本地库提供补全和自动include", "ahk2.commenttags": "用来从注释中提取命名标记的正则表达式, 并生成模块符号", - "ahk2.compile": "编译脚本", "ahk2.compilercmd": "编译器命令行选项. 如果未指定ahk2exe.exe, 将使用默认路径. `${execPath}`等价于当前选择的AutoHotkey.exe", "ahk2.completefunctionparens": "当右侧不存在`(`或`[`时, 给函数补全添加括号; 否则向右移动光标", "ahk2.completioncommitcharacters": "提交自动完成的字符, 例如`.(`", "ahk2.debug.attach": "附加到运行中的脚本", "ahk2.debug.params": "带参调试", - "ahk2.debug": "调试脚本", "ahk2.debugconfiguration": "追加调试配置到当前启动的调试器, 与launch.json配置相同", "ahk2.description": "基于 vscode-lsp 协议的 Autohotkey2 语言支持", "ahk2.diagnostic.full": "诊断全文", From 877696c69845df50381f3b2872bc68f923dda984 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 27 Aug 2024 20:59:59 -0700 Subject: [PATCH 21/60] Fix lint (#19) --- client/src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/extension.ts b/client/src/extension.ts index ce871681..da28587c 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -31,7 +31,7 @@ import { TransportKind } from 'vscode-languageclient/node'; import { resolve } from 'path'; -import { ChildProcess, exec, execSync, spawn } from 'child_process'; +import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; From 7a3e11a2bc2d45769128f6d147063c91a850f5b5 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Fri, 30 Aug 2024 20:12:16 -0700 Subject: [PATCH 22/60] update commands to match AHK++ style (#20) --- client/src/browserClientMain.ts | 4 +- client/src/extension.ts | 113 +++---------------------- package.json | 120 ++++++++++++--------------- package.nls.json | 23 +++-- package.nls.zh-cn.json | 23 +++-- server/src/commandProvider.ts | 7 +- server/src/server.ts | 2 +- syntaxes/ahk2-output.tmLanguage.json | 2 +- 8 files changed, 94 insertions(+), 200 deletions(-) diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts index 80103f11..72575960 100644 --- a/client/src/browserClientMain.ts +++ b/client/src/browserClientMain.ts @@ -65,7 +65,7 @@ export function activate(context: ExtensionContext) { }, new Worker(serverMain.toString())); context.subscriptions.push( - commands.registerTextEditorCommand('ahk2.updateversioninfo', async textEditor => { + commands.registerTextEditorCommand('ahk++.updateVersionInfo', async textEditor => { const info: { content: string, uri: string, range: Range } | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); if (!info) { await textEditor.insertSnippet(new SnippetString([ @@ -92,7 +92,7 @@ export function activate(context: ExtensionContext) { } } }), - commands.registerTextEditorCommand('ahk2.switch', textEditor => { + commands.registerTextEditorCommand('ahk++.switchAhkVersion', textEditor => { const doc = textEditor.document; languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); }), diff --git a/client/src/extension.ts b/client/src/extension.ts index da28587c..90bf08cc 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -189,23 +189,21 @@ export async function activate(context: ExtensionContext) { commands.executeCommand('setContext', 'ahk2:isRunning', false); ahkStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 75); - ahkStatusBarItem.command = 'ahk2.setinterpreter'; + ahkStatusBarItem.command = 'ahk++.setV2Interpreter'; const ahkLanguageStatusItem = languages.createLanguageStatusItem('AutoHotkey2', { language: 'ahk2' }); ahkLanguageStatusItem.text = '$(folder)syntaxes'; - ahkLanguageStatusItem.command = { title: 'Select Syntaxes', command: 'ahk2.selectsyntaxes' }; + ahkLanguageStatusItem.command = { title: 'Select AHK Syntaxes', command: 'ahk++.selectSyntaxes' }; context.subscriptions.push( ahkStatusBarItem, ahkLanguageStatusItem, outputchannel, extensions.onDidChange(update_extensions_info), - // todo remove this, AHK++ already has it - commands.registerTextEditorCommand('ahk2.help', quickHelp), - commands.registerTextEditorCommand('ahk2.run', textEditor => runScript(textEditor)), - commands.registerTextEditorCommand('ahk2.selection.run', textEditor => runScript(textEditor, true)), - commands.registerCommand('ahk2.stop', stopRunningScript), - commands.registerCommand('ahk2.setinterpreter', setInterpreter), - commands.registerCommand('ahk2.debug.params', () => beginDebug(extlist, debugexts, true)), - commands.registerCommand('ahk2.debug.attach', () => beginDebug(extlist, debugexts, false, true)), - commands.registerCommand('ahk2.selectsyntaxes', selectSyntaxes), - commands.registerTextEditorCommand('ahk2.updateversioninfo', async textEditor => { + commands.registerTextEditorCommand('ahk++.run', textEditor => runScript(textEditor)), + commands.registerTextEditorCommand('ahk++.runSelection', textEditor => runScript(textEditor, true)), + commands.registerCommand('ahk++.stop', stopRunningScript), + commands.registerCommand('ahk++.setV2Interpreter', setInterpreter), + commands.registerCommand('ahk++.debugParams', () => beginDebug(extlist, debugexts, true)), + commands.registerCommand('ahk++.debugAttach', () => beginDebug(extlist, debugexts, false, true)), + commands.registerCommand('ahk++.selectSyntaxes', selectSyntaxes), + commands.registerTextEditorCommand('ahk++.updateVersionInfo', async textEditor => { if (!server_is_ready) return; const info: { content: string, uri: string, range: Range } | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); @@ -234,11 +232,11 @@ export async function activate(context: ExtensionContext) { } } }), - commands.registerTextEditorCommand('ahk2.switch', textEditor => { + commands.registerTextEditorCommand('ahk++.switchAhkVersion', textEditor => { const doc = textEditor.document; languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); }), - commands.registerTextEditorCommand('ahk2.export.symbols', textEditor => { + commands.registerTextEditorCommand('ahk++.exportSymbols', textEditor => { const doc = textEditor.document; if (doc.languageId !== 'ahk2') return; @@ -370,68 +368,6 @@ async function stopRunningScript() { } } -async function quickHelp(textEditor: TextEditor) { - const document = textEditor.document, position = textEditor.selection.active; - const range = document.getWordRangeAtPosition(position), line = position.line; - const helpPath = findfile(['AutoHotkey.chm', '../v2/AutoHotkey.chm'], workspace.getWorkspaceFolder(textEditor.document.uri)?.uri.fsPath ?? ''); - let word = ''; - if (range && (word = document.getText(range)).match(/^[a-z_]+$/i)) { - if (range.start.character > 0 && document.getText(new Range(line, range.start.character - 1, line, range.start.character)) === '#') - word = '#' + word; - } - if (!helpPath) { - window.showErrorMessage(zhcn ? `"AutoHotkey.chm"未找到!` : `"AutoHotkey.chm" was not found!`); - return; - } - const executePath = resolvePath(ahkpath_cur, workspace.getWorkspaceFolder(textEditor.document.uri)?.uri.fsPath); - if (!executePath) { - const s = ahkpath_cur || 'AutoHotkey.exe'; - window.showErrorMessage(zhcn ? `"${s}"未找到!` : `"${s}" was not found!`); - return; - } - const script = ` -#NoTrayIcon -#DllLoad oleacc.dll -chm_hwnd := 0, chm_path := '${helpPath}', DetectHiddenWindows(true), !(WinGetExStyle(top := WinExist('A')) & 8) && (top := 0) -for hwnd in WinGetList('AutoHotkey ahk_class HH Parent') - for item in ComObjGet('winmgmts:').ExecQuery('SELECT CommandLine FROM Win32_Process WHERE ProcessID=' WinGetPID(hwnd)) - if InStr(item.CommandLine, chm_path) { - chm_hwnd := WinExist(hwnd) - break 2 - } -if top && top != chm_hwnd - WinSetAlwaysOnTop(0, top) -if !chm_hwnd - Run(chm_path, , , &pid), chm_hwnd := WinWait('AutoHotkey ahk_class HH Parent ahk_pid' pid) -WinShow(), WinActivate(), WinWaitActive(), ctl := 0, endt := A_TickCount + 3000 -while (!ctl && A_TickCount < endt) - try ctl := ControlGetHwnd('Internet Explorer_Server1') -NumPut('int64', 0x11CF3C3D618736E0, 'int64', 0x719B3800AA000C81, IID_IAccessible := Buffer(16)) -if ${!!word} && !DllCall('oleacc\\AccessibleObjectFromWindow', 'ptr', ctl, 'uint', 0, 'ptr', IID_IAccessible, 'ptr*', IAccessible := ComValue(13, 0)) { - IServiceProvider := ComObjQuery(IAccessible, IID_IServiceProvider := '{6D5140C1-7436-11CE-8034-00AA006009FA}') - NumPut('int64', 0x11D026CB332C4427, 'int64', 0x1901D94FC00083B4, IID_IHTMLWindow2 := Buffer(16)) - ComCall(3, IServiceProvider, 'ptr', IID_IHTMLWindow2, 'ptr', IID_IHTMLWindow2, 'ptr*', IHTMLWindow2 := ComValue(9, 0)) - IHTMLWindow2.execScript(' - ( - document.querySelector('#head > div > div.h-tabs > ul > li:nth-child(3) > button').click() - searchinput = document.querySelector('#left > div.search > div.input > input[type=search]') - keyevent = document.createEvent('KeyboardEvent') - keyevent.initKeyboardEvent('keyup', false, true, document.defaultView, 13, null, false, false, false, false) - searchinput.value = '${word}' - searchinput.dispatchEvent(keyevent) - Object.defineProperties(keyevent, { type: { get: function() { return 'keydown' } }, which: { get: function() { return 13 } } }) - searchinput.dispatchEvent(keyevent) - )') -}`; - if (ahkStatusBarItem.text.endsWith('[UIAccess]')) { - const file = resolve(__dirname, 'temp.ahk'); - writeFileSync(file, script, { encoding: 'utf-8' }); - execSync(`"${executePath}" /ErrorStdOut ${file}`); - unlinkSync(file); - } else - execSync(`"${executePath}" /ErrorStdOut *`, { input: script }); -} - async function beginDebug(extlist: string[], debugexts: { [type: string]: string }, params = false, attach = false) { let extname: string | undefined; const editor = window.activeTextEditor; @@ -582,31 +518,6 @@ function getInterpreterPath() { return { path }; } -function findfile(files: string[], workspace: string) { - let s: string; - const paths: string[] = []; - const t = ahkconfig.inspect('InterpreterPath'); - if (add(ahkpath_cur), t) { - add(t.workspaceFolderValue as string); - add(t.workspaceValue as string); - add(t.globalValue as string); - add(t.defaultValue as string); - } - for (const path of paths) - for (const file of files) - if (existsSync(s = resolve(path, '..', file))) - return s; - return ''; - - function add(path: string) { - path = resolvePath(path, workspace); - if (!path) return; - path = path.toLowerCase(); - if (!paths.includes(path)) - paths.push(path); - } -} - async function onDidChangegetInterpreter() { const uri = window.activeTextEditor?.document.uri; const ws = uri ? workspace.getWorkspaceFolder(uri)?.uri.fsPath : undefined; diff --git a/package.json b/package.json index faecad1d..755daa8e 100644 --- a/package.json +++ b/package.json @@ -67,89 +67,83 @@ "commands": [ { "enablement": "!isWeb", - "command": "ahk2.debug.attach", - "title": "%ahk2.debug.attach%", - "category": "ahk2" + "command": "ahk++.debugAttach", + "title": "%ahk++.debugAttach%", + "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk2.debug.params", - "title": "%ahk2.debug.params%", - "category": "ahk2" + "command": "ahk++.debugParams", + "title": "%ahk++.debugParams%", + "category": "AHK++" }, { "enablement": "editorLangId == ahk2", - "command": "ahk2.diagnostic.full", - "title": "%ahk2.diagnostic.full%", - "category": "ahk2" + "command": "ahk++.diagnostic.full", + "title": "%ahk++.diagnostic.full%", + "category": "AHK++" }, { "enablement": "editorLangId == ahk2", - "command": "ahk2.export.symbols", - "title": "%ahk2.export.symbols%", - "category": "ahk2" + "command": "ahk++.exportSymbols", + "title": "%ahk++.exportSymbols%", + "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk2.run", - "title": "%ahk2.run%", + "command": "ahk++.run", + "title": "%ahk++.run%", "icon": "$(play)", - "category": "ahk2" + "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.selection.run", - "title": "%ahk2.selection.run%", - "category": "ahk2" + "command": "ahk++.runSelection", + "title": "%ahk++.runSelection%", + "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.stop", - "title": "%ahk2.stop%", + "command": "ahk++.stop", + "title": "%ahk++.stop%", "icon": "$(stop)", - "category": "ahk2" - }, - { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.help", - "title": "%ahk2.help%", - "category": "ahk2" + "category": "AHK++" }, { "enablement": "editorLangId == ahk2", - "command": "ahk2.generate.comment", - "title": "%ahk2.generatecomment%", - "category": "ahk2" + "command": "ahk++.addDocComment", + "title": "%ahk++.addDocComment%", + "category": "AHK++" }, { "enablement": "!isWeb", - "command": "ahk2.setinterpreter", - "title": "%ahk2.setinterpreter%", - "category": "ahk2" + "command": "ahk++.setV2Interpreter", + "title": "%ahk++.setV2Interpreter%", + "category": "AHK++" }, { "enablement": "editorLangId == ahk2", - "command": "ahk2.updateversioninfo", - "title": "%ahk2.updateversioninfo%", - "category": "ahk2" + "command": "ahk++.updateVersionInfo", + "title": "%ahk++.updateVersionInfo%", + "category": "AHK++" }, { "enablement": "editorLangId == ahk2 || editorLangId == ahk", - "command": "ahk2.switch", - "title": "Switch v1/v2", - "category": "ahk2" + "command": "ahk++.switchAhkVersion", + "title": "Switch AHK Version", + "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.selectsyntaxes", - "title": "Select syntaxes", - "category": "ahk2" + "command": "ahk++.selectSyntaxes", + "title": "Select AHK Syntaxes", + "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && resourceScheme == file", - "command": "ahk2.setscriptdir", - "title": "%ahk2.setscriptdir%", - "category": "ahk2" + "command": "ahk++.setAScriptDir", + "title": "%ahk++.setAScriptDir%", + "category": "AHK++" } ], "configuration": { @@ -444,27 +438,22 @@ ], "keybindings": [ { - "command": "ahk2.run", + "command": "ahk++.run", "key": "ctrl+f5", "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection" }, { - "command": "ahk2.selection.run", + "command": "ahk++.runSelection", "key": "ctrl+f5", "when": "editorLangId == ahk2 && !isWeb && editorHasSelection" }, { - "command": "ahk2.debug.params", + "command": "ahk++.debugParams", "key": "shift+f5", "when": "editorLangId == ahk2 && !isWeb" }, { - "command": "ahk2.help", - "key": "ctrl+f1", - "when": "editorLangId == ahk2 && !isWeb" - }, - { - "command": "ahk2.stop", + "command": "ahk++.stop", "key": "ctrl+f6", "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning" } @@ -502,53 +491,48 @@ "editor/context": [ { "when": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.debug.attach", + "command": "ahk++.debugAttach", "group": "navigation@2" }, { "when": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.debug.params", + "command": "ahk++.debugParams", "group": "navigation@2" }, { "when": "editorLangId == ahk2 && !isWeb && editorHasSelection", - "command": "ahk2.selection.run", + "command": "ahk++.runSelection", "group": "navigation@0" }, { "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection", - "command": "ahk2.run", + "command": "ahk++.run", "group": "navigation@0" }, - { - "when": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.help", - "group": "navigation@1" - }, { "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning", - "command": "ahk2.stop", + "command": "ahk++.stop", "group": "navigation@0" }, { "when": "editorLangId == ahk2", - "command": "ahk2.generate.comment", + "command": "ahk++.addDocComment", "group": "navigation@2" }, { "when": "editorLangId == ahk2", - "command": "ahk2.updateversioninfo", + "command": "ahk++.updateVersionInfo", "group": "navigation@2" } ], "editor/title": [ { - "command": "ahk2.run", + "command": "ahk++.run", "group": "navigation@0", "when": "resourceLangId == ahk2 && shellExecutionSupported" }, { - "command": "ahk2.stop", + "command": "ahk++.stop", "group": "navigation@0", "when": "resourceLangId == ahk2 && ahk2:isRunning && shellExecutionSupported" } diff --git a/package.nls.json b/package.nls.json index 3bed38b5..cbee2c87 100644 --- a/package.nls.json +++ b/package.nls.json @@ -5,29 +5,28 @@ "ahk2.compilercmd": "Compiler command line options. If ahk2exe.exe is not specified, the default path will be used. `${execPath}` is equal to the currently selected AutoHotkey.exe", "ahk2.completefunctionparens": "Parentheses are added to function completion when there is no `(` or `[` on the right; otherwise move the cursor to the right", "ahk2.completioncommitcharacters": "Characters which commit auto completion, such as `.(`", - "ahk2.debug.attach": "Attach Running Script", - "ahk2.debug.params": "Debug Script with Params", + "ahk++.debugAttach": "Attach Running Script", + "ahk++.debugParams": "Debug Script with Params", "ahk2.debugconfiguration": "Append debugging configuration to the currently started debugger, same as launch.json configuration", "ahk2.description": "Autohotkey2 Language Support using vscode-lsp", - "ahk2.diagnostic.full": "Diagnostic full text", + "ahk++.diagnostic.full": "Diagnostic full text", "ahk2.diagnostics.class-non-dynamic-member-check": "Check whether non-dynamic members of class exist", "ahk2.diagnostics.paramscheck": "Check that the function call has the correct number of arguments", "ahk2.warn.varunset": "Display warnings for each variable that has never been directly assigned or used with the reference operator", "ahk2.warn.localsameasglobal": "Display warnings for each undeclared local variable which has the same name as a global variable", "ahk2.warn.callwithoutparentheses": "Display warnings for each function or method call without parentheses", - "ahk2.export.symbols": "Export ahk classes and functions", + "ahk++.exportSymbols": "Export AHK Symbols", "ahk2.files.exclude": "Configure glob patterns for excluding files and folders when scanning ahk files.", "ahk2.files.scanmaxdepth": "Controls the depth when scanning ahk files.", - "ahk2.generatecomment": "Generate Comment Template", - "ahk2.help": "Quick Help", + "ahk++.addDocComment": "Add Doc Comment", "ahk2.interpreterpath": "The path of the `AutoHotkey.exe` executable file. If `AutoHotkeyUX.exe` is selected, the script will be launched using UX Launcher.", - "ahk2.run": "Run Script", - "ahk2.selection.run": "Run Selected Script", - "ahk2.setinterpreter": "Select AutoHotkey2 Interpreter", - "ahk2.setscriptdir": "Set here as A_ScriptDir", - "ahk2.stop": "Stop Running Script", + "ahk++.run": "Run Script", + "ahk++.runSelection": "Run Selection", + "ahk++.setV2Interpreter": "Set AHK v2 Interpreter", + "ahk++.setAScriptDir": "Set A_ScriptDir Here", + "ahk++.stop": "Stop AHK Script", "ahk2.symbolfoldingfromopenbrace": "Forced symbol folding starts at open brace", "ahk2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", - "ahk2.updateversioninfo": "Update File Version Info", + "ahk++.updateVersionInfo": "Update File Version Info", "ahk2.workingdirs": "Sets the working directory for the script" } diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index 515b7785..12b5fc96 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -8,30 +8,29 @@ "ahk2.compilercmd": "编译器命令行选项. 如果未指定ahk2exe.exe, 将使用默认路径. `${execPath}`等价于当前选择的AutoHotkey.exe", "ahk2.completefunctionparens": "当右侧不存在`(`或`[`时, 给函数补全添加括号; 否则向右移动光标", "ahk2.completioncommitcharacters": "提交自动完成的字符, 例如`.(`", - "ahk2.debug.attach": "附加到运行中的脚本", - "ahk2.debug.params": "带参调试", + "ahk++.debugAttach": "附加到运行中的脚本", + "ahk++.debugParams": "带参调试", "ahk2.debugconfiguration": "追加调试配置到当前启动的调试器, 与launch.json配置相同", "ahk2.description": "基于 vscode-lsp 协议的 Autohotkey2 语言支持", - "ahk2.diagnostic.full": "诊断全文", + "ahk++.diagnostic.full": "诊断全文", "ahk2.diagnostics.class-non-dynamic-member-check": "检查类非动态成员是否存在", "ahk2.diagnostics.paramscheck": "检查函数调用参数个数是否正确", "ahk2.warn.varunset": "为每个从未直接赋值或与引用操作符一起使用的变量的显示警告", "ahk2.warn.localsameasglobal": "为每个与全局变量同名的未声明的局部变量显示警告", "ahk2.warn.callwithoutparentheses": "为每个不带括号的函数或方法调用显示警告", - "ahk2.export.symbols": "导出ahk类和函数", + "ahk++.exportSymbols": "导出ahk类和函数", "ahk2.files.exclude": "配置 glob 模式以在扫描ahk文件时排除文件和文件夹.", "ahk2.files.scanmaxdepth": "控制扫描ahk文件时的深度.", - "ahk2.generatecomment": "生成注释模板", - "ahk2.help": "快捷帮助", + "ahk++.addDocComment": "生成注释模板", "ahk2.interpreterpath": "`AutoHotkey.exe`可执行文件的路径. 如果选择`AutoHotkeyUX.exe`, 将使用UX Launcher启动脚本.", - "ahk2.run": "运行脚本", - "ahk2.selection.run": "运行选择的脚本", - "ahk2.setinterpreter": "选择AutoHotkey2解释器", - "ahk2.setscriptdir": "设置此处为A_ScriptDir", - "ahk2.stop": "停止运行中的脚本", + "ahk++.run": "运行脚本", + "ahk++.runSelection": "运行选择的脚本", + "ahk++.setV2Interpreter": "选择AutoHotkey2解释器", + "ahk++.setAScriptDir": "设置此处为A_ScriptDir", + "ahk++.stop": "停止运行中的脚本", "ahk2.symbolfoldingfromopenbrace": "强制符号折叠从大括号处开始", "ahk2.syntaxes": "指定用于智能感知的`ahk2.json`, `*.snippet.json`和`ahk2.d.ahk`文件的文件夹路径.", - "ahk2.updateversioninfo": "更新文件版本信息", + "ahk++.updateVersionInfo": "更新文件版本信息", "ahk2.workingdirs": "设置脚本的工作目录", "codeaction.include": "导入 '{0}'", "completionitem.author": "添加作者, 描述, 日期, 版本等文件信息.", diff --git a/server/src/commandProvider.ts b/server/src/commandProvider.ts index fd34f9e1..b927bc4e 100644 --- a/server/src/commandProvider.ts +++ b/server/src/commandProvider.ts @@ -74,6 +74,7 @@ export function generate_fn_comment(doc: Lexer, fn: FuncNode, detail?: string) { return text; } +/** Add a function header comment for the currently active function */ async function generateComment() { if (!checkCommand('ahk2.getActiveTextEditorUriAndPosition') || !checkCommand('ahk2.insertSnippet')) return; @@ -230,9 +231,9 @@ async function setscriptdir() { // eslint-disable-next-line @typescript-eslint/no-explicit-any export const commands: { [command: string]: (args: any[]) => any } = { - 'ahk2.diagnostic.full': () => diagnosticFull(), - 'ahk2.generate.comment': () => generateComment(), - 'ahk2.setscriptdir': setscriptdir + 'ahk++.diagnostic.full': () => diagnosticFull(), + 'ahk++.addDocComment': () => generateComment(), + 'ahk++.setAScriptDir': setscriptdir }; export function executeCommandProvider(params: ExecuteCommandParams, token?: CancellationToken) { diff --git a/server/src/server.ts b/server/src/server.ts index b8a2c5b1..b286142c 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -331,7 +331,7 @@ async function patherr(msg: string) { title: 'Select Interpreter', }) ) - connection.sendRequest('ahk2.executeCommand', ['ahk2.setinterpreter']); + connection.sendRequest('ahk2.executeCommand', ['ahk++.setV2Interpreter']); } async function initpathenv(samefolder = false, retry = true): Promise { diff --git a/syntaxes/ahk2-output.tmLanguage.json b/syntaxes/ahk2-output.tmLanguage.json index b29ae0e2..63eadaa2 100644 --- a/syntaxes/ahk2-output.tmLanguage.json +++ b/syntaxes/ahk2-output.tmLanguage.json @@ -15,7 +15,7 @@ } }, "match": "^(\\[Running\\])(.*)$", - "name": "ahk2.running" + "name": "ahk++.running" }, { "captures": { From f205dc28ea03c8fd30ae5a165e452be43cf159d0 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 31 Aug 2024 18:03:29 -0700 Subject: [PATCH 23/60] Update settings and readme (#21) --- .vscode/settings.json | 1 - README.md | 336 --------------------------- README.zh-CN.md | 333 -------------------------- client/src/browserClientMain.ts | 6 +- client/src/extension.ts | 45 ++-- package.json | 153 ++++++------ package.nls.json | 59 +++-- package.nls.zh-cn.json | 59 +++-- readme.md | 5 + server/cli/cli.ts | 3 +- server/src/Lexer.ts | 296 +++++++++++------------ server/src/browserServerMain.ts | 25 +- server/src/commandProvider.ts | 4 +- server/src/common.ts | 162 +++---------- server/src/completionProvider.ts | 34 +-- server/src/config.ts | 167 +++++++++++++ server/src/formattingProvider.ts | 41 ++-- server/src/localize.ts | 2 +- server/src/semanticTokensProvider.ts | 5 +- server/src/server.ts | 67 +++--- server/src/symbolProvider.ts | 8 +- server/src/utils.ts | 19 ++ syntaxes/ahk2_common.json | 2 +- webpack.config.js | 1 - 24 files changed, 608 insertions(+), 1225 deletions(-) delete mode 100644 README.md delete mode 100644 README.zh-CN.md create mode 100644 readme.md create mode 100644 server/src/config.ts create mode 100644 server/src/utils.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 371738b1..f494c7af 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,5 @@ "typescript.tsc.autoDetect": "off", "typescript.preferences.quoteStyle": "single", "git.ignoreLimitWarning": true, - "AutoHotkey2.InterpreterPath": "c:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe", "editor.formatOnSave": false } diff --git a/README.md b/README.md deleted file mode 100644 index 02e0445e..00000000 --- a/README.md +++ /dev/null @@ -1,336 +0,0 @@ -**English** | [中文](./README.zh-CN.md) - -# AutoHotkey v2 Language Support - -[![installs](https://img.shields.io/visual-studio-marketplace/i/thqby.vscode-autohotkey2-lsp?label=Extension%20Install&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) -[![version](https://img.shields.io/visual-studio-marketplace/v/thqby.vscode-autohotkey2-lsp?label=Extension%20Version&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) -[![](https://img.shields.io/badge/Compatibility-autohotkey%20v2.0+-green?style=for-the-badge&logo=autohotkey)](https://www.autohotkey.com/) - -**Repositories**: [Github](https://github.com/thqby/vscode-autohotkey2-lsp) | [Gitee](https://gitee.com/orz707/vscode-autohotkey2-lsp) - -AutoHotkey v2 Language support for VS Code, features realization based on v2 syntax analysis. -Supports running on the Web, such as `Chrome/Edge`. https://vscode.dev or https://github.dev/github/dev - -- [AutoHotkey v2 Language Support](#autohotkey-v2-language-support) - - [Language Features](#language-features) - - [Rename Symbol](#rename-symbol) - - [Diagnostics](#diagnostics) - - [IntelliSense](#intellisense) - - [Signature](#signature) - - [Document Symbol](#document-symbol) - - [Semantic Highlight](#semantic-highlight) - - [Tags](#tags) - - [Document Color](#document-color) - - [Hover](#hover) - - [Goto Definition](#goto-definition) - - [Find All References](#find-all-references) - - [CodeFormat](#codeformat) - - [Custom folding](#custom-folding) - - [Context Menu](#context-menu) - - [Quick Help](#quick-help) - - [Run Script](#run-script) - - [Run Selected Script](#run-selected-script) - - [Compile Script](#compile-script) - - [Debug Script](#debug-script) - - [Generate Comment](#generate-comment) - - [Use in other editors](#use-in-other-editors) - - [Sublime Text4](#sublime-text4) - - [Vim and Neovim](#vim-and-neovim) - - [Emacs](#Emacs) - - [Use in Web Browser](#use-in-web-browser) - -## Language Features - -### Rename Symbol - -Rename variables and function names in the scope in batches. - -![rename](./pic/rename.gif) - -### Diagnostics - -Simple syntax error diagnosis. - -![diagnostics](./pic/diagnostics2.png) - -### IntelliSense - -Supports intelligent completion of variables, functions, parameters, class names, and method names within the scope (by simple type deduction), and supports the completion of include files and function libraries. - -![snippet1](./pic/snippet.png) - -![snippet2](./pic/snippet.gif) - -### Signature - -Support for intelligent prompts for function parameters. - -![signature](./pic/signature.gif) - -### Document Symbol - -1. Displays class, method, function, variable, label, hotkey, hot string, block information in the left outline column. -2. press Ctrl + P, Input @symbol_name to retrieve and jump -3. You can comment a method with a semicolon or /\* \*/ on the top line of a function, variable. Jsdoc-style annotations can mark variable types. - - - -```js -/** - * @param {Array} a - a param - * @return {Integer} - */ -fn(a*) { - /** @type {Map} */ - d := Map() - /** - * @var {Map} e - * @var {Object} f - */ - e := Map(), f := {} - /** @type {(a,b)=>Integer} */ - cb := (a, b) => a + b - /** @type {ComObject} */ - wb := ComObject('Excel.Sheet.12') - return a[1] + a[2] -} -class abc { - /** @type {Map} */ - p := dosomethingandreturnmap() -} -``` - -### Semantic Highlight - -Semantic highlighting is an addition to syntax highlighting, resolves symbols in the context of a project. The editor applies the highlighting from semantic tokens on top of the highlighting from grammars. - -![semanticTokens](./pic/semanticTokens.png) - -### Tags - -usage: Add `;;`(default) or `; TODO ` to the comment code Tags. - -![codeSymbole](./pic/codeSymbol.png) - -### Document Color - -Compute and resolve colors inside a document to provide color picker in editor. - -![documentcolor](./pic/documentcolor.png) - -### Hover - -Supports hover prompts and comments for scoped variables, functions, global classes, and labels. -usage: Move the mouse over the symbol. - -![hover](./pic/hover.png) - -### Goto Definition - -1. Support for jumping to the declaration location of scoped variables, functions, global classes, and labels. -2. usage: Press ctrl Then move the mouse over to the code and click. - -![gotoDefinition](./pic/gotoDefinition.png) - -### Find All References - -See all the source code locations where a certain variable/function is being used. - -### CodeFormat - -usage: - -- Right-click the popup menu and click "Format document". -- Press `Shift+Alt+F`. -- Supports formatting code blocks when typing '}', formatting lines and indenting lines when typing '\n'. (`editor.formatOnType` needs to be enabled) -- Supports the use of formatting instructions `;@format array_style: collapse, object_style: expand` to change the object style of different blocks - -![codeFormat](./pic/codeFormat.gif) - -### Custom folding - -Fold the part between `;@region tag` and `;@endregion`, `;{` and `;}` - -```ini -;#region tag -code -;#endregion -``` - -## Context Menu - -### Quick Help - -Open the help file and navigate to the keyword at the current cursor. - -### Run Script - -Run the currently open script. - -### Run Selected Script - -Run the code snippet at the cursor selection. - -### Compile Script - -Compile the script to generate executable EXE files. - -### Debug Script - -No additional configuration is required to start the installed Debug extensions, and support debugging with parameters. - -### Generate Comment - -Generate JSDOC-style comments for a function or method. - -## Use in other editors - -1. Install [Node.js](https://nodejs.org/en/download/). -2. Download vscode-autohotkey2-lsp server using command line, or download and unpack through [vscode marketplace](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp). - -```shell -mkdir vscode-autohotkey2-lsp -cd vscode-autohotkey2-lsp -curl -L -o install.js https://raw.githubusercontent.com/thqby/vscode-autohotkey2-lsp/main/tools/install.js -node install.js -``` - -3. Set the LSP configuration of the editor that support [LSP(Language Server Protocol)](https://microsoft.github.io/language-server-protocol/), such as Sublime Text4, Vim, Neovim, Emacs, [etc](https://microsoft.github.io/language-server-protocol/implementors/tools/). - -### Sublime Text4 - -- `Package Control: Install Package`, and install [Sublime LSP](https://github.com/sublimelsp/LSP) plug-in. -- `Preferences: LSP Settings`, add lsp configuration, language selector, and syntax highlighting. This is a simple example [syntax highlighting](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), save the file in a similar path `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax`. - -```json -{ - "clients": { - "lsp-ahk2": { - "enabled": true, - "command": [ - "node", - "/server/dist/server.js", - "--stdio" - ], // Update the path of node.exe(maybe it's already in PATH, so you don't need to set it) and the folder of vscode-autohotkey2-lsp - "selector": "source.ahk2", // Same as scope in AutoHotkey2.sublime-syntax - "schemes": ["file", "buffer", "res"], - "initializationOptions": { - "locale": "en-us", // or "zh-cn" - "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" - "CommentTags": "^;;\\s*(?.+)", - "CompleteFunctionParens": false, - "Diagnostics": { - "ClassStaticMemberCheck": true, - "ParamsCheck": true - }, - "ActionWhenV1IsDetected": "Continue", - "FormatOptions": { - "array_style": "none", // or "collapse" or "expand" - "break_chained_methods": false, - "ignore_comment": false, - "indent_string": "\t", - "max_preserve_newlines": 2, - "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" - "object_style": "none", // or "collapse" or "expand" - "preserve_newlines": true, - "space_after_double_colon": true, - "space_before_conditional": true, - "space_in_empty_paren": false, - "space_in_other": true, - "space_in_paren": false, - "wrap_line_length": 0 - }, - "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - "WorkingDirs": [], - "SymbolFoldingFromOpenBrace": false - } - } - }, - "semantic_highlighting": true -} -``` - -### Vim and Neovim - -#### COC - -- Download [coc.nvim plugin](https://github.com/neoclide/coc.nvim). - -```bat -cd $VIMRUNTIME\plugin -git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 -``` - -- Open (n)vim and enter the command `:CocConfig` to enter the `coc.nvim` configuration file to add configuration information. - -```json -{ - "languageserver": { - "lsp-ahk2": { - "module": "/server/dist/server.js", - "filetypes": ["autohotkey"], - "args": ["--node-ipc"], - "initializationOptions": { - // Same as initializationOptions for Sublime Text4 - } - } - } -} -``` - -#### nvim-lspconfig - -- Download [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). -- Add the following to your NVIM configuration (init.lua e.g.). Ensure that `cmd` points to the path of your vscode-autohotkey2-lsp installation and `InterpreterPath` points to your AHK exe. - -```lua -local function custom_attach(client, bufnr) - require("lsp_signature").on_attach({ - bind = true, - use_lspsaga = false, - floating_window = true, - fix_pos = true, - hint_enable = true, - hi_parameter = "Search", - handler_opts = { "double" }, - }) -end - -local ahk2_configs = { - autostart = true, - cmd = { - "node", - vim.fn.expand("$HOME/vscode-autohotkey2-lsp/server/dist/server.js"), - "--stdio" - }, - filetypes = { "ahk", "autohotkey", "ah2" }, - init_options = { - locale = "en-us", - InterpreterPath = "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - -- Same as initializationOptions for Sublime Text4, convert json literal to lua dictionary literal - }, - single_file_support = true, - flags = { debounce_text_changes = 500 }, - capabilities = capabilities, - on_attach = custom_attach, -} -local configs = require "lspconfig.configs" -configs["ahk2"] = { default_config = ahk2_configs } -local nvim_lsp = require("lspconfig") -nvim_lsp.ahk2.setup({}) -``` - -### Emacs - -#### Eglot - -- Add the following lines to your emacs config file - -```emacs-lisp -(add-to-list 'eglot-server-programs '(ahk-mode "node" "/server/dist/server.js" "--stdio")) - -``` - -## Use in Web Browser - -visit https://github.dev or https://vscode.dev in `Chrome/Edge`, and install `thqby.vscode-autohotkey2-lsp` diff --git a/README.zh-CN.md b/README.zh-CN.md deleted file mode 100644 index 968fea42..00000000 --- a/README.zh-CN.md +++ /dev/null @@ -1,333 +0,0 @@ -[English](./README.md) | **中文** - -# AutoHotkey v2 语言支持 - -[![installs](https://img.shields.io/visual-studio-marketplace/i/thqby.vscode-autohotkey2-lsp?label=Extension%20Install&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) -[![version](https://img.shields.io/visual-studio-marketplace/v/thqby.vscode-autohotkey2-lsp?label=Extension%20Version&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) -[![](https://img.shields.io/badge/Compatibility-autohotkey%20v2.0+-green?style=for-the-badge&logo=autohotkey)](https://www.autohotkey.com/) - -**仓库**: [Github](https://github.com/thqby/vscode-autohotkey2-lsp) | [Gitee](https://gitee.com/orz707/vscode-autohotkey2-lsp) - -AutoHotkey v2 语言支持 for VS Code, 功能实现基于 v2 语法分析。 -支持在`Chrome/Edge`等浏览器中使用 https://vscode.dev 或 https://github.dev/github/dev - -- [AutoHotkey v2 语言支持](#autohotkey-v2-语言支持) - - [语言特性](#语言特性) - - [重命名符号](#重命名符号) - - [错误诊断](#错误诊断) - - [智能感知](#智能感知) - - [智能提示](#智能提示) - - [大纲](#大纲) - - [语义高亮](#语义高亮) - - [代码标记](#代码标记) - - [颜色提示](#颜色提示) - - [悬停提示](#悬停提示) - - [转到定义](#转到定义) - - [查找所有引用](#查找所有引用) - - [代码格式化](#代码格式化) - - [自定义折叠](#自定义折叠) - - [上下文菜单](#上下文菜单) - - [快速帮助](#快速帮助) - - [运行脚本](#运行脚本) - - [运行选定的脚本](#运行选定的脚本) - - [编译脚本](#编译脚本) - - [调试脚本](#调试脚本) - - [生成注释](#生成注释) - - [在其他编辑器中使用](#在其他编辑器中使用) - - [Sublime Text 4](#sublime-text-4) - - [Vim 和 Neovim](#vim-和-neovim) - - [Emacs](#Emacs) - - [在 Web 浏览器中使用](#在-web-浏览器中使用) - -## 语言特性 - -### 重命名符号 - -作用域范围内的变量、函数名批量重命名。 - -![rename](./pic/rename.gif) - -### 错误诊断 - -简单语法错误诊断。 - -![diagnostics](./pic/diagnostics.png) - -### 智能感知 - -支持对作用域范围内的变量、函数、参数、类名、方法名智能补全(简单的类型推导),支持对 include 文件和函数库补全。 - -![snippet1](./pic/snippet.png) - -![snippet2](./pic/snippet.gif) - -### 智能提示 - -支持对函数、方法参数的智能提示。 - -![signature](./pic/signature.gif) - -### 大纲 - -1. 在左侧大纲栏目显示类、方法、函数、变量、标签、热键、热字串、区块信息 -2. 按 Ctrl + P, 输入@符号名检索并跳转 -3. 您可以在函数、变量的上一行使用分号或/\* \*/向方法添加注释, jsdoc 样式的注释可以标记变量类型 - - - -```js -/** - * @param {Array} a - a param - * @return {Integer} - */ -fn(a*) { - /** @type {Map} */ - d := Map() - /** - * @var {Map} e - * @var {Object} f - */ - e := Map(), f := {} - /** @type {(a,b)=>Integer} */ - cb := (a, b) => a + b - /** @type {ComObject} */ - wb := ComObject('Excel.Sheet.12') - return a[1] + a[2] -} -class abc { - /** @type {Map} */ - p := dosomethingandreturnmap() -} -``` - -### 语义高亮 - -语义高亮显示是语法高亮显示的补充,改进和改进语法中的语法突出显示。编辑器在来自语法的高亮显示之上应用来自语义标记的高亮显示。 -![semanticTokens](./pic/semanticTokens.png) - -### 代码标记 - -用法: 在注释代码块中添加`;;`(默认)或`; TODO ` -![codeSymbole](./pic/codeSymbol.png) - -### 颜色提示 - -计算并解析文档中的颜色,并提供颜色选择器更直观地修改颜色数据。 - -![documentcolor](./pic/documentcolor.png) - -### 悬停提示 - -支持对作用域范围内变量、函数、全局类、标签的悬停提示并显示相关备注。 -用法: 移动鼠标到相关符号上。 -![hover](./pic/hover.png) - -### 转到定义 - -1. 支持跳转到作用域范围内变量、函数、全局类、标签的声明位置。 -2. 用法: 按住 ctrl 然后移动鼠标到代码处点击。 - -![gotoDefinition](./pic/gotoDefinition.png) - -### 查找所有引用 - -查看正在使用某个变量/函数的所有源代码位置。 - -### 代码格式化 - -用法: - -- 右键弹出菜单然后点击 格式化文档。 -- 或按 `Shift+Alt+F`。 -- 支持在键入`}`时格式化代码块,在代码行结束处键入`\n`时格式化行并缩进。支持在代码区(非注释、字符串)输入中文标点时替换为英文标点。 (需要开启`editor.format OnType`) -- 支持使用格式化指令`;@format array_style: collapse, object_style: expand`改变不同块的对象样式 - -![codeFormat](./pic/codeFormat.gif) - -### 自定义折叠 - -折叠`;@region tag`和`;@endregion`之间部分, `;{`和`;}`之间部分 - -```ini -;@region tag -code -;@endregion -``` - -## 上下文菜单 - -### 快速帮助 - -打开帮助文件并导航到当前光标处的关键字。 - -### 运行脚本 - -运行当前打开的脚本。 - -### 运行选定的脚本 - -运行光标选择范围的代码片段。 - -### 编译脚本 - -编译脚本生成可执行的 EXE 文件。 - -### 调试脚本 - -无需额外配置即可启动已安装的调试扩展,支持带参数调试。 - -### 生成注释 - -为函数或方法生成 JSDOC 样式的注释文档。 - -## 在其他编辑器中使用 - -1. 安装[Node.js](https://nodejs.org/en/download/)。 -2. 用命令行下载 vscode-autohotkey2-lsp 服务端, 或通过[vscode marketplace](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp)下载并解包。 - -```shell -mkdir vscode-autohotkey2-lsp -cd vscode-autohotkey2-lsp -curl -L -o install.js https://raw.githubusercontent.com/thqby/vscode-autohotkey2-lsp/main/tools/install.js -node install.js -``` - -3. 设置支持[LSP(语言服务器协议)](https://microsoft.github.io/language-server-protocol/)的编辑器的 LSP 配置, 例如 Sublime Text4, Vim, Neovim, Emacs, [等](https://microsoft.github.io/language-server-protocol/implementors/tools/)。 - -### Sublime Text 4 - -- `Package Control: Install Package`, 安装[Sublime LSP](https://github.com/sublimelsp/LSP)插件 -- `Preferences: LSP Settings`, 增加 lsp 配置、语言选择器和语法高亮. 这是一个简单的[语法高亮示例](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), 存放在类似路径下 `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax` - -```json -{ - "clients": { - "lsp-ahk2": { - "enabled": true, - "command": [ - "node", - "/server/dist/server.js", - "--stdio" - ], // 更新node.exe的路径(可能已经在环境变量中,所以你不需要设置)和vscode-autohotkey2-lsp的文件夹 - "selector": "source.ahk2", // 与AutoHotkey2.sublime-syntax中的scope相同 - "schemes": ["file", "buffer", "res"], - "initializationOptions": { - "locale": "en-us", // or "zh-cn" - "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" - "CommentTags": "^;;\\s*(?.+)", - "CompleteFunctionParens": false, - "Diagnostics": { - "ClassStaticMemberCheck": true, - "ParamsCheck": true - }, - "ActionWhenV1IsDetected": "Continue", - "FormatOptions": { - "array_style": "none", // or "collapse" or "expand" - "break_chained_methods": false, - "ignore_comment": false, - "indent_string": "\t", - "max_preserve_newlines": 2, - "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" - "object_style": "none", // or "collapse" or "expand" - "preserve_newlines": true, - "space_after_double_colon": true, - "space_before_conditional": true, - "space_in_empty_paren": false, - "space_in_other": true, - "space_in_paren": false, - "wrap_line_length": 0 - }, - "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - "WorkingDirs": [], - "SymbolFoldingFromOpenBrace": false - } - } - }, - "semantic_highlighting": true -} -``` - -### Vim 和 Neovim - -#### COC - -- 下载[coc.nvim 插件](https://github.com/neoclide/coc.nvim)。 - -```bat -cd $VIMRUNTIME\plugin -git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 -``` - -- 打开(n)vim, 输入命令 `:CocConfig` 进入`coc.nvim`配置文件增加配置信息。 - -```json -{ - "languageserver": { - "lsp-ahk2": { - "module": "/server/dist/server.js", - "filetypes": ["autohotkey"], - "args": ["--node-ipc"], - "initializationOptions": { - // Same as initializationOptions for Sublime Text4 - } - } - } -} -``` - -#### nvim-lspconfig - -- 下载[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)。 -- 将以下内容添加到您的NVIM配置中(init.lua 等). 确定`cmd`指向vscode-autohotkey2-lsp的安装路径,`InterpreterPath`指向AHK exe. - -```lua -local function custom_attach(client, bufnr) - require("lsp_signature").on_attach({ - bind = true, - use_lspsaga = false, - floating_window = true, - fix_pos = true, - hint_enable = true, - hi_parameter = "Search", - handler_opts = { "double" }, - }) -end - -local ahk2_configs = { - autostart = true, - cmd = { - "node", - vim.fn.expand("$HOME/vscode-autohotkey2-lsp/server/dist/server.js"), - "--stdio" - }, - filetypes = { "ahk", "autohotkey", "ah2" }, - init_options = { - locale = "en-us", - InterpreterPath = "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - -- Same as initializationOptions for Sublime Text4, convert json literal to lua dictionary literal - }, - single_file_support = true, - flags = { debounce_text_changes = 500 }, - capabilities = capabilities, - on_attach = custom_attach, -} -local configs = require "lspconfig.configs" -configs["ahk2"] = { default_config = ahk2_configs } -local nvim_lsp = require("lspconfig") -nvim_lsp.ahk2.setup({}) -``` - -### Emacs - -#### Eglot - -- 将以下内容添加到您的emacs配置文件中 - -```emacs-lisp -(add-to-list 'eglot-server-programs '(ahk-mode "node" "/server/dist/server.js" "--stdio")) - -``` - -## 在 Web 浏览器中使用 - -在`Chrome/Edge`中打开 https://github.dev 或 https://vscode.dev, 然后安装`thqby.vscode-autohotkey2-lsp`。 diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts index 72575960..906d0f0b 100644 --- a/client/src/browserClientMain.ts +++ b/client/src/browserClientMain.ts @@ -54,19 +54,19 @@ export function activate(context: ExtensionContext) { 'ahk2.getWorkspaceFileContent': async (params: string[]) => (await workspace.openTextDocument(Uri.parse(params[0]))).getText() }; - client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', { + client = new LanguageClient('ahk++', 'ahk++', { documentSelector: [{ language: 'ahk2' }], markdown: { isTrusted: true, supportHtml: true }, initializationOptions: { extensionUri: context.extensionUri.toString(), commands: Object.keys(request_handlers), - ...JSON.parse(JSON.stringify(workspace.getConfiguration('AutoHotkey2'))) + ...JSON.parse(JSON.stringify(workspace.getConfiguration('ahk++'))) } }, new Worker(serverMain.toString())); context.subscriptions.push( commands.registerTextEditorCommand('ahk++.updateVersionInfo', async textEditor => { - const info: { content: string, uri: string, range: Range } | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); + const info: { content: string, uri: string, range: Range } | null = await client.sendRequest('ahk++.getVersionInfo', textEditor.document.uri.toString()); if (!info) { await textEditor.insertSnippet(new SnippetString([ "/************************************************************************", diff --git a/client/src/extension.ts b/client/src/extension.ts index 90bf08cc..2a563c66 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -36,17 +36,15 @@ import { readdirSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); -const ahkconfig = workspace.getConfiguration('AutoHotkey2'); -let ahkpath_cur: string = ahkconfig.InterpreterPath, server_is_ready = false, zhcn = false; +const ahkppConfig = workspace.getConfiguration('ahk++'); +let ahkpath_cur: string = ahkppConfig.v2.file.interpreterPath, server_is_ready = false, zhcn = false; const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; const isWindows = process.platform === 'win32'; export async function activate(context: ExtensionContext) { - console.log('ahk2 activated'); /** Absolute path to `server.js` */ const defaultServerModule = context.asAbsolutePath(`ahk2/server/dist/server.js`); const serverModule = process.env.VSCODE_AHK_SERVER_PATH ? context.asAbsolutePath(process.env.VSCODE_AHK_SERVER_PATH) : defaultServerModule; - console.log('serverModule:', serverModule); // If the extension is launched in debug mode then the debug server options are used // Otherwise the run options are used @@ -96,20 +94,17 @@ export async function activate(context: ExtensionContext) { const clientOptions: LanguageClientOptions = { documentSelector: [{ language: 'ahk2' }], markdown: { isTrusted: true, supportHtml: true }, - outputChannel: outputchannel = window.createOutputChannel('AutoHotkey2', '~ahk2-output'), - outputChannelName: 'AutoHotkey2', + outputChannel: outputchannel = window.createOutputChannel('ahk++', '~ahk2-output'), + outputChannelName: 'ahk++', initializationOptions: { commands: Object.keys(request_handlers), GlobalStorage: context.globalStorageUri.fsPath, - ...ahkconfig + ...ahkppConfig } }; - if (ahkconfig.FormatOptions?.one_true_brace !== undefined) - window.showWarningMessage('configuration "AutoHotkey2.FormatOptions.one_true_brace" is deprecated!\nplease use "AutoHotkey2.FormatOptions.brace_style"'); - // Create the language client and start the client. - client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', serverOptions, clientOptions); + client = new LanguageClient('ahk++', 'ahk++', serverOptions, clientOptions); zhcn = env.language.startsWith('zh-'); textdecoders.push(new TextDecoder(zhcn ? 'gbk' : 'windows-1252')); @@ -152,7 +147,7 @@ export async function activate(context: ExtensionContext) { configs = configs?.filter(it => it.request === config.request && it.type === config.type); if (!config.__ahk2debug) { // eslint-disable-next-line @typescript-eslint/no-explicit-any - const def = { ...ahkconfig.get('DebugConfiguration') as any }; + const def = { ...ahkppConfig.get('v2.debugConfiguration') as any }; delete def.request, delete def.type; append_configs.push(def, configs?.filter(it => Object.entries(it).every(([k, v]) => equal(v, config[k])) @@ -190,7 +185,7 @@ export async function activate(context: ExtensionContext) { commands.executeCommand('setContext', 'ahk2:isRunning', false); ahkStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 75); ahkStatusBarItem.command = 'ahk++.setV2Interpreter'; - const ahkLanguageStatusItem = languages.createLanguageStatusItem('AutoHotkey2', { language: 'ahk2' }); + const ahkLanguageStatusItem = languages.createLanguageStatusItem('ahk++', { language: 'ahk2' }); ahkLanguageStatusItem.text = '$(folder)syntaxes'; ahkLanguageStatusItem.command = { title: 'Select AHK Syntaxes', command: 'ahk++.selectSyntaxes' }; context.subscriptions.push( @@ -206,7 +201,7 @@ export async function activate(context: ExtensionContext) { commands.registerTextEditorCommand('ahk++.updateVersionInfo', async textEditor => { if (!server_is_ready) return; - const info: { content: string, uri: string, range: Range } | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); + const info: { content: string, uri: string, range: Range } | null = await client.sendRequest('ahk++.getVersionInfo', textEditor.document.uri.toString()); if (!info) { await textEditor.insertSnippet(new SnippetString([ "/************************************************************************", @@ -371,7 +366,7 @@ async function stopRunningScript() { async function beginDebug(extlist: string[], debugexts: { [type: string]: string }, params = false, attach = false) { let extname: string | undefined; const editor = window.activeTextEditor; - const config = { ...ahkconfig.get('DebugConfiguration'), request: 'launch', __ahk2debug: true } as DebugConfiguration; + const config = { ...ahkppConfig.get('v2.debugConfiguration'), request: 'launch', __ahk2debug: true } as DebugConfiguration; if (!extlist.length) { window.showErrorMessage(zhcn ? '未找到debug扩展, 请先安装debug扩展!' : 'The debug extension was not found, please install the debug extension first!'); extname = await window.showQuickPick(['zero-plusplus.vscode-autohotkey-debug', 'helsmy.autohotkey-debug', 'mark-wiemer.vscode-autohotkey-plus-plus', 'cweijan.vscode-autohotkey-plus']); @@ -452,10 +447,10 @@ async function setInterpreter() { pick.dispose(); if (sel.detail) { ahkStatusBarItem.tooltip = ahkpath_cur = sel.detail; - ahkconfig.update('InterpreterPath', ahkpath_cur, from); + ahkppConfig.update('v2.file.interpreterPath', ahkpath_cur, from); ahkStatusBarItem.text = sel.label ||= (await getAHKversion([ahkpath_cur]))[0]; if (server_is_ready) - commands.executeCommand('ahk2.resetinterpreterpath', ahkpath_cur); + commands.executeCommand('ahk++.v2.setIntepreterPath', ahkpath_cur); } }); pick.onDidHide(() => pick.dispose()); @@ -488,7 +483,7 @@ async function setInterpreter() { async function selectSyntaxes() { const path = (await window.showOpenDialog({ canSelectFiles: false, canSelectFolders: true }))?.[0].fsPath; - const t = ahkconfig.inspect('Syntaxes'); + const t = ahkppConfig.inspect('Syntaxes'); let v = '', f = ConfigurationTarget.Global; if (t) { v = ((f = ConfigurationTarget.WorkspaceFolder, t.workspaceFolderValue) ?? @@ -497,7 +492,7 @@ async function selectSyntaxes() { } if (path === undefined || v.toLowerCase() === path.toLowerCase()) return; - ahkconfig.update('Syntaxes', path || undefined, f); + ahkppConfig.update('Syntaxes', path || undefined, f); } function getAHKversion(paths: string[]): Thenable { @@ -505,16 +500,16 @@ function getAHKversion(paths: string[]): Thenable { } function getInterpreterPath() { - const t = ahkconfig.inspect('InterpreterPath'); + const configDetails = ahkppConfig.inspect('v2.file.interpreterPath'); let path = ''; - if (t) - if ((path = t.workspaceFolderValue as string)) + if (configDetails) + if ((path = configDetails.workspaceFolderValue as string)) return { path, from: ConfigurationTarget.WorkspaceFolder }; - else if ((path = t.workspaceValue as string)) + else if ((path = configDetails.workspaceValue as string)) return { path, from: ConfigurationTarget.Workspace }; - else if ((path = t.globalValue as string)) + else if ((path = configDetails.globalValue as string)) return { path, from: ConfigurationTarget.Global }; - else path = t.defaultValue as string ?? ''; + else path = configDetails.defaultValue as string ?? ''; return { path }; } diff --git a/package.json b/package.json index 755daa8e..78657d82 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,8 @@ "clean": "del-cli client/dist server/dist/*.js*", "clean//": "Remove both the compiled extension and compiled test files", "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", - "compile-test": "cd client && tsc", - "compile-test//": "Compile test files", + "compile-ts": "cd client && tsc && cd ../server && tsc", + "compile-ts//": "Compile TS files", "compile//": "Compile the extension for packaging and publishing", "eslint": "npm run eslint:files -- client server && echo No ESLint problems", "eslint:files": "eslint --max-warnings=0", @@ -51,7 +51,7 @@ "sort-package-json:fix": "sort-package-json", "test": "npm run test-grammar && npm run test-unit", "test-grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", - "pretest-unit": "npm run compile-test", + "pretest-unit": "npm run compile-ts", "test-unit": "cd client && vscode-test", "test//": "Run unit tests, not grammar tests", "validate": "npm run lint && npm run test && npm run package", @@ -68,63 +68,63 @@ { "enablement": "!isWeb", "command": "ahk++.debugAttach", - "title": "%ahk++.debugAttach%", + "title": "%ahk++.command.debugAttach%", "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && shellExecutionSupported", "command": "ahk++.debugParams", - "title": "%ahk++.debugParams%", + "title": "%ahk++.command.debugParams%", "category": "AHK++" }, { "enablement": "editorLangId == ahk2", "command": "ahk++.diagnostic.full", - "title": "%ahk++.diagnostic.full%", + "title": "%ahk++.command.diagnostic.full%", "category": "AHK++" }, { "enablement": "editorLangId == ahk2", "command": "ahk++.exportSymbols", - "title": "%ahk++.exportSymbols%", + "title": "%ahk++.command.exportSymbols%", "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && shellExecutionSupported", "command": "ahk++.run", - "title": "%ahk++.run%", + "title": "%ahk++.command.run%", "icon": "$(play)", "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && !isWeb", "command": "ahk++.runSelection", - "title": "%ahk++.runSelection%", + "title": "%ahk++.command.runSelection%", "category": "AHK++" }, { "enablement": "editorLangId == ahk2 && !isWeb", "command": "ahk++.stop", - "title": "%ahk++.stop%", + "title": "%ahk++.command.stop%", "icon": "$(stop)", "category": "AHK++" }, { "enablement": "editorLangId == ahk2", "command": "ahk++.addDocComment", - "title": "%ahk++.addDocComment%", + "title": "%ahk++.command.addDocComment%", "category": "AHK++" }, { "enablement": "!isWeb", "command": "ahk++.setV2Interpreter", - "title": "%ahk++.setV2Interpreter%", + "title": "%ahk++.command.setV2Interpreter%", "category": "AHK++" }, { "enablement": "editorLangId == ahk2", "command": "ahk++.updateVersionInfo", - "title": "%ahk++.updateVersionInfo%", + "title": "%ahk++.command.updateVersionInfo%", "category": "AHK++" }, { @@ -142,14 +142,13 @@ { "enablement": "editorLangId == ahk2 && resourceScheme == file", "command": "ahk++.setAScriptDir", - "title": "%ahk++.setAScriptDir%", + "title": "%ahk++.command.setAScriptDir%", "category": "AHK++" } ], "configuration": { - "title": "AutoHotkey2", "properties": { - "AutoHotkey2.AutoLibInclude": { + "ahk++.v2.librarySuggestions": { "scope": "window", "type": "string", "enum": [ @@ -159,27 +158,21 @@ "All" ], "default": "Disabled", - "description": "%ahk2.autolibinclude%" + "description": "%ahk++.config.v2.librarySuggestions%" }, - "AutoHotkey2.CommentTags": { + "ahk++.v2.commentTagRegex": { "scope": "window", "type": "string", "default": "^;;\\s*(?.+)", - "description": "%ahk2.commenttags%" + "markdownDescription": "%ahk++.config.v2.commentTagRegex%" }, - "AutoHotkey2.CompilerCMD": { - "scope": "window", - "type": "string", - "default": "/compress 0 /base ${execPath}", - "markdownDescription": "%ahk2.compilercmd%" - }, - "AutoHotkey2.CompleteFunctionParens": { + "ahk++.v2.completeFunctionCalls": { "scope": "window", "type": "boolean", "default": false, - "markdownDescription": "%ahk2.completefunctionparens%" + "markdownDescription": "%ahk++.config.v2.completeFunctionCalls%" }, - "AutoHotkey2.DebugConfiguration": { + "ahk++.v2.debugConfiguration": { "scope": "window", "type": "object", "default": { @@ -189,33 +182,33 @@ "useDebugDirective": true, "usePerfTips": true }, - "description": "%ahk2.debugconfiguration%" + "markdownDescription": "%ahk++.config.v2.debugConfiguration%" }, - "AutoHotkey2.Diagnostics.ClassNonDynamicMemberCheck": { + "ahk++.v2.diagnostics.classNonDynamicMemberCheck": { "scope": "window", "type": "boolean", "default": true, - "description": "%ahk2.diagnostics.class-non-dynamic-member-check%" + "description": "%ahk++.config.v2.diagnostics.classNonDynamicMemberCheck%" }, - "AutoHotkey2.Diagnostics.ParamsCheck": { + "ahk++.v2.diagnostics.paramsCheck": { "scope": "window", "type": "boolean", "default": true, - "description": "%ahk2.diagnostics.paramscheck%" + "description": "%ahk++.config.v2.diagnostics.paramsCheck%" }, - "AutoHotkey2.Warn.VarUnset": { + "ahk++.v2.warn.varUnset": { "scope": "window", "type": "boolean", "default": true, - "description": "%ahk2.warn.varunset%" + "description": "%ahk++.config.v2.warn.varUnset%" }, - "AutoHotkey2.Warn.LocalSameAsGlobal": { + "ahk++.v2.warn.localSameAsGlobal": { "scope": "window", "type": "boolean", "default": false, - "description": "%ahk2.warn.localsameasglobal%" + "description": "%ahk++.config.v2.warn.localSameAsGlobal%" }, - "AutoHotkey2.Warn.CallWithoutParentheses": { + "ahk++.v2.warn.callWithoutParentheses": { "scope": "window", "type": "string", "enum": [ @@ -224,9 +217,9 @@ "On" ], "default": "Off", - "description": "%ahk2.warn.callwithoutparentheses%" + "description": "%ahk++.config.v2.warn.callWithoutParentheses%" }, - "AutoHotkey2.ActionWhenV1IsDetected": { + "ahk++.v2.actionWhenV1Detected": { "scope": "window", "type": "string", "default": "Warn", @@ -237,9 +230,9 @@ "SwitchToV1", "SkipLine" ], - "description": "%ahk2.actionwhenv1isdetected%" + "description": "%ahk++.config.v2.actionWhenV1Detected%" }, - "AutoHotkey2.CompletionCommitCharacters": { + "ahk++.v2.completionCommitCharacters": { "scope": "window", "type": "object", "properties": { @@ -250,16 +243,13 @@ "type": "string" } }, - "additionalProperties": { - "type": "string" - }, "default": { "Class": ".(", "Function": "(" }, - "markdownDescription": "%ahk2.completioncommitcharacters%" + "markdownDescription": "%ahk++.config.v2.completionCommitCharacters%" }, - "AutoHotkey2.Files.Exclude": { + "ahk++.Files.Exclude": { "scope": "window", "type": "array", "default": [], @@ -267,19 +257,19 @@ "type": "string" }, "uniqueItems": true, - "description": "%ahk2.files.exclude%" + "description": "%ahk++.config.v2.files.exclude%" }, - "AutoHotkey2.Files.ScanMaxDepth": { + "ahk++.Files.ScanMaxDepth": { "scope": "window", "type": "integer", "default": 2, - "description": "%ahk2.files.scanmaxdepth%" + "description": "%ahk++.config.v2.files.maxScanDepth%" }, - "AutoHotkey2.FormatOptions": { + "ahk++.v2.formatter": { "scope": "window", "type": "object", "properties": { - "array_style": { + "arrayStyle": { "type": "string", "enum": [ "collapse", @@ -288,7 +278,7 @@ ], "default": "none" }, - "brace_style": { + "braceStyle": { "type": "string", "enum": [ "One True Brace", @@ -301,31 +291,31 @@ "if 1 {\n}\nelse {\n}" ] }, - "break_chained_methods": { + "breakChainedMethods": { "type": "boolean", "default": false }, - "ignore_comment": { + "ignoreComment": { "type": "boolean", "default": false }, - "indent_string": { + "indentString": { "type": "string", "default": "\t" }, - "indent_between_hotif_directive": { + "indentBetweenHotIfDirectives": { "type": "boolean", "default": false }, - "keyword_start_with_uppercase": { + "keywordStartWithUppercase": { "type": "boolean", "default": false }, - "max_preserve_newlines": { + "maxPreserveNewlines": { "type": "number", "default": 2 }, - "object_style": { + "objectStyle": { "type": "string", "enum": [ "collapse", @@ -334,64 +324,61 @@ ], "default": "none" }, - "preserve_newlines": { + "preserveNewlines": { "type": "boolean", "default": true }, - "space_before_conditional": { + "spaceBeforeConditional": { "type": "boolean", "default": true }, - "space_after_double_colon": { + "spaceAfterDoubleColon": { "type": "boolean", "default": true }, - "space_in_empty_paren": { + "spaceInEmptyParen": { "type": "boolean", "default": false }, - "space_in_other": { + "spaceInOther": { "type": "boolean", "default": true }, - "space_in_paren": { + "spaceInParen": { "type": "boolean", "default": false }, - "switch_case_alignment": { + "switchCaseAlignment": { "type": "boolean", "default": false }, - "symbol_with_same_case": { + "symbolWithSameCase": { "type": "boolean", "default": false }, - "white_space_before_inline_comment": { + "whitespaceBeforeInlineComment": { "type": "string" }, - "wrap_line_length": { + "wrapLineLength": { "type": "number", "default": 0 } }, - "additionalProperties": { - "type": "string" - }, "default": {} }, - "AutoHotkey2.InterpreterPath": { + "ahk++.v2.file.interpreterPath": { "scope": "window", "type": "string", - "default": "C:\\Program Files\\Autohotkey\\v2\\AutoHotkey.exe", - "markdownDescription": "%ahk2.interpreterpath%" + "default": "C:/Program Files/Autohotkey/v2/AutoHotkey.exe", + "markdownDescription": "%ahk++.config.v2.file.interpreterPath%" }, - "AutoHotkey2.SymbolFoldingFromOpenBrace": { + "ahk++.symbolFoldingFromOpenBrace": { "scope": "window", "type": "boolean", "default": false, - "description": "%ahk2.symbolfoldingfromopenbrace%" + "description": "%ahk++.config.v2.symbolFoldingFromOpenBrace%" }, - "AutoHotkey2.WorkingDirs": { + "ahk++.workingDirectories": { "scope": "window", "type": "array", "default": [], @@ -399,12 +386,12 @@ "type": "string" }, "uniqueItems": true, - "description": "%ahk2.workingdirs%" + "description": "%ahk++.config.v2.workingDirectories%" }, - "AutoHotkey2.Syntaxes": { + "ahk++.v2.syntaxes": { "scope": "window", "type": "string", - "markdownDescription": "%ahk2.syntaxes%" + "markdownDescription": "%ahk++.config.v2.syntaxes%" } } }, @@ -462,7 +449,7 @@ { "id": "ahk2", "aliases": [ - "AutoHotkey2", + "ahk++", "autohotkey2", "ahk2" ], diff --git a/package.nls.json b/package.nls.json index cbee2c87..3c7f6aba 100644 --- a/package.nls.json +++ b/package.nls.json @@ -1,32 +1,31 @@ { - "ahk2.actionwhenv1isdetected": "Action when v1 script is detected", - "ahk2.autolibinclude": "Provide completion and automatic include from User and Standard library, Local library", - "ahk2.commenttags": "A regular expression used to extract named tags from comments and generate module symbols", - "ahk2.compilercmd": "Compiler command line options. If ahk2exe.exe is not specified, the default path will be used. `${execPath}` is equal to the currently selected AutoHotkey.exe", - "ahk2.completefunctionparens": "Parentheses are added to function completion when there is no `(` or `[` on the right; otherwise move the cursor to the right", - "ahk2.completioncommitcharacters": "Characters which commit auto completion, such as `.(`", - "ahk++.debugAttach": "Attach Running Script", - "ahk++.debugParams": "Debug Script with Params", - "ahk2.debugconfiguration": "Append debugging configuration to the currently started debugger, same as launch.json configuration", - "ahk2.description": "Autohotkey2 Language Support using vscode-lsp", - "ahk++.diagnostic.full": "Diagnostic full text", - "ahk2.diagnostics.class-non-dynamic-member-check": "Check whether non-dynamic members of class exist", - "ahk2.diagnostics.paramscheck": "Check that the function call has the correct number of arguments", - "ahk2.warn.varunset": "Display warnings for each variable that has never been directly assigned or used with the reference operator", - "ahk2.warn.localsameasglobal": "Display warnings for each undeclared local variable which has the same name as a global variable", - "ahk2.warn.callwithoutparentheses": "Display warnings for each function or method call without parentheses", - "ahk++.exportSymbols": "Export AHK Symbols", - "ahk2.files.exclude": "Configure glob patterns for excluding files and folders when scanning ahk files.", - "ahk2.files.scanmaxdepth": "Controls the depth when scanning ahk files.", - "ahk++.addDocComment": "Add Doc Comment", - "ahk2.interpreterpath": "The path of the `AutoHotkey.exe` executable file. If `AutoHotkeyUX.exe` is selected, the script will be launched using UX Launcher.", - "ahk++.run": "Run Script", - "ahk++.runSelection": "Run Selection", - "ahk++.setV2Interpreter": "Set AHK v2 Interpreter", - "ahk++.setAScriptDir": "Set A_ScriptDir Here", - "ahk++.stop": "Stop AHK Script", - "ahk2.symbolfoldingfromopenbrace": "Forced symbol folding starts at open brace", - "ahk2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", - "ahk++.updateVersionInfo": "Update File Version Info", - "ahk2.workingdirs": "Sets the working directory for the script" + "ahk++.command.addDocComment": "Add Doc Comment", + "ahk++.command.debugAttach": "Debug AHK and Attach", + "ahk++.command.debugParams": "Debug AHK with Params", + "ahk++.command.diagnostic.full": "Run AHK++ Diagnostic", + "ahk++.command.exportSymbols": "Export AHK Symbols", + "ahk++.command.run": "Run AHK Script", + "ahk++.command.runSelection": "Run Selection", + "ahk++.command.setAScriptDir": "Set A_ScriptDir Here", + "ahk++.command.setV2Interpreter": "Set AHK v2 Interpreter", + "ahk++.command.stop": "Stop AHK Script", + "ahk++.command.updateVersionInfo": "Update File Version Info", + "ahk++.config.v2.commentTagRegex": "The regular expression for custom symbols to appear in the breadcrumb and elsewhere. Default regex matches any line that starts with `;;`", + "ahk++.config.v2.completeFunctionCalls": "Whether to automatically add parenetheses when calling a function", + "ahk++.config.v2.debugConfiguration": "The [launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) to use when debugging", + "ahk++.config.v2.diagnostics.classNonDynamicMemberCheck": "Check whether non-dynamic members of a class exist", + "ahk++.config.v2.diagnostics.paramsCheck": "Check that the function call has the correct number of arguments", + "ahk++.config.v2.librarySuggestions": "Which libraries to suggest functions from, if any.", + "ahk++.config.v2.warn.localSameAsGlobal": "Display warnings for each undeclared local variable that has the same name as a global variable. Changes take effect after restart.", + "ahk++.config.v2.warn.varUnset": "Display a warning when referencing an unassigned variable. Changes take effect after restart.", + + "ahk++.config.v2.actionWhenV1Detected": "Action when v1 script is detected", + "ahk++.config.v2.completionCommitCharacters": "Characters which commit auto-completion. Defaults to `.(`", + "ahk++.config.v2.warn.callWithoutParentheses": "Display warnings for each function or method call without parentheses", + "ahk++.config.v2.files.exclude": "Configure glob patterns for excluding files and folders when scanning ahk files.", + "ahk++.config.v2.files.maxScanDepth": "Controls the depth when scanning ahk files.", + "ahk++.config.v2.file.interpreterPath": "The path of the `AutoHotkey.exe` executable file. If `AutoHotkeyUX.exe` is selected, the script will be launched using UX Launcher.", + "ahk++.config.v2.symbolFoldingFromOpenBrace": "Forced symbol folding starts at open brace", + "ahk++.config.v2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", + "ahk++.config.v2.workingDirectories": "Sets the working directory for the script" } diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index 12b5fc96..833f3e5f 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -1,37 +1,36 @@ { + "ahk++.command.addDocComment": "生成注释模板", + "ahk++.command.debugAttach": "附加到运行中的脚本", + "ahk++.command.debugParams": "带参调试", + "ahk++.command.diagnostic.full": "诊断全文", + "ahk++.command.exportSymbols": "导出ahk类和函数", + "ahk++.command.run": "运行脚本", + "ahk++.command.runSelection": "运行选择的脚本", + "ahk++.command.setAScriptDir": "设置此处为A_ScriptDir", + "ahk++.command.setV2Interpreter": "选择AutoHotkey2解释器", + "ahk++.command.stop": "停止运行中的脚本", + "ahk++.command.updateVersionInfo": "更新文件版本信息", + "ahk++.config.v2.commentTagRegex": "用来从注释中提取命名标记的正则表达式, 并生成模块符号", + "ahk++.config.v2.completeFunctionCalls": "当右侧不存在`(`或`[`时, 给函数补全添加括号; 否则向右移动光标", + "ahk++.config.v2.librarySuggestions": "对用户库和标准库, 本地库提供补全和自动include", + "ahk++.config.v2.debugConfiguration": "追加调试配置到当前启动的调试器, 与launch.json配置相同", + "ahk++.config.v2.diagnostics.classNonDynamicMemberCheck": "检查类非动态成员是否存在", + "ahk++.config.v2.diagnostics.paramsCheck": "检查函数调用参数个数是否正确", + "ahk++.config.v2.warn.localSameAsGlobal": "为每个与全局变量同名的未声明的局部变量显示警告", + "ahk++.config.v2.warn.varUnset": "为每个从未直接赋值或与引用操作符一起使用的变量的显示警告", + "action.skipline": "跳过行", "action.stopparsing": "停止解析", "action.switchtov1": "切换到ahk v1", - "ahk2.actionwhenv1isdetected": "检测到v1脚本时的行为", - "ahk2.autolibinclude": "对用户库和标准库, 本地库提供补全和自动include", - "ahk2.commenttags": "用来从注释中提取命名标记的正则表达式, 并生成模块符号", - "ahk2.compilercmd": "编译器命令行选项. 如果未指定ahk2exe.exe, 将使用默认路径. `${execPath}`等价于当前选择的AutoHotkey.exe", - "ahk2.completefunctionparens": "当右侧不存在`(`或`[`时, 给函数补全添加括号; 否则向右移动光标", - "ahk2.completioncommitcharacters": "提交自动完成的字符, 例如`.(`", - "ahk++.debugAttach": "附加到运行中的脚本", - "ahk++.debugParams": "带参调试", - "ahk2.debugconfiguration": "追加调试配置到当前启动的调试器, 与launch.json配置相同", - "ahk2.description": "基于 vscode-lsp 协议的 Autohotkey2 语言支持", - "ahk++.diagnostic.full": "诊断全文", - "ahk2.diagnostics.class-non-dynamic-member-check": "检查类非动态成员是否存在", - "ahk2.diagnostics.paramscheck": "检查函数调用参数个数是否正确", - "ahk2.warn.varunset": "为每个从未直接赋值或与引用操作符一起使用的变量的显示警告", - "ahk2.warn.localsameasglobal": "为每个与全局变量同名的未声明的局部变量显示警告", - "ahk2.warn.callwithoutparentheses": "为每个不带括号的函数或方法调用显示警告", - "ahk++.exportSymbols": "导出ahk类和函数", - "ahk2.files.exclude": "配置 glob 模式以在扫描ahk文件时排除文件和文件夹.", - "ahk2.files.scanmaxdepth": "控制扫描ahk文件时的深度.", - "ahk++.addDocComment": "生成注释模板", - "ahk2.interpreterpath": "`AutoHotkey.exe`可执行文件的路径. 如果选择`AutoHotkeyUX.exe`, 将使用UX Launcher启动脚本.", - "ahk++.run": "运行脚本", - "ahk++.runSelection": "运行选择的脚本", - "ahk++.setV2Interpreter": "选择AutoHotkey2解释器", - "ahk++.setAScriptDir": "设置此处为A_ScriptDir", - "ahk++.stop": "停止运行中的脚本", - "ahk2.symbolfoldingfromopenbrace": "强制符号折叠从大括号处开始", - "ahk2.syntaxes": "指定用于智能感知的`ahk2.json`, `*.snippet.json`和`ahk2.d.ahk`文件的文件夹路径.", - "ahk++.updateVersionInfo": "更新文件版本信息", - "ahk2.workingdirs": "设置脚本的工作目录", + "ahk++.config.v2.actionWhenV1Detected": "检测到v1脚本时的行为", + "ahk++.config.v2.completionCommitCharacters": "提交自动完成的字符, 例如`.(`", + "ahk++.config.v2.warn.callWithoutParentheses": "为每个不带括号的函数或方法调用显示警告", + "ahk++.config.v2.files.exclude": "配置 glob 模式以在扫描ahk文件时排除文件和文件夹.", + "ahk++.config.v2.files.maxScanDepth": "控制扫描ahk文件时的深度.", + "ahk++.config.v2.file.interpreterPath": "`AutoHotkey.exe`可执行文件的路径. 如果选择`AutoHotkeyUX.exe`, 将使用UX Launcher启动脚本.", + "ahk++.config.v2.symbolFoldingFromOpenBrace": "强制符号折叠从大括号处开始", + "ahk++.config.v2.syntaxes": "指定用于智能感知的`ahk2.json`, `*.snippet.json`和`ahk2.d.ahk`文件的文件夹路径.", + "ahk++.config.v2.workingDirectories": "设置脚本的工作目录", "codeaction.include": "导入 '{0}'", "completionitem.author": "添加作者, 描述, 日期, 版本等文件信息.", "completionitem.generatecomment": "生成当前作用域函数/方法的注释模板.", diff --git a/readme.md b/readme.md new file mode 100644 index 00000000..6e4d1702 --- /dev/null +++ b/readme.md @@ -0,0 +1,5 @@ +# AutoHotkey v2 Language Support + +This codebase is not meant for independent use, but rather as a submodule of [AHK++](https://github.com/mark-wiemer-org/ahkpp). + +It provides AHK v2 language support via the [Language Server Protocol](https://microsoft.github.io/language-server-protocol). diff --git a/server/cli/cli.ts b/server/cli/cli.ts index 35d6da97..414a6d42 100644 --- a/server/cli/cli.ts +++ b/server/cli/cli.ts @@ -1,4 +1,5 @@ import { openFile } from '../src/common'; +import { newFormatterConfig } from '../src/config'; import { Lexer } from '../src/Lexer'; function main() { @@ -13,7 +14,7 @@ function main() { try { const td = openFile(path, false); if (!td) return; - const sc = new Lexer(td).beautify({}); + const sc = new Lexer(td).beautify(newFormatterConfig()); console.log(sc); } catch (e) { console.error(e); diff --git a/server/src/Lexer.ts b/server/src/Lexer.ts index ab7c8cd7..c5024787 100644 --- a/server/src/Lexer.ts +++ b/server/src/Lexer.ts @@ -21,10 +21,11 @@ import { URI } from 'vscode-uri'; import { builtin_ahkv1_commands, builtin_variable, builtin_variable_h } from './constants'; import { action, completionitem, diagnostic, warn } from './localize'; import { - a_vars, ahk_version, ahkuris, ahkvars, alpha_3, connection, extsettings, + a_vars, ahk_version, ahkuris, ahkvars, alpha_3, connection, ahkppConfig, hoverCache, isBrowser, isahk2_h, lexers, libdirs, libfuncs, openAndParse, openFile, restorePath, rootdir, setTextDocumentLanguage, symbolProvider, utils, workspaceFolders } from './common'; +import { newFormatterConfig, FormatterConfig, ObjectOrArrayStyle, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses } from './config'; export interface ParamInfo { offset: number @@ -194,28 +195,6 @@ export interface Context { symbol?: AhkSymbol; }; -export interface FormatOptions { - array_style?: number - brace_style?: number - break_chained_methods?: boolean - ignore_comment?: boolean - indent_string?: string - indent_between_hotif_directive?: boolean - keyword_start_with_uppercase?: boolean - max_preserve_newlines?: number - object_style?: number - preserve_newlines?: boolean - space_before_conditional?: boolean - space_after_double_colon?: boolean - space_in_empty_paren?: boolean - space_in_other?: boolean - space_in_paren?: boolean - switch_case_alignment?: boolean - symbol_with_same_case?: boolean - white_space_before_inline_comment?: string - wrap_line_length?: number -} - interface ParamList extends Array { format?: (params: Variable[]) => void hasref?: boolean @@ -314,7 +293,7 @@ export const THIS: Variable = { export const SUPER: Variable = { ...THIS, name: 'super', detail: completionitem.super() }; export const allIdentifierChar = new RegExp('^[^\x00-\x2f\x3a-\x40\x5b-\x5e\x60\x7b-\x7f]+$'); -let commentTags = new RegExp('^;;\\s*(?.+)'); +let commentTagRegex = new RegExp('^;;\\s*(?.+)'); const ahkprotos = { ANY, OBJECT, STRING, NUMBER, INTEGER, FLOAT, CLASS: ANY, FUNC: ANY, REGEXMATCHINFO: ANY @@ -343,12 +322,10 @@ class ParseStopError { } } -export type ActionType = 'Continue' | 'Warn' | 'SkipLine' | 'SwitchToV1' | 'Stop'; - export class Lexer { - public actionwhenv1?: ActionType; + public actionWhenV1Detected: ActionType = newAhkppConfig().v2.actionWhenV1Detected; public actived = false; - public beautify: (options: FormatOptions, range?: Range) => string; + public beautify: (options: FormatterConfig, range?: Range) => string; public checkmember: boolean | undefined; public children: AhkSymbol[] = []; public d = 0; @@ -387,7 +364,7 @@ export class Lexer { public workspaceFolder = ''; private hotstringExecuteAction = false; constructor(document: TextDocument, scriptdir?: string, d = 0) { - let begin_line: boolean, callWithoutParentheses: boolean | 1, comments: { [line: number]: Token }; + let begin_line: boolean, callWithoutParentheses: CallWithoutParentheses, comments: { [line: number]: Token }; let continuation_sections_mode: boolean | null, currsymbol: AhkSymbol | undefined; let customblocks: { region: number[], bracket: number[] }; let dlldir: string, includedir: string, includetable: { [uri: string]: string }; @@ -400,7 +377,7 @@ export class Lexer { let in_loop = false, maybev1 = 0, requirev2 = false, string_mode = false; interface Flag { - array_style?: number, + arrayStyle?: number, case_body: boolean | null, catch_block: boolean, declaration_statement: boolean, @@ -418,7 +395,7 @@ export class Lexer { last_word: string, loop_block: number, mode: string, - object_style?: number, + objectStyle?: number, parent: Flag, start_line_index: number, ternary_depth?: number, @@ -426,7 +403,7 @@ export class Lexer { try_block: boolean }; let output_lines: { text: string[], indent: number }[], flags: Flag, previous_flags: Flag, flag_store: Flag[]; - let opt: FormatOptions, preindent_string: string, indent_string: string, space_in_other: boolean, ck: Token; + let opt: FormatterConfig, preindentString: string, indentString: string, spaceInOther: boolean, ck: Token; let token_text: string, token_text_low: string, token_type: string, last_type: string, last_text: string; let output_space_before_token: boolean | undefined, is_conditional: boolean; const handlers: { [index: string]: () => void } = { @@ -518,42 +495,29 @@ export class Lexer { return !ignore && _this.findStrOrComment(offset) || eof; } - this.beautify = function (options: FormatOptions, range?: Range) { + this.beautify = function (options: FormatterConfig, range?: Range) { let end_pos: number; !_this.isparsed && _this.parseScript(); - opt = { - break_chained_methods: false, - ignore_comment: false, - indent_string: '\t', - max_preserve_newlines: 3, - preserve_newlines: true, - space_before_conditional: true, - space_after_double_colon: true, - space_in_empty_paren: false, - space_in_other: true, - space_in_paren: false, - wrap_line_length: 0, - ...options - }; + opt = newFormatterConfig(options); last_type = last_text = '', begin_line = true, lst = { ...EMPTY_TOKEN }; last_LF = -1, end_pos = input_length, ck = _this.get_token(0); - preindent_string = input.substring(input.lastIndexOf('\n', parser_pos = ck.offset) + 1, parser_pos); + preindentString = input.substring(input.lastIndexOf('\n', parser_pos = ck.offset) + 1, parser_pos); is_conditional = output_space_before_token = false, format_mode = true; - indent_string = opt.indent_string ?? '\t', space_in_other = opt.space_in_other ?? true; + indentString = opt.indentString ?? '\t', spaceInOther = opt.spaceInOther ?? true; output_lines = [create_output_line()]; flag_store = [], flags = undefined as unknown as Flag; set_mode(MODE.BlockStatement); - if (opt.symbol_with_same_case) + if (opt.symbolWithSameCase) symbolProvider({ textDocument: _this.document }); if (range) { end_pos = _this.document.offsetAt(range.end); ck = _this.find_token(_this.document.offsetAt(range.start)); range.start = _this.document.positionAt(parser_pos = ck.offset); - preindent_string = input.substring(input.lastIndexOf('\n', parser_pos) + 1, parser_pos).match(/^[ \t]*/)![0]; + preindentString = input.substring(input.lastIndexOf('\n', parser_pos) + 1, parser_pos).match(/^[ \t]*/)![0]; } while (true) { @@ -581,7 +545,7 @@ export class Lexer { output_lines.pop(); } range.end = _this.document.positionAt(end); - options.indent_string = preindent_string + indent_string.repeat(flags.indentation_level); + options.indentString = preindentString + indentString.repeat(flags.indentation_level); } while (flags.mode === MODE.Statement) restore_mode(); @@ -601,8 +565,8 @@ export class Lexer { } else if (!is_conditional && !flags.in_expression) { if ((ck.type.endsWith('COMMENT') || !is_line_continue(flags.mode === MODE.Statement ? ck.previous_token ?? EMPTY_TOKEN : {} as Token, ck)) && !(last_type === 'TK_RESERVED' && ['catch', 'else', 'finally', 'until'].includes(last_text))) { - if (opt.max_preserve_newlines && n_newlines > opt.max_preserve_newlines) - n_newlines = opt.max_preserve_newlines; + if (opt.maxPreserveNewlines && n_newlines > opt.maxPreserveNewlines) + n_newlines = opt.maxPreserveNewlines; if (!just_added_newline()) output_lines.push(create_output_line()); @@ -665,9 +629,9 @@ export class Lexer { }; function format_params_default_val(tokens: { [offset: number]: Token }, params: ParamList) { - opt = { max_preserve_newlines: 1 }; - space_in_other = true, indent_string = '\t'; - format_mode = true, preindent_string = ''; + opt = newFormatterConfig({ maxPreserveNewlines: 1 }); + spaceInOther = true, indentString = '\t'; + format_mode = true, preindentString = ''; delete params.format; for (const param of params) { if (!param.range_offset) @@ -1178,7 +1142,7 @@ export class Lexer { begin_line = true, requirev2 = false, maybev1 = 0, lst = { ...EMPTY_TOKEN }, currsymbol = last_comment_fr = undefined; parser_pos = 0, last_LF = -1, customblocks = { region: [], bracket: [] }, continuation_sections_mode = false, h = isahk2_h; this.clear(), includetable = this.include, comments = {}, sharp_offsets = []; - callWithoutParentheses = extsettings.Warn?.CallWithoutParentheses; + callWithoutParentheses = ahkppConfig.v2.warn.callWithoutParentheses; try { const rs = utils.get_RCDATA('#2'); rs && (includetable[rs.uri] = rs.path); @@ -1195,7 +1159,7 @@ export class Lexer { this.diags = this.diagnostics.length, this.isparsed = true; customblocks.region.forEach(o => this.addFoldingRange(o, parser_pos - 1, 'region')); if (this.actived) - this.actionwhenv1 ??= 'Continue'; + this.actionWhenV1Detected ??= 'Continue'; } } @@ -1211,7 +1175,7 @@ export class Lexer { if (requirev2) return false; _this.maybev1 ??= maybev1 = 1; - switch (_this.actionwhenv1 ??= extsettings.ActionWhenV1IsDetected) { + switch (_this.actionWhenV1Detected ??= ahkppConfig.v2.actionWhenV1Detected) { case 'SkipLine': { if (!allow_skip) return true; @@ -1232,7 +1196,7 @@ export class Lexer { lst = { ...EMPTY_TOKEN }; } string_mode = true; - tk = get_token_ignore_comment(); + tk = get_token_ignoreComment(); while (tk.ignore && tk.type === 'TK_STRING') { next_LF = input.indexOf('\n', parser_pos); if (next_LF < 0) @@ -1240,7 +1204,7 @@ export class Lexer { if ((s = input.substring(parser_pos, next_LF).trimEnd())) tk.content += s, tk.length += s.length; parser_pos = next_LF; - tk = get_token_ignore_comment(); + tk = get_token_ignoreComment(); } string_mode = false; } while (is_line_continue({} as Token, tk)); @@ -1265,8 +1229,8 @@ export class Lexer { { title: action.skipline(), action: 'SkipLine' }, { title: action.stopparsing(), action: 'Stop' } ).then((reason?: { action: string }) => { - if ((_this.actionwhenv1 = (reason?.action ?? 'Continue') as ActionType) !== 'Stop') - if (_this.actionwhenv1 === 'SwitchToV1') + if ((_this.actionWhenV1Detected = (reason?.action ?? 'Continue') as ActionType) !== 'Stop') + if (_this.actionWhenV1Detected === 'SwitchToV1') setTextDocumentLanguage(_this.document.uri); else _this.update(); }); @@ -2139,7 +2103,7 @@ export class Lexer { } // fall through default: - nk = get_token_ignore_comment(); + nk = get_token_ignoreComment(); if (nk.type === 'TK_EQUALS' || nk.content.match(/^([<>]=?|~=|&&|\|\||[.|?:^]|\*\*?|\/\/?|<<|>>|!?==?)$/)) tk.type = 'TK_WORD', parser_pos = tpos, _this.addDiagnostic(diagnostic.reservedworderr(tk.content), tk.offset, tk.length); else { @@ -2188,10 +2152,10 @@ export class Lexer { let p: Token | undefined, nk: Token; const bp = tk.offset; line_begin_pos = bp; - lk = nk = tk, p = get_token_ignore_comment(); + lk = nk = tk, p = get_token_ignoreComment(); if (p.topofline || p.content !== '(') tk = p, p = undefined; - else tk = get_token_ignore_comment(); + else tk = get_token_ignoreComment(); if (tk.topofline || (tk.type !== 'TK_WORD' && !allIdentifierChar.test(tk.content))) { if (p) { parser_pos = p.offset - 1; @@ -2212,7 +2176,7 @@ export class Lexer { if (tk.type !== 'TK_WORD') _this.addDiagnostic(diagnostic.unexpected(tk.content), tk.offset, tk.length); else addvariable(tk), tp += tk.content; - lk = tk, tk = get_token_ignore_comment(); + lk = tk, tk = get_token_ignoreComment(); if (tk.type === 'TK_DOT') { nexttoken(); while (true) { @@ -2232,7 +2196,7 @@ export class Lexer { } !tp.startsWith('@') && tps.push(tp); if (tk.content === ',') { - lk = tk, tk = get_token_ignore_comment(); + lk = tk, tk = get_token_ignoreComment(); if (!allIdentifierChar.test(tk.content)) break; } else @@ -2252,14 +2216,14 @@ export class Lexer { } } if (tk.content.toLowerCase() === 'as') { - lk = tk, tk = get_token_ignore_comment(); + lk = tk, tk = get_token_ignoreComment(); next = false; if (tk.type !== 'TK_WORD' && !allIdentifierChar.test(tk.content)) { _this.addDiagnostic(diagnostic.unexpected(nk.content), nk.offset, nk.length); } else if (tk.type !== 'TK_WORD') _this.addDiagnostic(diagnostic.reservedworderr(tk.content), tk.offset, tk.length), tk.type = 'TK_WORD'; else { - const t = get_token_ignore_comment(); + const t = get_token_ignoreComment(); parser_pos = tk.offset + tk.length; if (!t.topofline && t.content !== '{' && !(p && t.content === ')')) _this.addDiagnostic(diagnostic.unexpected(nk.content), nk.offset, nk.length), next = false; @@ -2283,7 +2247,7 @@ export class Lexer { } else { if (p) { if (tk.content === ')') - lk = tk, tk = get_token_ignore_comment(); + lk = tk, tk = get_token_ignoreComment(); else _this.addDiagnostic(diagnostic.missing(')'), p.offset, 1); } if (!tk.topofline) @@ -2333,7 +2297,7 @@ export class Lexer { let act, offset; /^=>?$/.test(tk.content) && (act = tk.content, offset = tk.offset); if (maybev1 && act === '=' && stop_parse(tk, true) && - (next = false, lk = EMPTY_TOKEN, tk = get_token_ignore_comment())) + (next = false, lk = EMPTY_TOKEN, tk = get_token_ignoreComment())) return; reset_extra_index(tk), tk = lk, lk = EMPTY_TOKEN, next = false; parser_pos = tk.skip_pos ?? tk.offset + tk.length; @@ -2347,7 +2311,7 @@ export class Lexer { const pi: ParamInfo = { offset: fc.offset, miss: [], comma: [], count: 0, unknown: false, name: fc.content }; if (nextc === ',' || maybev1) { if (type === SymbolKind.Function && builtin_ahkv1_commands.includes(fc.content.toLowerCase()) && - stop_parse(fc, true) && (next = false, lk = EMPTY_TOKEN, tk = get_token_ignore_comment())) + stop_parse(fc, true) && (next = false, lk = EMPTY_TOKEN, tk = get_token_ignoreComment())) return; nextc === ',' && _this.addDiagnostic(diagnostic.funccallerr(), tk.offset, 1); } @@ -2371,7 +2335,7 @@ export class Lexer { } if (type === SymbolKind.Method) maybeclassprop(fc, true); - if (callWithoutParentheses && (callWithoutParentheses === true || tp === 'TK_START_EXPR')) + if (callWithoutParentheses != CallWithoutParentheses.Off && (callWithoutParentheses == CallWithoutParentheses.On || tp === 'TK_START_EXPR')) _this.diagnostics.push({ message: warn.callwithoutparentheses(), range: tn.selectionRange, severity: DiagnosticSeverity.Warning }); } @@ -2470,7 +2434,7 @@ export class Lexer { } if (diag) { if (act === '=' && stop_parse(tokens[nk!.next_token_offset], true) && - (next = false, lk = EMPTY_TOKEN, tk = get_token_ignore_comment())) + (next = false, lk = EMPTY_TOKEN, tk = get_token_ignoreComment())) return []; _this.addDiagnostic(`${diagnostic.unexpected(act)}, ${diagnostic.didyoumean(':=').toLowerCase()}`, min, act.length); } @@ -3171,7 +3135,7 @@ export class Lexer { } else _this.addDiagnostic(diagnostic.unexpected('*'), t.offset, 1); } else if (tk.content === '&') { const t = tk; - tk = get_token_ignore_comment(); + tk = get_token_ignoreComment(); if (tk.type === 'TK_WORD') { byref = true, next = false; continue; } else _this.addDiagnostic(diagnostic.unexpected('&'), t.offset, 1); @@ -3414,7 +3378,7 @@ export class Lexer { lk = llk, parser_pos = tp - 1, tk = get_next_token(), b = tk.offset; rs = [], par = parse_params(true); if (!par) { par = [], _this.addDiagnostic(diagnostic.invalidparam(), b, tk.offset - b + 1); } - nk = get_token_ignore_comment(); + nk = get_token_ignoreComment(); } else if (lk.type === 'TK_WORD' && input.charAt(lk.offset - 1) !== '.') { nk = tk, b = lk.offset; par = [Variable.create(lk.content, SymbolKind.Variable, make_range(lk.offset, lk.length))]; @@ -3669,7 +3633,7 @@ export class Lexer { nexttoken(), parse_pair('(', ')'); const pc = tokens[tk.previous_pair_pos!]?.paraminfo?.count ?? 0; if (pc !== 1) - extsettings.Diagnostics.ParamsCheck && _this.addDiagnostic(diagnostic.paramcounterr(1, pc), fc.offset, parser_pos - fc.offset); + ahkppConfig.v2.diagnostics.paramsCheck && _this.addDiagnostic(diagnostic.paramcounterr(1, pc), fc.offset, parser_pos - fc.offset); else if (result.length > l && lk.type === 'TK_WORD') { const vr = result.at(-1) as Variable; if (lk.content === vr.name && lk.offset === _this.document.offsetAt(vr.range.start)) @@ -4015,7 +3979,7 @@ export class Lexer { } function nexttoken() { - if (next) return lk = tk, next = (tk = get_token_ignore_comment()).type !== 'TK_EOF'; + if (next) return lk = tk, next = (tk = get_token_ignoreComment()).type !== 'TK_EOF'; else return next = tk.type !== 'TK_EOF'; } } @@ -4434,7 +4398,7 @@ export class Lexer { function create_flags(flags_base: Flag | undefined, mode: string) { let indentation_level = 0, had_comment = 0, ternary_depth; - let last_text = '', last_word = '', array_style, object_style; + let last_text = '', last_word = '', arrayStyle, objectStyle; let in_expression = [MODE.ArrayLiteral, MODE.Expression, MODE.ObjectLiteral].includes(mode); if (flags_base) { indentation_level = flags_base.indentation_level; @@ -4442,12 +4406,12 @@ export class Lexer { last_text = flags_base.last_text; last_word = flags_base.last_word; in_expression ||= flags_base.in_expression; - array_style = flags_base.array_style; - object_style = flags_base.object_style; + arrayStyle = flags_base.arrayStyle; + objectStyle = flags_base.objectStyle; } const next_flags: Flag = { - array_style, + arrayStyle, case_body: false, catch_block: false, declaration_statement: false, @@ -4463,7 +4427,7 @@ export class Lexer { last_word, loop_block: 0, mode, - object_style, + objectStyle, parent: flags_base!, start_line_index: output_lines.length, ternary_depth, @@ -4493,19 +4457,19 @@ export class Lexer { } function allow_wrap_or_preserved_newline(force_linewrap = false): void { - if (opt.wrap_line_length && !force_linewrap) { + if (opt.wrapLineLength && !force_linewrap) { const line = output_lines.at(-1)!; let proposed_line_length = 0; // never wrap the first token of a line. if (line.text.length > 0) { proposed_line_length = line.text.join('').length + token_text.length + (output_space_before_token ? 1 : 0); - if (proposed_line_length >= opt.wrap_line_length) { + if (proposed_line_length >= opt.wrapLineLength) { force_linewrap = true; } } } - if (((opt.preserve_newlines && input_wanted_newline) || force_linewrap) && !just_added_newline()) { + if (((opt.preserveNewlines && input_wanted_newline) || force_linewrap) && !just_added_newline()) { print_newline(true); } } @@ -4528,22 +4492,22 @@ export class Lexer { function print_token(printable_token?: string): void { const line = output_lines.at(-1)!; if (!line.text.length) { - if (preindent_string) - line.text.push(preindent_string); - flags.indentation_level = print_indent_string(flags.indentation_level); + if (preindentString) + line.text.push(preindentString); + flags.indentation_level = print_indentString(flags.indentation_level); } else if (output_space_before_token) line.text.push(' '); output_space_before_token = undefined; line.text.push(printable_token ?? token_text); - function print_indent_string(level: number) { + function print_indentString(level: number) { if (level) { for (let i = output_lines.length - 2; i >= 0; i--) if (output_lines[i].text.length) { level = Math.min(output_lines[i].indent + 1, level); break; } - line.text.push(indent_string.repeat(line.indent = level)); + line.text.push(indentString.repeat(line.indent = level)); } return level; } @@ -4624,7 +4588,7 @@ export class Lexer { return c === find_char ? local_pos : 0; } - function get_token_ignore_comment(depth = 0): Token { + function get_token_ignoreComment(depth = 0): Token { let tk: Token; do { tk = get_next_token(depth); } while (tk.type.endsWith('COMMENT')); return tk; @@ -4710,7 +4674,7 @@ export class Lexer { } string_mode = execute = true; const _lst = lst; - let tk = get_token_ignore_comment(depth + 1), t: number; + let tk = get_token_ignoreComment(depth + 1), t: number; while (tk.ignore && tk.type === 'TK_STRING') { if ((parser_pos = input.indexOf('\n', t = parser_pos)) < 0) parser_pos = input_length; @@ -4719,7 +4683,7 @@ export class Lexer { tk.content += s, tk.length += s.length; } _this.tokenranges.push({ start: tk.offset, end: tk.offset + tk.length, type: 3 }); - execute = false, tk = get_token_ignore_comment(depth + 1); + execute = false, tk = get_token_ignoreComment(depth + 1); } string_mode = false, lst = _lst; if (!execute && lst.type === 'TK_HOT') { @@ -4851,7 +4815,7 @@ export class Lexer { lst.data = { content, offset, length: parser_pos - offset }; lst.skip_pos = parser_pos; _this.tokenranges.push({ start: offset, end: parser_pos, type: 3, previous: lst.offset }); - const js = content.match(/(^|[ \t])join([^ \t]*)/i), ignore_comment = /(^|[ \t])[Cc]/.test(content); + const js = content.match(/(^|[ \t])join([^ \t]*)/i), ignoreComment = /(^|[ \t])[Cc]/.test(content); const _lst = lst, _mode = format_mode; let lk = lst, optionend = false, llf = parser_pos, sum = 0, tk: Token; let create_tokens: (n: number, LF: number) => typeof lk.previous_extra_tokens = () => undefined; @@ -4884,7 +4848,7 @@ export class Lexer { } format_mode = true, tk = get_next_token(); if (continuation_sections_mode && tk.type !== 'TK_EOF') { - if (ignore_comment && tk.topofline && tk.type.endsWith('COMMENT')) { + if (ignoreComment && tk.topofline && tk.type.endsWith('COMMENT')) { sum = n_newlines - 2; } else { if (n_newlines > 1) @@ -4895,7 +4859,7 @@ export class Lexer { } while (continuation_sections_mode && tk.type !== 'TK_EOF') { if (tk.topofline) { - if (ignore_comment && tk.type.endsWith('COMMENT')) { + if (ignoreComment && tk.type.endsWith('COMMENT')) { sum += n_newlines - 1; } else { if ((sum += n_newlines)) @@ -5013,7 +4977,7 @@ export class Lexer { return lst; } string_mode = block_mode = true; - let tk = get_token_ignore_comment(depth + 1); + let tk = get_token_ignoreComment(depth + 1); stringend: while (tk.ignore && tk.type === 'TK_STRING') { const p = parser_pos, data = tk.data as number[]; @@ -5044,7 +5008,7 @@ export class Lexer { tk.content += s, tk.length += s.length; _this.tokenranges.push({ start: tk.offset, end: tk.offset + tk.length, type: 3 }); } - tk = get_token_ignore_comment(depth + 1); + tk = get_token_ignoreComment(depth + 1); } if (!tk.ignore || tk.type !== 'TK_STRING') if ((pt = tk.previous_token)) @@ -5147,7 +5111,7 @@ export class Lexer { rg = make_range(parser_pos + 1, next_LF - parser_pos - 1), rg)); } else if ((t = customblocks.region.pop()) !== undefined) _this.addFoldingRange(t, parser_pos + 1, 'region'); - } else if ((t = line.match(commentTags))) { + } else if ((t = line.match(commentTagRegex))) { const g = t.groups; for (const tag in g) if (tag.startsWith('tag') && (t = g[tag]?.trim())) @@ -5228,7 +5192,7 @@ export class Lexer { return lst = createToken(c, 'TK_COMMA', offset, 1, bg); else if (c === '?') { lst = createToken(c, 'TK_OPERATOR', offset, 1, bg); - const bak = parser_pos, tk = lst, t = get_token_ignore_comment(depth + 1); + const bak = parser_pos, tk = lst, t = get_token_ignoreComment(depth + 1); parser_pos = bak; if (')]},:??'.includes(t.content) || t.content === '.' && t.type !== 'TK_OPERATOR') { tk.ignore = true; @@ -5294,9 +5258,9 @@ export class Lexer { function get_style() { if (flags.mode === MODE.ObjectLiteral) - return flags.object_style ?? opt.object_style; + return flags.objectStyle ?? opt.objectStyle; if (flags.mode === MODE.ArrayLiteral) - return flags.array_style ?? opt.array_style; + return flags.arrayStyle ?? opt.arrayStyle; } function handle_start_expr(): void { @@ -5317,7 +5281,7 @@ export class Lexer { set_mode(next_mode); print_token(); flags.indentation_level = real_indentation_level() + 1; - if (opt.space_in_paren) { + if (opt.spaceInParen) { output_space_before_token = true; } return; @@ -5337,12 +5301,12 @@ export class Lexer { if (last_text.match(/^(break|continue|goto)$/i)) output_space_before_token = false; else if (['if', 'for', 'while', 'loop', 'case', 'catch', 'switch'].includes(last_text)) - output_space_before_token = Boolean(opt.space_before_conditional); - else output_space_before_token = space_in_other; + output_space_before_token = Boolean(opt.spaceBeforeConditional); + else output_space_before_token = spaceInOther; } if (!start_of_object_property()) { - if (input_wanted_newline && opt.preserve_newlines) + if (input_wanted_newline && opt.preserveNewlines) print_newline(true); else if (last_type === 'TK_EQUALS' || last_type === 'TK_COMMA' || last_type === 'TK_OPERATOR') allow_wrap_or_preserved_newline(); @@ -5357,13 +5321,13 @@ export class Lexer { const c = (ck.data as Token).content; if (c) print_token(c); - } else if (opt.space_in_paren) + } else if (opt.spaceInParen) output_space_before_token = true; // In all cases, if we newline while inside an expression it should be indented. indent(); - if (token_text === '[' && (flags.array_style ?? opt.array_style) === STYLE.expand) + if (token_text === '[' && (flags.arrayStyle ?? opt.arrayStyle) === STYLE.expand) print_newline(true); } @@ -5374,17 +5338,17 @@ export class Lexer { restore_mode(); if (token_text === ']' && flags.mode === MODE.ArrayLiteral) { - const style = flags.array_style ?? opt.array_style; + const style = flags.arrayStyle ?? opt.arrayStyle; if (style === STYLE.collapse || last_text === '[') trim_newlines(); - else if (style || input_wanted_newline && opt.preserve_newlines) + else if (style || input_wanted_newline && opt.preserveNewlines) print_newline(true); } else if ((last_type === 'TK_END_EXPR' || last_type === 'TK_END_BLOCK') && flags.indentation_level < flags.parent.indentation_level) trim_newlines(); else if (last_type !== 'TK_START_EXPR') allow_wrap_or_preserved_newline(); - output_space_before_token = Boolean(opt.space_in_paren && !(last_type === 'TK_START_EXPR' && !opt.space_in_empty_paren)); + output_space_before_token = Boolean(opt.spaceInParen && !(last_type === 'TK_START_EXPR' && !opt.spaceInEmptyParen)); restore_mode(); if (just_added_newline() && output_lines.length > 1) { const level = flags.indentation_level; @@ -5402,11 +5366,11 @@ export class Lexer { if (previous_flags.mode !== MODE.Conditional) previous_flags.indentation_level = flags.indentation_level; - output_space_before_token ||= space_in_other && last_type !== 'TK_START_EXPR'; + output_space_before_token ||= spaceInOther && last_type !== 'TK_START_EXPR'; print_token(), indent(); - if ((flags.object_style ?? opt.object_style) === STYLE.expand) + if ((flags.objectStyle ?? opt.objectStyle) === STYLE.expand) print_newline(true); - else output_space_before_token = space_in_other; + else output_space_before_token = spaceInOther; } else { let level; if (['try', 'if', 'for', 'while', 'loop', 'catch', 'else', 'finally', 'switch'].includes(flags.last_word)) @@ -5416,22 +5380,22 @@ export class Lexer { flags.declaration_statement = false; set_mode(MODE.BlockStatement); flags.indentation_level = level ??= flags.indentation_level; - output_space_before_token ??= space_in_other; + output_space_before_token ??= spaceInOther; if (previous_flags.in_case_statement && last_type === 'TK_LABEL' && /^(default)?:$/.test(last_text)) flags.case_body = null, print_newline(), flags.indentation_level--; - else if (opt.brace_style === 0 || input_wanted_newline && opt.preserve_newlines && !opt.brace_style) + else if (opt.braceStyle === BraceStyle.Allman || input_wanted_newline && opt.preserveNewlines && !opt.braceStyle) if (ck.in_expr === undefined || flags.mode === MODE.Expression) print_newline(true); const need_newline = !just_added_newline(); print_token(); previous_flags.indentation_level = Math.min(previous_flags.indentation_level, flags.indentation_level); - if (!(opt.switch_case_alignment && flags.last_word === 'switch')) + if (!(opt.switchCaseAlignment && flags.last_word === 'switch')) indent(); - if (need_newline || opt.brace_style !== undefined) + if (need_newline || opt.braceStyle !== undefined) print_newline(true); - else output_space_before_token = space_in_other; + else output_space_before_token = spaceInOther; } } @@ -5442,13 +5406,13 @@ export class Lexer { const is_obj = flags.mode === MODE.ObjectLiteral, is_exp = is_obj || (ck.in_expr !== undefined); if (is_obj) { - const style = flags.object_style ?? opt.object_style; + const style = flags.objectStyle ?? opt.objectStyle; if (style === STYLE.collapse || last_text === '{') trim_newlines(); - else if (style || input_wanted_newline && opt.preserve_newlines) + else if (style || input_wanted_newline && opt.preserveNewlines) print_newline(true); - output_space_before_token = space_in_other && last_text !== '{'; - } else if (opt.brace_style !== undefined || input_wanted_newline) + output_space_before_token = spaceInOther && last_text !== '{'; + } else if (opt.braceStyle !== undefined || input_wanted_newline) print_newline(true); restore_mode(); @@ -5456,9 +5420,9 @@ export class Lexer { if (!is_exp) { if (previous_flags.case_body === null) indent(); - if (opt.brace_style !== undefined) + if (opt.braceStyle !== undefined) print_newline(true); - output_space_before_token = space_in_other; + output_space_before_token = spaceInOther; } else if (flags.mode !== MODE.BlockStatement) flags.indentation_level = (flags.parent ?? flags).indentation_level + 1; } @@ -5476,8 +5440,8 @@ export class Lexer { } if (token_type === 'TK_RESERVED') { - if (opt.keyword_start_with_uppercase !== undefined) - token_text = opt.keyword_start_with_uppercase ? + if (opt.keywordStartWithUppercase !== undefined) + token_text = opt.keywordStartWithUppercase ? token_text_low.replace(/^./, s => s.toUpperCase()) : token_text_low; if (is_special_word(token_text_low)) { if (input_wanted_newline) @@ -5570,11 +5534,11 @@ export class Lexer { } if (maybe_need_newline) { trim_newlines(); - if (flags.last_text !== '}' || opt.brace_style! < 1 || input_wanted_newline && opt.preserve_newlines && !opt.brace_style) + if (flags.last_text !== '}' || opt.braceStyle !== BraceStyle.OneTrueBrace || input_wanted_newline && opt.preserveNewlines && !opt.braceStyle) print_newline(true); - else output_space_before_token = space_in_other; + else output_space_before_token = spaceInOther; } else if (input_wanted_newline) - if (last_text === 'else' && !opt.preserve_newlines && ['if', 'for', 'loop', 'while', 'try', 'switch'].includes(token_text_low)) + if (last_text === 'else' && !opt.preserveNewlines && ['if', 'for', 'loop', 'while', 'try', 'switch'].includes(token_text_low)) deindent(); else print_newline(preserve_statement_flags); @@ -5601,7 +5565,7 @@ export class Lexer { if (input_wanted_newline && flags.mode === MODE.Statement && !flags.in_expression && !is_line_continue(ck.previous_token ?? EMPTY_TOKEN, ck)) print_newline(preserve_statement_flags); - else if (input_wanted_newline && (opt.preserve_newlines || ck.symbol)) { + else if (input_wanted_newline && (opt.preserveNewlines || ck.symbol)) { if (ck.symbol || get_style() !== STYLE.collapse) print_newline(!ck.symbol); } else if (['TK_COMMA', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR'].includes(last_type)) @@ -5610,7 +5574,7 @@ export class Lexer { if (!is_conditional && flags.mode === MODE.BlockStatement && ck.symbol?.children) set_mode(MODE.Statement), is_conditional = true; flags.last_word = '_'; - if (opt.symbol_with_same_case) + if (opt.symbolWithSameCase) token_text = ck.definition?.name || token_text; } @@ -5619,9 +5583,9 @@ export class Lexer { function handle_string() { if (start_of_statement()) { - if (input_wanted_newline && opt.preserve_newlines) + if (input_wanted_newline && opt.preserveNewlines) print_newline(true); - else output_space_before_token = flags.declaration_statement ? last_type !== 'TK_OPERATOR' : space_in_other; + else output_space_before_token = flags.declaration_statement ? last_type !== 'TK_OPERATOR' : spaceInOther; } else if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD') { if (input_wanted_newline) print_newline(); @@ -5640,7 +5604,7 @@ export class Lexer { if (ck.ignore) { let p: number; print_newline(true); - if (opt.ignore_comment && token_text.trimStart().startsWith('(') && (p = token_text.indexOf('\n')) > 0) { + if (opt.ignoreComment && token_text.trimStart().startsWith('(') && (p = token_text.indexOf('\n')) > 0) { const t = token_text.slice(0, p).trimEnd().replace(/[ \t]+;.*$/, ''); if (/(^[ \t]*\(|[ \t])c(om(ments?)?)?/i.test(t)) token_text = `${t}\n${token_text.slice(p + 1).replace(/^[ \t]*;.*\r?\n/gm, '').replace(/[ \t]+;.*/gm, '')}`; @@ -5658,9 +5622,9 @@ export class Lexer { // The conditional starts the statement if appropriate. } - output_space_before_token = space_in_other; + output_space_before_token = spaceInOther; print_token(); - output_space_before_token = space_in_other; + output_space_before_token = spaceInOther; } function handle_comma() { @@ -5673,12 +5637,12 @@ export class Lexer { set_mode(MODE.Statement), indent(); if (last_type === 'TK_WORD' && whitespace.includes(ck.prefix_is_whitespace || '\0') && ck.previous_token?.callsite) - input_wanted_newline && opt.preserve_newlines ? print_newline(true) : output_space_before_token = true; + input_wanted_newline && opt.preserveNewlines ? print_newline(true) : output_space_before_token = true; else { - output_space_before_token = space_in_other && last_type === 'TK_COMMA' || last_text === 'for' && last_type === 'TK_RESERVED'; + output_space_before_token = spaceInOther && last_type === 'TK_COMMA' || last_text === 'for' && last_type === 'TK_RESERVED'; if (flags.mode === MODE.Statement && flags.parent.mode === MODE.ObjectLiteral) restore_mode(); - if (input_wanted_newline && opt.preserve_newlines) + if (input_wanted_newline && opt.preserveNewlines) print_newline(true); else if (!just_added_newline()) input_wanted_newline = false; @@ -5689,11 +5653,11 @@ export class Lexer { print_token(); if (style === STYLE.expand) print_newline(true); - else output_space_before_token = space_in_other; + else output_space_before_token = spaceInOther; } function handle_operator() { - let space_before = Boolean(space_in_other || token_text.match(/^\w/)); + let space_before = Boolean(spaceInOther || token_text.match(/^\w/)); let space_after = space_before; if (ck.previous_token?.callsite) output_space_before_token = true; @@ -5726,7 +5690,7 @@ export class Lexer { if (token_text === '%') { space_after = Boolean(ck.previous_pair_pos !== undefined && ' \t'.includes(input.charAt(ck.offset + 1) || '\0')); output_space_before_token ||= Boolean(ck.next_pair_pos && ' \t'.includes(ck.prefix_is_whitespace || '\0')); - if (input_wanted_newline && opt.preserve_newlines) + if (input_wanted_newline && opt.preserveNewlines) if (flags.mode === MODE.Statement && is_line_continue(ck.previous_token ?? EMPTY_TOKEN, ck)) print_newline(true); print_token(); @@ -5742,7 +5706,7 @@ export class Lexer { indent(), print_token(); if (is_next_char('\n')) print_newline(); - else output_space_before_token = space_in_other; + else output_space_before_token = spaceInOther; flags.in_case = false; flags.case_body = true; set_mode(MODE.Statement); @@ -5751,7 +5715,7 @@ export class Lexer { return; } - if (input_wanted_newline && opt.preserve_newlines) + if (input_wanted_newline && opt.preserveNewlines) print_newline(true); else if (last_type === 'TK_OPERATOR' && !last_text.match(/^(--|\+\+|%|!|~|not)$/)) allow_wrap_or_preserved_newline(); @@ -5807,7 +5771,7 @@ export class Lexer { else if (flags.had_comment < 2) trim_newlines(); } - if (opt.ignore_comment) + if (opt.ignoreComment) return; const lines = token_text.split('\n'); @@ -5842,8 +5806,8 @@ export class Lexer { const p = s.indexOf(':'); let k; switch (k = s.substring(0, p).trim()) { - case 'array_style': - case 'object_style': + case 'arrayStyle': + case 'objectStyle': flags[k] = STYLE[s.substring(p + 1).trim() as keyof typeof STYLE]; break; } @@ -5852,13 +5816,13 @@ export class Lexer { function handle_inline_comment() { format_directives(token_text); - if (opt.ignore_comment) + if (opt.ignoreComment) return; if (just_added_newline() && output_lines.length > 1) output_lines.pop(); let t; output_lines[output_lines.length - 1].text.push( - opt.white_space_before_inline_comment || + opt.whitespaceBeforeInlineComment || (((t = ck.previous_token)) ? input.substring(t.skip_pos ?? t.offset + t.length, ck.offset) : '\t'), token_text); print_newline(true); @@ -5874,7 +5838,7 @@ export class Lexer { trim_newlines(); } format_directives(token_text); - if (opt.ignore_comment) + if (opt.ignoreComment) return; token_text.split('\n').forEach(s => { print_newline(true); @@ -5891,7 +5855,7 @@ export class Lexer { // allow preserved newlines before dots in general // force newlines on dots after close paren when break_chained - for bar().baz() - allow_wrap_or_preserved_newline(flags.last_text === ')' && opt.break_chained_methods); + allow_wrap_or_preserved_newline(flags.last_text === ')' && opt.breakChainedMethods); print_token(); } @@ -5902,9 +5866,9 @@ export class Lexer { function handle_sharp() { print_newline(); - if (opt.symbol_with_same_case && token_type === 'TK_SHARP') + if (opt.symbolWithSameCase && token_type === 'TK_SHARP') token_text = hoverCache[token_text_low]?.[0] || token_text; - if (token_text_low === '#hotif' && opt.indent_between_hotif_directive) { + if (token_text_low === '#hotif' && opt.indentBetweenHotIfDirectives) { if (flags.hotif_block) deindent(), flags.hotif_block = false; print_token(); @@ -5918,8 +5882,8 @@ export class Lexer { if (t) print_token(token_type === 'TK_HOTLINE' ? t : ' ' + t); else if (token_type === 'TK_HOT') - output_space_before_token = !!opt.space_after_double_colon; - else output_space_before_token = space_in_other || token_type === 'TK_SHARP'; + output_space_before_token = !!opt.spaceAfterDoubleColon; + else output_space_before_token = spaceInOther || token_type === 'TK_SHARP'; } function handle_label() { @@ -5931,7 +5895,7 @@ export class Lexer { print_token(), indent(); flags.in_case = false; flags.in_case_statement = true; - output_space_before_token = space_in_other; + output_space_before_token = spaceInOther; set_mode(MODE.Statement); flags.case_body = true; return; @@ -6247,7 +6211,7 @@ export class Lexer { return; let workfolder: string; if (!dir) { - for (workfolder of extsettings.WorkingDirs) + for (workfolder of ahkppConfig.v2.workingDirectories) if (this.uri.startsWith(workfolder)) { dir = restorePath(URI.parse(workfolder).fsPath.replace(/[\\/]$/, '')); break; @@ -6305,7 +6269,7 @@ export class Lexer { } private addSymbolFolding(symbol: AhkSymbol, first_brace: number) { - const l1 = extsettings.SymbolFoldingFromOpenBrace ? this.document.positionAt(first_brace).line : symbol.range.start.line; + const l1 = ahkppConfig.v2.symbolFoldingFromOpenBrace ? this.document.positionAt(first_brace).line : symbol.range.start.line; const l2 = symbol.range.end.line - 1; const ranges = this.foldingranges; if (l1 < l2) { @@ -7777,12 +7741,12 @@ export function is_line_continue(lk: Token, tk: Token, parent?: AhkSymbol): bool } } -export function update_comment_tags(regexp: string) { - const old = commentTags; +export function setCommentTagRegex(regex: string) { + const old = commentTagRegex; try { - commentTags = new RegExp(regexp, 'i'); + commentTagRegex = new RegExp(regex, 'i'); } catch (e) { - commentTags = old; + commentTagRegex = old; throw e; } } diff --git a/server/src/browserServerMain.ts b/server/src/browserServerMain.ts index bd1d6d94..79cc2968 100644 --- a/server/src/browserServerMain.ts +++ b/server/src/browserServerMain.ts @@ -8,13 +8,14 @@ import { InitializeResult, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver/browser'; import { - AHKLSSettings, chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, + chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, defintionProvider, documentFormatting, enumNames, executeCommandProvider, exportSymbols, hoverProvider, initahk2cache, Lexer, lexers, loadahk2, loadlocalize, prepareRename, rangeFormatting, referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, - signatureProvider, symbolProvider, typeFormatting, update_settings, workspaceSymbolProvider + signatureProvider, symbolProvider, typeFormatting, updateAhkppConfig, workspaceSymbolProvider } from './common'; +import { AhkppConfig } from './config'; const languageServer = 'ahk2-language-server'; const messageReader = new BrowserMessageReader(self); @@ -78,12 +79,12 @@ connection.onInitialize(params => { result.capabilities.workspace = { workspaceFolders: { supported: true } }; } - const configs: AHKLSSettings = params.initializationOptions; + const ahkppConfig: AhkppConfig = params.initializationOptions; set_ahk_h(true); set_locale(params.locale); - set_dirname(configs.extensionUri!); + set_dirname(ahkppConfig.extensionUri!); loadlocalize(); - update_settings(configs); + updateAhkppConfig(ahkppConfig); set_WorkspaceFolders(workspaceFolders); set_version('3.0.0'); initahk2cache(); @@ -108,14 +109,14 @@ connection.onInitialized(() => { }); connection.onDidChangeConfiguration(async change => { - let newset: AHKLSSettings | undefined = change?.settings; - if (hasConfigurationCapability && !newset) - newset = await connection.workspace.getConfiguration('AutoHotkey2'); - if (!newset) { + let newAhkppConfig: AhkppConfig | undefined = change?.settings; + if (hasConfigurationCapability && !newAhkppConfig) + newAhkppConfig = await connection.workspace.getConfiguration('ahk++'); + if (!newAhkppConfig) { connection.window.showWarningMessage('Failed to obtain the configuration'); return; } - update_settings(newset); + updateAhkppConfig(newAhkppConfig); set_WorkspaceFolders(workspaceFolders); }); @@ -127,7 +128,7 @@ documents.onDidOpen(e => { else lexers[uri] = doc = new Lexer(e.document); doc.actived = true; if (to_ahk2) - doc.actionwhenv1 = 'Continue'; + doc.actionWhenV1Detected = 'Continue'; }); documents.onDidClose(e => lexers[e.document.uri.toLowerCase()]?.close()); @@ -153,7 +154,7 @@ connection.languages.semanticTokens.on(semanticTokensOnFull); connection.languages.semanticTokens.onRange(semanticTokensOnRange); connection.onRequest('ahk2.exportSymbols', exportSymbols); connection.onRequest('ahk2.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); -connection.onRequest('ahk2.getVersionInfo', (uri: string) => { +connection.onRequest('ahk++.getVersionInfo', (uri: string) => { const doc = lexers[uri.toLowerCase()]; if (doc) { const tk = doc.get_token(0); diff --git a/server/src/commandProvider.ts b/server/src/commandProvider.ts index b927bc4e..ab984f4d 100644 --- a/server/src/commandProvider.ts +++ b/server/src/commandProvider.ts @@ -1,13 +1,13 @@ import { CancellationToken, ExecuteCommandParams, Position, Range, SymbolKind } from 'vscode-languageserver'; import { AhkSymbol, ClassNode, FuncNode, Lexer, Property, Token, Variable, - connection, extsettings, find_class, generate_type_annotation, + connection, ahkppConfig, find_class, generate_type_annotation, join_types, lexers, parse_include, restorePath, semanticTokensOnFull, traverse_include, update_include_cache } from './common'; function checkCommand(cmd: string) { - if (extsettings.commands?.includes(cmd)) + if (ahkppConfig.commands?.includes(cmd)) return true; connection.console.warn(`Command '${cmd}' is not implemented!`); return false; diff --git a/server/src/common.ts b/server/src/common.ts index b4933cc3..b996dfc8 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -4,9 +4,10 @@ import { readdirSync, readFileSync, existsSync, statSync, promises as fs } from import { Connection, MessageConnection } from 'vscode-languageserver'; import { TextDocument } from 'vscode-languageserver-textdocument'; import { CompletionItem, CompletionItemKind, Hover, InsertTextFormat, Range, SymbolKind } from 'vscode-languageserver-types'; -import { AhkSymbol, ActionType, FormatOptions, Lexer, update_comment_tags } from './Lexer'; +import { AhkSymbol, Lexer, setCommentTagRegex } from './Lexer'; import { diagnostic } from './localize'; import { isBrowser, jsDocTagNames } from './constants'; +import { AhkppConfig, newAhkppConfig } from './config'; export * from './codeActionProvider'; export * from './colorProvider'; export * from './commandProvider'; @@ -23,76 +24,10 @@ export * from './semanticTokensProvider'; export * from './signatureProvider'; export * from './symbolProvider'; -enum LibIncludeType { - 'Disabled', - 'Local', - 'User and Standard', - 'All' -} - -export interface AHKLSSettings { - locale?: string - commands?: string[] - extensionUri?: string - ActionWhenV1IsDetected: ActionType - AutoLibInclude: LibIncludeType - CommentTags?: string - CompleteFunctionParens: boolean - CompletionCommitCharacters?: { - Class: string - Function: string - } - Diagnostics: { - ClassNonDynamicMemberCheck: boolean - ParamsCheck: boolean - } - Files: { - Exclude: string[] - MaxDepth: number - } - FormatOptions: FormatOptions - InterpreterPath: string - GlobalStorage?: string - Syntaxes?: string - SymbolFoldingFromOpenBrace: boolean - Warn: { - VarUnset: boolean - LocalSameAsGlobal: boolean - CallWithoutParentheses: boolean | /* Parentheses */ 1 - } - WorkingDirs: string[] -} - export const winapis: string[] = []; export const lexers: { [uri: string]: Lexer } = {}; export const alpha_3 = encode_version('2.1-alpha.3'); -export const extsettings: AHKLSSettings = { - ActionWhenV1IsDetected: 'Warn', - AutoLibInclude: 0, - CommentTags: '^;;\\s*(.*)', - CompleteFunctionParens: false, - CompletionCommitCharacters: { - Class: '.(', - Function: '(' - }, - Diagnostics: { - ClassNonDynamicMemberCheck: true, - ParamsCheck: true - }, - Files: { - Exclude: [], - MaxDepth: 2 - }, - FormatOptions: {}, - InterpreterPath: 'C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey.exe', - SymbolFoldingFromOpenBrace: false, - Warn: { - VarUnset: true, - LocalSameAsGlobal: false, - CallWithoutParentheses: false - }, - WorkingDirs: [] -}; +export const ahkppConfig: AhkppConfig = newAhkppConfig(); export const utils = { get_DllExport: (_paths: string[] | Set, _onlyone = false) => Promise.resolve([] as string[]), get_RCDATA: (_path?: string) => ({ uri: '', path: '' } as { uri: string, path: string, paths?: string[] } | undefined), @@ -270,7 +205,7 @@ export function loadahk2(filename = 'ahk2', d = 3) { if ((data = getwebfile(file + '.json'))) build_item_cache(JSON.parse(data.text)); } else { - const syntaxes = extsettings.Syntaxes && existsSync(extsettings.Syntaxes) ? extsettings.Syntaxes : ''; + const syntaxes = ahkppConfig.v2.syntaxes && existsSync(ahkppConfig.v2.syntaxes) ? ahkppConfig.v2.syntaxes : ''; const file2 = syntaxes ? `${syntaxes}/<>/${filename}` : file; let td: TextDocument | undefined; if ((path = getfilepath('.d.ahk')) && (td = openFile(restorePath(path)))) { @@ -407,20 +342,20 @@ export function loadahk2(filename = 'ahk2', d = 3) { let scanExclude: { file?: RegExp[], folder?: RegExp[] } = {}; export function enum_ahkfiles(dirpath: string) { - const maxdepth = extsettings.Files.MaxDepth; - const { file: file_exclude, folder: folder_exclude } = scanExclude; + const maxScanDepth = ahkppConfig.v2.file.maxScanDepth; + const { file: fileExclude, folder: folderExclude } = scanExclude; return enumfile(restorePath(dirpath), 0); async function* enumfile(dirpath: string, depth: number): AsyncGenerator { try { const dir = await fs.opendir(dirpath); for await (const t of dir) { - if (t.isDirectory() && depth < maxdepth) { + if (t.isDirectory() && depth < maxScanDepth) { const path = resolve(dirpath, t.name); - if (!folder_exclude?.some(re => re.test(path))) + if (!folderExclude?.some(re => re.test(path))) yield* enumfile(path, depth + 1); } else if (t.isFile() && /\.(ahk2?|ah2)$/i.test(t.name)) { const path = resolve(dirpath, t.name); - if (!file_exclude?.some(re => re.test(path))) + if (!fileExclude?.some(re => re.test(path))) yield path; } } @@ -428,60 +363,37 @@ export function enum_ahkfiles(dirpath: string) { } } -export function update_settings(configs: AHKLSSettings) { - if (typeof configs.AutoLibInclude === 'string') - configs.AutoLibInclude = LibIncludeType[configs.AutoLibInclude] as unknown as LibIncludeType; - else if (typeof configs.AutoLibInclude === 'boolean') - configs.AutoLibInclude = configs.AutoLibInclude ? 3 : 0; - if (typeof configs.Warn?.CallWithoutParentheses === 'string') - configs.Warn.CallWithoutParentheses = { On: true, Off: false, Parentheses: 1 }[configs.Warn.CallWithoutParentheses]; - if (typeof configs.FormatOptions?.brace_style === 'string') - switch (configs.FormatOptions.brace_style) { - case '0': - case 'Allman': configs.FormatOptions.brace_style = 0; break; - case '1': - case 'One True Brace': configs.FormatOptions.brace_style = 1; break; - case '-1': - case 'One True Brace Variant': configs.FormatOptions.brace_style = -1; break; - default: delete configs.FormatOptions.brace_style; break; - } - for (const k of ['array_style', 'object_style'] as Array) - if (typeof configs.FormatOptions?.[k] === 'string') - // todo fix update_settings - // @ts-expect-error undefined not assignable to never - configs.FormatOptions[k] = { collapse: 2, expand: 1, none: 0 }[configs.FormatOptions[k] as string]; +/** Updates `extsettings` with the provided config values */ +export function updateAhkppConfig(newConfig: AhkppConfig) { try { - update_comment_tags(configs.CommentTags!); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } catch (e: any) { - delete e.stack; - delete configs.CommentTags; - console.log(e); + setCommentTagRegex(newConfig.v2.commentTagRegex!); + } catch (e) { + delete (e as { stack: unknown }).stack; + delete newConfig.v2.commentTagRegex; + connection.console.error(e as string); } - if (configs.WorkingDirs instanceof Array) - configs.WorkingDirs = configs.WorkingDirs.map(dir => + if (newConfig.v2.workingDirectories instanceof Array) + newConfig.v2.workingDirectories = newConfig.v2.workingDirectories.map(dir => (dir = URI.file(dir.includes(':') ? dir : resolve(dir)).toString().toLowerCase()) .endsWith('/') ? dir : dir + '/'); - else configs.WorkingDirs = []; + else newConfig.v2.workingDirectories = []; scanExclude = {}; - if (configs.Files) { - const file: RegExp[] = [], folder: RegExp[] = []; - for (const s of configs.Files.Exclude ?? []) - try { - (/[\\/]$/.test(s) ? folder : file).push(glob2regexp(s)); - } catch (e) { - console.log(`[Error] Invalid glob pattern: ${s}`); - } - if (file.length) - scanExclude.file = file; - if (folder.length) - scanExclude.folder = folder; - if ((configs.Files.MaxDepth ??= 2) < 0) - configs.Files.MaxDepth = Infinity; - } - if (configs.Syntaxes) - configs.Syntaxes = resolve(configs.Syntaxes).toLowerCase(); - Object.assign(extsettings, configs); + const file: RegExp[] = [], folder: RegExp[] = []; + for (const s of newConfig.v2.file.exclude ?? []) + try { + (/[\\/]$/.test(s) ? folder : file).push(glob2regexp(s)); + } catch (e) { + console.log(`[Error] Invalid glob pattern: ${s}`); + } + if (file.length) + scanExclude.file = file; + if (folder.length) + scanExclude.folder = folder; + if (newConfig.v2.file.maxScanDepth < 0) + newConfig.v2.file.maxScanDepth = Infinity; + if (newConfig.v2.syntaxes) + newConfig.v2.syntaxes = resolve(newConfig.v2.syntaxes).toLowerCase(); + Object.assign(ahkppConfig, newConfig); } function encode_version(version: string) { @@ -527,7 +439,7 @@ export function set_version(version: string) { ahk_version = encode_version(vers export function set_WorkspaceFolders(folders: Set) { const old = workspaceFolders; workspaceFolders = [...folders]; - extsettings.WorkingDirs.forEach(it => !folders.has(it) && workspaceFolders.push(it)); + ahkppConfig.v2.workingDirectories.forEach(dir => { if (!folders.has(dir)) workspaceFolders.push(dir) }); workspaceFolders.sort().reverse(); if (old.length === workspaceFolders.length && !old.some((v, i) => workspaceFolders[i] !== v)) @@ -605,4 +517,4 @@ function glob2regexp(glob: string) { if (isNot) reStr = reStr.startsWith('^') ? `^(?!${reStr})` : `(?!${reStr})`; return new RegExp(reStr, 'i'); -} \ No newline at end of file +} diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index fe2d8a79..0974828f 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -8,10 +8,13 @@ import { URI } from 'vscode-uri'; import { $DIRPATH, $DLLFUNC, $FILEPATH, ANY, AhkSymbol, ClassNode, FuncNode, Maybe, Property, STRING, SemanticTokenTypes, Token, Variable, a_vars, ahkuris, ahkvars, allIdentifierChar, completionItemCache, completionitem, - decltype_expr, dllcalltpe, extsettings, find_class, find_symbol, find_symbols, get_detail, + decltype_expr, dllcalltpe, ahkppConfig, find_class, find_symbol, find_symbols, get_detail, generate_fn_comment, get_callinfo, get_class_constructor, get_class_member, get_class_members, - isBrowser, lexers, libfuncs, make_search_re, sendAhkRequest, utils, winapis + isBrowser, lexers, libfuncs, make_search_re, sendAhkRequest, utils, winapis, + connection } from './common'; +import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; +import { BraceStyle } from './config'; export async function completionProvider(params: CompletionParams, _token: CancellationToken): Promise> { let { position, textDocument: { uri } } = params; @@ -78,7 +81,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance } //#endregion - const commitCharacters = Object.fromEntries(Object.entries(extsettings.CompletionCommitCharacters ?? {}) + const commitCharacters = Object.fromEntries(Object.entries(ahkppConfig.v2.completionCommitCharacters) // eslint-disable-next-line @typescript-eslint/no-explicit-any .map((v: any) => (v[1] = (v[1] || undefined)?.split(''), v))); // eslint-disable-next-line prefer-const @@ -496,7 +499,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance } let right_is_paren = '(['.includes(linetext[range.end.character] || '\0'); - const join_c = extsettings.FormatOptions.brace_style === 0 ? '\n' : ' '; + const join_c = ahkppConfig.v2.formatter.braceStyle === BraceStyle.Allman ? '\n' : ' '; // fn|()=>... if (symbol) { @@ -618,8 +621,8 @@ export async function completionProvider(params: CompletionParams, _token: Cance } // keyword - const keyword_start_with_uppercase = extsettings.FormatOptions?.keyword_start_with_uppercase; - const addkeyword = keyword_start_with_uppercase ? function (it: CompletionItem) { + const keywordStartWithUppercase = ahkppConfig.v2.formatter.keywordStartWithUppercase; + const addkeyword = keywordStartWithUppercase ? function (it: CompletionItem) { items.push(it = Object.assign({}, it)); it.insertText = (it.insertText ?? it.label).replace(/(?<=^(loop\s)?)[a-z]/g, m => m.toUpperCase()); } : (it: CompletionItem) => items.push(it); @@ -631,9 +634,9 @@ export async function completionProvider(params: CompletionParams, _token: Cance } else { const kind = CompletionItemKind.Snippet, insertTextFormat = InsertTextFormat.Snippet; let uppercase = (s: string) => s, remove_indent = uppercase; - if (keyword_start_with_uppercase) + if (keywordStartWithUppercase) uppercase = (s: string) => s.replace(/\b[a-z](?=\w)/g, m => m.toUpperCase()); - if (extsettings.FormatOptions?.switch_case_alignment) + if (ahkppConfig.v2.formatter.switchCaseAlignment) remove_indent = (s: string) => s.replace(/^\t/gm, ''); for (const [label, arr] of [ ['switch', ['switch ${1:[SwitchValue, CaseSense]}', remove_indent('{\n\tcase ${2:}:\n\t\t${3:}\n\tdefault:\n\t\t$0\n}')]], @@ -682,16 +685,21 @@ export async function completionProvider(params: CompletionParams, _token: Cance }); } - // auto-include - if (extsettings.AutoLibInclude) { + // library suggestions + if (ahkppConfig.v2.librarySuggestions) { + const librarySuggestions = ahkppConfig.v2.librarySuggestions; const libdirs = doc.libdirs, caches: { [path: string]: TextEdit[] } = {}; let exportnum = 0, line = -1, first_is_comment: boolean | undefined, cm: Token; let dir = doc.workspaceFolder; dir = (dir ? URI.parse(dir).fsPath : doc.scriptdir).toLowerCase(); doc.includedir.forEach((v, k) => line = k); for (const u in libfuncs) { - if (!list[u] && (path = libfuncs[u].fsPath) && ((extsettings.AutoLibInclude > 1 && libfuncs[u].islib) || - ((extsettings.AutoLibInclude & 1) && path.toLowerCase().startsWith(dir)))) { + if ( + !list[u] && (path = libfuncs[u].fsPath) + && ( + (includeUserAndStandardLibrary(librarySuggestions) && libfuncs[u].islib) + || (includeLocalLibrary(librarySuggestions) && path.toLowerCase().startsWith(dir))) + ) { for (const it of libfuncs[u]) { expg.test(l = it.name) && (vars[l.toUpperCase()] ??= ( cpitem = convertNodeCompletion(it), exportnum++, @@ -918,7 +926,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance // fall through case SymbolKind.Function: ci.kind = info.kind === SymbolKind.Method ? CompletionItemKind.Method : CompletionItemKind.Function; - if (extsettings.CompleteFunctionParens) { + if (ahkppConfig.v2.completeFunctionCalls) { const fn = info as FuncNode; if (right_is_paren) ci.command = { title: 'cursorRight', command: 'cursorRight' }; diff --git a/server/src/config.ts b/server/src/config.ts new file mode 100644 index 00000000..f53ed29f --- /dev/null +++ b/server/src/config.ts @@ -0,0 +1,167 @@ +/** Defined in package.json */ +export type ActionType = + | 'Continue' + | 'Warn' + | 'SkipLine' + | 'SwitchToV1' + | 'Stop'; + +/** Defined in package.json */ +export enum ObjectOrArrayStyle { + Collapse = 'collapse', + Expand = 'expand', + None = 'none', +} + +/** Defined in package.json */ +export enum BraceStyle { + OneTrueBrace = 'One True Brace', + Allman = 'Allman', + OneTrueBraceVariant = 'One True Brace Variant', +} + +export interface FormatterConfig { + arrayStyle: ObjectOrArrayStyle; + braceStyle: BraceStyle; + breakChainedMethods: boolean; + ignoreComment: boolean; + indentString: string; + indentBetweenHotIfDirectives: boolean; + keywordStartWithUppercase: boolean; + maxPreserveNewlines: number; + objectStyle: ObjectOrArrayStyle; + preserveNewlines: boolean; + spaceBeforeConditional: boolean; + spaceAfterDoubleColon: boolean; + spaceInEmptyParen: boolean; + spaceInOther: boolean; + spaceInParen: boolean; + switchCaseAlignment: boolean; + symbolWithSameCase: boolean; + whitespaceBeforeInlineComment: string; + wrapLineLength: number; +} + +/** Defined in package.json */ +export enum LibrarySuggestions { + Off = 'Off', + Local = 'Local', + UserAndStandard = 'User and Standard', + All = 'All', +} + +/** Defined in package.json */ +export enum CallWithoutParentheses { + Off = 'Off', + Parentheses = 'Parentheses', + On = 'On', +} + +export interface AhkppConfig { + v2: { + actionWhenV1Detected: ActionType; + /** The regex denoting a custom symbol. Defaults to `;;` */ + commentTagRegex?: string; + /** Automatically insert parentheses on function call */ + completeFunctionCalls: boolean; + completionCommitCharacters: { + Class: string; + Function: string; + }; + diagnostics: { + classNonDynamicMemberCheck: boolean; + paramsCheck: boolean; + }; + file: { + /** Glob pattern of files to ignore */ + exclude: string[]; + /** Path to the AHK v2 intepreter */ + interpreterPath: string; + /** Depth of folders to scan for IntelliSense */ + maxScanDepth: number; + }; + /** Config of the v2 formatter */ + formatter: FormatterConfig; + /** Suggest library functions */ + librarySuggestions: LibrarySuggestions; + warn: { + /** Ref to a potentially-unset variable */ + varUnset: boolean; + /** Undeclared local has same name as global */ + localSameAsGlobal: boolean; + /** Function call without parentheses */ + callWithoutParentheses: CallWithoutParentheses; + }; + symbolFoldingFromOpenBrace: boolean; + syntaxes: string; + workingDirectories: string[]; + }; + locale?: string; + commands?: string[]; + extensionUri?: string; + GlobalStorage?: string; +} + +/** + * Returns a formatter config built from the given config and defaults. + * Defaults defined in package.json + */ +export const newFormatterConfig = ( + config: Partial = {}, +): FormatterConfig => ({ + arrayStyle: ObjectOrArrayStyle.None, + braceStyle: BraceStyle.OneTrueBrace, + breakChainedMethods: false, + ignoreComment: false, + indentString: ' ', + indentBetweenHotIfDirectives: false, + keywordStartWithUppercase: false, + maxPreserveNewlines: 2, + objectStyle: ObjectOrArrayStyle.None, + preserveNewlines: true, + spaceBeforeConditional: true, + spaceAfterDoubleColon: true, + spaceInEmptyParen: false, + spaceInOther: true, + spaceInParen: false, + switchCaseAlignment: false, + symbolWithSameCase: false, + whitespaceBeforeInlineComment: '', + wrapLineLength: 120, + ...config, +}); + +export const newAhkppConfig = ( + config: Partial = {}, +): AhkppConfig => ({ + v2: { + actionWhenV1Detected: 'SwitchToV1', + librarySuggestions: LibrarySuggestions.Off, + commentTagRegex: '^;;\\s*(.*)', + completeFunctionCalls: false, + completionCommitCharacters: { + Class: '.(', + Function: '(', + }, + diagnostics: { + classNonDynamicMemberCheck: true, + paramsCheck: true, + }, + warn: { + varUnset: true, + localSameAsGlobal: false, + callWithoutParentheses: CallWithoutParentheses.Off, + }, + file: { + exclude: [], + interpreterPath: + 'C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey.exe', + maxScanDepth: 2, + }, + formatter: newFormatterConfig(), + symbolFoldingFromOpenBrace: false, + workingDirectories: [], + syntaxes: '', + }, + ...config, +}); diff --git a/server/src/formattingProvider.ts b/server/src/formattingProvider.ts index 26d5f992..1c7fa8ad 100644 --- a/server/src/formattingProvider.ts +++ b/server/src/formattingProvider.ts @@ -1,30 +1,31 @@ import { DocumentFormattingParams, DocumentOnTypeFormattingParams, DocumentRangeFormattingParams, Position, Range, TextEdit } from 'vscode-languageserver'; -import { chinese_punctuations, extsettings, lexers, Token } from './common'; +import { chinese_punctuations, ahkppConfig, lexers, Token } from './common'; +import { FormatterConfig } from './config'; export async function documentFormatting(params: DocumentFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], range = Range.create(0, 0, doc.document.lineCount, 0); - const opts = { ...extsettings.FormatOptions }; - opts.indent_string ??= params.options.insertSpaces ? ' '.repeat(params.options.tabSize) : '\t'; + const opts = { ...ahkppConfig.v2.formatter }; + opts.indentString ??= params.options.insertSpaces ? ' '.repeat(params.options.tabSize) : '\t'; const newText = doc.beautify(opts); return [{ range, newText }]; } export async function rangeFormatting(params: DocumentRangeFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], range = params.range; - const opts = { ...extsettings.FormatOptions }; - opts.indent_string = params.options.insertSpaces ? ' '.repeat(params.options.tabSize) : '\t'; + const opts = { ...ahkppConfig.v2.formatter }; + opts.indentString = params.options.insertSpaces ? ' '.repeat(params.options.tabSize) : '\t'; const newText = doc.beautify(opts, range).trim(); return [{ range, newText }]; } export async function typeFormatting(params: DocumentOnTypeFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], { ch, position } = params; - const opts = { ...extsettings.FormatOptions }; + const options: FormatterConfig = { ...ahkppConfig.v2.formatter }; let tk: Token, s: string, pp: number | undefined, result: TextEdit[] | undefined; - opts.indent_string = ' '.repeat(params.options.tabSize); + options.indentString = ' '.repeat(params.options.tabSize); s = doc.document.getText({ start: { line: 0, character: 0 }, end: { line: 0, character: 1 } }); if (s === '\t' || !params.options.insertSpaces && s !== ' ') - opts.indent_string = '\t'; + options.indentString = '\t'; if (ch === '\n') { // eslint-disable-next-line prefer-const let { line, character } = position; @@ -32,25 +33,25 @@ export async function typeFormatting(params: DocumentOnTypeFormattingParams): Pr start: { line: line - 1, character: 0 }, end: { line: line + 2, character: 0 } }).split(/\r?\n/); - let s = linetexts[0].trimEnd(), indent_string: string; + let s = linetexts[0].trimEnd(), indentString: string; if (!linetexts[1].trim()) character = linetexts[1].length; if (s.endsWith('{')) { - const prev = opts.indent_string; + const prev = options.indentString; if ((result = format_end_with_brace({ line: line - 1, character: s.length }))) { - indent_string = opts.indent_string; - if (linetexts[1].substring(0, character) !== indent_string) + indentString = options.indentString; + if (linetexts[1].substring(0, character) !== indentString) result.push({ - newText: indent_string, + newText: indentString, range: { start: { line, character: 0 }, end: { line, character } } }); if ((s = (linetexts[2] ??= '').trimStart()).startsWith('}') && - !linetexts[2].startsWith((indent_string = indent_string.replace(prev, '')) + '}')) + !linetexts[2].startsWith((indentString = indentString.replace(prev, '')) + '}')) result.push({ - newText: indent_string, + newText: indentString, range: { start: { line: line + 1, character: 0 }, end: { line: line + 1, character: linetexts[2].length - s.length } @@ -59,12 +60,12 @@ export async function typeFormatting(params: DocumentOnTypeFormattingParams): Pr } } else if ((pp = doc.linepos[line - 1]) !== undefined) { const range = { start: doc.document.positionAt(pp), end: { line: line - 1, character: s.length } }; - const newText = doc.beautify(opts, range).trim(); + const newText = doc.beautify(options, range).trim(); result = [{ range, newText }]; - indent_string = opts.indent_string; - if (linetexts[1].substring(0, character) !== indent_string) + indentString = options.indentString; + if (linetexts[1].substring(0, character) !== indentString) result.push({ - newText: indent_string, + newText: indentString, range: { start: { line, character: 0 }, end: { line, character } } }); } else if (!s) { @@ -107,7 +108,7 @@ export async function typeFormatting(params: DocumentOnTypeFormattingParams): Pr while ((tk = doc.tokens[pp])?.previous_pair_pos !== undefined) pp = tk.previous_pair_pos; const range = { start: doc.document.positionAt(pp), end: pos }; - const newText = doc.beautify(opts, range).trim(); + const newText = doc.beautify(options, range).trim(); return [{ range, newText }]; } } diff --git a/server/src/localize.ts b/server/src/localize.ts index f0e78cfe..ee6fa32d 100644 --- a/server/src/localize.ts +++ b/server/src/localize.ts @@ -83,7 +83,7 @@ export const warn = { } export const setting = { - ahkpatherr: localize('setting.ahkpatherr', 'The AutoHotkey interpreter does not exist, re-specify in\'Settings-AutoHotkey2.InterpreterPath\''), + ahkpatherr: localize('setting.ahkpatherr', "AutoHotkey interpreter not found, check settings: ahk++.v2.file.interpreterPath"), getenverr: localize('setting.getenverr', 'Failed to get environment variables'), uialimit: localize('setting.uialimit', 'The UIA executable does not allow redirection to stdin/stdout due to security restrictions, so some features that depend on this will not work'), versionerr: localize('setting.versionerr', 'The current AutoHotkey.exe is not the v2 version, and cannot get the correct syntax analysis, completion and other functions'), diff --git a/server/src/semanticTokensProvider.ts b/server/src/semanticTokensProvider.ts index cdea8fac..026b5e0a 100644 --- a/server/src/semanticTokensProvider.ts +++ b/server/src/semanticTokensProvider.ts @@ -1,7 +1,7 @@ import { CancellationToken, DocumentSymbol, Range, SemanticTokens, SemanticTokensParams, SemanticTokensRangeParams, SymbolKind } from 'vscode-languageserver'; import { ASSIGN_TYPE, AhkSymbol, ClassNode, FuncNode, Lexer, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, Token, Variable, - checkParams, diagnostic, extsettings, get_class_member, get_class_members, globalsymbolcache, lexers, symbolProvider + checkParams, diagnostic, ahkppConfig, get_class_member, get_class_members, globalsymbolcache, lexers, symbolProvider } from './common'; let curclass: ClassNode | undefined; @@ -124,13 +124,12 @@ function resolveSemanticType(name: string, tk: Token, doc: Lexer) { return sem.type = SemanticTokenTypes.property; } case undefined: - if ((curclass.checkmember ?? doc.checkmember) !== false && extsettings.Diagnostics.ClassNonDynamicMemberCheck) { + if ((curclass.checkmember ?? doc.checkmember) !== false && ahkppConfig.v2.diagnostics.classNonDynamicMemberCheck) { const tt = doc.tokens[tk.next_token_offset]; if (ASSIGN_TYPE.includes(tt?.content)) { cls_add_prop(curclass, tk.content, tk.offset); } else if ((memscache.get(curclass) as _Flag)?.['#checkmember'] !== false) ((curclass.undefined ??= {})[tk.content.toUpperCase()] ??= []).push(tk); - // doc.addDiagnostic(diagnostic.maybehavenotmember(curclass.name, tk.content), tk.offset, tk.length, 2); } } } diff --git a/server/src/server.ts b/server/src/server.ts index b286142c..8e9f0ec7 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -13,7 +13,6 @@ import { URI } from 'vscode-uri'; import { get_ahkProvider } from './ahkProvider'; import { a_vars, - AHKLSSettings, ahkpath_cur, chinese_punctuations, clearLibfuns, @@ -27,7 +26,7 @@ import { enum_ahkfiles, executeCommandProvider, exportSymbols, - extsettings, + ahkppConfig, hoverProvider, initahk2cache, isahk2_h, @@ -60,7 +59,7 @@ import { symbolProvider, traverse_include, typeFormatting, - update_settings, + updateAhkppConfig, utils, winapis, workspaceSymbolProvider, @@ -68,6 +67,8 @@ import { import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; import { resolvePath, runscript } from './scriptrunner'; import { TextDecoder } from 'util'; +import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; +import { AhkppConfig } from './config'; const languageServer = 'ahk2-language-server'; const documents = new TextDocuments(TextDocument); @@ -77,7 +78,7 @@ let hasConfigurationCapability = false, hasWorkspaceFolderCapability = false; let uri_switch_to_ahk2 = ''; -commands['ahk2.resetinterpreterpath'] = (args: string[]) => +commands['ahk++.v2.setIntepreterPath'] = (args: string[]) => setInterpreter(args[0].replace(/^[A-Z]:/, (m) => m.toLowerCase())); connection.onInitialize(async (params) => { @@ -147,27 +148,27 @@ connection.onInitialize(async (params) => { }; } - let configs: AHKLSSettings | undefined; + let envAhkppConfig: AhkppConfig | undefined; const env = process.env; if (env.AHK2_LS_CONFIG) try { - configs = JSON.parse(env.AHK2_LS_CONFIG); + envAhkppConfig = JSON.parse(env.AHK2_LS_CONFIG); } catch { /* do nothing */ } if (params.initializationOptions) - configs = Object.assign(configs ?? {}, params.initializationOptions); + envAhkppConfig = Object.assign(envAhkppConfig ?? {}, params.initializationOptions); set_dirname(resolve(__dirname, '../..')); - set_locale(configs?.locale ?? params.locale); + set_locale(envAhkppConfig?.locale ?? params.locale); utils.get_RCDATA = getRCDATA; utils.get_DllExport = getDllExport; utils.get_ahkProvider = get_ahkProvider; loadlocalize(); initahk2cache(); - if (configs) update_settings(configs); + if (envAhkppConfig) updateAhkppConfig(envAhkppConfig); if ( !(await setInterpreter( - resolvePath((extsettings.InterpreterPath ??= '')), + resolvePath((ahkppConfig.v2.file.interpreterPath ??= '')), )) ) patherr(setting.ahkpatherr()); @@ -200,36 +201,32 @@ connection.onInitialized(() => { }); connection.onDidChangeConfiguration(async (change) => { - let newset: AHKLSSettings | undefined = change?.settings; - if (hasConfigurationCapability && !newset) - // todo AutoHotkey2 config is provided by the ahk2 package.json - newset = await connection.workspace.getConfiguration('AutoHotkey2'); - if (!newset) { - connection.window.showWarningMessage( - 'Failed to obtain the configuration', - ); + let newAhkppConfig: AhkppConfig | undefined = change?.settings; + if (hasConfigurationCapability && !newAhkppConfig) + newAhkppConfig = await connection.workspace.getConfiguration('ahk++'); + if (!newAhkppConfig) { + connection.window.showWarningMessage('Failed to obtain the AHK++ configuration'); return; } - const { AutoLibInclude, InterpreterPath, Syntaxes } = extsettings; - update_settings(newset); + const { v2: oldV2 } = ahkppConfig; + updateAhkppConfig(newAhkppConfig); + const { v2: newV2 } = ahkppConfig; set_WorkspaceFolders(workspaceFolders); - if (InterpreterPath !== extsettings.InterpreterPath) { + if (oldV2.file.interpreterPath !== newV2.file.interpreterPath) { if ( await setInterpreter( - resolvePath((extsettings.InterpreterPath ??= '')), + resolvePath((newV2.file.interpreterPath ??= '')), ) ) - connection.sendRequest('ahk2.updateStatusBar', [ - extsettings.InterpreterPath, - ]); + connection.sendRequest('ahk2.updateStatusBar', [newV2.file.interpreterPath]); } - if (AutoLibInclude !== extsettings.AutoLibInclude) { - if (extsettings.AutoLibInclude > 1 && AutoLibInclude <= 1) + if (oldV2.librarySuggestions !== newV2.librarySuggestions) { + if (includeUserAndStandardLibrary(newV2.librarySuggestions) && !includeUserAndStandardLibrary(oldV2.librarySuggestions)) parseuserlibs(); - if (extsettings.AutoLibInclude & 1 && !(AutoLibInclude & 1)) + if (includeLocalLibrary(newV2.librarySuggestions) && !includeLocalLibrary(oldV2.librarySuggestions)) documents.all().forEach((e) => parseproject(e.uri.toLowerCase())); } - if (Syntaxes !== extsettings.Syntaxes) { + if (oldV2.syntaxes !== newV2.syntaxes) { initahk2cache(); loadahk2(); if (isahk2_h) { @@ -252,8 +249,8 @@ documents.onDidOpen((e) => { }); } doc.actived = true; - if (to_ahk2) doc.actionwhenv1 = 'Continue'; - if (extsettings.AutoLibInclude & 1) + if (to_ahk2) doc.actionWhenV1Detected = 'Continue'; + if (includeLocalLibrary(ahkppConfig.v2.librarySuggestions)) parseproject(uri).then( () => doc.last_diags && @@ -293,7 +290,7 @@ connection.onRequest('ahk2.getAHKversion', getAHKversion); connection.onRequest('ahk2.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText(), ); -connection.onRequest('ahk2.getVersionInfo', (uri: string) => { +connection.onRequest('ahk++.getVersionInfo', (uri: string) => { const doc = lexers[uri.toLowerCase()]; if (doc) { const tk = doc.get_token(0); @@ -324,7 +321,7 @@ documents.listen(connection); connection.listen(); async function patherr(msg: string) { - if (!extsettings.commands?.includes('ahk2.executeCommand')) + if (!ahkppConfig.commands?.includes('ahk2.executeCommand')) return connection.window.showErrorMessage(msg); if ( await connection.window.showErrorMessage(msg, { @@ -425,7 +422,7 @@ async function initpathenv(samefolder = false, retry = true): Promise { } } clearLibfuns(); - if (extsettings.AutoLibInclude > 1) parseuserlibs(); + if (includeUserAndStandardLibrary(ahkppConfig.v2.librarySuggestions)) parseuserlibs(); return true; async function update_rcdata() { const pe = new PEFile(ahkpath_cur); @@ -491,7 +488,7 @@ async function changeInterpreter(oldpath: string, newpath: string) { const doc = lexers[td.uri.toLowerCase()]; if (!doc) return; doc.initLibDirs(doc.scriptdir); - if (extsettings.AutoLibInclude & 1) parseproject(doc.uri); + if (includeLocalLibrary(ahkppConfig.v2.librarySuggestions)) parseproject(doc.uri); }); return true; } diff --git a/server/src/symbolProvider.ts b/server/src/symbolProvider.ts index 01fbec45..d15133f0 100644 --- a/server/src/symbolProvider.ts +++ b/server/src/symbolProvider.ts @@ -8,7 +8,7 @@ import { ANY, AhkSymbol, CallSite, ClassNode, FuncNode, FuncScope, Lexer, Property, SUPER, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, THIS, Token, VARREF, Variable, ahkuris, ahkvars, check_same_name_error, connection, decltype_expr, - diagnostic, enum_ahkfiles, extsettings, find_class, get_class_constructor, isBrowser, + diagnostic, enum_ahkfiles, ahkppConfig, find_class, get_class_constructor, isBrowser, is_line_continue, lexers, make_same_name_error, openFile, warn, workspaceFolders } from './common'; @@ -40,7 +40,7 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio return doc.symbolInformation; if (ahkuris.winapi && !list.includes(ahkuris.winapi)) winapis = lexers[ahkuris.winapi]?.declaration ?? winapis; - const warnLocalSameAsGlobal = extsettings.Warn?.LocalSameAsGlobal; + const warnLocalSameAsGlobal = ahkppConfig.v2.warn.localSameAsGlobal; const result: AhkSymbol[] = [], unset_vars = new Map(); const filter_types: SymbolKind[] = [SymbolKind.Method, SymbolKind.Property, SymbolKind.Class]; for (const [k, v] of Object.entries(doc.declaration)) { @@ -54,7 +54,7 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio result.push(v), converttype(v, v, islib || v === ahkvars[k]).definition = v; } flatTree(doc); - if (extsettings.Warn?.VarUnset) + if (ahkppConfig.v2.warn.varUnset) for (const [k, v] of unset_vars) k.assigned || doc.diagnostics.push({ message: warn.varisunset(v.name), range: v.selectionRange, severity: DiagnosticSeverity.Warning }); if (doc.actived) { @@ -290,7 +290,7 @@ function get_func_param_count(fn: FuncNode) { export function checkParams(doc: Lexer, node: FuncNode, info: CallSite) { const paraminfo = info.paraminfo; let is_cls: boolean, params; - if (!paraminfo || !extsettings.Diagnostics.ParamsCheck) return; + if (!paraminfo || !ahkppConfig.v2.diagnostics.paramsCheck) return; if ((is_cls = node?.kind === SymbolKind.Class)) node = get_class_constructor(node as unknown as ClassNode) as FuncNode; if (!(params = node?.params)) return; diff --git a/server/src/utils.ts b/server/src/utils.ts new file mode 100644 index 00000000..30ff2ff0 --- /dev/null +++ b/server/src/utils.ts @@ -0,0 +1,19 @@ +import { LibrarySuggestions } from './config'; + +export function includeUserAndStandardLibrary( + librarySuggestions: LibrarySuggestions, +): boolean { + return ( + librarySuggestions === LibrarySuggestions.All || + librarySuggestions === LibrarySuggestions.UserAndStandard + ); +} + +export function includeLocalLibrary( + librarySuggestions: LibrarySuggestions, +): boolean { + return ( + librarySuggestions === LibrarySuggestions.All || + librarySuggestions === LibrarySuggestions.Local + ); +} diff --git a/syntaxes/ahk2_common.json b/syntaxes/ahk2_common.json index 132bd5f6..ee23a9c6 100644 --- a/syntaxes/ahk2_common.json +++ b/syntaxes/ahk2_common.json @@ -32,7 +32,7 @@ "description": "Enables or disables class non-dynamic member checking for the current file/class" }, { - "body": ";@format ${1|array_style,object_style|}: ${2|collapse,expand,none|}", + "body": ";@format ${1|arrayStyle,objectStyle|}: ${2|collapse,expand,none|}", "prefix": "@format", "description": "Sets the object or array style of the current block for formatting" } diff --git a/webpack.config.js b/webpack.config.js index b16ec9db..cd249875 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -47,7 +47,6 @@ const nodeClientConfig = /** @type WebpackConfig */ { performance: { hints: false, }, - // todo minify production build devtool: 'source-map', }; From a99fd09eb55b6516bc3f334f5bea41ed9dec62c2 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 1 Sep 2024 14:21:23 -0700 Subject: [PATCH 24/60] Major trims, minor cleanup, reorganize config (#22) --- .github/workflows/node.js.yml | 2 +- client/src/browserClientMain.ts | 112 -- client/src/extension.ts | 102 +- package-lock.json | 1818 +------------------------- package.json | 492 +------ package.nls.json | 31 - package.nls.zh-cn.json | 107 -- server/src/Lexer.ts | 30 +- server/src/ahkProvider.ts | 4 +- server/src/browserServerMain.ts | 181 --- server/src/common.ts | 30 +- server/src/completionProvider.ts | 30 +- server/src/config.ts | 91 +- server/src/localize.ts | 3 +- server/src/scriptrunner.ts | 8 +- server/src/semanticTokensProvider.ts | 3 +- server/src/server.ts | 59 +- server/src/symbolProvider.ts | 8 +- syntaxes/samples/0-v2-demo.ahk2 | 3 - syntaxes/samples/0-v2-demo.ahk2.snap | 31 - webpack.config.js | 95 +- 21 files changed, 253 insertions(+), 2987 deletions(-) delete mode 100644 client/src/browserClientMain.ts delete mode 100644 package.nls.json delete mode 100644 package.nls.zh-cn.json delete mode 100644 server/src/browserServerMain.ts delete mode 100644 syntaxes/samples/0-v2-demo.ahk2 delete mode 100644 syntaxes/samples/0-v2-demo.ahk2.snap diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 05750265..1649bbfa 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -29,4 +29,4 @@ jobs: node-version: ${{ matrix.node-version }} cache: 'npm' - run: npm install - - run: npm run validate + - run: npm run validate:ci diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts deleted file mode 100644 index 906d0f0b..00000000 --- a/client/src/browserClientMain.ts +++ /dev/null @@ -1,112 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { commands, ExtensionContext, languages, Range, RelativePattern, SnippetString, Uri, window, workspace, WorkspaceEdit } from 'vscode'; -import { LanguageClient } from 'vscode-languageclient/browser'; - -let client: LanguageClient; - -// this method is called when vs code is activated -export function activate(context: ExtensionContext) { - const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browserServerMain.js'); - /* eslint-disable-next-line */ - const request_handlers: { [cmd: string]: (...params: any[]) => any } = { - 'ahk2.getActiveTextEditorUriAndPosition': () => { - const editor = window.activeTextEditor; - if (!editor) return; - const uri = editor.document.uri.toString(), position = editor.selection.end; - return { uri, position }; - }, - 'ahk2.insertSnippet': async (params: [string, Range?]) => { - const editor = window.activeTextEditor; - if (!editor) return; - if (params[1]) { - const { start, end } = params[1]; - await editor.insertSnippet(new SnippetString(params[0]), new Range(start.line, start.character, end.line, end.character)); - } else - editor.insertSnippet(new SnippetString(params[0])); - }, - 'ahk2.setTextDocumentLanguage': async (params: [string, string?]) => { - const lang = params[1] || 'ahk'; - if (!(await languages.getLanguages()).includes(lang)) { - window.showErrorMessage(`Unknown language id: ${lang}`); - return; - } - const uri = params[0], it = workspace.textDocuments.find(it => it.uri.toString() === uri); - it && languages.setTextDocumentLanguage(it, lang); - }, - 'ahk2.getWorkspaceFiles': async (params: string[]) => { - const all = !params.length; - if (workspace.workspaceFolders) { - if (all) - return (await workspace.findFiles('**/*.{ahk,ah2,ahk2}')).forEach(it => it.toString()); - else { - const files: string[] = []; - for (const folder of workspace.workspaceFolders) - if (params.includes(folder.uri.toString().toLowerCase())) - files.push(...(await workspace.findFiles(new RelativePattern(folder, '*.{ahk,ah2,ahk2}'))).map(it => it.toString())); - return files; - } - } - }, - 'ahk2.getWorkspaceFileContent': async (params: string[]) => (await workspace.openTextDocument(Uri.parse(params[0]))).getText() - }; - - client = new LanguageClient('ahk++', 'ahk++', { - documentSelector: [{ language: 'ahk2' }], - markdown: { isTrusted: true, supportHtml: true }, - initializationOptions: { - extensionUri: context.extensionUri.toString(), - commands: Object.keys(request_handlers), - ...JSON.parse(JSON.stringify(workspace.getConfiguration('ahk++'))) - } - }, new Worker(serverMain.toString())); - - context.subscriptions.push( - commands.registerTextEditorCommand('ahk++.updateVersionInfo', async textEditor => { - const info: { content: string, uri: string, range: Range } | null = await client.sendRequest('ahk++.getVersionInfo', textEditor.document.uri.toString()); - if (!info) { - await textEditor.insertSnippet(new SnippetString([ - "/************************************************************************", - " * @description ${1:}", - " * @file $TM_FILENAME", - " * @author ${2:}", - " * @date ${3:$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE}", - " * @version ${4:0.0.0}", - " ***********************************************************************/", - "", "" - ].join('\n')), new Range(0, 0, 0, 0)); - } else { - const d = new Date; - let content = info.content, ver; - content = content.replace(/(?<=^\s*[;*]?\s*@date[:\s]\s*)(\d+\/\d+\/\d+)/im, d.getFullYear() + '/' + ('0' + (d.getMonth() + 1)).slice(-2) + '/' + ('0' + d.getDate()).slice(-2)); - if (content.match(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S*)/im) && - (ver = await window.showInputBox({ prompt: 'Enter version info', value: content.match(/(?<=^[\s*]*@version[:\s]\s*)(\S*)/im)?.[1] }))) - content = content.replace(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S*)/im, ver); - if (content !== info.content) { - const ed = new WorkspaceEdit(); - ed.replace(textEditor.document.uri, info.range, content); - workspace.applyEdit(ed); - } - } - }), - commands.registerTextEditorCommand('ahk++.switchAhkVersion', textEditor => { - const doc = textEditor.document; - languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); - }), - workspace.onDidCloseTextDocument(e => { - client.sendNotification('onDidCloseTextDocument', e.isClosed ? - { uri: '', id: '' } : { uri: e.uri.toString(), id: e.languageId }); - }) - ); - - client.start().then(() => { - Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); - }); -} - -export function deactivate() { - return client?.stop(); -} \ No newline at end of file diff --git a/client/src/extension.ts b/client/src/extension.ts index 2a563c66..7812d025 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -36,8 +36,8 @@ import { readdirSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); -const ahkppConfig = workspace.getConfiguration('ahk++'); -let ahkpath_cur: string = ahkppConfig.v2.file.interpreterPath, server_is_ready = false, zhcn = false; +const ahkppConfig = workspace.getConfiguration('AHK++'); +let v2Interpreter: string = ahkppConfig?.v2?.file?.interpreterPath, server_is_ready = false, zhcn = false; const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; const isWindows = process.platform === 'win32'; @@ -85,7 +85,7 @@ export async function activate(context: ExtensionContext) { it && languages.setTextDocumentLanguage(it, lang); }, 'ahk2.updateStatusBar': async (params: [string]) => { - ahkpath_cur = params[0]; + v2Interpreter = params[0]; onDidChangegetInterpreter(); } }; @@ -94,8 +94,8 @@ export async function activate(context: ExtensionContext) { const clientOptions: LanguageClientOptions = { documentSelector: [{ language: 'ahk2' }], markdown: { isTrusted: true, supportHtml: true }, - outputChannel: outputchannel = window.createOutputChannel('ahk++', '~ahk2-output'), - outputChannelName: 'ahk++', + outputChannel: outputchannel = window.createOutputChannel('AHK++', '~ahk2-output'), + outputChannelName: 'AHK++', initializationOptions: { commands: Object.keys(request_handlers), GlobalStorage: context.globalStorageUri.fsPath, @@ -104,7 +104,7 @@ export async function activate(context: ExtensionContext) { }; // Create the language client and start the client. - client = new LanguageClient('ahk++', 'ahk++', serverOptions, clientOptions); + client = new LanguageClient('AHK++', 'AHK++', serverOptions, clientOptions); zhcn = env.language.startsWith('zh-'); textdecoders.push(new TextDecoder(zhcn ? 'gbk' : 'windows-1252')); @@ -167,7 +167,7 @@ export async function activate(context: ExtensionContext) { append_configs.push(configs.find(it => it.name === config.name) ?? configs[0]); Object.assign(config, ...append_configs); if (!config.runtime && (!config.runtime_v2 || config.type !== 'autohotkey')) { - config.runtime = resolvePath(ahkpath_cur, folder?.uri.fsPath); + config.runtime = resolvePath(v2Interpreter, folder?.uri.fsPath); if (ahkStatusBarItem.text.endsWith('[UIAccess]')) config.useUIAVersion = true; } @@ -182,7 +182,7 @@ export async function activate(context: ExtensionContext) { } update_extensions_info(); - commands.executeCommand('setContext', 'ahk2:isRunning', false); + commands.executeCommand('setContext', 'ahk:isRunning', false); ahkStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 75); ahkStatusBarItem.command = 'ahk++.setV2Interpreter'; const ahkLanguageStatusItem = languages.createLanguageStatusItem('ahk++', { language: 'ahk2' }); @@ -194,7 +194,7 @@ export async function activate(context: ExtensionContext) { commands.registerTextEditorCommand('ahk++.run', textEditor => runScript(textEditor)), commands.registerTextEditorCommand('ahk++.runSelection', textEditor => runScript(textEditor, true)), commands.registerCommand('ahk++.stop', stopRunningScript), - commands.registerCommand('ahk++.setV2Interpreter', setInterpreter), + commands.registerCommand('ahk++.setV2Interpreter', setInterpreterV2), commands.registerCommand('ahk++.debugParams', () => beginDebug(extlist, debugexts, true)), commands.registerCommand('ahk++.debugAttach', () => beginDebug(extlist, debugexts, false, true)), commands.registerCommand('ahk++.selectSyntaxes', selectSyntaxes), @@ -273,41 +273,55 @@ function decode(buf: Buffer) { return buf.toString(); } -function runScript(textEditor: TextEditor, selection = false) { - const executePath = resolvePath(ahkpath_cur, workspace.getWorkspaceFolder(textEditor.document.uri)?.uri.fsPath); +/** Also in original src */ +export enum LanguageId { + ahk1 = 'ahk', + ahk2 = 'ahk2', +} + +const isV1 = (): boolean => + window.activeTextEditor?.document.languageId === LanguageId.ahk1; + +function runScript(textEditor: TextEditor, runSelection = false) { + const interpreter: string | undefined = isV1() ? ahkppConfig.get('v1.file.interpreterPath') : ahkppConfig.get('v2.file.interpreterPath'); + const executePath = resolvePath(interpreter, workspace.getWorkspaceFolder(textEditor.document.uri)?.uri.fsPath); if (!executePath) { - const s = ahkpath_cur || 'AutoHotkey.exe'; - window.showErrorMessage(zhcn ? `"${s}"未找到!` : `"${s}" not find!`, 'Select Interpreter') - .then(r => r && setInterpreter()); + const s = interpreter || 'AutoHotkey.exe'; + window.showErrorMessage(zhcn ? `"${s}"未找到` : `"${s}" not found`, 'Select Interpreter') + .then(r => r && setInterpreterV2()); return; } - let selecttext = '', path = '*', command = `"${executePath}" /ErrorStdOut=utf-8 `; + let selectedText = '', path = '*', command = `"${executePath}" /ErrorStdOut=utf-8 `; let startTime: Date; outputchannel.show(true); if (!ahkprocesses.size) outputchannel.clear(); - if (selection) - selecttext = textEditor.selections.map(textEditor.document.getText).join('\n'); + + // Build the command + if (runSelection) + selectedText = textEditor.selections.map(textEditor.document.getText).join('\n'); else if (textEditor.document.isUntitled || !textEditor.document.uri.toString().startsWith('file:///')) - selecttext = textEditor.document.getText(); + selectedText = textEditor.document.getText(); executePath.replace(/^(.+[\\/])AutoHotkeyUX\.exe$/i, (...m) => { const lc = m[1] + 'launcher.ahk'; if (existsSync(lc)) command = `"${executePath}" "${lc}" `; return ''; }) + + // Spawn the process let process: ChildProcess & { path?: string }; - if (selecttext !== '') { + if (selectedText !== '') { if (ahkStatusBarItem.text.endsWith('[UIAccess]')) { path = resolve(__dirname, 'temp.ahk'); - writeFileSync(path, selecttext); + writeFileSync(path, selectedText); command += `"${path}"`, startTime = new Date(); process = spawn(command, { cwd: `${resolve(textEditor.document.fileName, '..')}`, shell: true }); unlinkSync(path); } else { command += path, startTime = new Date(); process = spawn(command, { cwd: `${resolve(textEditor.document.fileName, '..')}`, shell: true }); - process.stdin?.write(selecttext), process.stdin?.end(); + process.stdin?.write(selectedText), process.stdin?.end(); } } else { if (textEditor.document.isUntitled) @@ -316,11 +330,12 @@ function runScript(textEditor: TextEditor, selection = false) { path = textEditor.document.fileName, command += `"${path}"`, startTime = new Date(); process = spawn(command, { cwd: resolve(path, '..'), shell: true }); } + if (process.pid) { outputchannel.appendLine(`[Running] [pid:${process.pid}] ${command}`); ahkprocesses.set(process.pid, process); process.path = path; - commands.executeCommand('setContext', 'ahk2:isRunning', true); + commands.executeCommand('setContext', 'ahk:isRunning', true); process.stderr?.on('data', (data) => { outputchannel.appendLine(decode(data)); }); @@ -335,7 +350,7 @@ function runScript(textEditor: TextEditor, selection = false) { outputchannel.appendLine(`[Done] [pid:${process.pid}] exited with code=${code} in ${((new Date()).getTime() - startTime.getTime()) / 1000} seconds`); ahkprocesses.delete(process.pid!); if (!ahkprocesses.size) - commands.executeCommand('setContext', 'ahk2:isRunning', false); + commands.executeCommand('setContext', 'ahk:isRunning', false); }); } else outputchannel.appendLine(`[Fail] ${command}`); @@ -396,10 +411,15 @@ async function beginDebug(extlist: string[], debugexts: { [type: string]: string debug.startDebugging(editor && workspace.getWorkspaceFolder(editor.document.uri), config); } -async function setInterpreter() { +/** + * Sets the v2 interpreter path via quick pick. + * Updates the most local configuration target that has a custom interpreter path. + * If no target has a custom path, updates workspace folder config. + */ +async function setInterpreterV2() { // eslint-disable-next-line prefer-const - let index = -1, { path: ahkpath, from } = getInterpreterPath(); - const list: QuickPickItem[] = [], _ = (ahkpath = resolvePath(ahkpath_cur || ahkpath, undefined, false)).toLowerCase(); + let index = -1, { path: ahkpath, from } = getInterpreterV2Path(); + const list: QuickPickItem[] = [], _ = (ahkpath = resolvePath(v2Interpreter || ahkpath, undefined, false)).toLowerCase(); const pick = window.createQuickPick(); let it: QuickPickItem, active: QuickPickItem | undefined, sel: QuickPickItem = { label: '' }; if (zhcn) { @@ -413,7 +433,7 @@ async function setInterpreter() { await addpath(resolve(ahkpath, '..'), _.includes('autohotkey') ? 20 : 5); if (!_.includes('c:\\program files\\autohotkey\\')) await addpath('C:\\Program Files\\AutoHotkey\\', 20); - index = list.map(it => it.detail?.toLowerCase()).indexOf((ahkpath_cur || ahkpath).toLowerCase()); + index = list.map(it => it.detail?.toLowerCase()).indexOf((v2Interpreter || ahkpath).toLowerCase()); if (index !== -1) active = list[index]; @@ -421,7 +441,7 @@ async function setInterpreter() { pick.title = zhcn ? '选择解释器' : 'Select Interpreter'; if (active) pick.activeItems = [active]; - pick.placeholder = (zhcn ? '当前: ' : 'Current: ') + ahkpath_cur; + pick.placeholder = (zhcn ? '当前: ' : 'Current: ') + v2Interpreter; pick.show(); pick.onDidAccept(async () => { if (pick.selectedItems[0] === list[0]) { @@ -446,11 +466,11 @@ async function setInterpreter() { } pick.dispose(); if (sel.detail) { - ahkStatusBarItem.tooltip = ahkpath_cur = sel.detail; - ahkppConfig.update('v2.file.interpreterPath', ahkpath_cur, from); - ahkStatusBarItem.text = sel.label ||= (await getAHKversion([ahkpath_cur]))[0]; + ahkStatusBarItem.tooltip = v2Interpreter = sel.detail; + ahkppConfig.update('v2.file.interpreterPath', v2Interpreter, from); + ahkStatusBarItem.text = sel.label ||= (await getAHKversion([v2Interpreter]))[0]; if (server_is_ready) - commands.executeCommand('ahk++.v2.setIntepreterPath', ahkpath_cur); + commands.executeCommand('ahk++.v2.setIntepreterPath', v2Interpreter); } }); pick.onDidHide(() => pick.dispose()); @@ -499,7 +519,12 @@ function getAHKversion(paths: string[]): Thenable { return client.sendRequest('ahk2.getAHKversion', paths.map(p => resolvePath(p, undefined, true) || p)); } -function getInterpreterPath() { +/** + * Gets the interpreter v2 path from the folder, workspace, global, or default value. + * Returns both the value and the target it was retrieved from. + * `from` is undefined if default value was used. + */ +function getInterpreterV2Path(): { path: string, from?: ConfigurationTarget } { const configDetails = ahkppConfig.inspect('v2.file.interpreterPath'); let path = ''; if (configDetails) @@ -516,7 +541,7 @@ function getInterpreterPath() { async function onDidChangegetInterpreter() { const uri = window.activeTextEditor?.document.uri; const ws = uri ? workspace.getWorkspaceFolder(uri)?.uri.fsPath : undefined; - let ahkPath = resolvePath(ahkpath_cur, ws, false); + let ahkPath = resolvePath(v2Interpreter, ws, false); if (ahkPath.toLowerCase().endsWith('.exe') && existsSync(ahkPath)) { // ahkStatusBarItem.tooltip is the current saved interpreter path if (ahkPath !== ahkStatusBarItem.tooltip) { @@ -529,8 +554,13 @@ async function onDidChangegetInterpreter() { } } -/** Resolves a given path to an absolute path. Returns empty string if resolution fails. */ -export function resolvePath(path: string, workspace?: string, resolveSymbolicLink = true): string { +/** + * Returns the provided path as an absolute path. + * Resolves the provided path against the provided workspace. + * Resolves symbolic links by default. + * Returns empty string if resolution fails. + */ +export function resolvePath(path: string | undefined, workspace?: string, resolveSymbolicLink = true): string { if (!path) return ''; const paths: string[] = []; diff --git a/package-lock.json b/package-lock.json index 79129b02..3dd4ffaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,6 @@ "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", - "@vscode/vsce": "^3.0.0", "del-cli": "^5.1.0", "esbuild": "^0.23.1", "eslint": "^9.4.0", @@ -43,229 +42,6 @@ "vscode": "^1.82.0" } }, - "node_modules/@azure/abort-controller": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz", - "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/core-auth": { - "version": "1.7.2", - "resolved": "https://registry.npmmirror.com/@azure/core-auth/-/core-auth-1.7.2.tgz", - "integrity": "sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-client": { - "version": "1.9.2", - "resolved": "https://registry.npmmirror.com/@azure/core-client/-/core-client-1.9.2.tgz", - "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.6.1", - "@azure/logger": "^1.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-client/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-rest-pipeline": { - "version": "1.16.0", - "resolved": "https://registry.npmmirror.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.0.tgz", - "integrity": "sha512-CeuTvsXxCUmEuxH5g/aceuSl6w2EugvNHKAtKKVdiX915EjJJxAwfzNNWZreNnbxHZ2fi0zaM6wwS23x2JVqSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.9.0", - "@azure/logger": "^1.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-tracing": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/@azure/core-tracing/-/core-tracing-1.1.2.tgz", - "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-util": { - "version": "1.9.0", - "resolved": "https://registry.npmmirror.com/@azure/core-util/-/core-util-1.9.0.tgz", - "integrity": "sha512-AfalUQ1ZppaKuxPPMsFEUdX6GZPB3d9paR9d/TTL7Ow2De8cJaC7ibi7kWVlFAVPCYo31OcnGymc0R89DX8Oaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@azure/abort-controller": "^2.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/identity": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/@azure/identity/-/identity-4.2.0.tgz", - "integrity": "sha512-ve3aYv79qXOJ8wRxQ5jO0eIz2DZ4o0TyME4m4vlGV5YyePddVZ+pFMzusAMODNAflYAAv1cBIhKnd4xytmXyig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.5.0", - "@azure/core-client": "^1.4.0", - "@azure/core-rest-pipeline": "^1.1.0", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "@azure/msal-browser": "^3.11.1", - "@azure/msal-node": "^2.6.6", - "events": "^3.0.0", - "jws": "^4.0.0", - "open": "^8.0.0", - "stoppable": "^1.1.0", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/logger": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/@azure/logger/-/logger-1.1.2.tgz", - "integrity": "sha512-l170uE7bsKpIU6B/giRc9i4NI0Mj+tANMMMxf7Zi/5cKzEqPayP7+X1WPrG7e+91JgY8N+7K7nF2WOi7iVhXvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/msal-browser": { - "version": "3.16.0", - "resolved": "https://registry.npmmirror.com/@azure/msal-browser/-/msal-browser-3.16.0.tgz", - "integrity": "sha512-WKobvIisBK7sFSOwHuchH9tUMekwhJRLgLE9tKhIq0wFYGRcVGK0KivP5vZrobVZEMNCZWto0fI1VcSVoa+cig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@azure/msal-common": "14.11.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@azure/msal-common": { - "version": "14.11.0", - "resolved": "https://registry.npmmirror.com/@azure/msal-common/-/msal-common-14.11.0.tgz", - "integrity": "sha512-B6+IKLFs7Lsr06vjX8dPN61ENpTgiFrHf+CVo1UasHcmk5uEOq5D4thrbjsauKX+xtFryYsCDtznVDmWS4/sCg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@azure/msal-node": { - "version": "2.9.1", - "resolved": "https://registry.npmmirror.com/@azure/msal-node/-/msal-node-2.9.1.tgz", - "integrity": "sha512-I9Pc78mXwj/K8ydSgTfZ5A20vQ/xvfgnnhSCkienZ29b59zFy/hb2Vxmc6Gvg5pNkimSqkPnAtGoBMxYOLBm1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@azure/msal-common": "14.11.0", - "jsonwebtoken": "^9.0.0", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -1567,289 +1343,6 @@ "streamx": "^2.15.0" } }, - "node_modules/@vscode/vsce": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-3.0.0.tgz", - "integrity": "sha512-UKYcC7fcSw6AUK6nlfm8A8WSOA41H3DRAwafCMp9CQpg3K9COAQKkrgQ+dKPhwkFTP7SPZNEiulDpPLwvr5QQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@azure/identity": "^4.1.0", - "@vscode/vsce-sign": "^2.0.0", - "azure-devops-node-api": "^12.5.0", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "cockatiel": "^3.1.2", - "commander": "^6.2.1", - "form-data": "^4.0.0", - "glob": "^11.0.0", - "hosted-git-info": "^4.0.2", - "jsonc-parser": "^3.2.0", - "leven": "^3.1.0", - "markdown-it": "^12.3.2", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^7.5.2", - "tmp": "^0.2.3", - "typed-rest-client": "^1.8.4", - "url-join": "^4.0.1", - "xml2js": "^0.5.0", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "vsce" - }, - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "keytar": "^7.7.0" - } - }, - "node_modules/@vscode/vsce-sign": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign/-/vsce-sign-2.0.4.tgz", - "integrity": "sha512-0uL32egStKYfy60IqnynAChMTbL0oqpqk0Ew0YHiIb+fayuGZWADuIPHWUcY1GCnAA+VgchOPDMxnc2R3XGWEA==", - "dev": true, - "hasInstallScript": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optionalDependencies": { - "@vscode/vsce-sign-alpine-arm64": "2.0.2", - "@vscode/vsce-sign-alpine-x64": "2.0.2", - "@vscode/vsce-sign-darwin-arm64": "2.0.2", - "@vscode/vsce-sign-darwin-x64": "2.0.2", - "@vscode/vsce-sign-linux-arm": "2.0.2", - "@vscode/vsce-sign-linux-arm64": "2.0.2", - "@vscode/vsce-sign-linux-x64": "2.0.2", - "@vscode/vsce-sign-win32-arm64": "2.0.2", - "@vscode/vsce-sign-win32-x64": "2.0.2" - } - }, - "node_modules/@vscode/vsce-sign-alpine-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.2.tgz", - "integrity": "sha512-E80YvqhtZCLUv3YAf9+tIbbqoinWLCO/B3j03yQPbjT3ZIHCliKZlsy1peNc4XNZ5uIb87Jn0HWx/ZbPXviuAQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optional": true, - "os": [ - "alpine" - ] - }, - "node_modules/@vscode/vsce-sign-alpine-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.2.tgz", - "integrity": "sha512-n1WC15MSMvTaeJ5KjWCzo0nzjydwxLyoHiMJHu1Ov0VWTZiddasmOQHekA47tFRycnt4FsQrlkSCTdgHppn6bw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optional": true, - "os": [ - "alpine" - ] - }, - "node_modules/@vscode/vsce-sign-darwin-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.2.tgz", - "integrity": "sha512-rz8F4pMcxPj8fjKAJIfkUT8ycG9CjIp888VY/6pq6cuI2qEzQ0+b5p3xb74CJnBbSC0p2eRVoe+WgNCAxCLtzQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@vscode/vsce-sign-darwin-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.2.tgz", - "integrity": "sha512-MCjPrQ5MY/QVoZ6n0D92jcRb7eYvxAujG/AH2yM6lI0BspvJQxp0o9s5oiAM9r32r9tkLpiy5s2icsbwefAQIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@vscode/vsce-sign-linux-arm": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.2.tgz", - "integrity": "sha512-Fkb5jpbfhZKVw3xwR6t7WYfwKZktVGNXdg1m08uEx1anO0oUPUkoQRsNm4QniL3hmfw0ijg00YA6TrxCRkPVOQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@vscode/vsce-sign-linux-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.2.tgz", - "integrity": "sha512-Ybeu7cA6+/koxszsORXX0OJk9N0GgfHq70Wqi4vv2iJCZvBrOWwcIrxKjvFtwyDgdeQzgPheH5nhLVl5eQy7WA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@vscode/vsce-sign-linux-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.2.tgz", - "integrity": "sha512-NsPPFVtLaTlVJKOiTnO8Cl78LZNWy0Q8iAg+LlBiCDEgC12Gt4WXOSs2pmcIjDYzj2kY4NwdeN1mBTaujYZaPg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@vscode/vsce-sign-win32-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.2.tgz", - "integrity": "sha512-wPs848ymZ3Ny+Y1Qlyi7mcT6VSigG89FWQnp2qRYCyMhdJxOpA4lDwxzlpL8fG6xC8GjQjGDkwbkWUcCobvksQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@vscode/vsce-sign-win32-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.2.tgz", - "integrity": "sha512-pAiRN6qSAhDM5SVOIxgx+2xnoVUePHbRNC7OD2aOR3WltTKxxF25OfpK8h8UQ7A0BuRkSgREbB59DBlFk4iAeg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "SEE LICENSE IN LICENSE.txt", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@vscode/vsce/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@vscode/vsce/node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmmirror.com/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/vsce/node_modules/jackspeak": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-4.0.1.tgz", - "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/@vscode/vsce/node_modules/lru-cache": { - "version": "11.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.0.0.tgz", - "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@vscode/vsce/node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -2242,24 +1735,6 @@ "node": ">=0.10.0" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/azure-devops-node-api": { - "version": "12.5.0", - "resolved": "https://registry.npmmirror.com/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", - "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", - "dev": true, - "license": "MIT", - "dependencies": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmmirror.com/b4a/-/b4a-1.6.6.tgz", @@ -2370,33 +1845,13 @@ "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/bottleneck": { "version": "2.19.5", @@ -2479,49 +1934,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "optional": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", @@ -2634,26 +2046,6 @@ "node": ">= 6.0.0" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", @@ -2732,46 +2124,6 @@ "node": ">=4" } }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmmirror.com/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", @@ -2810,14 +2162,6 @@ "node": ">= 6" } }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true, - "license": "ISC", - "optional": true - }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", @@ -3003,16 +2347,6 @@ "node": ">= 0.12.0" } }, - "node_modules/cockatiel": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/cockatiel/-/cockatiel-3.1.3.tgz", - "integrity": "sha512-xC759TpZ69d7HhfDp8m2WkRwEUiCkxY8Ee2OQH/3H6zmy2D/5Sm+zSTbPRa+V2QyjDtpMvjOIAOVjA2gp6N1kQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", @@ -3037,29 +2371,6 @@ "dev": true, "license": "MIT" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmmirror.com/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", @@ -3133,36 +2444,6 @@ "node": ">= 8" } }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/debug": { "version": "4.3.5", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz", @@ -3231,23 +2512,6 @@ "node": ">=0.10.0" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.0.1.tgz", @@ -3255,17 +2519,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", @@ -3273,34 +2526,6 @@ "dev": true, "license": "MIT" }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/del": { "version": "7.1.0", "resolved": "https://registry.npmmirror.com/del/-/del-7.1.0.tgz", @@ -3391,16 +2616,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz", @@ -3439,17 +2654,6 @@ "node": ">=12.20" } }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" - } - }, "node_modules/detect-newline": { "version": "4.0.1", "resolved": "https://registry.npmmirror.com/detect-newline/-/detect-newline-4.0.1.tgz", @@ -3486,65 +2690,6 @@ "node": ">=8" } }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, "node_modules/duplexify": { "version": "3.7.1", "resolved": "https://registry.npmmirror.com/duplexify/-/duplexify-3.7.1.tgz", @@ -3598,16 +2743,6 @@ "dev": true, "license": "MIT" }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", @@ -3663,19 +2798,6 @@ "node": ">=10.13.0" } }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/envinfo": { "version": "7.13.0", "resolved": "https://registry.npmmirror.com/envinfo/-/envinfo-7.13.0.tgz", @@ -3699,29 +2821,6 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/es-module-lexer": { "version": "1.5.3", "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.5.3.tgz", @@ -4150,17 +3249,6 @@ "node": ">=0.8.x" } }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true, - "license": "(MIT OR WTFPL)", - "optional": true, - "engines": { - "node": ">=6" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4239,16 +3327,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -4328,28 +3406,13 @@ "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/fresh": { @@ -4362,14 +3425,6 @@ "node": ">= 0.6" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4412,26 +3467,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-stdin": { "version": "9.0.0", "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-9.0.0.tgz", @@ -4455,14 +3490,6 @@ "url": "https://github.com/fisker/git-hooks-list?sponsor=1" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmmirror.com/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", @@ -4539,19 +3566,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4604,32 +3618,6 @@ "node": ">=4" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz", @@ -4702,26 +3690,6 @@ "dev": true, "license": "MIT" }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, "node_modules/http-assert": { "version": "1.5.0", "resolved": "https://registry.npmmirror.com/http-assert/-/http-assert-1.5.0.tgz", @@ -4945,14 +3913,6 @@ "dev": true, "license": "ISC" }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC", - "optional": true - }, "node_modules/interpret": { "version": "2.2.0", "resolved": "https://registry.npmmirror.com/interpret/-/interpret-2.2.0.tgz", @@ -5003,22 +3963,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", @@ -5160,19 +4104,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", @@ -5364,59 +4295,6 @@ "dev": true, "license": "MIT" }, - "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jsonwebtoken/node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jsonwebtoken/node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmmirror.com/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "license": "MIT", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmmirror.com/jszip/-/jszip-3.10.1.tgz", @@ -5477,29 +4355,6 @@ "dev": true, "license": "MIT" }, - "node_modules/jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" - } - }, "node_modules/keygrip": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/keygrip/-/keygrip-1.1.0.tgz", @@ -5513,19 +4368,6 @@ "node": ">= 0.6" } }, - "node_modules/keytar": { - "version": "7.9.0", - "resolved": "https://registry.npmmirror.com/keytar/-/keytar-7.9.0.tgz", - "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "node-addon-api": "^4.3.0", - "prebuild-install": "^7.0.1" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", @@ -5739,16 +4581,6 @@ "node": ">= 0.6" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", @@ -5780,16 +4612,6 @@ "dev": true, "license": "MIT" }, - "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "uc.micro": "^1.0.1" - } - }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", @@ -5820,48 +4642,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -5869,13 +4649,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "dev": true, - "license": "MIT" - }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz", @@ -6011,40 +4784,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true, - "license": "MIT" - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz", @@ -6146,19 +4885,6 @@ "node": ">=8.6" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", @@ -6192,20 +4918,6 @@ "node": ">=6" } }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz", @@ -6274,14 +4986,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmmirror.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/mocha": { "version": "10.7.3", "resolved": "https://registry.npmmirror.com/mocha/-/mocha-10.7.3.tgz", @@ -6657,21 +5361,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmmirror.com/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true, - "license": "ISC" - }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6710,28 +5399,6 @@ "path-to-regexp": "^6.2.1" } }, - "node_modules/node-abi": { - "version": "3.63.0", - "resolved": "https://registry.npmmirror.com/node-abi/-/node-abi-3.63.0.tgz", - "integrity": "sha512-vAszCsOUrUxjGAmdnM/pq7gUgie0IRteCQMX6d4A534fQCR93EJU5qgzBvU6EkFfK27s0T3HEV3BOyJIr7OMYw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz", @@ -6751,41 +5418,18 @@ "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "engines": { + "node": ">=10" } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10.0" } }, "node_modules/on-finished": { @@ -6843,24 +5487,6 @@ "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==", "dev": true }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", @@ -7101,53 +5727,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^5.1.0" - } - }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz", @@ -7255,13 +5834,6 @@ "through2": "^2.0.3" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz", @@ -7327,34 +5899,6 @@ "node": ">=18" } }, - "node_modules/prebuild-install": { - "version": "7.1.2", - "resolved": "https://registry.npmmirror.com/prebuild-install/-/prebuild-install-7.1.2.tgz", - "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7432,22 +5976,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.12.1", - "resolved": "https://registry.npmmirror.com/qs/-/qs-6.12.1.tgz", - "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -7499,36 +6027,6 @@ "safe-buffer": "^5.1.0" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "optional": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/read-pkg": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-6.0.0.tgz", @@ -7901,13 +6399,6 @@ ], "license": "MIT" }, - "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "dev": true, - "license": "ISC" - }, "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz", @@ -7949,24 +6440,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz", @@ -8017,25 +6490,6 @@ "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", @@ -8049,55 +6503,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "optional": true - }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "optional": true, - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/sinon": { "version": "18.0.0", "resolved": "https://registry.npmmirror.com/sinon/-/sinon-18.0.0.tgz", @@ -8353,17 +6758,6 @@ "ieee754": "^1.2.1" } }, - "node_modules/stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4", - "npm": ">=6" - } - }, "node_modules/stream-shift": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/stream-shift/-/stream-shift-1.0.3.tgz", @@ -8509,17 +6903,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", @@ -8556,38 +6939,6 @@ "node": ">=6" } }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/terser": { "version": "5.31.1", "resolved": "https://registry.npmmirror.com/terser/-/terser-5.31.1.tgz", @@ -8725,16 +7076,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.14" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8881,13 +7222,6 @@ "node": ">=8" } }, - "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true, - "license": "0BSD" - }, "node_modules/tsscmp": { "version": "1.0.6", "resolved": "https://registry.npmmirror.com/tsscmp/-/tsscmp-1.0.6.tgz", @@ -8898,30 +7232,6 @@ "node": ">=0.6.x" } }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmmirror.com/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", @@ -8972,18 +7282,6 @@ "node": ">= 0.6" } }, - "node_modules/typed-rest-client": { - "version": "1.8.11", - "resolved": "https://registry.npmmirror.com/typed-rest-client/-/typed-rest-client-1.8.11.tgz", - "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.4.5.tgz", @@ -9139,20 +7437,6 @@ "eslint": "^8.56.0" } }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true, - "license": "MIT" - }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmmirror.com/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", - "dev": true, - "license": "MIT" - }, "node_modules/undici-types": { "version": "6.19.6", "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.19.6.tgz", @@ -9201,13 +7485,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true, - "license": "MIT" - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -9215,16 +7492,6 @@ "dev": true, "license": "MIT" }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmmirror.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -9728,30 +7995,6 @@ "dev": true, "license": "ISC" }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmmirror.com/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0" - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", @@ -9846,27 +8089,6 @@ "node": ">=8" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmmirror.com/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3" - } - }, "node_modules/ylru": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/ylru/-/ylru-1.4.0.tgz", diff --git a/package.json b/package.json index 78657d82..9b5d6959 100644 --- a/package.json +++ b/package.json @@ -45,497 +45,18 @@ "eslint:fix": "npm run eslint:files -- client server --fix", "format": "prettier --check .", "format:fix": "prettier --write .", - "lint": "npm run eslint && npm run sort-package-json", - "package": "vsce package", + "lint": "npm run format && npm run eslint && npm run sort-package-json", + "lint:ci": "npm run eslint && npm run sort-package-json", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", - "test": "npm run test-grammar && npm run test-unit", - "test-grammar": "vscode-tmgrammar-snap syntaxes/samples/*.{ahk1,ahk2}", + "test": "npm run test-unit", "pretest-unit": "npm run compile-ts", "test-unit": "cd client && vscode-test", "test//": "Run unit tests, not grammar tests", - "validate": "npm run lint && npm run test && npm run package", - "vscode:prepublish": "npm run build:old", + "validate": "npm run lint && npm run test", + "validate:ci": "npm run lint:ci && npm run test", "watch": "tsc -b -w" }, - "contributes": { - "breakpoints": [ - { - "language": "ahk2" - } - ], - "commands": [ - { - "enablement": "!isWeb", - "command": "ahk++.debugAttach", - "title": "%ahk++.command.debugAttach%", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk++.debugParams", - "title": "%ahk++.command.debugParams%", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2", - "command": "ahk++.diagnostic.full", - "title": "%ahk++.command.diagnostic.full%", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2", - "command": "ahk++.exportSymbols", - "title": "%ahk++.command.exportSymbols%", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk++.run", - "title": "%ahk++.command.run%", - "icon": "$(play)", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk++.runSelection", - "title": "%ahk++.command.runSelection%", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk++.stop", - "title": "%ahk++.command.stop%", - "icon": "$(stop)", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2", - "command": "ahk++.addDocComment", - "title": "%ahk++.command.addDocComment%", - "category": "AHK++" - }, - { - "enablement": "!isWeb", - "command": "ahk++.setV2Interpreter", - "title": "%ahk++.command.setV2Interpreter%", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2", - "command": "ahk++.updateVersionInfo", - "title": "%ahk++.command.updateVersionInfo%", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2 || editorLangId == ahk", - "command": "ahk++.switchAhkVersion", - "title": "Switch AHK Version", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk++.selectSyntaxes", - "title": "Select AHK Syntaxes", - "category": "AHK++" - }, - { - "enablement": "editorLangId == ahk2 && resourceScheme == file", - "command": "ahk++.setAScriptDir", - "title": "%ahk++.command.setAScriptDir%", - "category": "AHK++" - } - ], - "configuration": { - "properties": { - "ahk++.v2.librarySuggestions": { - "scope": "window", - "type": "string", - "enum": [ - "Disabled", - "Local", - "User and Standard", - "All" - ], - "default": "Disabled", - "description": "%ahk++.config.v2.librarySuggestions%" - }, - "ahk++.v2.commentTagRegex": { - "scope": "window", - "type": "string", - "default": "^;;\\s*(?.+)", - "markdownDescription": "%ahk++.config.v2.commentTagRegex%" - }, - "ahk++.v2.completeFunctionCalls": { - "scope": "window", - "type": "boolean", - "default": false, - "markdownDescription": "%ahk++.config.v2.completeFunctionCalls%" - }, - "ahk++.v2.debugConfiguration": { - "scope": "window", - "type": "object", - "default": { - "port": "9002-9100", - "useAnnounce": "detail", - "useAutoJumpToError": true, - "useDebugDirective": true, - "usePerfTips": true - }, - "markdownDescription": "%ahk++.config.v2.debugConfiguration%" - }, - "ahk++.v2.diagnostics.classNonDynamicMemberCheck": { - "scope": "window", - "type": "boolean", - "default": true, - "description": "%ahk++.config.v2.diagnostics.classNonDynamicMemberCheck%" - }, - "ahk++.v2.diagnostics.paramsCheck": { - "scope": "window", - "type": "boolean", - "default": true, - "description": "%ahk++.config.v2.diagnostics.paramsCheck%" - }, - "ahk++.v2.warn.varUnset": { - "scope": "window", - "type": "boolean", - "default": true, - "description": "%ahk++.config.v2.warn.varUnset%" - }, - "ahk++.v2.warn.localSameAsGlobal": { - "scope": "window", - "type": "boolean", - "default": false, - "description": "%ahk++.config.v2.warn.localSameAsGlobal%" - }, - "ahk++.v2.warn.callWithoutParentheses": { - "scope": "window", - "type": "string", - "enum": [ - "Off", - "Parentheses", - "On" - ], - "default": "Off", - "description": "%ahk++.config.v2.warn.callWithoutParentheses%" - }, - "ahk++.v2.actionWhenV1Detected": { - "scope": "window", - "type": "string", - "default": "Warn", - "enum": [ - "Continue", - "Warn", - "StopParsing", - "SwitchToV1", - "SkipLine" - ], - "description": "%ahk++.config.v2.actionWhenV1Detected%" - }, - "ahk++.v2.completionCommitCharacters": { - "scope": "window", - "type": "object", - "properties": { - "Class": { - "type": "string" - }, - "Function": { - "type": "string" - } - }, - "default": { - "Class": ".(", - "Function": "(" - }, - "markdownDescription": "%ahk++.config.v2.completionCommitCharacters%" - }, - "ahk++.Files.Exclude": { - "scope": "window", - "type": "array", - "default": [], - "items": { - "type": "string" - }, - "uniqueItems": true, - "description": "%ahk++.config.v2.files.exclude%" - }, - "ahk++.Files.ScanMaxDepth": { - "scope": "window", - "type": "integer", - "default": 2, - "description": "%ahk++.config.v2.files.maxScanDepth%" - }, - "ahk++.v2.formatter": { - "scope": "window", - "type": "object", - "properties": { - "arrayStyle": { - "type": "string", - "enum": [ - "collapse", - "expand", - "none" - ], - "default": "none" - }, - "braceStyle": { - "type": "string", - "enum": [ - "One True Brace", - "Allman", - "One True Brace Variant" - ], - "enumDescriptions": [ - "if 1 {\n} else {\n}", - "if 1\n{\n}\nelse\n{\n}", - "if 1 {\n}\nelse {\n}" - ] - }, - "breakChainedMethods": { - "type": "boolean", - "default": false - }, - "ignoreComment": { - "type": "boolean", - "default": false - }, - "indentString": { - "type": "string", - "default": "\t" - }, - "indentBetweenHotIfDirectives": { - "type": "boolean", - "default": false - }, - "keywordStartWithUppercase": { - "type": "boolean", - "default": false - }, - "maxPreserveNewlines": { - "type": "number", - "default": 2 - }, - "objectStyle": { - "type": "string", - "enum": [ - "collapse", - "expand", - "none" - ], - "default": "none" - }, - "preserveNewlines": { - "type": "boolean", - "default": true - }, - "spaceBeforeConditional": { - "type": "boolean", - "default": true - }, - "spaceAfterDoubleColon": { - "type": "boolean", - "default": true - }, - "spaceInEmptyParen": { - "type": "boolean", - "default": false - }, - "spaceInOther": { - "type": "boolean", - "default": true - }, - "spaceInParen": { - "type": "boolean", - "default": false - }, - "switchCaseAlignment": { - "type": "boolean", - "default": false - }, - "symbolWithSameCase": { - "type": "boolean", - "default": false - }, - "whitespaceBeforeInlineComment": { - "type": "string" - }, - "wrapLineLength": { - "type": "number", - "default": 0 - } - }, - "default": {} - }, - "ahk++.v2.file.interpreterPath": { - "scope": "window", - "type": "string", - "default": "C:/Program Files/Autohotkey/v2/AutoHotkey.exe", - "markdownDescription": "%ahk++.config.v2.file.interpreterPath%" - }, - "ahk++.symbolFoldingFromOpenBrace": { - "scope": "window", - "type": "boolean", - "default": false, - "description": "%ahk++.config.v2.symbolFoldingFromOpenBrace%" - }, - "ahk++.workingDirectories": { - "scope": "window", - "type": "array", - "default": [], - "items": { - "type": "string" - }, - "uniqueItems": true, - "description": "%ahk++.config.v2.workingDirectories%" - }, - "ahk++.v2.syntaxes": { - "scope": "window", - "type": "string", - "markdownDescription": "%ahk++.config.v2.syntaxes%" - } - } - }, - "configurationDefaults": { - "[ahk2]": { - "editor.defaultFormatter": "mark-wiemer.vscode-autohotkey-plus-plus", - "editor.quickSuggestions": { - "other": true, - "comments": false, - "strings": true - } - } - }, - "grammars": [ - { - "language": "ahk2", - "scopeName": "source.ahk2", - "path": "./syntaxes/ahk2.tmLanguage.json", - "embeddedLanguages": { - "meta.embedded.ahk2": "ahk2" - }, - "unbalancedBracketScopes": [ - "keyword.keys.ahk2" - ] - }, - { - "language": "~ahk2-output", - "scopeName": "ahk2.output", - "path": "./syntaxes/ahk2-output.tmLanguage.json" - } - ], - "keybindings": [ - { - "command": "ahk++.run", - "key": "ctrl+f5", - "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection" - }, - { - "command": "ahk++.runSelection", - "key": "ctrl+f5", - "when": "editorLangId == ahk2 && !isWeb && editorHasSelection" - }, - { - "command": "ahk++.debugParams", - "key": "shift+f5", - "when": "editorLangId == ahk2 && !isWeb" - }, - { - "command": "ahk++.stop", - "key": "ctrl+f6", - "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning" - } - ], - "languages": [ - { - "id": "ahk2", - "aliases": [ - "ahk++", - "autohotkey2", - "ahk2" - ], - "extensions": [ - ".ahk", - ".ah2", - ".ahk2" - ], - "configuration": "./ahk2.configuration.json", - "icon": { - "dark": "icon_filetype.png", - "light": "icon_filetype.png" - } - }, - { - "id": "ahk", - "aliases": [ - "AutoHotkey" - ] - }, - { - "id": "~ahk2-output" - } - ], - "menus": { - "editor/context": [ - { - "when": "editorLangId == ahk2 && !isWeb", - "command": "ahk++.debugAttach", - "group": "navigation@2" - }, - { - "when": "editorLangId == ahk2 && !isWeb", - "command": "ahk++.debugParams", - "group": "navigation@2" - }, - { - "when": "editorLangId == ahk2 && !isWeb && editorHasSelection", - "command": "ahk++.runSelection", - "group": "navigation@0" - }, - { - "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection", - "command": "ahk++.run", - "group": "navigation@0" - }, - { - "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning", - "command": "ahk++.stop", - "group": "navigation@0" - }, - { - "when": "editorLangId == ahk2", - "command": "ahk++.addDocComment", - "group": "navigation@2" - }, - { - "when": "editorLangId == ahk2", - "command": "ahk++.updateVersionInfo", - "group": "navigation@2" - } - ], - "editor/title": [ - { - "command": "ahk++.run", - "group": "navigation@0", - "when": "resourceLangId == ahk2 && shellExecutionSupported" - }, - { - "command": "ahk++.stop", - "group": "navigation@0", - "when": "resourceLangId == ahk2 && ahk2:isRunning && shellExecutionSupported" - } - ] - }, - "semanticTokenScopes": [ - { - "language": "ahk2", - "scopes": { - "operator": [ - "keyword.operator.wordlike.ahk2" - ] - } - } - ] - }, "prettier": { "singleQuote": true, "tabWidth": 4, @@ -567,13 +88,11 @@ "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", - "@vscode/vsce": "^3.0.0", "del-cli": "^5.1.0", "esbuild": "^0.23.1", "eslint": "^9.4.0", "globals": "^15.4.0", "mocha": "^10.7.0", - "path-browserify": "^1.0.1", "prettier": "3.3.3", "sinon": "^18.0.0", "sort-package-json": "^2.10.0", @@ -587,7 +106,6 @@ "engines": { "vscode": "^1.82.0" }, - "icon": "icon.png", "overrides": { "eslint": "^9.4.0" } diff --git a/package.nls.json b/package.nls.json deleted file mode 100644 index 3c7f6aba..00000000 --- a/package.nls.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "ahk++.command.addDocComment": "Add Doc Comment", - "ahk++.command.debugAttach": "Debug AHK and Attach", - "ahk++.command.debugParams": "Debug AHK with Params", - "ahk++.command.diagnostic.full": "Run AHK++ Diagnostic", - "ahk++.command.exportSymbols": "Export AHK Symbols", - "ahk++.command.run": "Run AHK Script", - "ahk++.command.runSelection": "Run Selection", - "ahk++.command.setAScriptDir": "Set A_ScriptDir Here", - "ahk++.command.setV2Interpreter": "Set AHK v2 Interpreter", - "ahk++.command.stop": "Stop AHK Script", - "ahk++.command.updateVersionInfo": "Update File Version Info", - "ahk++.config.v2.commentTagRegex": "The regular expression for custom symbols to appear in the breadcrumb and elsewhere. Default regex matches any line that starts with `;;`", - "ahk++.config.v2.completeFunctionCalls": "Whether to automatically add parenetheses when calling a function", - "ahk++.config.v2.debugConfiguration": "The [launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) to use when debugging", - "ahk++.config.v2.diagnostics.classNonDynamicMemberCheck": "Check whether non-dynamic members of a class exist", - "ahk++.config.v2.diagnostics.paramsCheck": "Check that the function call has the correct number of arguments", - "ahk++.config.v2.librarySuggestions": "Which libraries to suggest functions from, if any.", - "ahk++.config.v2.warn.localSameAsGlobal": "Display warnings for each undeclared local variable that has the same name as a global variable. Changes take effect after restart.", - "ahk++.config.v2.warn.varUnset": "Display a warning when referencing an unassigned variable. Changes take effect after restart.", - - "ahk++.config.v2.actionWhenV1Detected": "Action when v1 script is detected", - "ahk++.config.v2.completionCommitCharacters": "Characters which commit auto-completion. Defaults to `.(`", - "ahk++.config.v2.warn.callWithoutParentheses": "Display warnings for each function or method call without parentheses", - "ahk++.config.v2.files.exclude": "Configure glob patterns for excluding files and folders when scanning ahk files.", - "ahk++.config.v2.files.maxScanDepth": "Controls the depth when scanning ahk files.", - "ahk++.config.v2.file.interpreterPath": "The path of the `AutoHotkey.exe` executable file. If `AutoHotkeyUX.exe` is selected, the script will be launched using UX Launcher.", - "ahk++.config.v2.symbolFoldingFromOpenBrace": "Forced symbol folding starts at open brace", - "ahk++.config.v2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", - "ahk++.config.v2.workingDirectories": "Sets the working directory for the script" -} diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json deleted file mode 100644 index 833f3e5f..00000000 --- a/package.nls.zh-cn.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "ahk++.command.addDocComment": "生成注释模板", - "ahk++.command.debugAttach": "附加到运行中的脚本", - "ahk++.command.debugParams": "带参调试", - "ahk++.command.diagnostic.full": "诊断全文", - "ahk++.command.exportSymbols": "导出ahk类和函数", - "ahk++.command.run": "运行脚本", - "ahk++.command.runSelection": "运行选择的脚本", - "ahk++.command.setAScriptDir": "设置此处为A_ScriptDir", - "ahk++.command.setV2Interpreter": "选择AutoHotkey2解释器", - "ahk++.command.stop": "停止运行中的脚本", - "ahk++.command.updateVersionInfo": "更新文件版本信息", - "ahk++.config.v2.commentTagRegex": "用来从注释中提取命名标记的正则表达式, 并生成模块符号", - "ahk++.config.v2.completeFunctionCalls": "当右侧不存在`(`或`[`时, 给函数补全添加括号; 否则向右移动光标", - "ahk++.config.v2.librarySuggestions": "对用户库和标准库, 本地库提供补全和自动include", - "ahk++.config.v2.debugConfiguration": "追加调试配置到当前启动的调试器, 与launch.json配置相同", - "ahk++.config.v2.diagnostics.classNonDynamicMemberCheck": "检查类非动态成员是否存在", - "ahk++.config.v2.diagnostics.paramsCheck": "检查函数调用参数个数是否正确", - "ahk++.config.v2.warn.localSameAsGlobal": "为每个与全局变量同名的未声明的局部变量显示警告", - "ahk++.config.v2.warn.varUnset": "为每个从未直接赋值或与引用操作符一起使用的变量的显示警告", - - "action.skipline": "跳过行", - "action.stopparsing": "停止解析", - "action.switchtov1": "切换到ahk v1", - "ahk++.config.v2.actionWhenV1Detected": "检测到v1脚本时的行为", - "ahk++.config.v2.completionCommitCharacters": "提交自动完成的字符, 例如`.(`", - "ahk++.config.v2.warn.callWithoutParentheses": "为每个不带括号的函数或方法调用显示警告", - "ahk++.config.v2.files.exclude": "配置 glob 模式以在扫描ahk文件时排除文件和文件夹.", - "ahk++.config.v2.files.maxScanDepth": "控制扫描ahk文件时的深度.", - "ahk++.config.v2.file.interpreterPath": "`AutoHotkey.exe`可执行文件的路径. 如果选择`AutoHotkeyUX.exe`, 将使用UX Launcher启动脚本.", - "ahk++.config.v2.symbolFoldingFromOpenBrace": "强制符号折叠从大括号处开始", - "ahk++.config.v2.syntaxes": "指定用于智能感知的`ahk2.json`, `*.snippet.json`和`ahk2.d.ahk`文件的文件夹路径.", - "ahk++.config.v2.workingDirectories": "设置脚本的工作目录", - "codeaction.include": "导入 '{0}'", - "completionitem.author": "添加作者, 描述, 日期, 版本等文件信息.", - "completionitem.generatecomment": "生成当前作用域函数/方法的注释模板.", - "completionitem.include": "从'{0}'自动导入", - "completionitem.new": "构造类的新实例.", - "completionitem.prototype": "检索或设置类的所有实例所基于的对象.", - "completionitem.super": "在继承类中, super 可以代替 this 来访问在派生类中被重写的方法或属性的超类版本.", - "completionitem.this": "在类中, 通过 this 访问该类的其他实例变量和方法.", - "completionitem.thishotkey": "热键函数的隐藏参数.", - "completionitem.value": "在动态属性 set 中, Value 包含被分配的值.", - "diagnostic.acceptparams": "'{0}' 接受{1}个参数", - "diagnostic.assignerr": "{0} '{1}'不能用作输出变量", - "diagnostic.classinfuncerr": "函数不能包含类", - "diagnostic.classuseerr": "类不能用作输出变量", - "diagnostic.conflictserr": "{0} '{2}'声明和已存在的{1}冲突", - "diagnostic.declarationerr": "意外的声明", - "diagnostic.defaultvalmissing": "'{0}' 需要参数默认值", - "diagnostic.deprecated": "使用'{0}'而不是'{1}'", - "diagnostic.didyoumean": "你是想用'{0}'吗?", - "diagnostic.dupdeclaration": "重复声明", - "diagnostic.duplabel": "重复的标签声明", - "diagnostic.filenotexist": "'{0}'文件不存在", - "diagnostic.funccallerr": "函数调用需要空格或'(', 仅在参数之间使用逗号", - "diagnostic.funccallerr2": "在表达式中, 函数调用需要括号", - "diagnostic.hotdeferr": "热键/热字串不能在函数/类中定义", - "diagnostic.hotmissbrace": "热键或热字符串缺少左括号", - "diagnostic.invaliddefinition": "无效的{0}定义", - "diagnostic.invalidencoding": "'{0}' 无效的文件编码", - "diagnostic.invalidhotdef": "无效的热键定义", - "diagnostic.invalidparam": "无效的参数定义", - "diagnostic.invalidprop": "不是有效的getter/setter属性", - "diagnostic.invalidpropname": "对象字面量中的属性名无效", - "diagnostic.invalidsymbolname": "无效的符号命名 '{0}'", - "diagnostic.invalidscope": "'{0}'不能在函数/类中使用", - "diagnostic.invalidsuper": "'super'仅在类内部有效", - "diagnostic.maybehavenotmember": "类'{0}'可能没有成员'{1}'", - "diagnostic.maybev1": "这可能是一个v1脚本, lexer停止解析.", - "diagnostic.missing": "丢失对应的 '{0}'", - "diagnostic.missingparam": "缺少必需的参数", - "diagnostic.missingoperand": "缺少操作数", - "diagnostic.missingretval": "函数缺少返回值", - "diagnostic.missingspace": "前面缺少空格或运算符", - "diagnostic.objectliteralerr": "对象字面量存在错误", - "diagnostic.outofloop": "Break/Continue必须被循环包围", - "diagnostic.paramcounterr": "应有 {0} 个参数, 但获得 {1} 个", - "diagnostic.pathinvalid": "无效的文件路径", - "diagnostic.propdeclaraerr": "不是有效的方法, 类或属性定义", - "diagnostic.propemptyparams": "动态属性不允许使用空[]", - "diagnostic.propnotinit": "属性声明未初始化", - "diagnostic.requirev1": "此脚本需要AutoHotkey v1, lexer停止解析.", - "diagnostic.requirevariable": "'&'需要一个变量", - "diagnostic.requireversion": "该特性需要AutoHotkey版本 >= v{0}", - "diagnostic.reservedworderr": "保留字'{0}'不得用作变量名", - "diagnostic.resourcenotfound": "未找到或无法解析资源", - "diagnostic.skipline": "该行被跳过且未解析", - "diagnostic.syntaxerror": "语法错误. 具体为: {0}", - "diagnostic.tryswitchtov1": "尝试切换到AutoHotkey v1.", - "diagnostic.typemaybenot": "类型可能不是 '{0}'", - "diagnostic.unexpected": "意外的'{0}'", - "diagnostic.unknown": "未知的{0}", - "diagnostic.unknownoperatoruse": "未知的操作符使用", - "diagnostic.unknowntoken": "未知的Token '{0}'", - "diagnostic.unsupportinclude": "函数、类中的#include无法正确地推导作用域和代码补全", - "diagnostic.unterminated": "未终止的字符串文本", - "warn.varisunset": "变量'{0}'似乎从未被赋值", - "warn.localsameasglobal": "局部变量'{0}'与全局变量具有相同的名称", - "warn.callwithoutparentheses": "函数或方法调用没有使用括号", - "response.cannotrename": "无法重命名此元素。", - "response.cannotrenamestdlib": "不能重命名标准AutoHotkey库中定义的元素。", - "setting.ahkpatherr": "AutoHotkey解释器不存在, 在'设置-AutoHotkey2.InterpreterPath'中重新指定", - "setting.getenverr": "获取环境变量失败", - "setting.uialimit": "由于安全限制, UIA可执行文件不允许重定向stdin/stdout, 因此依赖于此的一些功能将无法工作", - "setting.versionerr": "当前AutoHotkey.exe不是v2版本, 无法获得正确的语法解析、补全等功能" -} diff --git a/server/src/Lexer.ts b/server/src/Lexer.ts index c5024787..cd0c9327 100644 --- a/server/src/Lexer.ts +++ b/server/src/Lexer.ts @@ -25,7 +25,7 @@ import { hoverCache, isBrowser, isahk2_h, lexers, libdirs, libfuncs, openAndParse, openFile, restorePath, rootdir, setTextDocumentLanguage, symbolProvider, utils, workspaceFolders } from './common'; -import { newFormatterConfig, FormatterConfig, ObjectOrArrayStyle, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses } from './config'; +import { newFormatterConfig, FormatterConfig, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses, getCfg, CfgKey } from './config'; export interface ParamInfo { offset: number @@ -323,7 +323,7 @@ class ParseStopError { } export class Lexer { - public actionWhenV1Detected: ActionType = newAhkppConfig().v2.actionWhenV1Detected; + public actionWhenV1Detected: ActionType = getCfg(newAhkppConfig(), CfgKey.ActionWhenV1Detected); public actived = false; public beautify: (options: FormatterConfig, range?: Range) => string; public checkmember: boolean | undefined; @@ -1142,7 +1142,7 @@ export class Lexer { begin_line = true, requirev2 = false, maybev1 = 0, lst = { ...EMPTY_TOKEN }, currsymbol = last_comment_fr = undefined; parser_pos = 0, last_LF = -1, customblocks = { region: [], bracket: [] }, continuation_sections_mode = false, h = isahk2_h; this.clear(), includetable = this.include, comments = {}, sharp_offsets = []; - callWithoutParentheses = ahkppConfig.v2.warn.callWithoutParentheses; + callWithoutParentheses = getCfg(ahkppConfig, CfgKey.CallWithoutParentheses); try { const rs = utils.get_RCDATA('#2'); rs && (includetable[rs.uri] = rs.path); @@ -1175,7 +1175,7 @@ export class Lexer { if (requirev2) return false; _this.maybev1 ??= maybev1 = 1; - switch (_this.actionWhenV1Detected ??= ahkppConfig.v2.actionWhenV1Detected) { + switch (_this.actionWhenV1Detected ??= getCfg(ahkppConfig, CfgKey.ActionWhenV1Detected)) { case 'SkipLine': { if (!allow_skip) return true; @@ -3632,8 +3632,8 @@ export class Lexer { addvariable(tk); nexttoken(), parse_pair('(', ')'); const pc = tokens[tk.previous_pair_pos!]?.paraminfo?.count ?? 0; - if (pc !== 1) - ahkppConfig.v2.diagnostics.paramsCheck && _this.addDiagnostic(diagnostic.paramcounterr(1, pc), fc.offset, parser_pos - fc.offset); + if (pc !== 1 && getCfg(ahkppConfig, CfgKey.ParamsCheck)) + _this.addDiagnostic(diagnostic.paramcounterr(1, pc), fc.offset, parser_pos - fc.offset); else if (result.length > l && lk.type === 'TK_WORD') { const vr = result.at(-1) as Variable; if (lk.content === vr.name && lk.offset === _this.document.offsetAt(vr.range.start)) @@ -6209,23 +6209,23 @@ export class Lexer { public initLibDirs(dir?: string) { if (isBrowser) return; - let workfolder: string; + let workDir: string; if (!dir) { - for (workfolder of ahkppConfig.v2.workingDirectories) - if (this.uri.startsWith(workfolder)) { - dir = restorePath(URI.parse(workfolder).fsPath.replace(/[\\/]$/, '')); + for (workDir of getCfg(ahkppConfig, CfgKey.WorkingDirectories)) + if (this.uri.startsWith(workDir)) { + dir = restorePath(URI.parse(workDir).fsPath.replace(/[\\/]$/, '')); break; } } if (dir) this.scriptdir = dir; - else if ((workfolder = resolve()).toLowerCase() !== this.scriptpath.toLowerCase() - && workfolder.toLowerCase() !== process.argv0.toLowerCase() - && this.scriptpath.toLowerCase().startsWith(workfolder.toLowerCase()) + else if ((workDir = resolve()).toLowerCase() !== this.scriptpath.toLowerCase() + && workDir.toLowerCase() !== process.argv0.toLowerCase() + && this.scriptpath.toLowerCase().startsWith(workDir.toLowerCase()) && !/\\lib(\\.+)?$/i.test(this.scriptpath)) { if (existsSync(this.scriptpath + '\\Lib') && statSync(this.scriptpath + '\\Lib').isDirectory()) this.scriptdir = this.scriptpath; - else this.scriptdir = workfolder; + else this.scriptdir = workDir; } else this.scriptdir = this.scriptpath.replace(/\\Lib(\\.+)?$/i, ''); this.libdirs = [dir = this.scriptdir + '\\Lib\\']; dir = dir.toLowerCase(); @@ -6269,7 +6269,7 @@ export class Lexer { } private addSymbolFolding(symbol: AhkSymbol, first_brace: number) { - const l1 = ahkppConfig.v2.symbolFoldingFromOpenBrace ? this.document.positionAt(first_brace).line : symbol.range.start.line; + const l1 = getCfg(ahkppConfig, CfgKey.SymbolFoldingFromOpenBrace) ? this.document.positionAt(first_brace).line : symbol.range.start.line; const l2 = symbol.range.end.line - 1; const ranges = this.foldingranges; if (l1 < l2) { diff --git a/server/src/ahkProvider.ts b/server/src/ahkProvider.ts index 22f67acd..6531fbaa 100644 --- a/server/src/ahkProvider.ts +++ b/server/src/ahkProvider.ts @@ -1,13 +1,13 @@ import { createClientSocketTransport, createMessageConnection, createServerSocketTransport, MessageConnection } from 'vscode-languageserver/node'; import { spawn } from 'child_process'; import { resolvePath } from './scriptrunner'; -import { ahkpath_cur, isWindows, rootdir } from './common'; +import { interpreterPathV2, isWindows, rootdir } from './common'; let ahk_server: MessageConnection | undefined | null; async function get_ahkProvider_port(): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async resolve => { - const executePath = resolvePath(ahkpath_cur); + const executePath = resolvePath(interpreterPathV2); if (!executePath) return resolve(0); let server, port = 1200; diff --git a/server/src/browserServerMain.ts b/server/src/browserServerMain.ts deleted file mode 100644 index 79cc2968..00000000 --- a/server/src/browserServerMain.ts +++ /dev/null @@ -1,181 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { - createConnection, BrowserMessageReader, BrowserMessageWriter, DidChangeConfigurationNotification, - InitializeResult, TextDocuments, TextDocumentSyncKind -} from 'vscode-languageserver/browser'; -import { - chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, - defintionProvider, documentFormatting, enumNames, executeCommandProvider, exportSymbols, - hoverProvider, initahk2cache, Lexer, lexers, loadahk2, loadlocalize, prepareRename, rangeFormatting, - referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, - SemanticTokenTypes, set_ahk_h, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, - signatureProvider, symbolProvider, typeFormatting, updateAhkppConfig, workspaceSymbolProvider -} from './common'; -import { AhkppConfig } from './config'; - -const languageServer = 'ahk2-language-server'; -const messageReader = new BrowserMessageReader(self); -const messageWriter = new BrowserMessageWriter(self); -const documents = new TextDocuments(TextDocument); -const workspaceFolders = new Set(); -const connection = set_Connection(createConnection(messageReader, messageWriter)); - -let hasConfigurationCapability = false, hasWorkspaceFolderCapability = false; -let uri_switch_to_ahk2 = ''; - -connection.onInitialize(params => { - const capabilities = params.capabilities; - hasConfigurationCapability = !!( - capabilities.workspace && !!capabilities.workspace.configuration - ); - hasWorkspaceFolderCapability = !!( - capabilities.workspace && !!capabilities.workspace.workspaceFolders - ); - - const result: InitializeResult = { - serverInfo: { - name: languageServer, - }, - capabilities: { - textDocumentSync: { - change: TextDocumentSyncKind.Incremental, - openClose: true - }, - completionProvider: { - resolveProvider: false, - triggerCharacters: ['.', '#', '*', '@'] - }, - signatureHelpProvider: { - triggerCharacters: ['(', ',', ' '] - }, - documentSymbolProvider: true, - definitionProvider: true, - documentFormattingProvider: true, - documentRangeFormattingProvider: true, - documentOnTypeFormattingProvider: { firstTriggerCharacter: '}', moreTriggerCharacter: ['\n', ...Object.keys(chinese_punctuations)] }, - executeCommandProvider: { commands: Object.keys(commands) }, - hoverProvider: true, - foldingRangeProvider: true, - colorProvider: true, - renameProvider: { prepareProvider: true }, - referencesProvider: { workDoneProgress: true }, - semanticTokensProvider: { - legend: { - tokenTypes: enumNames(SemanticTokenTypes), - tokenModifiers: enumNames(SemanticTokenModifiers) - }, - full: true, - range: true - }, - workspaceSymbolProvider: true - } - }; - if (hasWorkspaceFolderCapability) { - params.workspaceFolders?.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); - result.capabilities.workspace = { workspaceFolders: { supported: true } }; - } - - const ahkppConfig: AhkppConfig = params.initializationOptions; - set_ahk_h(true); - set_locale(params.locale); - set_dirname(ahkppConfig.extensionUri!); - loadlocalize(); - updateAhkppConfig(ahkppConfig); - set_WorkspaceFolders(workspaceFolders); - set_version('3.0.0'); - initahk2cache(); - loadahk2(); - loadahk2('ahk2_h'); - loadahk2('winapi', 4); - return result; -}); - -connection.onInitialized(() => { - if (hasConfigurationCapability) { - // Register for all configuration changes. - connection.client.register(DidChangeConfigurationNotification.type); - } - if (hasWorkspaceFolderCapability) { - connection.workspace.onDidChangeWorkspaceFolders(event => { - event.removed.forEach(it => workspaceFolders.delete(it.uri.toLowerCase() + '/')); - event.added.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); - set_WorkspaceFolders(workspaceFolders); - }); - } -}); - -connection.onDidChangeConfiguration(async change => { - let newAhkppConfig: AhkppConfig | undefined = change?.settings; - if (hasConfigurationCapability && !newAhkppConfig) - newAhkppConfig = await connection.workspace.getConfiguration('ahk++'); - if (!newAhkppConfig) { - connection.window.showWarningMessage('Failed to obtain the configuration'); - return; - } - updateAhkppConfig(newAhkppConfig); - set_WorkspaceFolders(workspaceFolders); -}); - -documents.onDidOpen(e => { - const to_ahk2 = uri_switch_to_ahk2 === e.document.uri; - const uri = e.document.uri.toLowerCase(); - let doc = lexers[uri]; - if (doc) doc.document = e.document; - else lexers[uri] = doc = new Lexer(e.document); - doc.actived = true; - if (to_ahk2) - doc.actionWhenV1Detected = 'Continue'; -}); - -documents.onDidClose(e => lexers[e.document.uri.toLowerCase()]?.close()); -documents.onDidChangeContent(e => lexers[e.document.uri.toLowerCase()].update()); - -connection.onCompletion(completionProvider); -connection.onColorPresentation(colorPresentation); -connection.onDocumentColor(colorProvider); -connection.onDefinition(defintionProvider); -connection.onDocumentFormatting(documentFormatting); -connection.onDocumentRangeFormatting(rangeFormatting); -connection.onDocumentOnTypeFormatting(typeFormatting); -connection.onDocumentSymbol(symbolProvider); -connection.onFoldingRanges(params => lexers[params.textDocument.uri.toLowerCase()].foldingranges); -connection.onHover(hoverProvider); -connection.onPrepareRename(prepareRename); -connection.onReferences(referenceProvider); -connection.onRenameRequest(renameProvider); -connection.onSignatureHelp(signatureProvider); -connection.onExecuteCommand(executeCommandProvider); -connection.onWorkspaceSymbol(workspaceSymbolProvider); -connection.languages.semanticTokens.on(semanticTokensOnFull); -connection.languages.semanticTokens.onRange(semanticTokensOnRange); -connection.onRequest('ahk2.exportSymbols', exportSymbols); -connection.onRequest('ahk2.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); -connection.onRequest('ahk++.getVersionInfo', (uri: string) => { - const doc = lexers[uri.toLowerCase()]; - if (doc) { - const tk = doc.get_token(0); - if ((tk.type === 'TK_BLOCK_COMMENT' || tk.type === '') && tk.content.match(/^\s*[;*]?\s*@(date|version)\b/im)) { - return { - uri: uri, - content: tk.content, - range: { - start: doc.document.positionAt(tk.offset), - end: doc.document.positionAt(tk.offset + tk.length) - } - }; - } - } - return null; -}); -connection.onNotification('onDidCloseTextDocument', - (params: { uri: string, id: string }) => { - if (params.id === 'ahk2') - lexers[params.uri.toLowerCase()]?.close(true); - else uri_switch_to_ahk2 = params.uri; - }); -documents.listen(connection); -connection.listen(); diff --git a/server/src/common.ts b/server/src/common.ts index b996dfc8..488bc86e 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -7,7 +7,7 @@ import { CompletionItem, CompletionItemKind, Hover, InsertTextFormat, Range, Sym import { AhkSymbol, Lexer, setCommentTagRegex } from './Lexer'; import { diagnostic } from './localize'; import { isBrowser, jsDocTagNames } from './constants'; -import { AhkppConfig, newAhkppConfig } from './config'; +import { AhkppConfig, CfgKey, getCfg, newAhkppConfig } from './config'; export * from './codeActionProvider'; export * from './colorProvider'; export * from './commandProvider'; @@ -36,7 +36,7 @@ export const utils = { export type Maybe = T | undefined; export let connection: Connection; -export let ahkpath_cur = '', locale = 'en-us', rootdir = '', isahk2_h = false; +export let interpreterPathV2 = '', locale = 'en-us', rootdir = '', isahk2_h = false; export let ahk_version = encode_version('3.0.0.0'); export let ahkuris: { [name: string]: string } = {}; export let ahkvars: { [key: string]: AhkSymbol } = {}; @@ -205,7 +205,9 @@ export function loadahk2(filename = 'ahk2', d = 3) { if ((data = getwebfile(file + '.json'))) build_item_cache(JSON.parse(data.text)); } else { - const syntaxes = ahkppConfig.v2.syntaxes && existsSync(ahkppConfig.v2.syntaxes) ? ahkppConfig.v2.syntaxes : ''; + const cfgSyntaxes: string = getCfg(ahkppConfig, CfgKey.Syntaxes); + /** The validated syntax path. Empty string if config syntax path failed to validate. */ + const syntaxes = cfgSyntaxes && existsSync(cfgSyntaxes) ? cfgSyntaxes : ''; const file2 = syntaxes ? `${syntaxes}/<>/${filename}` : file; let td: TextDocument | undefined; if ((path = getfilepath('.d.ahk')) && (td = openFile(restorePath(path)))) { @@ -342,7 +344,7 @@ export function loadahk2(filename = 'ahk2', d = 3) { let scanExclude: { file?: RegExp[], folder?: RegExp[] } = {}; export function enum_ahkfiles(dirpath: string) { - const maxScanDepth = ahkppConfig.v2.file.maxScanDepth; + const maxScanDepth = getCfg(ahkppConfig, CfgKey.MaxScanDepth); const { file: fileExclude, folder: folderExclude } = scanExclude; return enumfile(restorePath(dirpath), 0); async function* enumfile(dirpath: string, depth: number): AsyncGenerator { @@ -366,20 +368,18 @@ export function enum_ahkfiles(dirpath: string) { /** Updates `extsettings` with the provided config values */ export function updateAhkppConfig(newConfig: AhkppConfig) { try { - setCommentTagRegex(newConfig.v2.commentTagRegex!); + setCommentTagRegex(getCfg(newConfig, CfgKey.CommentTagRegex)); } catch (e) { delete (e as { stack: unknown }).stack; - delete newConfig.v2.commentTagRegex; + delete newConfig.v2.general.commentTagRegex; connection.console.error(e as string); } - if (newConfig.v2.workingDirectories instanceof Array) - newConfig.v2.workingDirectories = newConfig.v2.workingDirectories.map(dir => - (dir = URI.file(dir.includes(':') ? dir : resolve(dir)).toString().toLowerCase()) - .endsWith('/') ? dir : dir + '/'); - else newConfig.v2.workingDirectories = []; + newConfig.v2.workingDirectories = newConfig.v2.workingDirectories.map(dir => + (dir = URI.file(dir.includes(':') ? dir : resolve(dir)).toString().toLowerCase()) + .endsWith('/') ? dir : dir + '/'); scanExclude = {}; const file: RegExp[] = [], folder: RegExp[] = []; - for (const s of newConfig.v2.file.exclude ?? []) + for (const s of getCfg(newConfig, CfgKey.Exclude) ?? []) try { (/[\\/]$/.test(s) ? folder : file).push(glob2regexp(s)); } catch (e) { @@ -391,8 +391,8 @@ export function updateAhkppConfig(newConfig: AhkppConfig) { scanExclude.folder = folder; if (newConfig.v2.file.maxScanDepth < 0) newConfig.v2.file.maxScanDepth = Infinity; - if (newConfig.v2.syntaxes) - newConfig.v2.syntaxes = resolve(newConfig.v2.syntaxes).toLowerCase(); + if (newConfig.v2.general.syntaxes) + newConfig.v2.general.syntaxes = resolve(newConfig.v2.general.syntaxes).toLowerCase(); Object.assign(ahkppConfig, newConfig); } @@ -431,7 +431,7 @@ export function arrayEqual(a: string[], b: string[]) { export function clearLibfuns() { libfuncs = {}; } export function set_ahk_h(v: boolean) { isahk2_h = v; } -export function set_ahkpath(path: string) { ahkpath_cur = path.replace(/^.:/, s => s.toLowerCase()); } +export function setInterpreterPathV2(path: string) { interpreterPathV2 = path.replace(/^.:/, s => s.toLowerCase()); } export function set_Connection(conn: Connection) { return connection = conn; } export function set_dirname(dir: string) { rootdir = dir.replace(/[/\\]$/, ''); } export function set_locale(str?: string) { if (str) locale = str.toLowerCase(); } diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index 0974828f..75b5cfd3 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -11,10 +11,9 @@ import { decltype_expr, dllcalltpe, ahkppConfig, find_class, find_symbol, find_symbols, get_detail, generate_fn_comment, get_callinfo, get_class_constructor, get_class_member, get_class_members, isBrowser, lexers, libfuncs, make_search_re, sendAhkRequest, utils, winapis, - connection } from './common'; import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; -import { BraceStyle } from './config'; +import { BraceStyle, CompletionCommitCharacters, CfgKey, FormatterConfig, getCfg } from './config'; export async function completionProvider(params: CompletionParams, _token: CancellationToken): Promise> { let { position, textDocument: { uri } } = params; @@ -24,6 +23,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance let l: string, path: string, pt: Token | undefined, scope: AhkSymbol | undefined, temp; const { triggerKind, triggerCharacter } = params.context ?? {}; let cls2index = (name: string) => name; + const formatterConfig = getCfg(ahkppConfig, CfgKey.Formatter); //#region /**| if (triggerCharacter === '*') { @@ -80,10 +80,16 @@ export async function completionProvider(params: CompletionParams, _token: Cance return; } //#endregion - - const commitCharacters = Object.fromEntries(Object.entries(ahkppConfig.v2.completionCommitCharacters) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .map((v: any) => (v[1] = (v[1] || undefined)?.split(''), v))); + + const commitCharacters = Object.fromEntries( + Object.entries( + getCfg( + ahkppConfig, + CfgKey.CompletionCommitCharacters, + ), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ).map((v: any) => ((v[1] = (v[1] || undefined)?.split('')), v)), + ); // eslint-disable-next-line prefer-const let { text, word, token, range, linetext, kind, symbol } = doc.getContext(position, true); const list = doc.relevance, { line, character } = position; @@ -499,7 +505,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance } let right_is_paren = '(['.includes(linetext[range.end.character] || '\0'); - const join_c = ahkppConfig.v2.formatter.braceStyle === BraceStyle.Allman ? '\n' : ' '; + const join_c = formatterConfig.braceStyle === BraceStyle.Allman ? '\n' : ' '; // fn|()=>... if (symbol) { @@ -621,7 +627,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance } // keyword - const keywordStartWithUppercase = ahkppConfig.v2.formatter.keywordStartWithUppercase; + const keywordStartWithUppercase = formatterConfig.keywordStartWithUppercase; const addkeyword = keywordStartWithUppercase ? function (it: CompletionItem) { items.push(it = Object.assign({}, it)); it.insertText = (it.insertText ?? it.label).replace(/(?<=^(loop\s)?)[a-z]/g, m => m.toUpperCase()); @@ -636,7 +642,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance let uppercase = (s: string) => s, remove_indent = uppercase; if (keywordStartWithUppercase) uppercase = (s: string) => s.replace(/\b[a-z](?=\w)/g, m => m.toUpperCase()); - if (ahkppConfig.v2.formatter.switchCaseAlignment) + if (formatterConfig.switchCaseAlignment) remove_indent = (s: string) => s.replace(/^\t/gm, ''); for (const [label, arr] of [ ['switch', ['switch ${1:[SwitchValue, CaseSense]}', remove_indent('{\n\tcase ${2:}:\n\t\t${3:}\n\tdefault:\n\t\t$0\n}')]], @@ -686,8 +692,8 @@ export async function completionProvider(params: CompletionParams, _token: Cance } // library suggestions - if (ahkppConfig.v2.librarySuggestions) { - const librarySuggestions = ahkppConfig.v2.librarySuggestions; + if (ahkppConfig.v2.general.librarySuggestions) { + const librarySuggestions = ahkppConfig.v2.general.librarySuggestions; const libdirs = doc.libdirs, caches: { [path: string]: TextEdit[] } = {}; let exportnum = 0, line = -1, first_is_comment: boolean | undefined, cm: Token; let dir = doc.workspaceFolder; @@ -926,7 +932,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance // fall through case SymbolKind.Function: ci.kind = info.kind === SymbolKind.Method ? CompletionItemKind.Method : CompletionItemKind.Function; - if (ahkppConfig.v2.completeFunctionCalls) { + if (getCfg(ahkppConfig, CfgKey.CompleteFunctionCalls)) { const fn = info as FuncNode; if (right_is_paren) ci.command = { title: 'cursorRight', command: 'cursorRight' }; diff --git a/server/src/config.ts b/server/src/config.ts index f53ed29f..098ae7ec 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -57,24 +57,52 @@ export enum CallWithoutParentheses { On = 'On', } +export enum CfgKey { + ActionWhenV1Detected = 'v2.general.actionWhenV1Detected', + CommentTagRegex = 'v2.general.commentTagRegex', // still used directly in some places + CompleteFunctionCalls = 'v2.general.completeFunctionCalls', + CompletionCommitCharacters = 'v2.completionCommitCharacters', + LibrarySuggestions = 'v2.general.librarySuggestions', + SymbolFoldingFromOpenBrace = 'v2.general.symbolFoldingFromOpenBrace', + Syntaxes = 'v2.general.syntaxes', + ClassNonDynamicMemberCheck = 'v2.diagnostics.classNonDynamicMemberCheck', + ParamsCheck = 'v2.diagnostics.paramsCheck', + Exclude = 'v2.exclude', // still used directly in some places + InterpreterPath = 'v2.file.interpreterPath', // still used directly in some places + MaxScanDepth = 'v2.file.maxScanDepth', + Formatter = 'v2.formatter', + VarUnset = 'v2.warn.varUnset', + LocalSameAsGlobal = 'v2.warn.localSameAsGlobal', + CallWithoutParentheses = 'v2.warn.callWithoutParentheses', + WorkingDirectories = 'v2.workingDirectories', // still used directly in some places +} + +export interface CompletionCommitCharacters { + Class: string; + Function: string; +} + export interface AhkppConfig { v2: { - actionWhenV1Detected: ActionType; - /** The regex denoting a custom symbol. Defaults to `;;` */ - commentTagRegex?: string; - /** Automatically insert parentheses on function call */ - completeFunctionCalls: boolean; - completionCommitCharacters: { - Class: string; - Function: string; + general: { + actionWhenV1Detected: ActionType; + /** The regex denoting a custom symbol. Defaults to `;;` */ + commentTagRegex?: string; + /** Automatically insert parentheses on function call */ + completeFunctionCalls: boolean; + /** Suggest library functions */ + librarySuggestions: LibrarySuggestions; + symbolFoldingFromOpenBrace: boolean; + syntaxes: string; }; + completionCommitCharacters: CompletionCommitCharacters; diagnostics: { classNonDynamicMemberCheck: boolean; paramsCheck: boolean; }; + /** Glob pattern of files to ignore */ + exclude: string[]; file: { - /** Glob pattern of files to ignore */ - exclude: string[]; /** Path to the AHK v2 intepreter */ interpreterPath: string; /** Depth of folders to scan for IntelliSense */ @@ -82,8 +110,6 @@ export interface AhkppConfig { }; /** Config of the v2 formatter */ formatter: FormatterConfig; - /** Suggest library functions */ - librarySuggestions: LibrarySuggestions; warn: { /** Ref to a potentially-unset variable */ varUnset: boolean; @@ -92,8 +118,7 @@ export interface AhkppConfig { /** Function call without parentheses */ callWithoutParentheses: CallWithoutParentheses; }; - symbolFoldingFromOpenBrace: boolean; - syntaxes: string; + /** Directories containing AHK files that can be #included */ workingDirectories: string[]; }; locale?: string; @@ -135,10 +160,14 @@ export const newAhkppConfig = ( config: Partial = {}, ): AhkppConfig => ({ v2: { - actionWhenV1Detected: 'SwitchToV1', - librarySuggestions: LibrarySuggestions.Off, - commentTagRegex: '^;;\\s*(.*)', - completeFunctionCalls: false, + general: { + actionWhenV1Detected: 'SwitchToV1', + commentTagRegex: '^;;\\s*(.*)', + completeFunctionCalls: false, + librarySuggestions: LibrarySuggestions.Off, + symbolFoldingFromOpenBrace: false, + syntaxes: '', + }, completionCommitCharacters: { Class: '.(', Function: '(', @@ -147,21 +176,31 @@ export const newAhkppConfig = ( classNonDynamicMemberCheck: true, paramsCheck: true, }, - warn: { - varUnset: true, - localSameAsGlobal: false, - callWithoutParentheses: CallWithoutParentheses.Off, - }, + exclude: [], file: { - exclude: [], interpreterPath: 'C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey.exe', maxScanDepth: 2, }, formatter: newFormatterConfig(), - symbolFoldingFromOpenBrace: false, + warn: { + varUnset: true, + localSameAsGlobal: false, + callWithoutParentheses: CallWithoutParentheses.Off, + }, workingDirectories: [], - syntaxes: '', }, ...config, }); + +/** Gets a single config value from the given config */ +export const getCfg = (config: AhkppConfig, key: CfgKey): T => { + const keyPath = key.split('.'); + // ConfigKey values are guaranteed to work ;) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let value: any = config; + for (const k of keyPath) { + value = value[k]; + } + return value; +}; diff --git a/server/src/localize.ts b/server/src/localize.ts index ee6fa32d..a42298bb 100644 --- a/server/src/localize.ts +++ b/server/src/localize.ts @@ -1,4 +1,5 @@ import { rootdir, getlocalefile, getwebfile, isBrowser } from './common'; +import { CfgKey } from './config'; let loadedCollection: { [key: string]: string } = {}; @@ -83,7 +84,7 @@ export const warn = { } export const setting = { - ahkpatherr: localize('setting.ahkpatherr', "AutoHotkey interpreter not found, check settings: ahk++.v2.file.interpreterPath"), + ahkpatherr: localize('setting.ahkpatherr', `AutoHotkey interpreter not found, check settings: AHK++.${CfgKey.InterpreterPath}`), getenverr: localize('setting.getenverr', 'Failed to get environment variables'), uialimit: localize('setting.uialimit', 'The UIA executable does not allow redirection to stdin/stdout due to security restrictions, so some features that depend on this will not work'), versionerr: localize('setting.versionerr', 'The current AutoHotkey.exe is not the v2 version, and cannot get the correct syntax analysis, completion and other functions'), diff --git a/server/src/scriptrunner.ts b/server/src/scriptrunner.ts index 292b45e9..68900eef 100644 --- a/server/src/scriptrunner.ts +++ b/server/src/scriptrunner.ts @@ -1,10 +1,14 @@ import { execSync, spawnSync } from 'child_process'; -import { ahkpath_cur, isWindows } from './common'; +import { interpreterPathV2, isWindows } from './common'; import { lstatSync, readlinkSync } from 'fs'; import { resolve } from 'path'; +/** + * Simple runner for LSP server initializiaton via AHK. + * Not used for running user-defined scripts. + */ export function runscript(script: string) { - const executePath = resolvePath(ahkpath_cur, true); + const executePath = resolvePath(interpreterPathV2, true); if (!executePath) return; const process = spawnSync(`"${executePath}" /CP65001 /ErrorStdOut=utf-8 *`, [], { cwd: executePath.replace(/[\\/].+?$/, ''), shell: true, input: script }); diff --git a/server/src/semanticTokensProvider.ts b/server/src/semanticTokensProvider.ts index 026b5e0a..fed05156 100644 --- a/server/src/semanticTokensProvider.ts +++ b/server/src/semanticTokensProvider.ts @@ -3,6 +3,7 @@ import { ASSIGN_TYPE, AhkSymbol, ClassNode, FuncNode, Lexer, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, Token, Variable, checkParams, diagnostic, ahkppConfig, get_class_member, get_class_members, globalsymbolcache, lexers, symbolProvider } from './common'; +import { CfgKey, getCfg } from './config'; let curclass: ClassNode | undefined; const memscache = new Map(); @@ -124,7 +125,7 @@ function resolveSemanticType(name: string, tk: Token, doc: Lexer) { return sem.type = SemanticTokenTypes.property; } case undefined: - if ((curclass.checkmember ?? doc.checkmember) !== false && ahkppConfig.v2.diagnostics.classNonDynamicMemberCheck) { + if ((curclass.checkmember ?? doc.checkmember) !== false && getCfg(ahkppConfig, CfgKey.ClassNonDynamicMemberCheck)) { const tt = doc.tokens[tk.next_token_offset]; if (ASSIGN_TYPE.includes(tt?.content)) { cls_add_prop(curclass, tk.content, tk.offset); diff --git a/server/src/server.ts b/server/src/server.ts index 8e9f0ec7..7b19b523 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -13,7 +13,7 @@ import { URI } from 'vscode-uri'; import { get_ahkProvider } from './ahkProvider'; import { a_vars, - ahkpath_cur, + interpreterPathV2, chinese_punctuations, clearLibfuns, codeActionProvider, @@ -47,7 +47,7 @@ import { semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, - set_ahkpath, + setInterpreterPathV2, set_Connection, set_dirname, set_locale, @@ -68,7 +68,7 @@ import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; import { resolvePath, runscript } from './scriptrunner'; import { TextDecoder } from 'util'; import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; -import { AhkppConfig } from './config'; +import { AhkppConfig, CfgKey, getCfg, LibrarySuggestions } from './config'; const languageServer = 'ahk2-language-server'; const documents = new TextDocuments(TextDocument); @@ -203,30 +203,31 @@ connection.onInitialized(() => { connection.onDidChangeConfiguration(async (change) => { let newAhkppConfig: AhkppConfig | undefined = change?.settings; if (hasConfigurationCapability && !newAhkppConfig) - newAhkppConfig = await connection.workspace.getConfiguration('ahk++'); + newAhkppConfig = await connection.workspace.getConfiguration('AHK++'); if (!newAhkppConfig) { connection.window.showWarningMessage('Failed to obtain the AHK++ configuration'); return; } - const { v2: oldV2 } = ahkppConfig; + const oldCfg = ahkppConfig; updateAhkppConfig(newAhkppConfig); - const { v2: newV2 } = ahkppConfig; + const newCfg = ahkppConfig; set_WorkspaceFolders(workspaceFolders); - if (oldV2.file.interpreterPath !== newV2.file.interpreterPath) { - if ( - await setInterpreter( - resolvePath((newV2.file.interpreterPath ??= '')), - ) - ) - connection.sendRequest('ahk2.updateStatusBar', [newV2.file.interpreterPath]); + + const newInterpreterPath: string = getCfg(newCfg, CfgKey.InterpreterPath); + if (getCfg(oldCfg, CfgKey.InterpreterPath) !== newInterpreterPath) { + if (await setInterpreter(resolvePath(newInterpreterPath))) + connection.sendRequest('ahk2.updateStatusBar', [newInterpreterPath]); } - if (oldV2.librarySuggestions !== newV2.librarySuggestions) { - if (includeUserAndStandardLibrary(newV2.librarySuggestions) && !includeUserAndStandardLibrary(oldV2.librarySuggestions)) + + const oldLibSuggestions: LibrarySuggestions = getCfg(oldCfg, CfgKey.LibrarySuggestions); + const newLibSuggestions: LibrarySuggestions = getCfg(newCfg, CfgKey.LibrarySuggestions); + if (oldLibSuggestions !== newLibSuggestions) { + if (includeUserAndStandardLibrary(newLibSuggestions) && !includeUserAndStandardLibrary(oldLibSuggestions)) parseuserlibs(); - if (includeLocalLibrary(newV2.librarySuggestions) && !includeLocalLibrary(oldV2.librarySuggestions)) + if (includeLocalLibrary(newLibSuggestions) && !includeLocalLibrary(oldLibSuggestions)) documents.all().forEach((e) => parseproject(e.uri.toLowerCase())); } - if (oldV2.syntaxes !== newV2.syntaxes) { + if (getCfg(oldCfg, CfgKey.Syntaxes) !== getCfg(newCfg, CfgKey.Syntaxes)) { initahk2cache(); loadahk2(); if (isahk2_h) { @@ -250,7 +251,7 @@ documents.onDidOpen((e) => { } doc.actived = true; if (to_ahk2) doc.actionWhenV1Detected = 'Continue'; - if (includeLocalLibrary(ahkppConfig.v2.librarySuggestions)) + if (includeLocalLibrary(ahkppConfig.v2.general.librarySuggestions)) parseproject(uri).then( () => doc.last_diags && @@ -351,7 +352,7 @@ async function initpathenv(samefolder = false, retry = true): Promise { return false; } if (!(data = data.trim())) { - const path = ahkpath_cur; + const path = interpreterPathV2; if ((await getAHKversion([path]))[0].endsWith('[UIAccess]')) { let ret = false, n = path.replace(/_uia\.exe$/i, '.exe'); @@ -361,9 +362,9 @@ async function initpathenv(samefolder = false, retry = true): Promise { (n = resolvePath(n, true)) && !(await getAHKversion([n]))[0].endsWith('[UIAccess]') ) { - set_ahkpath(n); + setInterpreterPathV2(n); if ((ret = await initpathenv(samefolder))) fail = 0; - set_ahkpath(path); + setInterpreterPathV2(path); } if (fail) connection.window.showWarningMessage(setting.uialimit()); await update_rcdata(); @@ -383,7 +384,7 @@ async function initpathenv(samefolder = false, retry = true): Promise { .map((l) => l.split('\t')), ), ); - a_vars.ahkpath = ahkpath_cur; + a_vars.ahkpath = interpreterPathV2; set_version((a_vars.ahkversion ??= '2.0.0')); if (a_vars.ahkversion.startsWith('1.')) patherr(setting.versionerr()); if (!samefolder || !libdirs.length) { @@ -422,10 +423,10 @@ async function initpathenv(samefolder = false, retry = true): Promise { } } clearLibfuns(); - if (includeUserAndStandardLibrary(ahkppConfig.v2.librarySuggestions)) parseuserlibs(); + if (includeUserAndStandardLibrary(ahkppConfig.v2.general.librarySuggestions)) parseuserlibs(); return true; async function update_rcdata() { - const pe = new PEFile(ahkpath_cur); + const pe = new PEFile(interpreterPathV2); try { const rc = await pe.getResource(RESOURCE_TYPE.RCDATA); curPERCDATA = rc; @@ -488,16 +489,16 @@ async function changeInterpreter(oldpath: string, newpath: string) { const doc = lexers[td.uri.toLowerCase()]; if (!doc) return; doc.initLibDirs(doc.scriptdir); - if (includeLocalLibrary(ahkppConfig.v2.librarySuggestions)) parseproject(doc.uri); + if (includeLocalLibrary(ahkppConfig.v2.general.librarySuggestions)) parseproject(doc.uri); }); return true; } async function setInterpreter(path: string) { - const old = ahkpath_cur; + const old = interpreterPathV2; if (!path || path.toLowerCase() === old.toLowerCase()) return false; - set_ahkpath(path); - if (!(await changeInterpreter(old, path))) set_ahkpath(old); + setInterpreterPathV2(path); + if (!(await changeInterpreter(old, path))) setInterpreterPathV2(old); return true; } @@ -592,7 +593,7 @@ async function getDllExport(paths: string[] | Set, onlyone = false) { let curPERCDATA: { [key: string]: Buffer } | undefined = undefined; function getRCDATA(name?: string) { - const exe = resolvePath(ahkpath_cur, true); + const exe = resolvePath(interpreterPathV2, true); if (!exe) return; if (!name) return { uri: '', path: '', paths: Object.keys(curPERCDATA ?? {}) }; diff --git a/server/src/symbolProvider.ts b/server/src/symbolProvider.ts index d15133f0..d1d65230 100644 --- a/server/src/symbolProvider.ts +++ b/server/src/symbolProvider.ts @@ -11,6 +11,7 @@ import { diagnostic, enum_ahkfiles, ahkppConfig, find_class, get_class_constructor, isBrowser, is_line_continue, lexers, make_same_name_error, openFile, warn, workspaceFolders } from './common'; +import { CfgKey, getCfg } from './config'; export let globalsymbolcache: { [name: string]: AhkSymbol } = {}; @@ -40,7 +41,7 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio return doc.symbolInformation; if (ahkuris.winapi && !list.includes(ahkuris.winapi)) winapis = lexers[ahkuris.winapi]?.declaration ?? winapis; - const warnLocalSameAsGlobal = ahkppConfig.v2.warn.localSameAsGlobal; + const warnLocalSameAsGlobal = getCfg(ahkppConfig, CfgKey.LocalSameAsGlobal); const result: AhkSymbol[] = [], unset_vars = new Map(); const filter_types: SymbolKind[] = [SymbolKind.Method, SymbolKind.Property, SymbolKind.Class]; for (const [k, v] of Object.entries(doc.declaration)) { @@ -54,7 +55,7 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio result.push(v), converttype(v, v, islib || v === ahkvars[k]).definition = v; } flatTree(doc); - if (ahkppConfig.v2.warn.varUnset) + if (getCfg(ahkppConfig, CfgKey.VarUnset)) for (const [k, v] of unset_vars) k.assigned || doc.diagnostics.push({ message: warn.varisunset(v.name), range: v.selectionRange, severity: DiagnosticSeverity.Warning }); if (doc.actived) { @@ -290,10 +291,11 @@ function get_func_param_count(fn: FuncNode) { export function checkParams(doc: Lexer, node: FuncNode, info: CallSite) { const paraminfo = info.paraminfo; let is_cls: boolean, params; - if (!paraminfo || !ahkppConfig.v2.diagnostics.paramsCheck) return; + if (!paraminfo || !getCfg(ahkppConfig, CfgKey.ParamsCheck)) return; if ((is_cls = node?.kind === SymbolKind.Class)) node = get_class_constructor(node as unknown as ClassNode) as FuncNode; if (!(params = node?.params)) return; + const { max, min } = get_func_param_count(node), l = params.length - (node.variadic ? 1 : 0); const _miss: { [index: number]: boolean } = {}; // eslint-disable-next-line prefer-const diff --git a/syntaxes/samples/0-v2-demo.ahk2 b/syntaxes/samples/0-v2-demo.ahk2 deleted file mode 100644 index 6dd66f59..00000000 --- a/syntaxes/samples/0-v2-demo.ahk2 +++ /dev/null @@ -1,3 +0,0 @@ -#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle) -#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle -#HotIf diff --git a/syntaxes/samples/0-v2-demo.ahk2.snap b/syntaxes/samples/0-v2-demo.ahk2.snap deleted file mode 100644 index e9f040a5..00000000 --- a/syntaxes/samples/0-v2-demo.ahk2.snap +++ /dev/null @@ -1,31 +0,0 @@ ->#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle) -#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 -# ^^^^^ source.ahk2 keyword.control.directive.ahk2 -# ^ source.ahk2 -# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 -# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 -# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 -# ^^^^^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 -# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 -# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 -# ^ source.ahk2 -# ^^ source.ahk2 keyword.operator.expression.ahk2 -# ^ source.ahk2 -# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 -# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 -# ^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 variable.other.ahk2 -# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 ->#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle -#^^^^^^ source.ahk2 hotkey.ahk2 keyword.keys.ahk2 -# ^^ source.ahk2 punctuation.definition.colon -# ^^^^^^ source.ahk2 variable.other.ahk2 support.function.ahk2 -# ^ source.ahk2 -# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.ahk2 string.quoted.ahk2 -# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 -# ^ source.ahk2 -# ^^^^^^^^^^^^^ source.ahk2 variable.other.ahk2 ->#HotIf -#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 -# ^^^^^ source.ahk2 keyword.control.directive.ahk2 -> \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index cd249875..1936730b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -89,97 +89,4 @@ const nodeServerConfig = /** @type WebpackConfig */ { devtool: 'source-map', }; -const browserClientConfig = /** @type WebpackConfig */ { - context: path.join(__dirname, 'client'), - mode: 'none', - target: 'webworker', // web extensions run in a webworker context - entry: { - browserClientMain: './src/browserClientMain.ts', - }, - output: { - filename: '[name].js', - path: path.join(__dirname, 'client', 'dist'), - libraryTarget: 'commonjs', - }, - resolve: { - mainFields: ['module', 'main'], - extensions: ['.ts', '.js'], // support ts-files and js-files - alias: {}, - fallback: { - path: require.resolve('path-browserify'), - }, - }, - module: { - rules: [ - { - test: /\.ts$/, - exclude: /node_modules/, - use: [ - { - loader: 'ts-loader', - }, - ], - }, - ], - }, - externals: { - vscode: 'commonjs vscode', // ignored because it doesn't exist - }, - performance: { - hints: false, - }, - devtool: 'source-map', -}; - -const browserServerConfig = /** @type WebpackConfig */ { - context: path.join(__dirname, 'server'), - mode: 'none', - target: 'webworker', // web extensions run in a webworker context - entry: { - browserServerMain: './src/browserServerMain.ts', - }, - output: { - filename: '[name].js', - path: path.join(__dirname, 'server', 'dist'), - libraryTarget: 'var', - library: 'serverExportVar', - }, - resolve: { - mainFields: ['module', 'main'], - extensions: ['.ts', '.js'], // support ts-files and js-files - alias: {}, - fallback: { - fs: false, - child_process: false, - path: require.resolve('path-browserify'), - process: false, - }, - }, - module: { - rules: [ - { - test: /\.ts$/, - exclude: /node_modules/, - use: [ - { - loader: 'ts-loader', - }, - ], - }, - ], - }, - externals: { - vscode: 'commonjs vscode', // ignored because it doesn't exist - }, - performance: { - hints: false, - }, - devtool: 'source-map', -}; - -module.exports = [ - nodeClientConfig, - nodeServerConfig, - browserClientConfig, - browserServerConfig, -]; +module.exports = [nodeClientConfig, nodeServerConfig]; From 611cef343efd23e52018723b0895978779bcaa70 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:43:24 -0500 Subject: [PATCH 25/60] Add `showOutputView` config (#23) --- .gitignore | 4 +--- client/src/config.ts | 44 ++++++++++++++++++++++++++++++++++++ client/src/extension.ts | 50 +++++++++++++++++++++++------------------ server/src/common.ts | 3 ++- server/src/config.ts | 21 ++++++++++------- 5 files changed, 88 insertions(+), 34 deletions(-) create mode 100644 client/src/config.ts diff --git a/.gitignore b/.gitignore index fe409685..e1224926 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,7 @@ -out -dist node_modules .test-data .vscode-test .vscode-test-web *.vsix scripts/* -server/expr_parser/* \ No newline at end of file +*.js diff --git a/client/src/config.ts b/client/src/config.ts new file mode 100644 index 00000000..2b12b93f --- /dev/null +++ b/client/src/config.ts @@ -0,0 +1,44 @@ +// Very similar to ahk2/server/src/config.ts +// todo dedupe config.ts + +import * as vscode from 'vscode'; + +/** Defined in package.json */ +export type ShowOutputView = 'always' | 'never'; + +export enum CfgKey { + ActionWhenV1Detected = 'v2.general.actionWhenV1Detected', + CallWithoutParentheses = 'v2.warn.callWithoutParentheses', + ClassNonDynamicMemberCheck = 'v2.diagnostics.classNonDynamicMemberCheck', + CommentTagRegex = 'v2.general.commentTagRegex', + CompleteFunctionCalls = 'v2.general.completeFunctionCalls', + CompletionCommitCharacters = 'v2.completionCommitCharacters', + DebugConfiguration = 'v2.debugConfiguration', + Exclude = 'v2.exclude', + Formatter = 'v2.formatter', + InterpreterPathV1 = 'v1.file.interpreterPath', + InterpreterPathV2 = 'v2.file.interpreterPath', + LibrarySuggestions = 'v2.general.librarySuggestions', + LocalSameAsGlobal = 'v2.warn.localSameAsGlobal', + MaxScanDepth = 'v2.file.maxScanDepth', + ParamsCheck = 'v2.diagnostics.paramsCheck', + ShowOutputView = 'general.showOutputView', + SymbolFoldingFromOpenBrace = 'v2.general.symbolFoldingFromOpenBrace', + Syntaxes = 'v2.general.syntaxes', + VarUnset = 'v2.warn.varUnset', + WorkingDirectories = 'v2.workingDirectories', // still used directly in some places +} + +const configPrefix = 'AHK++'; + +/** + * Gets AHK++ config value from VS Code. + * Use `getAhkppConfig` to get the full config object. + */ +export function getCfg(key: CfgKey): T | undefined { + return getAhkppConfig().get(key); +} + +export function getAhkppConfig() { + return vscode.workspace.getConfiguration(configPrefix); +} diff --git a/client/src/extension.ts b/client/src/extension.ts index 7812d025..75efca89 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -33,11 +33,11 @@ import { import { resolve } from 'path'; import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; +import { CfgKey, getAhkppConfig, getCfg, ShowOutputView } from './config'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); -const ahkppConfig = workspace.getConfiguration('AHK++'); -let v2Interpreter: string = ahkppConfig?.v2?.file?.interpreterPath, server_is_ready = false, zhcn = false; +let v2Interpreter = getCfg(CfgKey.InterpreterPathV2), server_is_ready = false, zhcn = false; const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; const isWindows = process.platform === 'win32'; @@ -99,7 +99,7 @@ export async function activate(context: ExtensionContext) { initializationOptions: { commands: Object.keys(request_handlers), GlobalStorage: context.globalStorageUri.fsPath, - ...ahkppConfig + ...getAhkppConfig() } }; @@ -137,19 +137,18 @@ export async function activate(context: ExtensionContext) { context.subscriptions.push(debug.registerDebugConfigurationProvider(id, { async resolveDebugConfiguration(folder, config) { if (config.__ahk2debug || window.activeTextEditor?.document.languageId !== 'ahk') { - const append_configs: (DebugConfiguration | undefined)[] = []; - const allconfigs = workspace.getConfiguration('launch').inspect('configurations'); - let configs = allconfigs && [ - ...allconfigs.workspaceFolderValue ?? [], - ...allconfigs.workspaceValue ?? [], - ...allconfigs.globalValue ?? []]; + const appendConfigs: (Partial | undefined)[] = []; + const allConfigs = workspace.getConfiguration('launch').inspect('configurations'); + let configs = allConfigs && [ + ...allConfigs.workspaceFolderValue ?? [], + ...allConfigs.workspaceValue ?? [], + ...allConfigs.globalValue ?? []]; config.request ||= 'launch'; configs = configs?.filter(it => it.request === config.request && it.type === config.type); if (!config.__ahk2debug) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const def = { ...ahkppConfig.get('v2.debugConfiguration') as any }; + const def = { ...getCfg(CfgKey.DebugConfiguration) as Partial }; delete def.request, delete def.type; - append_configs.push(def, configs?.filter(it => + appendConfigs.push(def, configs?.filter(it => Object.entries(it).every(([k, v]) => equal(v, config[k])) )?.sort((a, b) => Object.keys(a).length - Object.keys(b).length).pop()); // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -164,8 +163,8 @@ export async function activate(context: ExtensionContext) { return kv.length === Object.keys(b).length && kv.every(([k, v]) => equal(v, b[k])); } } else if (configs) - append_configs.push(configs.find(it => it.name === config.name) ?? configs[0]); - Object.assign(config, ...append_configs); + appendConfigs.push(configs.find(it => it.name === config.name) ?? configs[0]); + Object.assign(config, ...appendConfigs); if (!config.runtime && (!config.runtime_v2 || config.type !== 'autohotkey')) { config.runtime = resolvePath(v2Interpreter, folder?.uri.fsPath); if (ahkStatusBarItem.text.endsWith('[UIAccess]')) @@ -282,8 +281,13 @@ export enum LanguageId { const isV1 = (): boolean => window.activeTextEditor?.document.languageId === LanguageId.ahk1; +/** + * Runs the script or selection in the provided editor. + * Works for both AHK v1 and AHK v2 + * Does not work on never-saved files (new untitled documents) + */ function runScript(textEditor: TextEditor, runSelection = false) { - const interpreter: string | undefined = isV1() ? ahkppConfig.get('v1.file.interpreterPath') : ahkppConfig.get('v2.file.interpreterPath'); + const interpreter: string | undefined = isV1() ? getCfg(CfgKey.InterpreterPathV1) : getCfg(CfgKey.InterpreterPathV2); const executePath = resolvePath(interpreter, workspace.getWorkspaceFolder(textEditor.document.uri)?.uri.fsPath); if (!executePath) { const s = interpreter || 'AutoHotkey.exe'; @@ -293,7 +297,9 @@ function runScript(textEditor: TextEditor, runSelection = false) { } let selectedText = '', path = '*', command = `"${executePath}" /ErrorStdOut=utf-8 `; let startTime: Date; - outputchannel.show(true); + const showOutputView = getCfg(CfgKey.ShowOutputView); + if (showOutputView === 'always') + outputchannel.show(true); if (!ahkprocesses.size) outputchannel.clear(); @@ -381,7 +387,7 @@ async function stopRunningScript() { async function beginDebug(extlist: string[], debugexts: { [type: string]: string }, params = false, attach = false) { let extname: string | undefined; const editor = window.activeTextEditor; - const config = { ...ahkppConfig.get('v2.debugConfiguration'), request: 'launch', __ahk2debug: true } as DebugConfiguration; + const config = { ...getCfg(CfgKey.DebugConfiguration), request: 'launch', __ahk2debug: true } as DebugConfiguration; if (!extlist.length) { window.showErrorMessage(zhcn ? '未找到debug扩展, 请先安装debug扩展!' : 'The debug extension was not found, please install the debug extension first!'); extname = await window.showQuickPick(['zero-plusplus.vscode-autohotkey-debug', 'helsmy.autohotkey-debug', 'mark-wiemer.vscode-autohotkey-plus-plus', 'cweijan.vscode-autohotkey-plus']); @@ -467,7 +473,7 @@ async function setInterpreterV2() { pick.dispose(); if (sel.detail) { ahkStatusBarItem.tooltip = v2Interpreter = sel.detail; - ahkppConfig.update('v2.file.interpreterPath', v2Interpreter, from); + getAhkppConfig().update(CfgKey.InterpreterPathV2, v2Interpreter, from); ahkStatusBarItem.text = sel.label ||= (await getAHKversion([v2Interpreter]))[0]; if (server_is_ready) commands.executeCommand('ahk++.v2.setIntepreterPath', v2Interpreter); @@ -503,7 +509,7 @@ async function setInterpreterV2() { async function selectSyntaxes() { const path = (await window.showOpenDialog({ canSelectFiles: false, canSelectFolders: true }))?.[0].fsPath; - const t = ahkppConfig.inspect('Syntaxes'); + const t = getAhkppConfig().inspect('Syntaxes'); let v = '', f = ConfigurationTarget.Global; if (t) { v = ((f = ConfigurationTarget.WorkspaceFolder, t.workspaceFolderValue) ?? @@ -512,7 +518,7 @@ async function selectSyntaxes() { } if (path === undefined || v.toLowerCase() === path.toLowerCase()) return; - ahkppConfig.update('Syntaxes', path || undefined, f); + getAhkppConfig().update('Syntaxes', path || undefined, f); } function getAHKversion(paths: string[]): Thenable { @@ -525,7 +531,7 @@ function getAHKversion(paths: string[]): Thenable { * `from` is undefined if default value was used. */ function getInterpreterV2Path(): { path: string, from?: ConfigurationTarget } { - const configDetails = ahkppConfig.inspect('v2.file.interpreterPath'); + const configDetails = getAhkppConfig().inspect(CfgKey.InterpreterPathV2); let path = ''; if (configDetails) if ((path = configDetails.workspaceFolderValue as string)) @@ -605,4 +611,4 @@ function statSync(path: string) { if (st.isSymbolicLink()) return lstatSync(resolve(path, '..', readlinkSync(path))); return st; -} \ No newline at end of file +} diff --git a/server/src/common.ts b/server/src/common.ts index 488bc86e..3ed5d4d9 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -371,7 +371,8 @@ export function updateAhkppConfig(newConfig: AhkppConfig) { setCommentTagRegex(getCfg(newConfig, CfgKey.CommentTagRegex)); } catch (e) { delete (e as { stack: unknown }).stack; - delete newConfig.v2.general.commentTagRegex; + // reset to default if invalid + setCommentTagRegex(getCfg(newAhkppConfig(), CfgKey.CommentTagRegex)) connection.console.error(e as string); } newConfig.v2.workingDirectories = newConfig.v2.workingDirectories.map(dir => diff --git a/server/src/config.ts b/server/src/config.ts index 098ae7ec..88b91753 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -1,3 +1,6 @@ +// Same as ahk2/client/src/config.ts +// todo dedupe config.ts + /** Defined in package.json */ export type ActionType = | 'Continue' @@ -59,21 +62,21 @@ export enum CallWithoutParentheses { export enum CfgKey { ActionWhenV1Detected = 'v2.general.actionWhenV1Detected', + CallWithoutParentheses = 'v2.warn.callWithoutParentheses', + ClassNonDynamicMemberCheck = 'v2.diagnostics.classNonDynamicMemberCheck', CommentTagRegex = 'v2.general.commentTagRegex', // still used directly in some places CompleteFunctionCalls = 'v2.general.completeFunctionCalls', CompletionCommitCharacters = 'v2.completionCommitCharacters', - LibrarySuggestions = 'v2.general.librarySuggestions', - SymbolFoldingFromOpenBrace = 'v2.general.symbolFoldingFromOpenBrace', - Syntaxes = 'v2.general.syntaxes', - ClassNonDynamicMemberCheck = 'v2.diagnostics.classNonDynamicMemberCheck', - ParamsCheck = 'v2.diagnostics.paramsCheck', Exclude = 'v2.exclude', // still used directly in some places + Formatter = 'v2.formatter', InterpreterPath = 'v2.file.interpreterPath', // still used directly in some places + LibrarySuggestions = 'v2.general.librarySuggestions', + LocalSameAsGlobal = 'v2.warn.localSameAsGlobal', MaxScanDepth = 'v2.file.maxScanDepth', - Formatter = 'v2.formatter', + ParamsCheck = 'v2.diagnostics.paramsCheck', + SymbolFoldingFromOpenBrace = 'v2.general.symbolFoldingFromOpenBrace', + Syntaxes = 'v2.general.syntaxes', VarUnset = 'v2.warn.varUnset', - LocalSameAsGlobal = 'v2.warn.localSameAsGlobal', - CallWithoutParentheses = 'v2.warn.callWithoutParentheses', WorkingDirectories = 'v2.workingDirectories', // still used directly in some places } @@ -82,6 +85,7 @@ export interface CompletionCommitCharacters { Function: string; } +/** Defined in package.json */ export interface AhkppConfig { v2: { general: { @@ -156,6 +160,7 @@ export const newFormatterConfig = ( ...config, }); +/** Defaults according to package.json */ export const newAhkppConfig = ( config: Partial = {}, ): AhkppConfig => ({ From 012bf38615fb5ef81bcee4b71921156e5f9cc3d7 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 22 Sep 2024 09:53:20 -0700 Subject: [PATCH 26/60] Remove logs, unused package (#24) --- .gitignore | 1 + client/src/extension.ts | 1 - package-lock.json | 8 -------- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index e1224926..921a5229 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ node_modules *.vsix scripts/* *.js +*.js.map \ No newline at end of file diff --git a/client/src/extension.ts b/client/src/extension.ts index 75efca89..912855da 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -110,7 +110,6 @@ export async function activate(context: ExtensionContext) { // Start the client. This will also launch the server client.start().then(() => { - console.log('Language client started'); Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); onDidChangegetInterpreter(); if (window.activeTextEditor?.document.languageId === 'ahk2') diff --git a/package-lock.json b/package-lock.json index 3dd4ffaa..6bf452f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,6 @@ "eslint": "^9.4.0", "globals": "^15.4.0", "mocha": "^10.7.0", - "path-browserify": "^1.0.1", "prettier": "3.3.3", "sinon": "^18.0.0", "sort-package-json": "^2.10.0", @@ -5737,13 +5736,6 @@ "node": ">= 0.8" } }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true, - "license": "MIT" - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", From fddd2e0f25f333c9d09bae918fe15c646d5a924a Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 22 Sep 2024 10:13:41 -0700 Subject: [PATCH 27/60] Fix syntaxes, rename showOutputView to showOutput (#25) --- client/src/config.ts | 19 ++----------------- client/src/extension.ts | 10 +++++----- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/client/src/config.ts b/client/src/config.ts index 2b12b93f..573c6bd6 100644 --- a/client/src/config.ts +++ b/client/src/config.ts @@ -4,29 +4,14 @@ import * as vscode from 'vscode'; /** Defined in package.json */ -export type ShowOutputView = 'always' | 'never'; +export type ShowOutput = 'always' | 'never'; export enum CfgKey { - ActionWhenV1Detected = 'v2.general.actionWhenV1Detected', - CallWithoutParentheses = 'v2.warn.callWithoutParentheses', - ClassNonDynamicMemberCheck = 'v2.diagnostics.classNonDynamicMemberCheck', - CommentTagRegex = 'v2.general.commentTagRegex', - CompleteFunctionCalls = 'v2.general.completeFunctionCalls', - CompletionCommitCharacters = 'v2.completionCommitCharacters', DebugConfiguration = 'v2.debugConfiguration', - Exclude = 'v2.exclude', - Formatter = 'v2.formatter', InterpreterPathV1 = 'v1.file.interpreterPath', InterpreterPathV2 = 'v2.file.interpreterPath', - LibrarySuggestions = 'v2.general.librarySuggestions', - LocalSameAsGlobal = 'v2.warn.localSameAsGlobal', - MaxScanDepth = 'v2.file.maxScanDepth', - ParamsCheck = 'v2.diagnostics.paramsCheck', - ShowOutputView = 'general.showOutputView', - SymbolFoldingFromOpenBrace = 'v2.general.symbolFoldingFromOpenBrace', + ShowOutput = 'general.showOutput', Syntaxes = 'v2.general.syntaxes', - VarUnset = 'v2.warn.varUnset', - WorkingDirectories = 'v2.workingDirectories', // still used directly in some places } const configPrefix = 'AHK++'; diff --git a/client/src/extension.ts b/client/src/extension.ts index 912855da..efbe76e1 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -33,7 +33,7 @@ import { import { resolve } from 'path'; import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; -import { CfgKey, getAhkppConfig, getCfg, ShowOutputView } from './config'; +import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); @@ -296,8 +296,8 @@ function runScript(textEditor: TextEditor, runSelection = false) { } let selectedText = '', path = '*', command = `"${executePath}" /ErrorStdOut=utf-8 `; let startTime: Date; - const showOutputView = getCfg(CfgKey.ShowOutputView); - if (showOutputView === 'always') + const showOutput = getCfg(CfgKey.ShowOutput); + if (showOutput === 'always') outputchannel.show(true); if (!ahkprocesses.size) outputchannel.clear(); @@ -508,7 +508,7 @@ async function setInterpreterV2() { async function selectSyntaxes() { const path = (await window.showOpenDialog({ canSelectFiles: false, canSelectFolders: true }))?.[0].fsPath; - const t = getAhkppConfig().inspect('Syntaxes'); + const t = getAhkppConfig().inspect(CfgKey.Syntaxes); let v = '', f = ConfigurationTarget.Global; if (t) { v = ((f = ConfigurationTarget.WorkspaceFolder, t.workspaceFolderValue) ?? @@ -517,7 +517,7 @@ async function selectSyntaxes() { } if (path === undefined || v.toLowerCase() === path.toLowerCase()) return; - getAhkppConfig().update('Syntaxes', path || undefined, f); + getAhkppConfig().update(CfgKey.Syntaxes, path || undefined, f); } function getAHKversion(paths: string[]): Thenable { From 651e79b4e24caf1512319a768deae098397f9a39 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 22 Sep 2024 22:05:22 -0700 Subject: [PATCH 28/60] Log build mode (#26) --- build.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.mjs b/build.mjs index cfc8d003..0cd27f44 100644 --- a/build.mjs +++ b/build.mjs @@ -3,6 +3,12 @@ import path from 'path'; const isProd = process.argv.indexOf('--mode=production') >= 0; +console.log( + 'Building v2 support in', + isProd ? 'production' : 'development', + 'mode', +); + // Node server // https://esbuild.github.io/api build({ From 7e22224f4708553e7ce9360785fe60024b7159f9 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 22 Sep 2024 23:24:01 -0700 Subject: [PATCH 29/60] Merge thqby@main (2.5.2) (#27) --- .vscode-test.mjs | 17 ++ .vscode/launch.json | 21 +- CHANGELOG.md | 27 +- client/src/browserClientMain.ts | 127 ++++++++ client/src/extension.test.ts | 244 +++++++++++++-- client/src/extension.ts | 235 ++++++++++----- client/src/test/runTest.ts | 36 +++ eslint.config.mjs | 68 ++--- package-lock.json | 53 +--- package.json | 2 +- package.nls.json | 37 +++ package.nls.zh-cn.json | 127 ++++++++ readme.md | 360 +++++++++++++++++++++- server/cli/cli.ts | 2 +- server/src/Lexer.ts | 434 +++++++++++++++++---------- server/src/PEFile.ts | 8 +- server/src/browserServerMain.ts | 164 ++++++++++ server/src/codeActionProvider.ts | 4 +- server/src/commandProvider.ts | 67 ++++- server/src/common.ts | 78 ++--- server/src/completionProvider.ts | 50 +-- server/src/constants.ts | 6 +- server/src/localize.ts | 2 +- server/src/referencesProvider.ts | 8 +- server/src/renameProvider.ts | 2 +- server/src/semanticTokensProvider.ts | 22 +- server/src/server.ts | 132 ++++---- server/src/signatureProvider.ts | 2 +- server/src/symbolProvider.ts | 45 +-- syntaxes/ahk2.d.ahk | 2 +- syntaxes/ahk2.tmLanguage.json | 6 +- syntaxes/ahk2_common.json | 5 + tmgrammar-test/0-v2-demo.ahk | 3 + tmgrammar-test/0-v2-demo.ahk.snap | 31 ++ 34 files changed, 1878 insertions(+), 549 deletions(-) create mode 100644 .vscode-test.mjs create mode 100644 client/src/browserClientMain.ts create mode 100644 client/src/test/runTest.ts create mode 100644 package.nls.json create mode 100644 package.nls.zh-cn.json create mode 100644 server/src/browserServerMain.ts create mode 100644 tmgrammar-test/0-v2-demo.ahk create mode 100644 tmgrammar-test/0-v2-demo.ahk.snap diff --git a/.vscode-test.mjs b/.vscode-test.mjs new file mode 100644 index 00000000..5e9f9fbd --- /dev/null +++ b/.vscode-test.mjs @@ -0,0 +1,17 @@ +// https://github.com/microsoft/vscode-test-cli +import { defineConfig } from '@vscode/test-cli'; +import { execSync } from 'child_process'; + +let vscode_path = undefined; +try { + const m = execSync('chcp 65001 && reg query HKCR\\vscode\\shell\\open\\command', { encoding: 'utf8' }) + .match(/REG_SZ\s+("([^"]+)"|\S+)/); + vscode_path = m[2] || m[1]; +} catch { }; + +export default defineConfig({ + files: 'client/dist/test/**/*.test.js', + useInstallation: vscode_path && { + fromPath: vscode_path + } +}); \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 528abe84..52f7f025 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,17 +14,30 @@ "outFiles": ["${workspaceFolder}/client/dist/**/*.js"], "preLaunchTask": "npm: build:watch" }, + { + "name": "Extension Tests", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "preLaunchTask": "npm: watch", + "args": [ + "--disable-extensions", + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/client/dist/test/runTest" + ], + "outFiles": ["${workspaceFolder}/client/dist/test/**/*.js"] + }, { "type": "extensionHost", "request": "launch", "name": "Launch Client", "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}"], + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], "env": { "VSCODE_AHK_SERVER_PATH": "server/dist/server.js", "SYNTAXES_PATH": "syntaxes" }, - "outFiles": ["${workspaceRoot}/client/dist/**/*.js"], + "outFiles": ["${workspaceFolder}/client/dist/**/*.js"], "preLaunchTask": "npm: build:dev" }, { @@ -34,8 +47,8 @@ "port": 6009, "restart": true, "outFiles": [ - "${workspaceRoot}/server/out/**/*.js", - "${workspaceRoot}/server/dist/**/*.js" + "${workspaceFolder}/server/out/**/*.js", + "${workspaceFolder}/server/dist/**/*.js" ] } ], diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f5ae961..2ad6c8d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +## 2.5.2 + +- 修复[#591](https://github.com/thqby/vscode-autohotkey2-lsp/issues/591) +- 修复[#594](https://github.com/thqby/vscode-autohotkey2-lsp/issues/594) +- 修复[#595](https://github.com/thqby/vscode-autohotkey2-lsp/issues/595) +- 修复[#596](https://github.com/thqby/vscode-autohotkey2-lsp/issues/596) + +## 2.5.1 + +- 修复[#584](https://github.com/thqby/vscode-autohotkey2-lsp/issues/584) + -57](https://github.com/thqby/vscode-autohotkey2-lsp/issues/587) +- [FR #565](https://github.com/thqby/vscode-autohotkey2-lsp/issues/565) +- 修复一些bug + +## 2.5.0 + +- 修复[#533](https://github.com/thqby/vscode-autohotkey2-lsp/issues/533) +- 修复[#562](https://github.com/thqby/vscode-autohotkey2-lsp/issues/562) +- 修复[#563](https://github.com/thqby/vscode-autohotkey2-lsp/issues/563) +- 修复[#571](https://github.com/thqby/vscode-autohotkey2-lsp/issues/571) +- 修复[#574](https://github.com/thqby/vscode-autohotkey2-lsp/issues/574) +- 修复[#576](https://github.com/thqby/vscode-autohotkey2-lsp/issues/576) +- [FR #564](https://github.com/thqby/vscode-autohotkey2-lsp/issues/564) +- [FR #570](https://github.com/thqby/vscode-autohotkey2-lsp/issues/570) + ## 2.4.9 - 修复[#548](https://github.com/thqby/vscode-autohotkey2-lsp/issues/548) @@ -287,7 +312,7 @@ - 修复[#306](https://github.com/thqby/vscode-autohotkey2-lsp/issues/306) - 支持同时运行多个脚本[#307] -- 增加命令`ahk2.export.symbols`, 导出类、函数等信息 +- 增加命令`ahk2.extract.symbols`, 提取类、函数等信息 ## 1.9.5 diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts new file mode 100644 index 00000000..5e8e4267 --- /dev/null +++ b/client/src/browserClientMain.ts @@ -0,0 +1,127 @@ +//* ⚠️ Not currently used in AHK++ + +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { commands, ExtensionContext, languages, Range, RelativePattern, SnippetString, Uri, window, workspace, WorkspaceEdit } from 'vscode'; +import { LanguageClient } from 'vscode-languageclient/browser'; + +let client: LanguageClient; + +// this method is called when vs code is activated +export function activate(context: ExtensionContext) { + const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browserServerMain.js'); + /* eslint-disable-next-line */ + const request_handlers: Record any> = { + 'ahk2.getActiveTextEditorUriAndPosition': () => { + const editor = window.activeTextEditor; + if (!editor) return; + const uri = editor.document.uri.toString(), position = editor.selection.end; + return { uri, position }; + }, + 'ahk2.insertSnippet': async (params: [string, Range?]) => { + const editor = window.activeTextEditor; + if (!editor) return; + if (params[1]) { + const { start, end } = params[1]; + await editor.insertSnippet(new SnippetString(params[0]), new Range(start.line, start.character, end.line, end.character)); + } else + editor.insertSnippet(new SnippetString(params[0])); + }, + 'ahk2.setTextDocumentLanguage': async (params: [string, string?]) => { + const lang = params[1] || 'ahk'; + if (!(await languages.getLanguages()).includes(lang)) { + window.showErrorMessage(`Unknown language id: ${lang}`); + return; + } + const uri = params[0], it = workspace.textDocuments.find(it => it.uri.toString() === uri); + it && languages.setTextDocumentLanguage(it, lang); + }, + 'ahk2.getWorkspaceFiles': async (params: string[]) => { + const all = !params.length; + if (workspace.workspaceFolders) { + if (all) + return (await workspace.findFiles('**/*.{ahk,ah2,ahk2}')).forEach(it => it.toString()); + else { + const files: string[] = []; + for (const folder of workspace.workspaceFolders) + if (params.includes(folder.uri.toString().toLowerCase())) + files.push(...(await workspace.findFiles(new RelativePattern(folder, '*.{ahk,ah2,ahk2}'))).map(it => it.toString())); + return files; + } + } + }, + 'ahk2.getWorkspaceFileContent': async (params: string[]) => (await workspace.openTextDocument(Uri.parse(params[0]))).getText() + }; + + client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', { + documentSelector: [{ language: 'ahk2' }], + markdown: { isTrusted: true, supportHtml: true }, + initializationOptions: { + extensionUri: context.extensionUri.toString(), + commands: Object.keys(request_handlers), + ...JSON.parse(JSON.stringify(workspace.getConfiguration('AutoHotkey2'))) + } + }, new Worker(serverMain.toString())); + + context.subscriptions.push( + commands.registerTextEditorCommand('ahk2.update.versioninfo', async textEditor => { + const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); + if (!infos?.length) { + await textEditor.insertSnippet(new SnippetString([ + "/************************************************************************", + " * @description ${1:}", + " * @author ${2:}", + " * @date ${3:$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE}", + " * @version ${4:0.0.0}", + " ***********************************************************************/", + "", "" + ].join('\n')), new Range(0, 0, 0, 0)); + } else { + const d = new Date; + let contents: string[] = [], value: string | undefined; + for (const info of infos) { + if (info.single) + contents.push(info.content.replace( + /(?<=^;\s*@ahk2exe-setversion\s+)(\S+|(?=[\r\n]))/i, + s => (value ||= s, '\0'))); + else contents.push(info.content.replace( + /(?<=^\s*[;*]?\s*@date[:\s]\s*)(\S+|(?=[\r\n]))/im, + date => [d.getFullYear(), d.getMonth() + 1, d.getDate()].map( + n => n.toString().padStart(2, '0')).join(date.includes('.') ? '.' : '/') + ).replace(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S+|(?=[\r\n]))/im, s => (value ||= s, '\0'))); + } + if (value !== undefined) { + value = await window.showInputBox({ + value, prompt: 'Enter version info' + }); + if (!value) + return; + contents = contents.map(s => s.replace('\0', value!)); + } + const ed = new WorkspaceEdit(), uri = textEditor.document.uri; + infos.forEach(it => it.content !== (value = contents.shift()) && + ed.replace(uri, it.range, value!)); + ed.size && workspace.applyEdit(ed); + } + }), + commands.registerTextEditorCommand('ahk2.switch', textEditor => { + const doc = textEditor.document; + languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); + }), + workspace.onDidCloseTextDocument(e => { + client.sendNotification('onDidCloseTextDocument', e.isClosed ? + { uri: '', id: '' } : { uri: e.uri.toString(), id: e.languageId }); + }) + ); + + client.start().then(() => { + Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); + }); +} + +export function deactivate() { + return client?.stop(); +} \ No newline at end of file diff --git a/client/src/extension.test.ts b/client/src/extension.test.ts index bb4390b6..38393599 100644 --- a/client/src/extension.test.ts +++ b/client/src/extension.test.ts @@ -1,28 +1,234 @@ import * as assert from 'assert'; -import * as sinon from 'sinon'; -import * as fs from 'fs'; -import { resolvePath } from './extension'; +import * as vscode from 'vscode'; +import { resolve } from 'path'; +import { + LanguageClient, + CompletionRequest, + CompletionParams, + CompletionItem, + DocumentSymbolRequest, + DocumentSymbolParams, + SymbolInformation, + DefinitionRequest, + DefinitionParams, + LocationLink, + DocumentFormattingRequest, + DocumentFormattingParams, + TextEdit, + FoldingRangeRequest, + FoldingRangeParams, + FoldingRange, + HoverRequest, + HoverParams, + Hover, + PrepareRenameRequest, + PrepareRenameParams, + ReferencesRequest, + ReferenceParams, + Location, + RenameRequest, + RenameParams, + WorkspaceEdit, + SignatureHelpRequest, + SignatureHelpParams, + SignatureHelp, + SemanticTokensRequest, + SemanticTokensParams, + SemanticTokens, + WorkspaceSymbolRequest, + WorkspaceSymbolParams, + ExecuteCommandRequest, + ExecuteCommandParams, +} from 'vscode-languageclient/node'; -suite('resolvePath', () => { - let lstatSyncStub: sinon.SinonStub; +suite('Start ahk language server', () => { + test('should be running', async () => { + await vscode.commands.executeCommand( + 'workbench.action.closeAllEditors', + ); + const client: LanguageClient = await vscode.extensions + .getExtension('thqby.vscode-autohotkey2-lsp') + ?.activate(); + assert.equal(client?.isRunning(), true); - suiteSetup(() => { - lstatSyncStub = sinon.stub(fs, 'lstatSync'); - }); + suite('Open ahk file', () => { + test('should be opened', async () => { + const path = resolve( + __dirname, + '../../../server/dist/ahkProvider.ahk', + ); + let document = ( + await vscode.window.showTextDocument( + await vscode.workspace.openTextDocument(path), + ) + ).document; + const uri = document.uri.toString(); + if (document.languageId !== 'ahk2') + document = await vscode.languages.setTextDocumentLanguage( + document, + 'ahk2', + ); + const content = (await client!.sendRequest( + 'ahk2.getContent', + uri, + )) as string; + assert.equal(document.getText() === content, true); + + suite('Test language server features', () => { + const textDocument = { uri }; + const position = { line: 10, character: 5 }; + + test(CompletionRequest.method, async function () { + const params: CompletionParams = { + textDocument, + position, + }; + const result: CompletionItem[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(DefinitionRequest.method, async function () { + const params: DefinitionParams = { + textDocument, + position, + }; + const result: LocationLink[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(DocumentFormattingRequest.method, async function () { + const params: DocumentFormattingParams = { + textDocument, + options: { insertSpaces: false, tabSize: 4 }, + }; + const result: TextEdit[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(DocumentSymbolRequest.method, async function () { + const params: DocumentSymbolParams = { textDocument }; + const result: SymbolInformation[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(FoldingRangeRequest.method, async function () { + const params: FoldingRangeParams = { textDocument }; + const result: FoldingRange[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(HoverRequest.method, async function () { + const params: HoverParams = { textDocument, position }; + const result: Hover | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.contents); + }); + + test(PrepareRenameRequest.method, async function () { + const params: PrepareRenameParams = { + textDocument, + position, + }; + const result: unknown | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result); + }); + + test(ReferencesRequest.method, async function () { + const params: ReferenceParams = { + textDocument, + position, + context: { includeDeclaration: true }, + }; + const result: Location[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(RenameRequest.method, async function () { + const params: RenameParams = { + textDocument, + position, + newName: '', + }; + const result: WorkspaceEdit | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.changes); + }); + + test(SignatureHelpRequest.method, async function () { + const params: SignatureHelpParams = { + textDocument, + position: { line: 8, character: 36 }, + }; + const result: SignatureHelp | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.signatures); + }); - const theories: ([string, string] | [string, string, boolean])[] = [ - ['', ''], - ['C:/out.txt', 'C:/out.txt'], - ]; + test(ExecuteCommandRequest.method, async function () { + const params: ExecuteCommandParams = { + command: 'ahk2.diagnose.all', + }; + await client.sendRequest(this.runnable().title, params); + }); - theories.forEach(([input, expected, isSymbolicLink = false]) => { - test(`resolvePath('${input}') === '${expected}'`, () => { - // Mock the behavior of fs.lstatSync - lstatSyncStub - .withArgs(input) - .returns({ isSymbolicLink: () => isSymbolicLink }); + test(WorkspaceSymbolRequest.method, async function () { + const params: WorkspaceSymbolParams = { query: 'msg' }; + const result: SymbolInformation[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); - assert.strictEqual(resolvePath(input), expected); + test(SemanticTokensRequest.method, async function () { + const params: SemanticTokensParams = { textDocument }; + const result: SemanticTokens | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.data); + }); + }); + }); }); }); }); diff --git a/client/src/extension.ts b/client/src/extension.ts index efbe76e1..251d7926 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -30,18 +30,37 @@ import { ServerOptions, TransportKind } from 'vscode-languageclient/node'; -import { resolve } from 'path'; -import { ChildProcess, execSync, spawn } from 'child_process'; -import { readdirSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; +import { resolve, basename } from 'path'; +import { ChildProcess, exec, execSync, spawn } from 'child_process'; +import { readdirSync, readFileSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); -let v2Interpreter = getCfg(CfgKey.InterpreterPathV2), server_is_ready = false, zhcn = false; +let v2Interpreter = getCfg(CfgKey.InterpreterPathV2), server_is_ready = false const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; const isWindows = process.platform === 'win32'; +let extlist: string[] = [], debugexts: Record = {}, langs: string[] = []; +const loadedCollection = { + 'ahk2.browse': 'Browse your file system to find AutoHotkey2 interpreter', + 'ahk2.compiledfailed': 'Compiled failed!', + 'ahk2.compiledsuccessfully': 'Compiled successfully!', + 'ahk2.current': 'Current: {0}', + 'ahk2.debugextnotexist': 'The debug extension was not found, please install the debug extension first!', + 'ahk2.diagnose.all': 'Diagnostic All', + 'ahk2.enterahkpath': 'Enter path to AutoHotkey2 interpreter', + 'ahk2.entercmd': 'Enter the command line parameters that need to be passed', + 'ahk2.enterorfind': 'Enter path or find an existing interpreter', + 'ahk2.enterversion': 'Enter version', + 'ahk2.filenotexist': '\'{0}\' does not exist', + 'ahk2.find': 'Find...', + 'ahk2.savebeforecompilation': 'Please save the script before compilation', + 'ahk2.select': 'Select', + 'ahk2.set.interpreter': 'Select AutoHotkey2 Interpreter', + 'ahk2.unknownversion': 'Unknown version', +}; -export async function activate(context: ExtensionContext) { +export function activate(context: ExtensionContext): Promise { /** Absolute path to `server.js` */ const defaultServerModule = context.asAbsolutePath(`ahk2/server/dist/server.js`); const serverModule = process.env.VSCODE_AHK_SERVER_PATH ? context.asAbsolutePath(process.env.VSCODE_AHK_SERVER_PATH) : defaultServerModule; @@ -91,11 +110,13 @@ export async function activate(context: ExtensionContext) { }; // Options to control the language client + const fsw = workspace.createFileSystemWatcher('**/*.{ahk}'); const clientOptions: LanguageClientOptions = { documentSelector: [{ language: 'ahk2' }], markdown: { isTrusted: true, supportHtml: true }, outputChannel: outputchannel = window.createOutputChannel('AHK++', '~ahk2-output'), outputChannelName: 'AHK++', + synchronize: { fileEvents: fsw }, initializationOptions: { commands: Object.keys(request_handlers), GlobalStorage: context.globalStorageUri.fsPath, @@ -104,20 +125,22 @@ export async function activate(context: ExtensionContext) { }; // Create the language client and start the client. - client = new LanguageClient('AHK++', 'AHK++', serverOptions, clientOptions); - zhcn = env.language.startsWith('zh-'); - textdecoders.push(new TextDecoder(zhcn ? 'gbk' : 'windows-1252')); + client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', serverOptions, clientOptions); + loadlocalize(context.extensionPath + '/package.nls'); + textdecoders.push(new TextDecoder(env.language.startsWith('zh-') ? 'gbk' : 'windows-1252')); // Start the client. This will also launch the server + let onInitialized: undefined | ((value: LanguageClient) => void); client.start().then(() => { Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); onDidChangegetInterpreter(); if (window.activeTextEditor?.document.languageId === 'ahk2') ahkStatusBarItem.show(); server_is_ready = true; + onInitialized!(client); + onInitialized = undefined; }); - let extlist: string[], debugexts: { [type: string]: string }, langs: string[] = []; const id_has_register: string[] = []; function update_extensions_info() { debugexts = {}; @@ -136,20 +159,17 @@ export async function activate(context: ExtensionContext) { context.subscriptions.push(debug.registerDebugConfigurationProvider(id, { async resolveDebugConfiguration(folder, config) { if (config.__ahk2debug || window.activeTextEditor?.document.languageId !== 'ahk') { - const appendConfigs: (Partial | undefined)[] = []; - const allConfigs = workspace.getConfiguration('launch').inspect('configurations'); - let configs = allConfigs && [ - ...allConfigs.workspaceFolderValue ?? [], - ...allConfigs.workspaceValue ?? [], - ...allConfigs.globalValue ?? []]; - config.request ||= 'launch'; - configs = configs?.filter(it => it.request === config.request && it.type === config.type); + let runtime: string | undefined; if (!config.__ahk2debug) { + config.request ||= 'launch'; + const match_config = get_debug_configs()?.filter(it => + Object.entries(it).every(([k, v]) => equal(v, config[k])) + )?.sort((a, b) => Object.keys(a).length - Object.keys(b).length).pop(); const def = { ...getCfg(CfgKey.DebugConfiguration) as Partial }; delete def.request, delete def.type; - appendConfigs.push(def, configs?.filter(it => - Object.entries(it).every(([k, v]) => equal(v, config[k])) - )?.sort((a, b) => Object.keys(a).length - Object.keys(b).length).pop()); + Object.assign(config, def, match_config); + if (match_config?.type === 'autohotkey') + runtime = match_config.runtime_v2; // eslint-disable-next-line @typescript-eslint/no-explicit-any function equal(a: any, b: any): boolean { if (a === b) @@ -161,17 +181,17 @@ export async function activate(context: ExtensionContext) { const kv = Object.entries(a); return kv.length === Object.keys(b).length && kv.every(([k, v]) => equal(v, b[k])); } - } else if (configs) - appendConfigs.push(configs.find(it => it.name === config.name) ?? configs[0]); - Object.assign(config, ...appendConfigs); - if (!config.runtime && (!config.runtime_v2 || config.type !== 'autohotkey')) { + } else if (config.runtime === 'autohotkey') + runtime = config.runtime_v2; + if (!(config.runtime ||= runtime)) { config.runtime = resolvePath(v2Interpreter, folder?.uri.fsPath); if (ahkStatusBarItem.text.endsWith('[UIAccess]')) config.useUIAVersion = true; } if (config.request === 'launch') config.program ||= '${file}'; - config.AhkExecutable ||= config.runtime; + if (config.type === 'ahkdbg') + config.AhkExecutable ||= config.runtime; } return config; } @@ -182,29 +202,33 @@ export async function activate(context: ExtensionContext) { commands.executeCommand('setContext', 'ahk:isRunning', false); ahkStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 75); - ahkStatusBarItem.command = 'ahk++.setV2Interpreter'; + ahkStatusBarItem.command = 'ahk++.setv2Interpreter'; + for (const it of [ + { text: '$(folder)syntaxes', command: { title: localize('ahk2.select'), command: 'ahk2.select.syntaxes' } }, + ]) + context.subscriptions.push(Object.assign(languages.createLanguageStatusItem(it.command.command, { language: 'ahk2' }), it)); const ahkLanguageStatusItem = languages.createLanguageStatusItem('ahk++', { language: 'ahk2' }); ahkLanguageStatusItem.text = '$(folder)syntaxes'; ahkLanguageStatusItem.command = { title: 'Select AHK Syntaxes', command: 'ahk++.selectSyntaxes' }; context.subscriptions.push( - ahkStatusBarItem, ahkLanguageStatusItem, outputchannel, + ahkStatusBarItem, outputchannel, fsw, extensions.onDidChange(update_extensions_info), commands.registerTextEditorCommand('ahk++.run', textEditor => runScript(textEditor)), commands.registerTextEditorCommand('ahk++.runSelection', textEditor => runScript(textEditor, true)), commands.registerCommand('ahk++.stop', stopRunningScript), - commands.registerCommand('ahk++.setV2Interpreter', setInterpreterV2), - commands.registerCommand('ahk++.debugParams', () => beginDebug(extlist, debugexts, true)), - commands.registerCommand('ahk++.debugAttach', () => beginDebug(extlist, debugexts, false, true)), + commands.registerCommand('ahk2.debug.file', () => beginDebug('f')), + commands.registerCommand('ahk2.debug.configs', () => beginDebug('c')), + commands.registerCommand('ahk2.debug.params', () => beginDebug('p')), + commands.registerCommand('ahk2.debug.attach', () => beginDebug('a')), commands.registerCommand('ahk++.selectSyntaxes', selectSyntaxes), commands.registerTextEditorCommand('ahk++.updateVersionInfo', async textEditor => { if (!server_is_ready) return; - const info: { content: string, uri: string, range: Range } | null = await client.sendRequest('ahk++.getVersionInfo', textEditor.document.uri.toString()); - if (!info) { + const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest('ahk++.getVersionInfo', textEditor.document.uri.toString()); + if (!infos?.length) { await textEditor.insertSnippet(new SnippetString([ "/************************************************************************", " * @description ${1:}", - " * @file $TM_FILENAME", " * @author ${2:}", " * @date ${3:$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE}", " * @version ${4:0.0.0}", @@ -213,16 +237,30 @@ export async function activate(context: ExtensionContext) { ].join('\n')), new Range(0, 0, 0, 0)); } else { const d = new Date; - let content = info.content, ver; - content = content.replace(/(?<=^\s*[;*]?\s*@date[:\s]\s*)(\d+\/\d+\/\d+)/im, d.getFullYear() + '/' + ('0' + (d.getMonth() + 1)).slice(-2) + '/' + ('0' + d.getDate()).slice(-2)); - if (content.match(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S*)/im) && - (ver = await window.showInputBox({ prompt: zhcn ? '输入版本信息' : 'Enter version info', value: content.match(/(?<=^[\s*]*@version[:\s]\s*)(\S*)/im)?.[1] }))) - content = content.replace(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S*)/im, ver); - if (content !== info.content) { - const ed = new WorkspaceEdit(); - ed.replace(Uri.parse(info.uri), info.range, content); - workspace.applyEdit(ed); + let contents: string[] = [], value: string | undefined; + for (const info of infos) { + if (info.single) + contents.push(info.content.replace( + /(?<=^;\s*@ahk2exe-setversion\s+)(\S+|(?=[\r\n]))/i, + s => (value ||= s, '\0'))); + else contents.push(info.content.replace( + /(?<=^\s*[;*]?\s*@date[:\s]\s*)(\S+|(?=[\r\n]))/im, + date => [d.getFullYear(), d.getMonth() + 1, d.getDate()].map( + n => n.toString().padStart(2, '0')).join(date.includes('.') ? '.' : '/') + ).replace(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S+|(?=[\r\n]))/im, s => (value ||= s, '\0'))); } + if (value !== undefined) { + value = await window.showInputBox({ + value, prompt: localize('ahk2.enterversion') + }); + if (!value) + return; + contents = contents.map(s => s.replace('\0', value!)); + } + const ed = new WorkspaceEdit(), uri = textEditor.document.uri; + infos.forEach(it => it.content !== (value = contents.shift()) && + ed.replace(uri, it.range, value!)); + ed.size && workspace.applyEdit(ed); } }), commands.registerTextEditorCommand('ahk++.switchAhkVersion', textEditor => { @@ -256,6 +294,7 @@ export async function activate(context: ExtensionContext) { window.onDidChangeActiveTextEditor(e => e?.document.languageId === 'ahk2' ? ahkStatusBarItem.show() : ahkStatusBarItem.hide()), ); + return new Promise(resolve => onInitialized = resolve); } export function deactivate() { @@ -285,13 +324,13 @@ const isV1 = (): boolean => * Works for both AHK v1 and AHK v2 * Does not work on never-saved files (new untitled documents) */ -function runScript(textEditor: TextEditor, runSelection = false) { +async function runScript(textEditor: TextEditor, runSelection = false) { const interpreter: string | undefined = isV1() ? getCfg(CfgKey.InterpreterPathV1) : getCfg(CfgKey.InterpreterPathV2); const executePath = resolvePath(interpreter, workspace.getWorkspaceFolder(textEditor.document.uri)?.uri.fsPath); if (!executePath) { const s = interpreter || 'AutoHotkey.exe'; - window.showErrorMessage(zhcn ? `"${s}"未找到` : `"${s}" not found`, 'Select Interpreter') - .then(r => r && setInterpreterV2()); + window.showErrorMessage(localize('ahk2.filenotexist', s), localize('ahk2.set.interpreter')) + .then(r => r ? setInterpreterV2() : undefined); return; } let selectedText = '', path = '*', command = `"${executePath}" /ErrorStdOut=utf-8 `; @@ -331,7 +370,7 @@ function runScript(textEditor: TextEditor, runSelection = false) { } else { if (textEditor.document.isUntitled) return; - commands.executeCommand('workbench.action.files.save'); + await commands.executeCommand('workbench.action.files.save'); path = textEditor.document.fileName, command += `"${path}"`, startTime = new Date(); process = spawn(command, { cwd: resolve(path, '..'), shell: true }); } @@ -383,26 +422,39 @@ async function stopRunningScript() { } } -async function beginDebug(extlist: string[], debugexts: { [type: string]: string }, params = false, attach = false) { + + +function get_debug_configs() { + const allconfigs = workspace.getConfiguration('launch').inspect('configurations'); + return allconfigs && [ + ...allconfigs.workspaceFolderValue ?? [], + ...allconfigs.workspaceValue ?? [], + ...allconfigs.globalValue ?? []].filter(it => it.type in debugexts); +} + +// todo validate calls +async function beginDebug(type: string) { let extname: string | undefined; const editor = window.activeTextEditor; - const config = { ...getCfg(CfgKey.DebugConfiguration), request: 'launch', __ahk2debug: true } as DebugConfiguration; + let config = { ...getCfg(CfgKey.DebugConfiguration), request: 'launch', __ahk2debug: true } as DebugConfiguration; if (!extlist.length) { - window.showErrorMessage(zhcn ? '未找到debug扩展, 请先安装debug扩展!' : 'The debug extension was not found, please install the debug extension first!'); + window.showErrorMessage(localize('ahk2.debugextnotexist')); extname = await window.showQuickPick(['zero-plusplus.vscode-autohotkey-debug', 'helsmy.autohotkey-debug', 'mark-wiemer.vscode-autohotkey-plus-plus', 'cweijan.vscode-autohotkey-plus']); if (extname) commands.executeCommand('workbench.extensions.installExtension', extname); return; } - if (params || attach) { + if ('ap'.includes(type)) { if (!extlist.includes(extname = 'zero-plusplus.vscode-autohotkey-debug')) { window.showErrorMessage('zero-plusplus.vscode-autohotkey-debug was not found!'); return; } config.type = Object.entries(debugexts).find(([, v]) => v === extname)![0]; - if (params) { - let input = await window.showInputBox({ prompt: zhcn ? '输入需要传递的命令行参数' : 'Enter the command line parameters that need to be passed' }); - if ((input = input?.trim())) { + if (type === 'p') { + let input = await window.showInputBox({ prompt: localize('ahk2.entercmd') }); + if (input === undefined) + return; + if ((input = input.trim())) { const args: string[] = []; input.replace(/('|")(.*?(? { args.push(m[4] || m[2]); @@ -411,7 +463,24 @@ async function beginDebug(extlist: string[], debugexts: { [type: string]: string config.args = args; } } else config.request = 'attach'; - } else config.type ||= Object.keys(debugexts).sort().pop()!; + } else if (type === 'c') { + const configs = get_debug_configs(); + if (configs?.length) { + const pick = window.createQuickPick(); + pick.items = configs.map(it => ({ label: it.name, data: it })); + pick.show(); + const it = await new Promise(resolve => { + pick.onDidAccept(() => resolve( + (pick.selectedItems[0] as unknown as { data: DebugConfiguration })?.data)); + pick.onDidHide(() => resolve(undefined)); + }); + pick.dispose(); + if (!it) + return; + config = it as DebugConfiguration; + } + } else config.program = '${file}'; + config.type ||= Object.keys(debugexts).sort().pop()!; config.name ||= `AutoHotkey ${config.request === 'attach' ? 'Attach' : 'Debug'}`; debug.startDebugging(editor && workspace.getWorkspaceFolder(editor.document.uri), config); } @@ -427,13 +496,8 @@ async function setInterpreterV2() { const list: QuickPickItem[] = [], _ = (ahkpath = resolvePath(v2Interpreter || ahkpath, undefined, false)).toLowerCase(); const pick = window.createQuickPick(); let it: QuickPickItem, active: QuickPickItem | undefined, sel: QuickPickItem = { label: '' }; - if (zhcn) { - list.push({ alwaysShow: true, label: '输入解释器路径...', detail: '输入路径或选择一个现有的解释器' }); - it = { label: '浏览...', detail: '浏览文件系统来选择一个 AutoHotkey2 解释器。' }; - } else { - list.push({ alwaysShow: true, label: 'Enter interpreter path...', detail: 'Enter path or find an existing interpreter' }); - it = { label: 'Find...', detail: 'Browse your file system to find a AutoHotkey2 interpreter.' }; - } + list.push({ alwaysShow: true, label: localize('ahk2.enterahkpath') + '...', detail: localize('ahk2.enterorfind') }); + it = { label: localize('ahk2.find'), detail: localize('ahk2.browse') }; if (ahkpath) await addpath(resolve(ahkpath, '..'), _.includes('autohotkey') ? 20 : 5); if (!_.includes('c:\\program files\\autohotkey\\')) @@ -443,22 +507,22 @@ async function setInterpreterV2() { active = list[index]; pick.matchOnDetail = true, pick.items = list; - pick.title = zhcn ? '选择解释器' : 'Select Interpreter'; + pick.title = localize('ahk2.set.interpreter'); if (active) pick.activeItems = [active]; - pick.placeholder = (zhcn ? '当前: ' : 'Current: ') + v2Interpreter; + pick.placeholder = localize('ahk2.current', v2Interpreter); pick.show(); pick.onDidAccept(async () => { if (pick.selectedItems[0] === list[0]) { pick.title = undefined, pick.activeItems = [], pick.value = '', pick.items = [it]; - pick.placeholder = zhcn ? '请输入 AutoHotkey2 解释器的路径。' : 'Enter path to a AutoHotkey2 interpreter.'; + pick.placeholder = localize('ahk2.enterahkpath'); return; } else if (pick.selectedItems[0] === it) { pick.ignoreFocusOut = true; const path = await window.showOpenDialog({ defaultUri: ahkpath ? Uri.file(ahkpath) : undefined, filters: { Executables: ['exe'] }, - openLabel: zhcn ? '选择解释器' : 'Select Interpreter' + openLabel: localize('ahk2.select') }); if (path) sel.detail = path[0].fsPath; @@ -551,10 +615,10 @@ async function onDidChangegetInterpreter() { // ahkStatusBarItem.tooltip is the current saved interpreter path if (ahkPath !== ahkStatusBarItem.tooltip) { ahkStatusBarItem.tooltip = ahkPath; - ahkStatusBarItem.text = (await getAHKversion([ahkPath]))[0] || (zhcn ? '未知版本' : 'Unknown version'); + ahkStatusBarItem.text = (await getAHKversion([ahkPath]))[0] || localize('ahk2.unknownversion'); } } else { - ahkStatusBarItem.text = (zhcn ? '选择AutoHotkey2解释器' : 'Select AutoHotkey2 Interpreter'); + ahkStatusBarItem.text = localize('ahk2.set.interpreter') ahkStatusBarItem.tooltip = undefined, ahkPath = ''; } } @@ -582,10 +646,7 @@ export function resolvePath(path: string | undefined, workspace?: string, resolv if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) path = resolve(path, '..', readlinkSync(path)); return path; - } catch (ex) { - console.log("resolvePath threw exception", ex); - continue; - } + } catch { } } return ''; } @@ -598,7 +659,7 @@ function existsSync(path: string): boolean { try { lstatSync(path); } catch (err) { - if ((err as { code: string})?.code === 'ENOENT') + if ((err as { code: string })?.code === 'ENOENT') return false; } return true; @@ -611,3 +672,33 @@ function statSync(path: string) { return lstatSync(resolve(path, '..', readlinkSync(path))); return st; } + +function loadlocalize(nls: string) { + let s = `${nls}.${env.language}.json`; + if (!existsSync(s)) { + if (!env.language.startsWith('zh-') || !existsSync(s = `${nls}.zh-cn.json`)) + return; + } + try { + const obj = JSON.parse(readFileSync(s, { encoding: 'utf8' })); + for (const key of Object.keys(loadedCollection) as Array) + if ((s = obj[key])) + loadedCollection[key] = s; + } catch { } +} + +function localize(key: keyof typeof loadedCollection, ...args: unknown[]) { + const val = loadedCollection[key]; + if (args.length) + return format(val, ...args as string[]); + return val; +} + +function format(message: string, ...args: string[]): string { + return message.replace(/\{(\d+)\}/g, (...m) => { + const i = parseInt(m[1]); + if (i < args.length) + return args[i]; + return ' '; + }); +} diff --git a/client/src/test/runTest.ts b/client/src/test/runTest.ts new file mode 100644 index 00000000..856b58c4 --- /dev/null +++ b/client/src/test/runTest.ts @@ -0,0 +1,36 @@ +import { resolve } from 'path'; +import * as Mocha from 'mocha'; +import { readdir } from 'fs'; + +export function run(): Promise { + // Create the mocha test + const mocha = new Mocha({ + ui: 'tdd', + timeout: 0 + }); + + return new Promise((c, e) => { + readdir(__dirname, (err, files) => { + if (err) { + return e(err); + } + + // Add files to the test suite + files.forEach(f => f.endsWith('.test.js') && mocha.addFile(resolve(__dirname, f))); + + try { + // Run the mocha test + mocha.run(failures => { + if (failures > 0) { + e(new Error(`${failures} tests failed.`)); + } else { + c(); + } + }); + } catch (err) { + console.error(err); + e(err); + } + }); + }); +} \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs index 7dc2a7b8..a805ba0e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -4,38 +4,38 @@ import tseslint from 'typescript-eslint'; /** @type {typeof tseslint.configs.recommended} */ export default [ - { - languageOptions: { - globals: { - ...globals.browser, - ...globals.node, - }, - }, - }, - pluginJs.configs.recommended, - ...tseslint.configs.recommended, - { - ignores: [ - '**/*.js', - '**/*.d.ts', - '**/.vscode-test-web/*', - '**/.vscode-test/*', - ], - }, - { - rules: { - 'no-control-regex': 'off', - 'no-empty': ['error', { allowEmptyCatch: true }], - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { - argsIgnorePattern: '^_', - varsIgnorePattern: '^_', - caughtErrors: 'none', - ignoreRestSiblings: true, - }, - ], - }, - }, + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + }, + }, + }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + ignores: [ + '**/*.js', + '**/*.d.ts', + '**/.vscode-test-web/*', + '**/.vscode-test/*', + ], + }, + { + rules: { + 'no-control-regex': 'off', + 'no-empty': ['error', { allowEmptyCatch: true }], + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrors: 'none', + ignoreRestSiblings: true, + }, + ], + }, + }, ]; diff --git a/package-lock.json b/package-lock.json index 6bf452f7..996e9244 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1142,7 +1142,6 @@ "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", "dev": true, - "license": "MIT", "dependencies": { "@types/mocha": "^10.0.2", "c8": "^9.1.0", @@ -1226,7 +1225,6 @@ "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", "dev": true, - "license": "MIT", "dependencies": { "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", @@ -2205,7 +2203,6 @@ "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, - "license": "MIT", "dependencies": { "restore-cursor": "^4.0.0" }, @@ -2221,7 +2218,6 @@ "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz", "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" }, @@ -2425,8 +2421,7 @@ "version": "1.0.3", "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", @@ -3820,8 +3815,7 @@ "version": "3.0.6", "resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz", "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -4026,7 +4020,6 @@ "resolved": "https://registry.npmmirror.com/is-interactive/-/is-interactive-2.0.0.tgz", "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -4107,8 +4100,7 @@ "version": "1.0.0", "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/isexe": { "version": "2.0.0", @@ -4299,7 +4291,6 @@ "resolved": "https://registry.npmmirror.com/jszip/-/jszip-3.10.1.tgz", "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "dev": true, - "license": "(MIT OR GPL-3.0-or-later)", "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -4319,7 +4310,6 @@ "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, - "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -4334,15 +4324,13 @@ "version": "5.1.2", "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/jszip/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, - "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -4599,7 +4587,6 @@ "resolved": "https://registry.npmmirror.com/lie/-/lie-3.3.0.tgz", "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "dev": true, - "license": "MIT", "dependencies": { "immediate": "~3.0.5" } @@ -4912,7 +4899,6 @@ "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -5469,7 +5455,6 @@ "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, - "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -5509,7 +5494,6 @@ "resolved": "https://registry.npmmirror.com/ora/-/ora-7.0.1.tgz", "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^4.0.0", @@ -5533,7 +5517,6 @@ "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -5546,7 +5529,6 @@ "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz", "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -5558,15 +5540,13 @@ "version": "10.3.0", "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.3.0.tgz", "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/ora/node_modules/is-unicode-supported": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -5579,7 +5559,6 @@ "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-5.1.0.tgz", "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^5.0.0", "is-unicode-supported": "^1.1.0" @@ -5596,7 +5575,6 @@ "resolved": "https://registry.npmmirror.com/string-width/-/string-width-6.1.0.tgz", "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", "dev": true, - "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^10.2.1", @@ -5614,7 +5592,6 @@ "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -5797,13 +5774,6 @@ "dev": true, "license": "ISC" }, - "node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", - "dev": true, - "license": "MIT" - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", @@ -5921,8 +5891,7 @@ "version": "2.0.1", "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/pump": { "version": "3.0.0", @@ -6299,7 +6268,6 @@ "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, - "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -6315,8 +6283,7 @@ "version": "3.0.7", "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" + "dev": true }, "node_modules/reusify": { "version": "1.0.4", @@ -6436,8 +6403,7 @@ "version": "1.0.5", "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -6702,7 +6668,6 @@ "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", "dev": true, - "license": "MIT", "dependencies": { "bl": "^5.0.0" }, @@ -6718,7 +6683,6 @@ "resolved": "https://registry.npmmirror.com/bl/-/bl-5.1.0.tgz", "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", "dev": true, - "license": "MIT", "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", @@ -6744,7 +6708,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" diff --git a/package.json b/package.json index 9b5d6959..869afc31 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vscode-autohotkey2-lsp", "displayName": "AutoHotkey v2 Language Support", - "version": "2.4.9", + "version": "2.5.2", "description": "AutoHotkey v2 language support, forked from thqby's extension", "categories": [ "Debuggers", diff --git a/package.nls.json b/package.nls.json new file mode 100644 index 00000000..f82ad6af --- /dev/null +++ b/package.nls.json @@ -0,0 +1,37 @@ +{ + "ahk2.actionwhenv1isdetected": "Action when v1 script is detected", + "ahk2.autolibinclude": "Provide completion and automatic include from User and Standard library, Local library", + "ahk2.commenttags": "A regular expression used to extract named tags from comments and generate module symbols", + "ahk2.compile": "Compile Script", + "ahk2.compilercmd": "Compiler command line options. If ahk2exe.exe is not specified, the default path will be used. `${execPath}` is equal to the currently selected AutoHotkey.exe", + "ahk2.completefunctionparens": "Parentheses are added to function completion when there is no `(` or `[` on the right; otherwise move the cursor to the right", + "ahk2.completioncommitcharacters": "Characters which commit auto completion, such as `.(`", + "ahk2.debug.attach": "Attach to ahk process", + "ahk2.debug.configs": "Debug ahk File using launch.json", + "ahk2.debug.file": "Debug ahk File", + "ahk2.debug.params": "Debug ahk File with Params", + "ahk2.debugconfiguration": "Append debugging configuration to the currently started debugger, same as launch.json configuration", + "ahk2.description": "Autohotkey2 Language Support using vscode-lsp", + "ahk2.diagnose.all": "Diagnostic All", + "ahk2.diagnostics.class-non-dynamic-member-check": "Check whether non-dynamic members of class exist", + "ahk2.diagnostics.paramscheck": "Check that the function call has the correct number of arguments", + "ahk2.warn.varunset": "Display warnings for each variable that has never been directly assigned or used with the reference operator", + "ahk2.warn.localsameasglobal": "Display warnings for each undeclared local variable which has the same name as a global variable", + "ahk2.warn.callwithoutparentheses": "Display warnings for each function or method call without parentheses", + "ahk2.extract.symbols": "Extract Symbol Information", + "ahk2.files.exclude": "Configure glob patterns for excluding files and folders when scanning ahk files.", + "ahk2.files.scanmaxdepth": "Controls the depth when scanning ahk files.", + "ahk2.generate.comment": "Generate Comment Template", + "ahk2.help": "Quick Help", + "ahk2.interpreterpath": "The path of the `AutoHotkey.exe` executable file. If `AutoHotkeyUX.exe` is selected, the script will be launched using UX Launcher.", + "ahk2.run": "Run ahk File", + "ahk2.run.selection": "Run Selected Script", + "ahk2.select.syntaxes": "Select Language Definition Folder", + "ahk2.set.interpreter": "Select AutoHotkey2 Interpreter", + "ahk2.set.scriptdir": "Set Here as A_ScriptDir", + "ahk2.stop": "Stop Running Script", + "ahk2.symbolfoldingfromopenbrace": "Forced symbol folding starts at open brace", + "ahk2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", + "ahk2.update.versioninfo": "Update File Version Info", + "ahk2.workingdirs": "Sets the working directory for the script" +} \ No newline at end of file diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json new file mode 100644 index 00000000..ed30b04f --- /dev/null +++ b/package.nls.zh-cn.json @@ -0,0 +1,127 @@ +{ + "ahk2.actionwhenv1isdetected": "检测到v1脚本时的行为", + "ahk2.autolibinclude": "对用户库和标准库, 本地库提供补全和自动include", + "ahk2.browse": "浏览文件系统来选择一个 AutoHotkey2 解释器", + "ahk2.commenttags": "用来从注释中提取命名标记的正则表达式, 并生成模块符号", + "ahk2.compile": "编译脚本", + "ahk2.compiledfailed": "编译失败!", + "ahk2.compiledsuccessfully": "编译成功!", + "ahk2.compilercmd": "编译器命令行选项. 如果未指定ahk2exe.exe, 将使用默认路径. `${execPath}`等价于当前选择的AutoHotkey.exe", + "ahk2.completefunctionparens": "当右侧不存在`(`或`[`时, 给函数补全添加括号; 否则向右移动光标", + "ahk2.completioncommitcharacters": "提交自动完成的字符, 例如`.(`", + "ahk2.current": "当前: {0}", + "ahk2.debug.attach": "附加到ahk进程", + "ahk2.debug.configs": "使用launch.json调试ahk文件", + "ahk2.debug.file": "调试ahk文件", + "ahk2.debug.params": "带参数调试", + "ahk2.debugconfiguration": "追加调试配置到当前启动的调试器, 与launch.json配置相同", + "ahk2.debugextnotexist": "未找到debug扩展, 请先安装debug扩展!", + "ahk2.description": "基于 vscode-lsp 协议的 Autohotkey2 语言支持", + "ahk2.diagnose.all": "诊断全部", + "ahk2.diagnostics.class-non-dynamic-member-check": "检查类非动态成员是否存在", + "ahk2.diagnostics.paramscheck": "检查函数调用参数个数是否正确", + "ahk2.enterahkpath": "请输入 AutoHotkey2 解释器的路径", + "ahk2.entercmd": "输入需要传递的命令行参数", + "ahk2.enterorfind": "输入路径或选择一个现有的解释器", + "ahk2.enterversion": "输入版本号", + "ahk2.filenotexist": "'{0}'文件不存在", + "ahk2.files.exclude": "配置 glob 模式以在扫描ahk文件时排除文件和文件夹.", + "ahk2.files.scanmaxdepth": "控制扫描ahk文件时的深度.", + "ahk2.find": "浏览...", + "ahk2.generate.comment": "生成注释模板", + "ahk2.help": "快捷帮助", + "ahk2.interpreterpath": "`AutoHotkey.exe`可执行文件的路径. 如果选择`AutoHotkeyUX.exe`, 将使用UX Launcher启动脚本.", + "ahk2.extract.symbols": "提取符号信息", + "ahk2.run": "运行ahk文件", + "ahk2.run.selection": "运行选择的脚本", + "ahk2.savebeforecompilation": "编译前请先保存脚本", + "ahk2.select": "选择", + "ahk2.select.syntaxes": "选择语言定义文件夹", + "ahk2.set.interpreter": "选择AutoHotkey2解释器", + "ahk2.set.scriptdir": "设置此处为A_ScriptDir", + "ahk2.stop": "停止运行中的脚本", + "ahk2.symbolfoldingfromopenbrace": "强制符号折叠从大括号处开始", + "ahk2.syntaxes": "指定用于智能感知的`ahk2.json`, `*.snippet.json`和`ahk2.d.ahk`文件的文件夹路径.", + "ahk2.unknownversion": "未知版本", + "ahk2.update.versioninfo": "更新文件版本信息", + "ahk2.warn.callwithoutparentheses": "为每个不带括号的函数或方法调用显示警告", + "ahk2.warn.localsameasglobal": "为每个与全局变量同名的未声明的局部变量显示警告", + "ahk2.warn.varunset": "为每个从未直接赋值或与引用操作符一起使用的变量的显示警告", + "ahk2.workingdirs": "设置脚本的工作目录", + "action.skipline": "跳过行", + "action.stopparsing": "停止解析", + "action.switchtov1": "切换到ahk v1", + "codeaction.include": "导入 '{0}'", + "completionitem.author": "添加作者, 描述, 日期, 版本等文件信息.", + "completionitem.generatecomment": "生成当前作用域函数/方法的注释模板.", + "completionitem.include": "从'{0}'自动导入", + "completionitem.new": "构造类的新实例.", + "completionitem.prototype": "检索或设置类的所有实例所基于的对象.", + "completionitem.super": "在继承类中, super 可以代替 this 来访问在派生类中被重写的方法或属性的超类版本.", + "completionitem.this": "在类中, 通过 this 访问该类的其他实例变量和方法.", + "completionitem.thishotkey": "热键函数的隐藏参数.", + "completionitem.value": "在动态属性 set 中, Value 包含被分配的值.", + "diagnostic.acceptparams": "'{0}' 接受{1}个参数", + "diagnostic.assignerr": "{0} '{1}'不能用作输出变量", + "diagnostic.classinfuncerr": "函数不能包含类", + "diagnostic.classuseerr": "类不能用作输出变量", + "diagnostic.conflictserr": "{0} '{2}'声明和已存在的{1}冲突", + "diagnostic.declarationerr": "意外的声明", + "diagnostic.defaultvalmissing": "'{0}' 需要参数默认值", + "diagnostic.deprecated": "使用'{0}'而不是'{1}'", + "diagnostic.didyoumean": "你是想用'{0}'吗?", + "diagnostic.dupdeclaration": "重复声明", + "diagnostic.duplabel": "重复的标签声明", + "diagnostic.filenotexist": "'{0}'文件不存在", + "diagnostic.funccallerr": "函数调用需要空格或'(', 仅在参数之间使用逗号", + "diagnostic.funccallerr2": "在表达式中, 函数调用需要括号", + "diagnostic.hotdeferr": "热键/热字串不能在函数/类中定义", + "diagnostic.hotmissbrace": "热键或热字符串缺少左括号", + "diagnostic.invaliddefinition": "无效的{0}定义", + "diagnostic.invalidencoding": "'{0}' 无效的文件编码", + "diagnostic.invalidhotdef": "无效的热键定义", + "diagnostic.invalidparam": "无效的参数定义", + "diagnostic.invalidprop": "不是有效的getter/setter属性", + "diagnostic.invalidpropname": "对象字面量中的属性名无效", + "diagnostic.invalidsymbolname": "无效的符号命名 '{0}'", + "diagnostic.invalidscope": "'{0}'不能在函数/类中使用", + "diagnostic.invalidsuper": "'super'仅在类内部有效", + "diagnostic.maybehavenotmember": "类'{0}'可能没有成员'{1}'", + "diagnostic.maybev1": "这可能是一个v1脚本, lexer停止解析.", + "diagnostic.missing": "丢失对应的 '{0}'", + "diagnostic.missingparam": "缺少必需的参数", + "diagnostic.missingoperand": "缺少操作数", + "diagnostic.missingretval": "函数缺少返回值", + "diagnostic.missingspace": "前面缺少空格或运算符", + "diagnostic.objectliteralerr": "对象字面量存在错误", + "diagnostic.outofloop": "Break/Continue必须被循环包围", + "diagnostic.paramcounterr": "应有 {0} 个参数, 但获得 {1} 个", + "diagnostic.pathinvalid": "无效的文件路径", + "diagnostic.propdeclaraerr": "不是有效的方法, 类或属性定义", + "diagnostic.propemptyparams": "动态属性不允许使用空[]", + "diagnostic.propnotinit": "属性声明未初始化", + "diagnostic.requirev1": "此脚本需要AutoHotkey v1, lexer停止解析.", + "diagnostic.requirevariable": "'&'需要一个变量", + "diagnostic.requireversion": "该特性需要AutoHotkey版本 >= v{0}", + "diagnostic.reservedworderr": "保留字'{0}'不得用作变量名", + "diagnostic.resourcenotfound": "未找到或无法解析资源", + "diagnostic.skipline": "该行被跳过且未解析", + "diagnostic.syntaxerror": "语法错误. 具体为: {0}", + "diagnostic.tryswitchtov1": "尝试切换到AutoHotkey v1.", + "diagnostic.typemaybenot": "类型可能不是 '{0}'", + "diagnostic.unexpected": "意外的'{0}'", + "diagnostic.unknown": "未知的{0}", + "diagnostic.unknownoperatoruse": "未知的操作符使用", + "diagnostic.unknowntoken": "未知的Token '{0}'", + "diagnostic.unsupportinclude": "函数、类中的#include无法正确地推导作用域和代码补全", + "diagnostic.unterminated": "未终止的字符串文本", + "warn.varisunset": "变量'{0}'似乎从未被赋值", + "warn.localsameasglobal": "局部变量'{0}'与全局变量具有相同的名称", + "warn.callwithoutparentheses": "函数或方法调用没有使用括号", + "response.cannotrename": "无法重命名此元素。", + "response.cannotrenamestdlib": "不能重命名标准AutoHotkey库中定义的元素。", + "setting.ahkpatherr": "AutoHotkey解释器不存在, 在'设置-AutoHotkey2.InterpreterPath'中重新指定", + "setting.getenverr": "获取环境变量失败", + "setting.uialimit": "由于安全限制, UIA可执行文件不允许重定向stdin/stdout, 因此依赖于此的一些功能将无法工作", + "setting.versionerr": "当前AutoHotkey.exe不是v2版本, 无法获得正确的语法解析、补全等功能" +} \ No newline at end of file diff --git a/readme.md b/readme.md index 6e4d1702..1a13cc0b 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,361 @@ +**English** | [中文](./README.zh-CN.md) + # AutoHotkey v2 Language Support -This codebase is not meant for independent use, but rather as a submodule of [AHK++](https://github.com/mark-wiemer-org/ahkpp). +[![installs](https://img.shields.io/visual-studio-marketplace/i/thqby.vscode-autohotkey2-lsp?label=Extension%20Install&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) +[![version](https://img.shields.io/visual-studio-marketplace/v/thqby.vscode-autohotkey2-lsp?label=Extension%20Version&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) +[![](https://img.shields.io/badge/Compatibility-autohotkey%20v2.0+-green?style=for-the-badge&logo=autohotkey)](https://www.autohotkey.com/) + +**Repositories**: [Github](https://github.com/thqby/vscode-autohotkey2-lsp) | [Gitee](https://gitee.com/orz707/vscode-autohotkey2-lsp) + +AutoHotkey v2 Language support for VS Code, features realization based on v2 syntax analysis. +Supports running on the Web, such as `Chrome/Edge`. https://vscode.dev or https://github.dev/github/dev + +- [AutoHotkey v2 Language Support](#autohotkey-v2-language-support) + - [Language Features](#language-features) + - [Rename Symbol](#rename-symbol) + - [Diagnostics](#diagnostics) + - [IntelliSense](#intellisense) + - [Signature](#signature) + - [Document Symbol](#document-symbol) + - [Semantic Highlight](#semantic-highlight) + - [Tags](#tags) + - [Document Color](#document-color) + - [Hover](#hover) + - [Goto Definition](#goto-definition) + - [Find All References](#find-all-references) + - [CodeFormat](#codeformat) + - [Custom folding](#custom-folding) + - [Declaration document](#declaration-document) + - [Context Menu](#context-menu) + - [Quick Help](#quick-help) + - [Run Script](#run-script) + - [Run Selected Script](#run-selected-script) + - [Compile Script](#compile-script) + - [Debug Script](#debug-script) + - [Generate Comment](#generate-comment) + - [Use in other editors](#use-in-other-editors) + - [Sublime Text4](#sublime-text4) + - [Vim and Neovim](#vim-and-neovim) + - [Emacs](#Emacs) + - [Use in Web Browser](#use-in-web-browser) + +## Language Features + +### Rename Symbol + +Rename variables and function names in the scope in batches. + +![rename](./pic/rename.gif) + +### Diagnostics + +Simple syntax error diagnosis. + +![diagnostics](./pic/diagnostics2.png) + +### IntelliSense + +Supports intelligent completion of variables, functions, parameters, class names, and method names within the scope (by simple type deduction), and supports the completion of include files and function libraries. + +![snippet1](./pic/snippet.png) + +![snippet2](./pic/snippet.gif) + +### Signature + +Support for intelligent prompts for function parameters. + +![signature](./pic/signature.gif) + +### Document Symbol + +1. Displays class, method, function, variable, label, hotkey, hot string, block information in the left outline column. +2. press Ctrl + P, Input @symbol_name to retrieve and jump +3. You can comment a method with a semicolon or /\* \*/ on the top line of a function, variable. Jsdoc-style annotations can mark variable types. + + + +```js +/** + * @param {Array} a - a param + * @return {Integer} + */ +fn(a*) { + /** @type {Map} */ + d := Map() + /** + * @var {Map} e + * @var {Object} f + */ + e := Map(), f := {} + /** @type {(a,b)=>Integer} */ + cb := (a, b) => a + b + /** @type {ComObject} */ + wb := ComObject('Excel.Sheet.12') + return a[1] + a[2] +} +class abc { + /** @type {Map} */ + p := dosomethingandreturnmap() +} +``` + +### Semantic Highlight + +Semantic highlighting is an addition to syntax highlighting, resolves symbols in the context of a project. The editor applies the highlighting from semantic tokens on top of the highlighting from grammars. + +![semanticTokens](./pic/semanticTokens.png) + +### Tags + +usage: Add `;;`(default) or `; TODO ` to the comment code Tags. + +![codeSymbole](./pic/codeSymbol.png) + +### Document Color + +Compute and resolve colors inside a document to provide color picker in editor. + +![documentcolor](./pic/documentcolor.png) + +### Hover + +Supports hover prompts and comments for scoped variables, functions, global classes, and labels. +usage: Move the mouse over the symbol. + +![hover](./pic/hover.png) + +### Goto Definition + +1. Support for jumping to the declaration location of scoped variables, functions, global classes, and labels. +2. usage: Press ctrl Then move the mouse over to the code and click. + +![gotoDefinition](./pic/gotoDefinition.png) + +### Find All References + +See all the source code locations where a certain variable/function is being used. + +### CodeFormat + +usage: + +- Right-click the popup menu and click "Format document". +- Press `Shift+Alt+F`. +- Supports formatting code blocks when typing '}', formatting lines and indenting lines when typing '\n'. (`editor.formatOnType` needs to be enabled) +- Supports the use of formatting instructions `;@format array_style: collapse, object_style: expand` to change the object style of different blocks + +![codeFormat](./pic/codeFormat.gif) + +### Custom folding + +Fold the part between `;@region tag` and `;@endregion`, `;{` and `;}` + +```ini +;#region tag +code +;#endregion +``` + +### Declaration document + +The declaration file is a file with the suffix of `.d.ahk` as the file name, which is used to describe the implemented functions or classes, etc., does not contain the implementation part of the code, and is referenced by the ahk file with the same name by default, and the syntax refers to `ahk2.d.ahk` provided by the extension. The declaration file can extend or rewrite the declaration of ahk built-in functions or classes, and the annotation document can be separated from the source code to provide a multilingual version of intellisense. + +``` +; array.d.ahk +; #ClsName represents the ahk built-in class +/** @extends {#Array} */ +class Array { + /** jsdoc-default */ + Filter(FilterFunc) => Array +} + +; array.zh-cn.d.ahk +; #ClsName 表示ahk内置类 +/** @extends {#Array} */ +class Array { + /** jsdoc-zh */ + Filter(FilterFunc) => Array +} + +; array.ahk +; %A_Locale% is VSCode's Display Language +;@reference array.%A_Locale%.d.ahk +Array.Prototype.DefineProp('Filter', { call: Array_Filter_impl }) +``` + +## Context Menu + +### Quick Help + +Open the help file and navigate to the keyword at the current cursor. + +### Run Script + +Run the currently open script. + +### Run Selected Script + +Run the code snippet at the cursor selection. + +### Compile Script + +Compile the script to generate executable EXE files. + +### Debug Script + +No additional configuration is required to start the installed Debug extensions, and support debugging with parameters. + +### Generate Comment + +Generate JSDOC-style comments for a function or method. + +## Use in other editors + +1. Install [Node.js](https://nodejs.org/en/download/). +2. Download vscode-autohotkey2-lsp server using command line, or download and unpack through [vscode marketplace](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp). + +```shell +mkdir vscode-autohotkey2-lsp +cd vscode-autohotkey2-lsp +curl.exe -L -o install.js https://raw.githubusercontent.com/thqby/vscode-autohotkey2-lsp/main/tools/install.js +node install.js +``` + +3. Set the LSP configuration of the editor that support [LSP(Language Server Protocol)](https://microsoft.github.io/language-server-protocol/), such as Sublime Text4, Vim, Neovim, Emacs, [etc](https://microsoft.github.io/language-server-protocol/implementors/tools/). + +### Sublime Text4 + +- `Package Control: Install Package`, and install [Sublime LSP](https://github.com/sublimelsp/LSP) plug-in. +- `Preferences: LSP Settings`, add lsp configuration, language selector, and syntax highlighting. This is a simple example [syntax highlighting](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), save the file in a similar path `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax`. + +```json +{ + "clients": { + "lsp-ahk2": { + "enabled": true, + "command": [ + "node", + "/server/dist/server.js", + "--stdio" + ], // Update the path of node.exe(maybe it's already in PATH, so you don't need to set it) and the folder of vscode-autohotkey2-lsp + "selector": "source.ahk2", // Same as scope in AutoHotkey2.sublime-syntax + "schemes": ["file", "buffer", "res"], + "initializationOptions": { + "locale": "en-us", // or "zh-cn" + "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" + "CommentTags": "^;;\\s*(?.+)", + "CompleteFunctionParens": false, + "Diagnostics": { + "ClassStaticMemberCheck": true, + "ParamsCheck": true + }, + "ActionWhenV1IsDetected": "Continue", + "FormatOptions": { + "array_style": "none", // or "collapse" or "expand" + "break_chained_methods": false, + "ignore_comment": false, + "indent_string": "\t", + "max_preserve_newlines": 2, + "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" + "object_style": "none", // or "collapse" or "expand" + "preserve_newlines": true, + "space_after_double_colon": true, + "space_before_conditional": true, + "space_in_empty_paren": false, + "space_in_other": true, + "space_in_paren": false, + "wrap_line_length": 0 + }, + "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + "WorkingDirs": [], + "SymbolFoldingFromOpenBrace": false + } + } + }, + "semantic_highlighting": true +} +``` + +### Vim and Neovim + +#### COC +- Download [coc.nvim plugin](https://github.com/neoclide/coc.nvim). + +```bat +cd $VIMRUNTIME\plugin +git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 +``` + +- Open (n)vim and enter the command `:CocConfig` to enter the `coc.nvim` configuration file to add configuration information. + +```json +{ + "languageserver": { + "lsp-ahk2": { + "module": "/server/dist/server.js", + "filetypes": ["autohotkey"], + "args": ["--node-ipc"], + "initializationOptions": { + // Same as initializationOptions for Sublime Text4 + } + } + } +} +``` + +#### nvim-lspconfig +- Download [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). +- Add the following to your NVIM configuration (init.lua e.g.). Ensure that `cmd` points to the path of your vscode-autohotkey2-lsp installation and `InterpreterPath` points to your AHK exe. + +```lua +local function custom_attach(client, bufnr) + require("lsp_signature").on_attach({ + bind = true, + use_lspsaga = false, + floating_window = true, + fix_pos = true, + hint_enable = true, + hi_parameter = "Search", + handler_opts = { "double" }, + }) +end + +local ahk2_configs = { + autostart = true, + cmd = { + "node", + vim.fn.expand("$HOME/vscode-autohotkey2-lsp/server/dist/server.js"), + "--stdio" + }, + filetypes = { "ahk", "autohotkey", "ah2" }, + init_options = { + locale = "en-us", + InterpreterPath = "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + -- Same as initializationOptions for Sublime Text4, convert json literal to lua dictionary literal + }, + single_file_support = true, + flags = { debounce_text_changes = 500 }, + capabilities = capabilities, + on_attach = custom_attach, +} +local configs = require "lspconfig.configs" +configs["ahk2"] = { default_config = ahk2_configs } +local nvim_lsp = require("lspconfig") +nvim_lsp.ahk2.setup({}) +``` + +### Emacs + +#### Eglot +- Add the following lines to your emacs config file + +``` emacs-lisp +(add-to-list 'eglot-server-programs '(ahk-mode "node" "/server/dist/server.js" "--stdio")) + +``` + +## Use in Web Browser -It provides AHK v2 language support via the [Language Server Protocol](https://microsoft.github.io/language-server-protocol). +visit https://github.dev or https://vscode.dev in `Chrome/Edge`, and install `thqby.vscode-autohotkey2-lsp` diff --git a/server/cli/cli.ts b/server/cli/cli.ts index 414a6d42..71a29d2a 100644 --- a/server/cli/cli.ts +++ b/server/cli/cli.ts @@ -3,7 +3,7 @@ import { newFormatterConfig } from '../src/config'; import { Lexer } from '../src/Lexer'; function main() { - const options: { [k: string]: string } = {}; + const options: Record = {}; process.argv.slice(2).forEach((s) => { const arr = s.split('='); options[arr[0]] = arr[1]; diff --git a/server/src/Lexer.ts b/server/src/Lexer.ts index cd0c9327..c0d1b59a 100644 --- a/server/src/Lexer.ts +++ b/server/src/Lexer.ts @@ -22,7 +22,7 @@ import { builtin_ahkv1_commands, builtin_variable, builtin_variable_h } from './ import { action, completionitem, diagnostic, warn } from './localize'; import { a_vars, ahk_version, ahkuris, ahkvars, alpha_3, connection, ahkppConfig, - hoverCache, isBrowser, isahk2_h, lexers, libdirs, libfuncs, openAndParse, openFile, + hoverCache, isBrowser, isahk2_h, lexers, libdirs, libfuncs, locale, openAndParse, openFile, restorePath, rootdir, setTextDocumentLanguage, symbolProvider, utils, workspaceFolders } from './common'; import { newFormatterConfig, FormatterConfig, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses, getCfg, CfgKey } from './config'; @@ -79,6 +79,7 @@ export interface AhkSymbol extends DocumentSymbol { data?: unknown def?: boolean full?: string + has_warned?: boolean | number markdown_detail?: string ignore?: boolean overwrite?: number @@ -96,17 +97,17 @@ export interface FuncNode extends AhkSymbol { params: Variable[] param_offsets: number[] param_def_len: number - global: { [name: string]: Variable } - local: { [name: string]: Variable } + global: Record + local: Record full: string hasref: boolean variadic: boolean - labels: { [name: string]: AhkSymbol[] } - declaration: { [name: string]: AhkSymbol } + labels: Record + declaration: Record overloads?: string | FuncNode[] - overload_params?: { [name: string]: Variable } + overload_params?: Record has_this_param?: boolean - unresolved_vars?: { [name: string]: Variable } + unresolved_vars?: Record ranges?: [number, number][] // class's __init } @@ -117,14 +118,14 @@ export interface ClassNode extends AhkSymbol { extendsuri?: string parent?: AhkSymbol prototype?: ClassNode - property: { [name: string]: FuncNode | ClassNode | Variable } - $property?: { [name: string]: FuncNode | ClassNode | Variable } // aliases for prototype.property + property: Record + $property?: Record // aliases for prototype.property cache?: Variable[] - undefined?: { [name: string]: Token[] } + undefined?: Record checkmember?: boolean static?: boolean // not use generic_types?: (string | AhkSymbol)[][] - type_params?: { [name: string]: AhkSymbol } + type_params?: Record } export interface Variable extends AhkSymbol { @@ -142,8 +143,8 @@ export interface Variable extends AhkSymbol { } export interface Property extends Variable { - local?: { [name: string]: AhkSymbol } - declaration?: { [name: string]: AhkSymbol } + local?: Record + declaration?: Record has_this_param?: boolean params?: Variable[] param_offsets?: number[] @@ -164,6 +165,7 @@ export interface Token { data?: unknown definition?: AhkSymbol fat_arrow_end?: boolean + has_warned?: boolean | number hover_word?: string ignore?: boolean in_expr?: number @@ -263,7 +265,7 @@ const whitespace = " \t\r\n", punct = '+ - * / % & ++ -- ** // = += -= *= /= //= const line_starters = 'try,throw,return,global,local,static,if,switch,case,for,while,loop,continue,break,goto'.split(','); const reserved_words = line_starters.concat(['class', 'in', 'is', 'isset', 'contains', 'else', 'until', 'catch', 'finally', 'and', 'or', 'not', 'as', 'super']); const MODE = { BlockStatement: 'BlockStatement', Statement: 'Statement', ObjectLiteral: 'ObjectLiteral', ArrayLiteral: 'ArrayLiteral', Conditional: 'Conditional', Expression: 'Expression' }; -const KEYS_RE = /^(alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab|shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton1|xbutton2|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\d]{1,2}(sc[a-f\d]+)?|sc[a-f\d]+|`[;{]|[\x21-\x7E])$/i; +const KEYS_RE = /^(alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab|shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton1|xbutton2|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\d]{1,2}(sc[a-f\d]+)?|sc[a-f\d]+|`[;{]|[\x21-\x7E])$/i; const EMPTY_TOKEN: Token = { type: '', content: '', offset: 0, length: 0, topofline: 0, next_token_offset: -1 }; export const ASSIGN_TYPE = [':=', '??=']; const STYLE = { collapse: 2, expand: 1, none: 0 }; @@ -294,11 +296,7 @@ export const SUPER: Variable = { ...THIS, name: 'super', detail: completionitem. export const allIdentifierChar = new RegExp('^[^\x00-\x2f\x3a-\x40\x5b-\x5e\x60\x7b-\x7f]+$'); let commentTagRegex = new RegExp('^;;\\s*(?.+)'); -const ahkprotos = { - ANY, OBJECT, STRING, NUMBER, INTEGER, FLOAT, - CLASS: ANY, FUNC: ANY, REGEXMATCHINFO: ANY -}; -const S2O: { [n: string]: AhkSymbol } = { +const S2O: Record = { $DIRPATH, $DLLFUNC, $FILEPATH, @@ -330,9 +328,8 @@ export class Lexer { public children: AhkSymbol[] = []; public d = 0; public d_uri = ''; - public declaration: { [name: string]: AhkSymbol } = {}; + public declaration: Record = {}; public diagnostics: Diagnostic[] = []; - public diags = 0; public last_diags = 0; public dlldir = new Map(); public dllpaths: string[] = []; @@ -342,32 +339,32 @@ export class Lexer { public fsPath = ''; public get_token: (offset?: number, ignorecomment?: boolean) => Token; public need_scriptdir = false; - public include: { [uri: string]: string } = {}; + public include: Record = {}; public includedir = new Map(); public isparsed = false; public is_virtual = false; // uris like `vscode-local-history:` - public labels: { [name: string]: AhkSymbol[] } = {}; + public labels: Record = {}; public libdirs: string[] = []; - public linepos: { [line: number]: number } = {}; + public linepos: Record = {}; public maybev1?: number; - public object: { method: { [name: string]: FuncNode[] }, property: { [name: string]: Variable[] } } = { method: {}, property: {} }; + public object: { method: Record, property: Record } = { method: {}, property: {} }; public parseScript: () => void; public scriptdir = ''; public scriptpath = ''; public STB = new SemanticTokensBuilder; public symbolInformation: SymbolInformation[] | undefined; - public texts: { [text: string]: string } = {}; - public typedef: { [name: string]: AhkSymbol } = {}; + public texts: Record = {}; + public typedef: Record = {}; public tokenranges: { start: number, end: number, type: number, previous?: number }[] = []; - public tokens: { [offset: number]: Token } = {}; + public tokens: Record = {}; public uri = ''; public workspaceFolder = ''; private hotstringExecuteAction = false; constructor(document: TextDocument, scriptdir?: string, d = 0) { - let begin_line: boolean, callWithoutParentheses: CallWithoutParentheses, comments: { [line: number]: Token }; + let begin_line: boolean, callWithoutParentheses: CallWithoutParentheses, comments: Record; let continuation_sections_mode: boolean | null, currsymbol: AhkSymbol | undefined; let customblocks: { region: number[], bracket: number[] }; - let dlldir: string, includedir: string, includetable: { [uri: string]: string }; + let dlldir: string, includedir: string, includetable: Record; let input: string, input_length: number, input_wanted_newline: boolean; let last_comment_fr: FoldingRange | undefined, last_LF: number, lst: Token; let n_newlines: number, parser_pos: number, sharp_offsets: number[]; @@ -403,10 +400,10 @@ export class Lexer { try_block: boolean }; let output_lines: { text: string[], indent: number }[], flags: Flag, previous_flags: Flag, flag_store: Flag[]; - let opt: FormatterConfig, preindentString: string, indentString: string, spaceInOther: boolean, ck: Token; + let opt: FormatterConfig, preindentString: string, indentString: string, space_in_other: boolean, ck: Token; let token_text: string, token_text_low: string, token_type: string, last_type: string, last_text: string; let output_space_before_token: boolean | undefined, is_conditional: boolean; - const handlers: { [index: string]: () => void } = { + const handlers: Record void> = { 'TK_START_EXPR': handle_start_expr, 'TK_END_EXPR': handle_end_expr, 'TK_START_BLOCK': handle_start_block, @@ -505,7 +502,7 @@ export class Lexer { last_LF = -1, end_pos = input_length, ck = _this.get_token(0); preindentString = input.substring(input.lastIndexOf('\n', parser_pos = ck.offset) + 1, parser_pos); is_conditional = output_space_before_token = false, format_mode = true; - indentString = opt.indentString ?? '\t', spaceInOther = opt.spaceInOther ?? true; + indentString = opt.indentString ?? '\t', space_in_other = opt.spaceInOther ?? true; output_lines = [create_output_line()]; flag_store = [], flags = undefined as unknown as Flag; set_mode(MODE.BlockStatement); @@ -628,9 +625,9 @@ export class Lexer { } }; - function format_params_default_val(tokens: { [offset: number]: Token }, params: ParamList) { + function format_params_default_val(tokens: Record, params: ParamList) { opt = newFormatterConfig({ maxPreserveNewlines: 1 }); - spaceInOther = true, indentString = '\t'; + space_in_other = true, indentString = '\t'; format_mode = true, preindentString = ''; delete params.format; for (const param of params) { @@ -650,7 +647,7 @@ export class Lexer { format_mode = false, output_lines = []; } - if (d || document.uri.match(/\.d\.(ahk2?|ah2)(?=(\?|$))/i)) { + if (d || /\.d\.(ahk2?|ah2)$/i.test(this.fsPath)) { this.d = d || 1, allow_$ ||= true; this.parseScript = function (): void { const p: ClassNode[] = [], cls: string[] = [], uri = this.uri @@ -882,13 +879,10 @@ export class Lexer { } else if ((s = this.declaration.STRUCT)?.kind === SymbolKind.Class) s.def = false; } - for (const k in ahkprotos) - if ((s = (ahkvars[k] as ClassNode)?.prototype)) - ahkprotos[k as keyof typeof ahkprotos] = s; } parse_unresolved_typedef(); check_same_name_error({}, this.children, this.diagnostics); - this.diags = this.diagnostics.length, this.isparsed = true; + this.isparsed = true; customblocks.region.forEach(o => this.addFoldingRange(o, parser_pos - 1, 'region')); function parse_types(sym: AhkSymbol) { @@ -947,7 +941,7 @@ export class Lexer { break; case 'TK_START_BLOCK': { let full = ''; - const props: { [name: string]: AhkSymbol } = {}, b = lk; + const props: Record = {}, b = lk; const prop_types = ['TK_NUMBER', 'TK_RESERVED', 'TK_WORD']; while (prop_types.includes((lk = skip_comment())?.type)) { const p = Variable.create(lk.content, SymbolKind.Property, make_range(lk.offset, lk.length)); @@ -1017,6 +1011,18 @@ export class Lexer { let defVal = 0, full = '', star_offset = 0; loop: while ((lk = tokens[++j]) && lk.content !== endc) { switch (lk.type) { + case 'TK_STRING': + if (next_is_param !== true) { + skip(endc); + break; + } + vr = Variable.create(lk.content, SymbolKind.String, make_range(lk.offset, lk.length)); + offset.push(full.length), full += lk.content; + params.push(vr), next_is_param = false; + if ((lk = tokens[++j])?.content === '[') + defVal++, lk.ignore = true, full += ' ['; + else j--; + break; case 'TK_WORD': if (!next_is_param) { skip(endc); @@ -1129,14 +1135,7 @@ export class Lexer { } } } else { - this.fsPath.replace(/^(.*)\.(ahk2?|ah2)$/i, (m, m0) => { - const path = m0 + '.d.ahk', uri = this.d_uri = URI.file(path).toString().toLowerCase(); - if (!isBrowser && !lexers[this.d_uri]) { - const t = openFile(restorePath(path), false); - t && (lexers[uri] = new Lexer(t, undefined, 1)).parseScript(); - } - return ''; - }); + const d_path = this.fsPath.replace(/\.\w+$/, '.d.ahk'); this.parseScript = function (): void { input = this.document.getText(), input_length = input.length, includedir = this.scriptpath, dlldir = ''; begin_line = true, requirev2 = false, maybev1 = 0, lst = { ...EMPTY_TOKEN }, currsymbol = last_comment_fr = undefined; @@ -1154,9 +1153,15 @@ export class Lexer { } else console.error(e); } + if (!isBrowser) { + const m = _this.d_uri && find_d_ahk(resolve_scriptdir(_this.d_uri)) || find_d_ahk(d_path); + if (m) + includetable[_this.d_uri = m.uri] = m.path; + else _this.d_uri = ''; + } parse_unresolved_typedef(); check_same_name_error(this.declaration, this.children, this.diagnostics); - this.diags = this.diagnostics.length, this.isparsed = true; + this.isparsed = true; customblocks.region.forEach(o => this.addFoldingRange(o, parser_pos - 1, 'region')); if (this.actived) this.actionWhenV1Detected ??= 'Continue'; @@ -1215,7 +1220,7 @@ export class Lexer { case 'SwitchToV1': if (!_this.actived) break; - connection.console.info([_this.document.uri, message, diagnostic.tryswitchtov1()].join(' ')); + connection?.console.info([_this.document.uri, message, diagnostic.tryswitchtov1()].join(' ')); message = '', setTextDocumentLanguage(_this.document.uri); break; case 'Continue': @@ -1223,7 +1228,7 @@ export class Lexer { case 'Warn': { if (!_this.actived) break; - connection.window.showWarningMessage( + connection?.window.showWarningMessage( `file: '${_this.fsPath}', ${message}`, { title: action.switchtov1(), action: 'SwitchToV1' }, { title: action.skipline(), action: 'SkipLine' }, @@ -2275,14 +2280,19 @@ export class Lexer { maybe && v && (v.returns = null); while (nexttoken()) { if (tk.type as string === 'TK_WORD') { + let maybecaller = true; if (input.charAt(parser_pos) === '%') { - // + maybecaller = false; } else if (addprop(tk), nexttoken(), ASSIGN_TYPE.includes(tk.content)) - maybeclassprop(lk); + maybecaller = false, maybeclassprop(lk, undefined, () => { + const beg = parser_pos; + result.push(...parse_expression()); + return [beg, lk.offset + lk.length]; + }); else if (tk.ignore && tk.content === '?' && (tk = get_next_token()), tk.type === 'TK_DOT') continue; next = false; - if (tk.type as string !== 'TK_EQUALS' && !'=??'.includes(tk.content || ' ') && + if (maybecaller && tk.type as string !== 'TK_EQUALS' && !'=??'.includes(tk.content || ' ') && ', \t\r\n'.includes(c = input.charAt(lk.offset + lk.length))) parse_funccall(SymbolKind.Method, c); else @@ -2460,7 +2470,7 @@ export class Lexer { case '#dllimport': if ((m = data.content.match(/^((\w|[^\x00-\x7f])+)/i))) { const rg = make_range(data.offset, m[0].length), rg2 = Range.create(0, 0, 0, 0); - const tps: { [t: string]: string } = { t: 'ptr', i: 'int', s: 'str', a: 'astr', w: 'wstr', h: 'short', c: 'char', f: 'float', d: 'double', I: 'int64' }; + const tps: Record = { t: 'ptr', i: 'int', s: 'str', a: 'astr', w: 'wstr', h: 'short', c: 'char', f: 'float', d: 'double', I: 'int64' }; const n = m[0], args: Variable[] = []; let arg: Variable | undefined, u = '', i = 0, rt = 'i'; h = true, m = data.content.substring(m[0].length).match(/^[ \t]*,[^,]+,([^,]*)/); @@ -2565,6 +2575,8 @@ export class Lexer { if (!dots && assign && _parent.static && llk.content.toLowerCase() === 'prototype') { const prop = Variable.create(p.content, SymbolKind.Property, make_range(p.offset, p.length)); const cls = (_parent.parent as ClassNode).prototype!; + if ((_cm = comments[prop.selectionRange.start.line])) + set_detail(prop, _cm); prop.parent = cls, prop.returns = t; cls.cache!.push(prop); } @@ -2808,10 +2820,14 @@ export class Lexer { } else next = false, lk.ignore = true; } else { + addprop(lk); if ((next = tk.type as string === 'TK_EQUALS')) if (ASSIGN_TYPE.includes(tk.content)) - maybeclassprop(lk); - addprop(lk); + maybeclassprop(lk, undefined, () => { + const beg = parser_pos; + result.push(...parse_expression(inpair, mustexp, end ?? (ternarys.length ? ':' : undefined))); + return [beg, lk.offset + lk.length]; + }); } break; } @@ -3194,7 +3210,7 @@ export class Lexer { } function parse_obj(must = false): boolean { - const l = lk, b = tk, rl = result.length, mark: number[] = [], props: { [k: string]: AhkSymbol } = {}; + const l = lk, b = tk, rl = result.length, mark: number[] = [], props: Record = {}; let isobj = true, k: Token | undefined, e: Token | undefined; block_mode = false, next = true, tk.data = OBJECT; while (isobj) { @@ -3513,7 +3529,12 @@ export class Lexer { } else { addprop(tk), nexttoken(), next = false; if (tk.type as string === 'TK_EQUALS') - maybeclassprop(lk); + if (ASSIGN_TYPE.includes(tk.content)) + maybeclassprop(lk, undefined, () => { + const beg = parser_pos; + result.push(...parse_expression(e, 2, ternarys.length ? ':' : undefined)); + return [beg, lk.offset + lk.length]; + }); } break; case 'TK_START_BLOCK': @@ -3661,7 +3682,7 @@ export class Lexer { } } - function maybeclassprop(tk: Token, flag: boolean | null = false) { + function maybeclassprop(tk: Token, flag: boolean | null = false, parse_expr?: () => number[]) { if (classfullname === '') return; let rg: Range, cls: ClassNode | undefined; @@ -3686,13 +3707,13 @@ export class Lexer { cls.checkmember = false; else { const o = tokens[tokens[end].next_token_offset], prop = nk.content.slice(1, -1); - let t: Property | FuncNode, pp; + let t: Property | FuncNode, pp, sym; rg = make_range(nk.offset + 1, prop.length); if (o.type !== 'TK_START_BLOCK' || !(pp = (o.data as ClassNode)?.property) || pp.GET || pp.VALUE || pp.SET) { t = Variable.create(prop, SymbolKind.Property, rg); t.full = `(${classfullname.slice(0, -1)}) ${((t.static = s)) ? 'static ' : ''}${prop}`; - cls.cache.push(t), t.parent = cls; + t.parent = cls, sym = t; if ((t.returns = pp?.GET?.returns)) (t as FuncNode).alias = true; else t.returns = pp?.VALUE?.returns; @@ -3700,10 +3721,19 @@ export class Lexer { if ((pp = pp?.CALL)) { t = Variable.create('', SymbolKind.Variable, make_range(0, 0)), t.arr = true; t = FuncNode.create(prop, SymbolKind.Method, rg, rg, [t], undefined, s); - t.full = `(${classfullname.slice(0, -1)}) ` + t.full; + t.full = `(${classfullname.slice(0, -1)}) ${t.full}`; t.returns = pp.returns, (t as FuncNode).alias = true; - cls.cache.push(t), t.parent = cls; + t.parent = cls; + if (!sym) + sym = t; + else { + sym = { ...sym, [(sym as FuncNode).alias ? 'get' : sym.returns ? 'val' : 'set']: sym }; + if (!sym.val) + sym.call = t as FuncNode; + else sym = t; + } } + sym && cls.cache.push(sym); } } } else { @@ -3711,14 +3741,23 @@ export class Lexer { return cls.checkmember = false, undefined; const t = Variable.create(tk.content, SymbolKind.Property, rg = make_range(tk.offset, tk.length)); t.static = !!cls.prototype, cls.cache.push(t), t.def = false, t.parent = cls; + t.returns = parse_expr?.(); + if ((_cm = comments[t.selectionRange.start.line])) + set_detail(t, _cm); } return; function get_class() { - let p = _parent; - while (p && p.kind !== SymbolKind.Class) + const kinds: SymbolKind[] = [SymbolKind.Method, SymbolKind.Property]; + let p = _parent, s = true; + while (p && p.kind !== SymbolKind.Class) { + if (kinds.includes(p.kind)) + s = !!p.static; p = p.parent!; - return p as ClassNode; + } + if (s) + return p as ClassNode; + return (p as ClassNode)?.prototype; } } @@ -3765,10 +3804,11 @@ export class Lexer { function adddeclaration(node: FuncNode | ClassNode) { const _diags = _this.diagnostics, severity = DiagnosticSeverity.Error; - let t: Variable, lpv = false, pars: { [name: string]: Variable } = {}; + let t: Variable, lpv = false, pars: Record = {}; if (node.kind === SymbolKind.Class) { const cls = node as ClassNode, dec = cls.$property!, sdec = cls.property ??= {}, children = cls.children ??= []; const __init = [sdec.__INIT], prototype = cls.prototype!; + prototype.checkmember ??= cls.checkmember; adddeclaration(sdec.__INIT as FuncNode); if ((dec.__INIT as FuncNode)?.ranges?.length) adddeclaration(dec.__INIT as FuncNode), __init.push(dec.__INIT); @@ -3824,7 +3864,7 @@ export class Lexer { delete cls.prototype!.cache; } else { const fn = node as FuncNode, dec = fn.declaration, has_this_param = fn.has_this_param; - let vars: { [k: string]: Variable } = {}, unresolved_vars: { [k: string]: Variable } = {}, vr: Variable; + let vars: Record = {}, unresolved_vars: Record = {}, vr: Variable; let named_params: Variable[] | undefined = []; if (has_this_param) { pars.THIS = dec.THIS = THIS; @@ -3985,7 +4025,7 @@ export class Lexer { } function set_extends(tn: ClassNode, str: string) { - tn.extends = str.trim().replace(/^(.+[\\/])?/, m => { + tn.extends = (str = str.trim()).replace(/^(.+[\\/])?/, m => { if ((m = m.slice(0, -1))) { let u: URI; m = m.replace(/\\/g, '/').toLowerCase(); @@ -4010,17 +4050,23 @@ export class Lexer { } return ''; }); + if (!tn.extendsuri && tn.extends.startsWith('#')) + tn.extendsuri = ahkvars[(tn.extends = tn.extends.substring(1)).toUpperCase()]?.uri ?? ahkuris.ahk2; + } + + function resolve_scriptdir(path: string) { + return path.replace(/%(a_scriptdir|a_workingdir)%/i, () => (_this.need_scriptdir = true, _this.scriptdir)) + .replace(/%a_linefile%/i, _this.fsPath); } function add_include_dllload(text: string, tk?: Pick, mode = 0, isdll = false) { - let m, raw: string, ignore = false; + let m, ignore = false; const q = text[0]; if (`'"`.includes(q) && text.endsWith(q)) text = text.slice(1, -1); if ((m = text.match(/^(\*[iI][ \t])?(.*)$/))) { - raw = m[2], ignore = Boolean(m[1]); - m = raw.replace(/%(a_scriptdir|a_workingdir)%/i, () => (_this.need_scriptdir = true, _this.scriptdir)) - .replace(/%a_linefile%/i, _this.fsPath); + ignore = Boolean(m[1]); + m = resolve_scriptdir(m[2]); if (tk) _this[isdll ? 'dlldir' : 'includedir'].set( (tk.pos ??= _this.document.positionAt(tk.offset)).line, isdll ? dlldir : includedir); @@ -4059,7 +4105,7 @@ export class Lexer { else includetable[m.uri] = m.path, tk.data = [m.path, m.uri]; if (mode !== 0) _this.addDiagnostic(diagnostic.unsupportinclude(), tk.offset, tk.length, DiagnosticSeverity.Warning); - } else if ((m = find_include_path(m.replace(/(\.d)?>$/i, '.d>'), _this.libdirs, _this.scriptpath)) && existsSync(m.path) && !statSync(m.path).isDirectory()) + } else if ((m = find_d_ahk(m))) includetable[m.uri] = m.path; _this.need_scriptdir ||= islib && (!m || m.path.toLowerCase().startsWith(_this.libdirs[0].toLowerCase())); } @@ -4068,6 +4114,17 @@ export class Lexer { _this.addDiagnostic(diagnostic.pathinvalid(), tk.offset, tk.length); } + function find_d_ahk(path: string) { + if (path.startsWith('<')) + path = path.replace(/(\.d)?>$/i, '.d>'); + else path = path.replace(/(\.d\.ahk)?$/i, '.d.ahk'); + const m = find_include_path(path, + _this.libdirs, _this.scriptpath, true, + { ...a_vars, locale }); + if (m && !statSync(m.path).isDirectory()) + return m; + } + function join_markdown(s1: string, s2: string) { if (s2) return (s1 && (s1 + '\n\n')) + s2; @@ -4125,10 +4182,10 @@ export class Lexer { type_str?: string } } | undefined, tp = '', t; - const fn = sym as FuncNode, objs: { [name: string]: ClassNode } = {}, params: { [name: string]: Variable } = {}; + const fn = sym as FuncNode, objs: Record = {}, params: Record = {}; let get_param = (_: string) => undefined as Variable | undefined; let m: RegExpMatchArray | null, vr: Variable | undefined, obj: ClassNode | undefined; - const kind = ({ [SymbolKind.Variable]: 'var', [SymbolKind.Property]: 'prop' } as { [k: number]: string })[sym.kind]; + const kind = ({ [SymbolKind.Variable]: 'var', [SymbolKind.Property]: 'prop' } as Record)[sym.kind]; if (fn.params) { const _params = fn.params; get_param = (name: string) => { @@ -4256,6 +4313,17 @@ export class Lexer { continue; case 'ignore': sym.ignore = true; break; case 'deprecated': sym.tags ??= [1]; break; + case 'alias': + if (sym.kind === SymbolKind.Class && (tp = line.trim()).endsWith('>') && tp.startsWith(sym.name + '<')) { + const lex = new Lexer(TextDocument.create('', 'ahk2', 0, `class ${tp}{\n}`), undefined, 1); + lex.parseScript(); + const params = (lex.declaration[sym.name.toUpperCase()] as ClassNode)?.type_params;; + if (params) { + (sym as ClassNode).type_params = params; + Object.values(params).forEach(it => it.range = it.selectionRange = ZERO_RANGE); + } + } + break; } details.push(`*@${t}*${join_detail(line)}`); } @@ -5070,16 +5138,29 @@ export class Lexer { if (line.startsWith(';')) { ln++; if ((t = line.match(/^;\s*@/))) { - let s = line.substring(t[0].length); - if ((s = s.toLowerCase()) === 'include-winapi') { - h && (t = lexers[ahkuris.winapi]) && Object.defineProperty(includetable, ahkuris.winapi, { value: t.fsPath, enumerable: false }); - } else if ((t = s.match(/^include\s+(.*)/i))) - add_include_dllload(t[1].replace(/\s+;.*$/, '').trim()); - else if ((t = s.match(/^lint-(enable|disable)\b\s*(\S*)/))) { - if (t[2] === 'class-non-dynamic-member-check') - if (t[1] === 'enable') - delete (currsymbol as ClassNode ?? _this).checkmember; - else (currsymbol as ClassNode ?? _this).checkmember = false; + if (ln > 1) break; + let s = line.substring(t[0].length).replace(/\s+;.*$/, '').toLowerCase(); + if ((t = s.match(/^([-.\w]+)(?=(\s|$))/))) { + switch (t[1]) { + case 'include': + (s = s.substring(t[1].length).trimStart()) && add_include_dllload(s); + break; + case 'include-winapi': + h && (t = lexers[ahkuris.winapi]) && Object.defineProperty( + includetable, ahkuris.winapi, { value: t.fsPath, enumerable: false }); + break; + case 'reference': + _this.d_uri ||= s.substring(t[1].length).trimStart(); + break; + case 'lint-disable': + case 'lint-enable': + s = s.substring(t[1].length).trimStart(); + if (s === 'class-non-dynamic-member-check') + if (t[1] === 'lint-enable') + delete (currsymbol as ClassNode ?? _this).checkmember; + else (currsymbol as ClassNode ?? _this).checkmember = false; + break; + } } ignore = true; } else if ((t = line.match(/^;+\s*([{}])/))) { @@ -5275,11 +5356,13 @@ export class Lexer { set_mode(next_mode); output_space_before_token = ck.previous_token?.content !== '('; print_token(); + flags.last_word = ''; return; } if (ck.topofline < 1 && yields_an_operand(ck.previous_token ?? EMPTY_TOKEN)) { set_mode(next_mode); print_token(); + flags.last_word = ''; flags.indentation_level = real_indentation_level() + 1; if (opt.spaceInParen) { output_space_before_token = true; @@ -5302,7 +5385,7 @@ export class Lexer { output_space_before_token = false; else if (['if', 'for', 'while', 'loop', 'case', 'catch', 'switch'].includes(last_text)) output_space_before_token = Boolean(opt.spaceBeforeConditional); - else output_space_before_token = spaceInOther; + else output_space_before_token = space_in_other; } if (!start_of_object_property()) { @@ -5313,6 +5396,7 @@ export class Lexer { } set_mode(next_mode); + flags.last_word = ''; flags.indentation_level = real_indentation_level(); print_token(); @@ -5366,21 +5450,25 @@ export class Lexer { if (previous_flags.mode !== MODE.Conditional) previous_flags.indentation_level = flags.indentation_level; - output_space_before_token ||= spaceInOther && last_type !== 'TK_START_EXPR'; + output_space_before_token ||= space_in_other && last_type !== 'TK_START_EXPR'; print_token(), indent(); if ((flags.objectStyle ?? opt.objectStyle) === STYLE.expand) print_newline(true); - else output_space_before_token = spaceInOther; + else output_space_before_token = space_in_other; } else { let level; - if (['try', 'if', 'for', 'while', 'loop', 'catch', 'else', 'finally', 'switch'].includes(flags.last_word)) + // fn := () {\n} + if (ck.in_expr) + level = real_indentation_level(); + else if (['try', 'if', 'for', 'while', 'loop', 'catch', 'else', 'finally', 'switch'].includes(flags.last_word)) level = real_indentation_level(); else while (flags.mode === MODE.Statement) restore_mode(); flags.declaration_statement = false; set_mode(MODE.BlockStatement); + flags.in_expression = false; flags.indentation_level = level ??= flags.indentation_level; - output_space_before_token ??= spaceInOther; + output_space_before_token ??= space_in_other; if (previous_flags.in_case_statement && last_type === 'TK_LABEL' && /^(default)?:$/.test(last_text)) flags.case_body = null, print_newline(), flags.indentation_level--; @@ -5395,8 +5483,9 @@ export class Lexer { indent(); if (need_newline || opt.braceStyle !== undefined) print_newline(true); - else output_space_before_token = spaceInOther; + else output_space_before_token = space_in_other; } + flags.last_word = ''; } function handle_end_block() { @@ -5411,7 +5500,7 @@ export class Lexer { trim_newlines(); else if (style || input_wanted_newline && opt.preserveNewlines) print_newline(true); - output_space_before_token = spaceInOther && last_text !== '{'; + output_space_before_token = space_in_other && last_text !== '{'; } else if (opt.braceStyle !== undefined || input_wanted_newline) print_newline(true); @@ -5422,7 +5511,7 @@ export class Lexer { indent(); if (opt.braceStyle !== undefined) print_newline(true); - output_space_before_token = spaceInOther; + output_space_before_token = space_in_other; } else if (flags.mode !== MODE.BlockStatement) flags.indentation_level = (flags.parent ?? flags).indentation_level + 1; } @@ -5536,7 +5625,7 @@ export class Lexer { trim_newlines(); if (flags.last_text !== '}' || opt.braceStyle !== BraceStyle.OneTrueBrace || input_wanted_newline && opt.preserveNewlines && !opt.braceStyle) print_newline(true); - else output_space_before_token = spaceInOther; + else output_space_before_token = space_in_other; } else if (input_wanted_newline) if (last_text === 'else' && !opt.preserveNewlines && ['if', 'for', 'loop', 'while', 'try', 'switch'].includes(token_text_low)) deindent(); @@ -5585,7 +5674,14 @@ export class Lexer { if (start_of_statement()) { if (input_wanted_newline && opt.preserveNewlines) print_newline(true); - else output_space_before_token = flags.declaration_statement ? last_type !== 'TK_OPERATOR' : spaceInOther; + else { + if (flags.declaration_statement) + output_space_before_token = last_type !== 'TK_OPERATOR'; + else { + const pk = ck.previous_token!; + output_space_before_token = pk.op_type !== -1 && !pk.next_pair_pos && space_in_other; + } + } } else if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD') { if (input_wanted_newline) print_newline(); @@ -5622,9 +5718,9 @@ export class Lexer { // The conditional starts the statement if appropriate. } - output_space_before_token = spaceInOther; + output_space_before_token = space_in_other; print_token(); - output_space_before_token = spaceInOther; + output_space_before_token = space_in_other; } function handle_comma() { @@ -5639,7 +5735,7 @@ export class Lexer { ck.previous_token?.callsite) input_wanted_newline && opt.preserveNewlines ? print_newline(true) : output_space_before_token = true; else { - output_space_before_token = spaceInOther && last_type === 'TK_COMMA' || last_text === 'for' && last_type === 'TK_RESERVED'; + output_space_before_token = space_in_other && last_type === 'TK_COMMA' || last_text === 'for' && last_type === 'TK_RESERVED'; if (flags.mode === MODE.Statement && flags.parent.mode === MODE.ObjectLiteral) restore_mode(); if (input_wanted_newline && opt.preserveNewlines) @@ -5653,11 +5749,11 @@ export class Lexer { print_token(); if (style === STYLE.expand) print_newline(true); - else output_space_before_token = spaceInOther; + else output_space_before_token = space_in_other; } function handle_operator() { - let space_before = Boolean(spaceInOther || token_text.match(/^\w/)); + let space_before = Boolean(space_in_other || token_text.match(/^\w/)); let space_after = space_before; if (ck.previous_token?.callsite) output_space_before_token = true; @@ -5706,7 +5802,7 @@ export class Lexer { indent(), print_token(); if (is_next_char('\n')) print_newline(); - else output_space_before_token = spaceInOther; + else output_space_before_token = space_in_other; flags.in_case = false; flags.case_body = true; set_mode(MODE.Statement); @@ -5883,7 +5979,7 @@ export class Lexer { print_token(token_type === 'TK_HOTLINE' ? t : ' ' + t); else if (token_type === 'TK_HOT') output_space_before_token = !!opt.spaceAfterDoubleColon; - else output_space_before_token = spaceInOther || token_type === 'TK_SHARP'; + else output_space_before_token = space_in_other || token_type === 'TK_SHARP'; } function handle_label() { @@ -5895,7 +5991,7 @@ export class Lexer { print_token(), indent(); flags.in_case = false; flags.in_case_statement = true; - output_space_before_token = spaceInOther; + output_space_before_token = space_in_other; set_mode(MODE.Statement); flags.case_body = true; return; @@ -5925,10 +6021,11 @@ export class Lexer { private clear() { this.texts = {}, this.declaration = {}, this.include = {}, this.tokens = {}, this.linepos = {}; this.labels = {}, this.typedef = {}, this.object = { method: {}, property: {} }; - this.diagnostics.length = this.foldingranges.length = 0; + this.need_scriptdir = this.hotstringExecuteAction = this.isparsed = false; this.children.length = this.dllpaths.length = this.tokenranges.length = 0; + this.diagnostics.length = this.foldingranges.length = 0; this.includedir.clear(), this.dlldir.clear(); - this.need_scriptdir = this.hotstringExecuteAction = this.isparsed = false; + this.d_uri = ''; delete this.maybev1; delete this.checkmember; delete this.symbolInformation; @@ -6170,7 +6267,7 @@ export class Lexer { offset = this.document.offsetAt(pos), cls = item as ClassNode; for (fn of [cls.property.__INIT, cls.$property?.__INIT] as FuncNode[]) for (const rg of fn?.ranges ?? []) - if (offset <= rg[0]) break; + if (offset < rg[0]) break; else if (offset <= rg[1]) return this.searchScopedNode(pos, fn.children) ?? fn; } @@ -6181,7 +6278,7 @@ export class Lexer { return; } - public getScopeSymbols(scope?: AhkSymbol): { [name: string]: Variable } { + public getScopeSymbols(scope?: AhkSymbol): Record { if (!scope || scope.kind === SymbolKind.Class || scope.kind === SymbolKind.Property) return {}; let fn = scope as FuncNode; @@ -6190,7 +6287,7 @@ export class Lexer { if (fn.kind === SymbolKind.Class) break; else roots.push(fn); - let vars: { [name: string]: Variable } = fn?.kind === SymbolKind.Class ? { THIS, SUPER } : {}; + let vars: Record = fn?.kind === SymbolKind.Class ? { THIS, SUPER } : {}; while ((fn = roots.pop() as FuncNode)) { if (fn.kind === SymbolKind.Property) continue; @@ -6289,9 +6386,8 @@ export class Lexer { const after = this.include; let l = Object.keys(after).length, change = 0; for (const u in initial) - if (!after[u]) { change = 2; break; } - if (!change && (l > Object.keys(initial).length || - !l && initial[''] === '' && Object.keys(includedcache[uri] ?? {}).length)) + if (!(u in after)) { change = 2; break; } + if (!change && (l > Object.keys(initial).length || '' in initial)) change = 1; if (!change) return this.sendDiagnostics(true); @@ -6330,13 +6426,13 @@ export class Lexer { if (!this.last_diags) return; this.include = {}, this.last_diags = 0; - connection.sendDiagnostics({ uri: this.document.uri, diagnostics: [] }); + connection?.sendDiagnostics({ uri: this.document.uri, diagnostics: [] }); } public sendDiagnostics(update = false, all = false) { const last_diags = this.last_diags; if (last_diags !== this.diagnostics.length || update && last_diags) { - connection.sendDiagnostics({ uri: this.document.uri, diagnostics: this.diagnostics }); + connection?.sendDiagnostics({ uri: this.document.uri, diagnostics: this.diagnostics }); this.last_diags = this.diagnostics.length; } if (!all) return; @@ -6361,8 +6457,8 @@ export class Lexer { if (d) { if (d > 2 && !uri.includes('?')) return true; - if (lexers[uri.slice(0, -5) + 'ahk']?.keepAlive()) - return true; + // if (lexers[uri.slice(0, -5) + 'ahk']?.keepAlive()) + // return true; } let it; for (const u in this.relevance) @@ -6424,7 +6520,7 @@ function is_valid_hotkey(s: string) { return true; } -export function find_include_path(path: string, libdirs: string[], workdir: string = '', check_exists = false) { +function find_include_path(path: string, libdirs: string[], workdir: string = '', check_exists = false, vars = a_vars) { let m: RegExpMatchArray | null, uri = ''; const raw = path; @@ -6442,8 +6538,8 @@ export function find_include_path(path: string, libdirs: string[], workdir: stri } else { while ((m = path.match(/%a_(\w+)%/i))) { const a_ = m[1].toLowerCase(); - if (a_vars[a_]) - path = path.replace(m[0], a_vars[a_]); + if (vars[a_]) + path = path.replace(m[0], vars[a_]); else return; } if (path.indexOf(':') < 0) @@ -6474,27 +6570,31 @@ export function parse_include(lex: Lexer, dir: string, _set = new Set()) { } export function get_class_base(node: AhkSymbol, lex?: Lexer) { + let iscls = false, uri, base, name: string, cls: ClassNode; switch (node.kind) { case SymbolKind.Method: - case SymbolKind.Function: return ahkprotos.FUNC; - case SymbolKind.Number: return ahkprotos[node.name.toUpperCase() as keyof typeof ahkprotos]; - case SymbolKind.String: return ahkprotos.STRING; + case SymbolKind.Function: name = 'func'; break; + case SymbolKind.Number: name = node.name; break; + case SymbolKind.String: name = 'string'; break; default: if (!(node as ClassNode).property) return; // fall through - case SymbolKind.Class: { - let cls = node as ClassNode, base, iscls; + case SymbolKind.Class: + cls = node as ClassNode, base; if ((base = cls.base)) return base; - if ((iscls = !!cls.prototype, cls.extends)) { - cls = find_class(lex ?? lexers[cls.uri!], cls.extends, cls.extendsuri)!; - return iscls ? cls : cls?.prototype; - } else switch (cls) { - case ahkprotos.ANY: return; - case ahkvars.ANY: return ahkprotos.CLASS; - default: return iscls ? ahkvars.OBJECT : ahkprotos.OBJECT; + iscls = !!cls.prototype, name = cls.extends; + lex ??= lexers[cls.uri!], uri = cls.extendsuri; + if (!name) { + if ((cls.full || cls.name).toLowerCase() === 'any') + if (iscls) + iscls = false, name = 'class'; + else return; + else name = 'object'; } - } + break; } + cls = find_class(lex ?? lexers[ahkuris.ahk2], name, uri)!; + return iscls ? cls : cls?.prototype; } export function get_class_member(lex: Lexer, node: AhkSymbol, name: string, ismethod: boolean, bases?: (ClassNode | null)[]): AhkSymbol | undefined { @@ -6508,13 +6608,17 @@ export function get_class_member(lex: Lexer, node: AhkSymbol, name: string, isme _bases.push(cls); } if ((sym = cls.property?.[name])) { - if (sym.kind === SymbolKind.Method === ismethod) - return sym.uri ??= cls.uri, sym; - if (ismethod && ((t = sym).kind === SymbolKind.Class || (t = (sym as Property).call))) - return t.uri ??= cls.uri, t; - if (ismethod) + if (ismethod) { + if (sym.kind === SymbolKind.Method) + return sym.uri ??= cls.uri, sym; + if ((t = sym).kind === SymbolKind.Class || (t = (sym as Property).call)) + return t.uri ??= cls.uri, t; prop ??= (sym.uri ??= cls.uri, sym); - else method ??= (sym.uri ??= cls.uri, sym); + } else if (sym.kind === SymbolKind.Method) + method ??= (sym.uri ??= cls.uri, sym); + else if (sym.children) + return sym.uri ??= cls.uri, sym; + else prop ??= (sym.uri ??= cls.uri, sym); } if ((t = _bases[++i]) === null) @@ -6528,7 +6632,7 @@ export function get_class_member(lex: Lexer, node: AhkSymbol, name: string, isme return prop; } -export function get_class_members(lex: Lexer, node: AhkSymbol, bases?: ClassNode[]): { [name: string]: AhkSymbol } { +export function get_class_members(lex: Lexer, node: AhkSymbol, bases?: ClassNode[]): Record { let cls = node as ClassNode; const _bases = bases ?? [], properties = []; while (cls && !_bases.includes(cls)) @@ -6999,7 +7103,7 @@ export function decltype_invoke(lex: Lexer, syms: Set | AhkSymbol[], else continue; if (n.kind !== SymbolKind.Property) { if ((n as FuncNode).alias) { - if (paraminfo) continue; + // if (paraminfo) continue; const tt = decltype_returns(n, lexers[n.uri!] ?? lex, _this); for (const t of call ? decltype_invoke(lex, tt, 'call', true) : tt) tps.add(t); @@ -7227,7 +7331,7 @@ function var_in_for_block(it: Variable, offset: number) { return range[0] <= offset && offset < range[1]; } -function decltype_type_annotations(annotations: (string | AhkSymbol)[], lex: Lexer, _this?: ClassNode, type_params?: { [name: string]: AhkSymbol }) { +function decltype_type_annotations(annotations: (string | AhkSymbol)[], lex: Lexer, _this?: ClassNode, type_params?: Record) { const types = new Set; let is_typeof; for (let tp of annotations) { @@ -7251,7 +7355,7 @@ function decltype_type_annotations(annotations: (string | AhkSymbol)[], lex: Lex } function resolve_cached_types(tps: (string | AhkSymbol)[], resolved_types: Set, lex: Lexer, - _this?: ClassNode, type_params?: { [name: string]: AhkSymbol }) { + _this?: ClassNode, type_params?: Record) { let re: RegExp, i = -1, is_this, is_typeof, t, param, update; for (let tp of tps) { if (i++, typeof tp === 'string') { @@ -7393,8 +7497,8 @@ function type_naming(sym: AhkSymbol) { } } -export function generate_type_annotation(sym: AhkSymbol, lex?: Lexer) { - return join_types((sym.type_annotations || decltype_returns(sym, lexers[sym.uri!] ?? lex))); +export function generate_type_annotation(sym: AhkSymbol, lex?: Lexer, _this?: ClassNode) { + return join_types((sym.type_annotations || decltype_returns(sym, lexers[sym.uri!] ?? lex, _this))); } export function join_types(tps?: Array | false) { @@ -7473,7 +7577,7 @@ export function find_symbol(lex: Lexer, fullname: string, kind?: SymbolKind, pos if ((t = lexers[uri = ahkuris.winapi]?.declaration[name])) return t.uri ??= uri, t; } - function find_include_symbol(list: { [uri: string]: string }, name: string) { + function find_include_symbol(list: Record, name: string) { let ret, t; for (const uri in list) { if ((t = (lexers[uri] ?? openAndParse(restorePath(list[uri]), false))?.findSymbol(name, kind))) @@ -7567,14 +7671,14 @@ export function get_callinfo(doc: Lexer, position: Position, pi?: ParamInfo) { } } -let includecache: { [uri: string]: { [uri: string]: string } } = {}; -let includedcache: { [uri: string]: { [uri: string]: string } } = {}; +let includecache: Record> = {}; +let includedcache: Record> = {}; export function update_include_cache() { includecache = {}, includedcache = {}; for (const lex of Object.values(lexers)) traverse_include(lex); } -export function traverse_include(lex: Lexer, included?: { [uri: string]: string }) { +export function traverse_include(lex: Lexer, included?: Record) { const { uri, include } = lex; let hascache = true; let cache = includecache[uri] ??= (hascache = false, { [uri]: lex.fsPath }); @@ -7658,8 +7762,9 @@ export function make_same_name_error(a: AhkSymbol, b: AhkSymbol): string { } } -export function check_same_name_error(decs: { [name: string]: AhkSymbol }, arr: AhkSymbol[], diags: Diagnostic[]) { +export function check_same_name_error(decs: Record, arr: AhkSymbol[], diags: Diagnostic[]) { let _low = '', v1: Variable, v2: Variable; + const severity = DiagnosticSeverity.Error; for (const it of arr) { if (!it.name || !it.selectionRange.end.character) continue; @@ -7675,30 +7780,35 @@ export function check_same_name_error(decs: { [name: string]: AhkSymbol }, arr: if (v1.kind === SymbolKind.Variable) { if (v1.def && v2.kind !== SymbolKind.Variable) { if (v1.assigned !== 1) - diags.push({ message: diagnostic.assignerr(v2.kind === SymbolKind.Function ? 'Func' : 'Class', it.name), range: it.selectionRange, severity: DiagnosticSeverity.Error }); + it.has_warned ??= diags.push({ message: diagnostic.assignerr(v2.kind === SymbolKind.Function ? 'Func' : 'Class', it.name), range: it.selectionRange, severity }); continue; } - } else if (v2.def) - v2.assigned !== 1 && diags.push({ message: diagnostic.assignerr(it.kind === SymbolKind.Function ? 'Func' : 'Class', it.name), range: v2.selectionRange, severity: DiagnosticSeverity.Error }); - else if (v2.kind === SymbolKind.Function) { - diags.push({ message: make_same_name_error(v2, it), range: it.selectionRange, severity: DiagnosticSeverity.Error }); + } else if (v2.kind === SymbolKind.Function) { + it.has_warned ??= diags.push({ message: make_same_name_error(v2, it), range: it.selectionRange, severity }); continue; - } + } else if (v2.def && v2.assigned !== 1) + v2.has_warned ??= diags.push({ message: diagnostic.assignerr(it.kind === SymbolKind.Function ? 'Func' : 'Class', it.name), range: v2.selectionRange, severity }); decs[_low] = it; } else if (v1.kind === SymbolKind.Variable) { if (v2.kind === SymbolKind.Variable) { if (v1.def && !v2.def) decs[_low] = it; else v2.assigned ||= v1.assigned; - } else if (v1.def) - delete v1.def, v1.assigned !== 1 && diags.push({ message: make_same_name_error(v2, it), range: it.selectionRange, severity: DiagnosticSeverity.Error }); + } else if (v1.def) { + delete v1.def; + if (v1.assigned !== 1) + it.has_warned ??= diags.push({ message: make_same_name_error(v2, it), range: it.selectionRange, severity }); + } } else { if (v2.kind === SymbolKind.Variable) { - if (v2.def) - delete v2.def, v2.assigned !== 1 && diags.push({ message: make_same_name_error(it, v2), range: v2.selectionRange, severity: DiagnosticSeverity.Error }); + if (v2.def) { + delete v2.def; + if (v2.assigned !== 1) + v2.has_warned ??= diags.push({ message: make_same_name_error(it, v2), range: v2.selectionRange, severity }); + } decs[_low] = it; } else if (v2.def !== false) - diags.push({ message: make_same_name_error(v2, it), range: it.selectionRange, severity: DiagnosticSeverity.Error }); + it.has_warned ??= diags.push({ message: make_same_name_error(v2, it), range: it.selectionRange, severity }); else if (v1.def !== false) decs[_low] = it; } diff --git a/server/src/PEFile.ts b/server/src/PEFile.ts index 372c3021..a02206df 100644 --- a/server/src/PEFile.ts +++ b/server/src/PEFile.ts @@ -20,7 +20,7 @@ export class PEFile { readUInt32LE(offset?: number): Promise, RVA2Offset(addr: number): number }>; - private resource: { [key: number]: any } = {}; + private resource: Record = {}; private dataDirectory: { virtualAddress: number, size: number, data?: any }[] = []; private sectionTable: { virtualAddress: number, sizeOfRawData: number, pointerToRawData: number }[] = []; constructor(path: string) { @@ -96,7 +96,7 @@ export class PEFile { const funcTblOffset = fd.RVA2Offset(buf.readUInt32LE(0x1c)); let nameTblOffset = fd.RVA2Offset(buf.readUInt32LE(0x20)); let ordTblOffset = fd.RVA2Offset(buf.readUInt32LE(0x24)); - const Exports: ExportInfo = { Module: await fd.readString(modNamePtr), Functions: [], OrdinalBase }, ordinalList: { [ord: number]: boolean } = {}; + const Exports: ExportInfo = { Module: await fd.readString(modNamePtr), Functions: [], OrdinalBase }, ordinalList: Record = {}; for (let i = 0; i < nameCount; i++) { const nameOffset = await fd.readUInt32LE(nameTblOffset), ordinal = await fd.readUInt16LE(ordTblOffset), fnOffset = await fd.readUInt32LE(funcTblOffset + ordinal * 4); nameTblOffset += 4, ordTblOffset += 2, ordinalList[ordinal] = true; @@ -124,7 +124,7 @@ export class PEFile { if (await this.is_bit64) ptrsize = 8, ffff = BigInt(0xffff), IMAGE_ORDINAL_FLAG = BigInt('0x8000000000000000'), readPtr = async (offset: number) => (await fd.read(offset, 8)).readBigUInt64LE(); else ffff = 0xffff, IMAGE_ORDINAL_FLAG = 0x80000000, readPtr = fd.readUInt32LE; - const Imports: { [dll: string]: string[] } = {}; + const Imports: Record = {}; while (firstThunk) { const dllname = await fd.readString(nameOffset), arr = Imports[dllname] ??= []; for (let i = 0; (ordinal = await readPtr(fd.RVA2Offset(firstThunk + i * ptrsize))); i++) @@ -141,7 +141,7 @@ export class PEFile { return; if (types.length === 1 && this.resource[types[0]]) return this.resource[types[0]]; - const baseOffset = fd.RVA2Offset(resinfo.virtualAddress), dirs = [baseOffset], resources: { [k: number]: any } = {}; + const baseOffset = fd.RVA2Offset(resinfo.virtualAddress), dirs = [baseOffset], resources: Record = {}; types.forEach(type => this.resource[type] ??= resources[type] = []); resources[RESOURCE_TYPE.RCDATA] &&= this.resource[RESOURCE_TYPE.RCDATA] = {}; await parseResourcesDirectory(baseOffset); diff --git a/server/src/browserServerMain.ts b/server/src/browserServerMain.ts new file mode 100644 index 00000000..49f248dd --- /dev/null +++ b/server/src/browserServerMain.ts @@ -0,0 +1,164 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { + createConnection, BrowserMessageReader, BrowserMessageWriter, DidChangeConfigurationNotification, + InitializeResult, TextDocuments, TextDocumentSyncKind +} from 'vscode-languageserver/browser'; +import { + AHKLSSettings, chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, + defintionProvider, documentFormatting, enumNames, executeCommandProvider, exportSymbols, getVersionInfo, + hoverProvider, initahk2cache, Lexer, lexers, loadahk2, loadlocalize, prepareRename, rangeFormatting, + referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, + SemanticTokenTypes, set_ahk_h, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, + signatureProvider, symbolProvider, typeFormatting, update_settings, workspaceSymbolProvider +} from './common'; + +const languageServer = 'ahk2-language-server'; +const messageReader = new BrowserMessageReader(self); +const messageWriter = new BrowserMessageWriter(self); +const documents = new TextDocuments(TextDocument); +const workspaceFolders = new Set(); +const connection = set_Connection(createConnection(messageReader, messageWriter)); + +let hasConfigurationCapability = false, hasWorkspaceFolderCapability = false; +let uri_switch_to_ahk2 = ''; + +connection.onInitialize(params => { + const capabilities = params.capabilities; + hasConfigurationCapability = !!( + capabilities.workspace && !!capabilities.workspace.configuration + ); + hasWorkspaceFolderCapability = !!( + capabilities.workspace && !!capabilities.workspace.workspaceFolders + ); + + const result: InitializeResult = { + serverInfo: { + name: languageServer, + }, + capabilities: { + textDocumentSync: { + change: TextDocumentSyncKind.Incremental, + openClose: true + }, + completionProvider: { + resolveProvider: false, + triggerCharacters: ['.', '#', '*', '@'] + }, + signatureHelpProvider: { + triggerCharacters: ['(', ',', ' '] + }, + documentSymbolProvider: true, + definitionProvider: true, + documentFormattingProvider: true, + documentRangeFormattingProvider: true, + documentOnTypeFormattingProvider: { firstTriggerCharacter: '}', moreTriggerCharacter: ['\n', ...Object.keys(chinese_punctuations)] }, + executeCommandProvider: { commands: Object.keys(commands) }, + hoverProvider: true, + foldingRangeProvider: true, + colorProvider: true, + renameProvider: { prepareProvider: true }, + referencesProvider: { workDoneProgress: true }, + semanticTokensProvider: { + legend: { + tokenTypes: enumNames(SemanticTokenTypes), + tokenModifiers: enumNames(SemanticTokenModifiers) + }, + full: true, + range: true + }, + workspaceSymbolProvider: true + } + }; + if (hasWorkspaceFolderCapability) { + params.workspaceFolders?.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); + result.capabilities.workspace = { workspaceFolders: { supported: true } }; + } + + const configs: AHKLSSettings = params.initializationOptions; + set_ahk_h(true); + set_locale(params.locale); + set_dirname(configs.extensionUri!); + loadlocalize(); + update_settings(configs); + set_WorkspaceFolders(workspaceFolders); + set_version('3.0.0'); + initahk2cache(); + loadahk2(); + loadahk2('ahk2_h'); + loadahk2('winapi', 4); + return result; +}); + +connection.onInitialized(() => { + if (hasConfigurationCapability) { + // Register for all configuration changes. + connection.client.register(DidChangeConfigurationNotification.type); + } + if (hasWorkspaceFolderCapability) { + connection.workspace.onDidChangeWorkspaceFolders(event => { + event.removed.forEach(it => workspaceFolders.delete(it.uri.toLowerCase() + '/')); + event.added.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); + set_WorkspaceFolders(workspaceFolders); + }); + } +}); + +connection.onDidChangeConfiguration(async change => { + let newset: AHKLSSettings | undefined = change?.settings; + if (hasConfigurationCapability && !newset) + newset = await connection.workspace.getConfiguration('AutoHotkey2'); + if (!newset) { + connection.window.showWarningMessage('Failed to obtain the configuration'); + return; + } + update_settings(newset); + set_WorkspaceFolders(workspaceFolders); +}); + +documents.onDidOpen(e => { + const to_ahk2 = uri_switch_to_ahk2 === e.document.uri; + const uri = e.document.uri.toLowerCase(); + let doc = lexers[uri]; + if (doc) doc.document = e.document; + else lexers[uri] = doc = new Lexer(e.document); + doc.actived = true; + if (to_ahk2) + doc.actionwhenv1 = 'Continue'; +}); + +documents.onDidClose(e => lexers[e.document.uri.toLowerCase()]?.close()); +documents.onDidChangeContent(e => lexers[e.document.uri.toLowerCase()].update()); + +connection.onCompletion(completionProvider); +connection.onColorPresentation(colorPresentation); +connection.onDocumentColor(colorProvider); +connection.onDefinition(defintionProvider); +connection.onDocumentFormatting(documentFormatting); +connection.onDocumentRangeFormatting(rangeFormatting); +connection.onDocumentOnTypeFormatting(typeFormatting); +connection.onDocumentSymbol(symbolProvider); +connection.onFoldingRanges(params => lexers[params.textDocument.uri.toLowerCase()].foldingranges); +connection.onHover(hoverProvider); +connection.onPrepareRename(prepareRename); +connection.onReferences(referenceProvider); +connection.onRenameRequest(renameProvider); +connection.onSignatureHelp(signatureProvider); +connection.onExecuteCommand(executeCommandProvider); +connection.onWorkspaceSymbol(workspaceSymbolProvider); +connection.languages.semanticTokens.on(semanticTokensOnFull); +connection.languages.semanticTokens.onRange(semanticTokensOnRange); +connection.onRequest('ahk2.exportSymbols', exportSymbols); +connection.onRequest('ahk2.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); +connection.onRequest('ahk2.getVersionInfo', getVersionInfo); +connection.onNotification('onDidCloseTextDocument', + (params: { uri: string, id: string }) => { + if (params.id === 'ahk2') + lexers[params.uri.toLowerCase()]?.close(true); + else uri_switch_to_ahk2 = params.uri; + }); +documents.listen(connection); +connection.listen(); diff --git a/server/src/codeActionProvider.ts b/server/src/codeActionProvider.ts index efd4f02b..602ec3c0 100644 --- a/server/src/codeActionProvider.ts +++ b/server/src/codeActionProvider.ts @@ -4,9 +4,9 @@ import { codeaction, diagnostic } from './localize'; import { Maybe, lexers, restorePath, warn } from './common'; export async function codeActionProvider(params: CodeActionParams, token: CancellationToken): Promise> { - const uri = params.textDocument.uri, lex = lexers[uri.toLowerCase()], document = lex.document; + const uri = params.textDocument.uri, lex = lexers[uri.toLowerCase()], document = lex?.document; if (!lex || token.isCancellationRequested) return; - const acts: CodeAction[] = [], replaces: { [k: string]: TextEdit[] } = {}, parens: TextEdit[] = []; + const acts: CodeAction[] = [], replaces: Record = {}, parens: TextEdit[] = []; let r: string, t: RegExpExecArray | null; const cwp = warn.callwithoutparentheses(); const include_re = new RegExp('^' + diagnostic.filenotexist('(.+?)\\*\\.(\\w+)')); diff --git a/server/src/commandProvider.ts b/server/src/commandProvider.ts index ab984f4d..1ee3f571 100644 --- a/server/src/commandProvider.ts +++ b/server/src/commandProvider.ts @@ -9,7 +9,7 @@ import { function checkCommand(cmd: string) { if (ahkppConfig.commands?.includes(cmd)) return true; - connection.console.warn(`Command '${cmd}' is not implemented!`); + connection?.console.warn(`Command '${cmd}' is not implemented!`); return false; } @@ -21,18 +21,18 @@ function trim_jsdoc(detail?: string) { function insertSnippet(value: string, range?: Range) { if (!checkCommand('ahk2.insertSnippet')) return; - connection.sendRequest('ahk2.insertSnippet', [value, range]); + connection?.sendRequest('ahk2.insertSnippet', [value, range]); } export function setTextDocumentLanguage(uri: string, lang?: string) { if (!checkCommand('ahk2.setTextDocumentLanguage')) return; - return connection.sendRequest('ahk2.setTextDocumentLanguage', [uri, lang]); + return connection?.sendRequest('ahk2.setTextDocumentLanguage', [uri, lang]); } export function generate_fn_comment(doc: Lexer, fn: FuncNode, detail?: string) { const comments = detail?.replace(/\$/g, '\\$').split('\n'); - const params: { [name: string]: string[] } = {}, returns: string[] = []; + const params: Record = {}, returns: string[] = []; const details: string[] = [], result = ['/**']; let lastarr: string[] | undefined, m: RegExpMatchArray | null; let i = 0, z = true; @@ -78,7 +78,7 @@ export function generate_fn_comment(doc: Lexer, fn: FuncNode, detail?: string) { async function generateComment() { if (!checkCommand('ahk2.getActiveTextEditorUriAndPosition') || !checkCommand('ahk2.insertSnippet')) return; - const { uri, position } = await connection.sendRequest('ahk2.getActiveTextEditorUriAndPosition') as { uri: string, position: Position }; + const { uri, position } = await connection?.sendRequest('ahk2.getActiveTextEditorUriAndPosition') as { uri: string, position: Position }; const doc = lexers[uri.toLowerCase()]; let scope = doc.searchScopedNode(position); const ts = scope?.children || doc.children; @@ -118,7 +118,7 @@ async function generateComment() { export function exportSymbols(uri: string) { let doc = lexers[uri.toLowerCase()]; // eslint-disable-next-line @typescript-eslint/no-explicit-any - const cache: { [k: string]: string } = {}, result: any = {}; + const cache: Record = {}, result: any = {}; if (!doc) return; update_include_cache(); @@ -128,11 +128,11 @@ export function exportSymbols(uri: string) { let includes; includes = Object.entries(doc.include).map(p => lexers[p[0]]?.fsPath ?? restorePath(p[1])); !includes.length && (includes = undefined); - dump(Object.values(doc.declaration), result[doc.fsPath || doc.document.uri] = { includes }); + dump(Object.values(doc.declaration), result[doc.fsPath || doc.document.uri] = { includes }, doc); } return result; // eslint-disable-next-line @typescript-eslint/no-explicit-any - function dump(nodes: AhkSymbol[], result: any) { + function dump(nodes: AhkSymbol[], result: any, lex: Lexer, _this?: ClassNode) { let kind: SymbolKind, fn: FuncNode, cl: ClassNode, t; for (let it of nodes) { if (!it.selectionRange.end.character) @@ -145,8 +145,8 @@ export function exportSymbols(uri: string) { extends: _extends(cl), detail: get_detail(it) }); - dump(Object.values(cl.property ?? {}), t); - dump(Object.values(cl.$property ?? {}), t); + dump(Object.values(cl.property ?? {}), t, lex, cl); + dump(Object.values(cl.$property ?? {}), t, lex, cl.prototype); break; case SymbolKind.Property: fn = it as FuncNode; @@ -156,7 +156,8 @@ export function exportSymbols(uri: string) { variadic: fn.variadic ?? false, params: dump_params(fn.params), readonly: fn.params && !(it as Property).set || false, - detail: get_detail(it) + type: generate_type_annotation(fn, lex, _this), + detail: get_detail(it), }); if (!(it = (it as Property).call!)) break; @@ -169,7 +170,8 @@ export function exportSymbols(uri: string) { static: fn.static ?? false, variadic: fn.variadic ?? false, params: dump_params(fn.params), - detail: get_detail(it) + returns: generate_type_annotation(fn, lex, _this), + detail: get_detail(it), }); break; } @@ -204,10 +206,10 @@ export function exportSymbols(uri: string) { } } -async function diagnosticFull() { +async function diagnoseAll() { if (!checkCommand('ahk2.getActiveTextEditorUriAndPosition')) return; - const { uri } = await connection.sendRequest('ahk2.getActiveTextEditorUriAndPosition') as { uri: string }; + const { uri } = await connection?.sendRequest('ahk2.getActiveTextEditorUriAndPosition') as { uri: string }; const doc = lexers[uri.toLowerCase()]; if (!doc) return; update_include_cache(); @@ -219,7 +221,7 @@ async function diagnosticFull() { async function setscriptdir() { if (!checkCommand('ahk2.getActiveTextEditorUriAndPosition')) return; - const { uri } = await connection.sendRequest('ahk2.getActiveTextEditorUriAndPosition') as { uri: string }; + const { uri } = await connection?.sendRequest('ahk2.getActiveTextEditorUriAndPosition') as { uri: string }; const lex = lexers[uri.toLowerCase()]; if (!lex) return; if (lex.scriptdir !== lex.scriptpath) @@ -229,9 +231,42 @@ async function setscriptdir() { lex.sendDiagnostics(false, true); } +export function getVersionInfo(uri: string) { + const lex = lexers[uri.toLowerCase()]; + if (!lex) return; + const doc = lex.document, tks = lex.tokens, pos = { line: 0, character: 0 }; + let tk = lex.get_token(0); + while (tk.type === 'TK_SHARP') { + pos.line = doc.positionAt(tk.offset).line + 1; + tk = lex.get_token(doc.offsetAt(pos)); + } + const info = []; + if ((!tk.type || tk.type.endsWith('COMMENT')) && /^\s*[;*]?\s*@(date|version)\b/im.test(tk.content)) { + info.push({ + uri, content: tk.content, single: false, + range: { + start: doc.positionAt(tk.offset), + end: doc.positionAt(tk.offset + tk.length) + } + }); + } + for (const it of lex.tokenranges) { + if (it.type === 1 && (tk = tks[it.start])?.topofline && + /^;\s*@ahk2exe-setversion\b/i.test(tk.content)) + return info.concat({ + uri, content: tk.content, single: true, + range: { + start: doc.positionAt(it.start), + end: doc.positionAt(it.end) + } + }); + } + return info; +} + // eslint-disable-next-line @typescript-eslint/no-explicit-any export const commands: { [command: string]: (args: any[]) => any } = { - 'ahk++.diagnostic.full': () => diagnosticFull(), + 'ahk++.diagnostic.full': () => diagnoseAll(), 'ahk++.addDocComment': () => generateComment(), 'ahk++.setAScriptDir': setscriptdir }; diff --git a/server/src/common.ts b/server/src/common.ts index 3ed5d4d9..b9274c62 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -25,7 +25,7 @@ export * from './signatureProvider'; export * from './symbolProvider'; export const winapis: string[] = []; -export const lexers: { [uri: string]: Lexer } = {}; +export const lexers: Record = {}; export const alpha_3 = encode_version('2.1-alpha.3'); export const ahkppConfig: AhkppConfig = newAhkppConfig(); export const utils = { @@ -38,18 +38,18 @@ export type Maybe = T | undefined; export let connection: Connection; export let interpreterPathV2 = '', locale = 'en-us', rootdir = '', isahk2_h = false; export let ahk_version = encode_version('3.0.0.0'); -export let ahkuris: { [name: string]: string } = {}; -export let ahkvars: { [key: string]: AhkSymbol } = {}; -export let libfuncs: { [uri: string]: LibSymbol } = {}; -export const hoverCache: { [key: string]: [string, Hover | undefined] } = {}; +export let ahkuris: Record = {}; +export let ahkvars: Record = {}; +export let libfuncs: Record = {}; +export const hoverCache: Record = {}; export const libdirs: string[] = []; export let workspaceFolders: string[] = []; export let completionItemCache: { constant: CompletionItem[]; - directive: { [c: string]: CompletionItem[] }; + directive: Record; key: CompletionItem[]; keyword: CompletionItem[]; - option: { [k: string]: CompletionItem[] }; + option: Record; snippet: CompletionItem[]; static: CompletionItem text: CompletionItem[]; @@ -60,37 +60,39 @@ interface LibSymbol extends Array { islib: boolean } +export function read_ahk_file(path: string, showError = true) { + let buf: Buffer; + try { + buf = readFileSync(path); + if (buf[0] === 0xff && buf[1] === 0xfe) + return buf.toString('utf16le'); + if (buf[0] === 0xef && buf[1] === 0xbb && buf[2] === 0xbf) + return buf.toString('utf8').substring(1); + try { + return new TextDecoder('utf8', { fatal: true }).decode(buf); + } catch { + showError && connection?.window.showErrorMessage(diagnostic.invalidencoding(path)); + } + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + catch (e: any) { + if (showError) { + delete e.stack; + e.path = path; + console.log(e); + } + } +} + export function openFile(path: string, showError = true): TextDocument | undefined { if (isBrowser) { const data = getwebfile(path); if (data) return TextDocument.create(data.url, 'ahk2', -10, data.text); - return undefined; } else { - let buf: Buffer | string; - try { buf = readFileSync(path); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - catch (e: any) { - if (showError) { - delete e.stack; - e.path = path; - console.log(e); - } - return undefined; - } - if (buf[0] === 0xff && buf[1] === 0xfe) - buf = buf.toString('utf16le'); - else if (buf[0] === 0xef && buf[1] === 0xbb && buf[2] === 0xbf) - buf = buf.toString('utf8').substring(1); - else { - try { - buf = new TextDecoder('utf8', { fatal: true }).decode(buf); - } catch { - showError && connection.window.showErrorMessage(diagnostic.invalidencoding(path)); - return undefined; - } - } - return TextDocument.create(URI.file(path).toString(), 'ahk2', -10, buf); + const text = read_ahk_file(path, showError); + if (text !== undefined) + return TextDocument.create(URI.file(path).toString(), 'ahk2', -10, text); } } @@ -261,7 +263,7 @@ export function loadahk2(filename = 'ahk2', d = 3) { label: snip.prefix.replace(/^[^#\w]/, ''), insertText: snip.body.replace(/^\W+/, ''), kind, insertTextFormat, - documentation: snip.description && { kind: 'markdown', value: snip.description }, + detail: snip.description, data: snip.body.charAt(0) }); if (c === '#') @@ -275,7 +277,7 @@ export function loadahk2(filename = 'ahk2', d = 3) { for (snip of arr) { completionItemCache.key.push({ label: snip.body, kind, - documentation: snip.description + detail: snip.description }); } break; @@ -287,7 +289,7 @@ export function loadahk2(filename = 'ahk2', d = 3) { completionItemCache.keyword.push({ label: snip.prefix, kind, insertTextFormat, insertText: snip.body, - documentation: snip.description, + detail: snip.description, preselect: true }); hoverCache[snip.prefix.toLowerCase()] = [snip.prefix, { contents: { kind: 'markdown', value: '```ahk2\n' + (snip.syntax ?? trim(snip.body)) + '\n```\n\n' + (snip.description ?? '') } }]; @@ -300,7 +302,7 @@ export function loadahk2(filename = 'ahk2', d = 3) { completionItemCache.snippet.push({ label: snip.prefix!, insertText: bodytostring(snip.body), - documentation: snip.description, + detail: snip.description, kind, insertTextFormat }); } @@ -327,7 +329,7 @@ export function loadahk2(filename = 'ahk2', d = 3) { for (snip of arr[k]) t.push({ label: snip.body, kind, - documentation: snip.description && { kind: 'markdown', value: snip.description } + detail: snip.description }); } break; @@ -398,7 +400,7 @@ export function updateAhkppConfig(newConfig: AhkppConfig) { } function encode_version(version: string) { - const STAGE: { [t: string]: number } = { ALPHA: -3, BETA: -2, RC: -1 }; + const STAGE: Record = { ALPHA: -3, BETA: -2, RC: -1 }; const v = (version.replace(/-\w+/, s => `.${STAGE[s.substring(1).toUpperCase()]}`) + '.0').split('.'); let n = 0; for (let i = 0; i < 4; i++) diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index 75b5cfd3..3ba3144f 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -17,7 +17,7 @@ import { BraceStyle, CompletionCommitCharacters, CfgKey, FormatterConfig, getCfg export async function completionProvider(params: CompletionParams, _token: CancellationToken): Promise> { let { position, textDocument: { uri } } = params; - const doc = lexers[uri = uri.toLowerCase()], vars: { [key: string]: unknown } = {}; + const doc = lexers[uri = uri.toLowerCase()], vars: Record = {}; if (!doc || _token.isCancellationRequested) return; let items: CompletionItem[] = [], cpitem = items.pop()!; let l: string, path: string, pt: Token | undefined, scope: AhkSymbol | undefined, temp; @@ -40,7 +40,6 @@ export async function completionProvider(params: CompletionParams, _token: Cance }, [ '/************************************************************************', ' * @description ${1:}', - ' * @file $TM_FILENAME', ' * @author ${2:}', ' * @date ${3:$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE}', ' * @version ${4:0.0.0}', @@ -238,7 +237,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance items.push(...completionItemCache.key), kind = SymbolKind.Event; break; case 'TK_BLOCK_COMMENT': - if (!/[<{|,][ \t]*$/.test(linetext.substring(0, range.start.character))) + if (!/[<{|:.,][ \t]*$/.test(linetext.substring(0, range.start.character))) return; if (text.includes('.')) { for (const it of Object.values(find_class(doc, text.replace(/\.[^.]*$/, ''))?.property ?? {})) { @@ -358,7 +357,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance if (set.includes(fn)) continue; set.push(fn); is_builtin = uris.includes(fn.uri!), index = ci.index, l = fn.name.toLowerCase(); kind = CompletionItemKind.Value, command = { title: 'cursorRight', command: 'cursorRight' }; - switch (is_builtin && ci.kind) { + switch (is_builtin && ((it as { kind?: SymbolKind }).kind ?? ci.kind)) { case SymbolKind.Method: switch (l) { case 'deleteprop': case 'getmethod': case 'getownpropdesc': @@ -373,11 +372,15 @@ export async function completionProvider(params: CompletionParams, _token: Cance continue; } case 'bind': case 'call': + set.pop(); // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (![SymbolKind.Function, l === 'call' && SymbolKind.Class].includes(it.parent?.kind as any)) + if (!it.parent || ![SymbolKind.Function, l === 'call' && SymbolKind.Class].includes(it.parent.kind as any)) break; - syms.push({ node: it.parent!, uri: '' }); - continue; + else { + const node = it.parent; + syms.push({ node, uri: node.uri!, kind: node.kind } as typeof syms[0]); + continue; + } } break; case SymbolKind.Function: @@ -421,7 +424,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance case 'objbindmethod': case 'hasmethod': case 'objhasownprop': case 'hasprop': if (index === 1) { - const comma = pi!.comma[0]; + const comma = pi?.comma[0]; if (!comma) continue; const filter = l.endsWith('method') ? (kind: SymbolKind) => kind !== SymbolKind.Method : undefined; for (const cls of decltype_expr(doc, doc.find_token(pi!.offset + 1, true), comma)) @@ -510,7 +513,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance // fn|()=>... if (symbol) { if (!symbol.children && (scope ??= doc.searchScopedNode(position))?.kind === SymbolKind.Class) { - const cls = scope as ClassNode; + let cls = scope as ClassNode; const metafns = ['__Init()', '__Call(${1:Name}, ${2:Params})', '__Delete()', '__Enum(${1:NumberOfVars})', '__Get(${1:Key}, ${2:Params})', '__Item[$1]', '__New($1)', '__Set(${1:Key}, ${2:Params}, ${3:Value})']; @@ -525,6 +528,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance const is_static = (symbol as Variable).static ?? false; if (is_static) metafns.splice(0, 1); + else cls = cls.prototype ?? {} as ClassNode; if (token.topofline) metafns.forEach(s => { const label = s.replace(/[([].*$/, ''); @@ -549,10 +553,10 @@ export async function completionProvider(params: CompletionParams, _token: Cance if (kind === SymbolKind.Property || kind === SymbolKind.Method) { if (!token.symbol && token.semantic?.type === SemanticTokenTypes.property) return; - const props: { [k: string]: CompletionItem } = {}; + const props: Record = {}; let tps = decltype_expr(doc, token, range.end), index = 0; const is_any = tps.includes(ANY), bases: ClassNode[] = []; - const clsindex: { [k: string]: string } = {}; + const clsindex: Record = {}; if (linetext[range.end.character] === '.') right_is_paren = '(['.includes(linetext.charAt(range.end.character + word.length + 1) || '\0'); if (is_any) @@ -563,7 +567,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance if (node.kind === SymbolKind.Interface) { const params = ((node as ClassNode).generic_types?.[0] as string[])?.map(s => `'"`.includes(s[0]) ? s.slice(1, -1) : s); if (!params?.length) continue; - const result = (await sendAhkRequest('GetDispMember', params) ?? {}) as { [func: string]: number }; + const result = (await sendAhkRequest('GetDispMember', params) ?? {}) as Record; Object.entries(result).forEach(it => expg.test(it[0]) && add_item(it[0], it[1] === 1 ? CompletionItemKind.Method : CompletionItemKind.Property)); continue; @@ -669,16 +673,16 @@ export async function completionProvider(params: CompletionParams, _token: Cance if (expg.test(l = it.name.toUpperCase()) && !at_edit_pos(it) && (!vars[l] || it.kind !== SymbolKind.Variable)) vars[l] = convertNodeCompletion(it); } - const list_arr = Object.keys(list); - for (const uri of [doc.d_uri, ...list_arr.map(p => lexers[p]?.d_uri), ...list_arr]) { - if (!(temp = lexers[uri]?.declaration)) + const list_arr = Object.keys(list).reverse(); + for (const uri of new Set([doc.d_uri, ...list_arr.map(p => lexers[p]?.d_uri), ...list_arr])) { + if (!(temp = lexers[uri])) continue; - path = lexers[uri].fsPath; - const all = !!list[uri]; + const d = temp.d; + path = temp.fsPath, temp = temp.declaration; for (const n in temp) { const it = temp[n]; - if (all && expg.test(n) && (!vars[n] || ((vars[n] as CompletionItem).kind === CompletionItemKind.Variable && it.kind !== SymbolKind.Variable))) - vars[n] = cpitem = convertNodeCompletion(it), cpitem.detail = `${completionitem.include(path)}\n\n${cpitem.detail ?? ''}`; + if (expg.test(n) && (d || !vars[n] || ((vars[n] as CompletionItem).kind === CompletionItemKind.Variable && it.kind !== SymbolKind.Variable))) + vars[n] = cpitem = convertNodeCompletion(it); } } @@ -694,7 +698,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance // library suggestions if (ahkppConfig.v2.general.librarySuggestions) { const librarySuggestions = ahkppConfig.v2.general.librarySuggestions; - const libdirs = doc.libdirs, caches: { [path: string]: TextEdit[] } = {}; + const libdirs = doc.libdirs, caches: Record = {}; let exportnum = 0, line = -1, first_is_comment: boolean | undefined, cm: Token; let dir = doc.workspaceFolder; dir = (dir ? URI.parse(dir).fsPath : doc.scriptdir).toLowerCase(); @@ -794,8 +798,10 @@ export async function completionProvider(params: CompletionParams, _token: Cance return; offset ??= doc.document.offsetAt(position); let path = token.content.substring(1, offset - token.offset), suf = ''; - if (!/^\w:[\\/]/.test(path) || /[*?"<>|\t]/.test(path)) + if (/[*?"<>|\t]/.test(path)) return; + if (!/^\w:[\\/]/.test(path)) + path = `${doc.scriptdir}/${path}`; path = path.replace(/`(.)/g, '$1').replace(/[^\\/]+$/, m => (suf = m, '')); try { if (!existsSync(path) || !statSync(path).isDirectory()) @@ -839,7 +845,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance return; offset ??= doc.document.offsetAt(position); let pre = token.content.substring(1, offset - token.offset), suf = '', t; - const docs = [doc], ls: { [k: string]: unknown } = {}; + const docs = [doc], ls: Record = {}; for (const u in list) (t = lexers[u]) && docs.push(t); pre = pre.replace(/`(.)/g, '$1').replace(/[^\\/]+$/, m => (suf = m, '')); diff --git a/server/src/constants.ts b/server/src/constants.ts index a7c0b7ba..28c6de83 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -1,11 +1,11 @@ export const builtin_variable = ['true', 'false', 'unset', 'a_ahkpath', 'a_ahkversion', 'a_allowmainwindow', 'a_appdata', 'a_appdatacommon', 'a_args', 'a_clipboard', 'a_computername', 'a_comspec', 'a_controldelay', 'a_coordmodecaret', 'a_coordmodemenu', 'a_coordmodemouse', 'a_coordmodepixel', 'a_coordmodetooltip', 'a_cursor', 'a_dd', 'a_ddd', 'a_dddd', 'a_defaultmousespeed', 'a_desktop', 'a_desktopcommon', 'a_detecthiddentext', 'a_detecthiddenwindows', 'a_endchar', 'a_eventinfo', 'a_fileencoding', 'a_hotkeyinterval', 'a_hotkeymodifiertimeout', 'a_hour', 'a_iconfile', 'a_iconhidden', 'a_iconnumber', 'a_icontip', 'a_index', 'a_initialworkingdir', 'a_is64bitos', 'a_isadmin', 'a_iscompiled', 'a_iscritical', 'a_ispaused', 'a_issuspended', 'a_keydelay', 'a_keydelayplay', 'a_keyduration', 'a_keydurationplay', 'a_language', 'a_lasterror', 'a_linefile', 'a_linenumber', 'a_listlines', 'a_loopfield', 'a_loopfileattrib', 'a_loopfiledir', 'a_loopfileext', 'a_loopfilefullpath', 'a_loopfilename', 'a_loopfilepath', 'a_loopfileshortname', 'a_loopfileshortpath', 'a_loopfilesize', 'a_loopfilesizekb', 'a_loopfilesizemb', 'a_loopfiletimeaccessed', 'a_loopfiletimecreated', 'a_loopfiletimemodified', 'a_loopreadline', 'a_loopregkey', 'a_loopregname', 'a_loopregtimemodified', 'a_loopregtype', 'a_maxhotkeysperinterval', 'a_mday', 'a_menumaskkey', 'a_min', 'a_mm', 'a_mmm', 'a_mmmm', 'a_mon', 'a_mousedelay', 'a_mousedelayplay', 'a_msec', 'a_mydocuments', 'a_now', 'a_nowutc', 'a_osversion', 'a_priorhotkey', 'a_priorkey', 'a_programfiles', 'a_programs', 'a_programscommon', 'a_ptrsize', 'a_regview', 'a_screendpi', 'a_screenheight', 'a_screenwidth', 'a_scriptdir', 'a_scriptfullpath', 'a_scripthwnd', 'a_scriptname', 'a_sec', 'a_sendlevel', 'a_sendmode', 'a_space', 'a_startmenu', 'a_startmenucommon', 'a_startup', 'a_startupcommon', 'a_storecapslockmode', 'a_tab', 'a_temp', 'a_thisfunc', 'a_thishotkey', 'a_tickcount', 'a_timeidle', 'a_timeidlekeyboard', 'a_timeidlemouse', 'a_timeidlephysical', 'a_timesincepriorhotkey', 'a_timesincethishotkey', 'a_titlematchmode', 'a_titlematchmodespeed', 'a_traymenu', 'a_username', 'a_wday', 'a_windelay', 'a_windir', 'a_workingdir', 'a_yday', 'a_year', 'a_yweek', 'a_yyyy']; -export const builtin_variable_h = ['a_ahkdir', 'a_dlldir', 'a_dllpath', 'a_globalstruct', 'a_isdll', 'a_mainthreadid', 'a_memorymodule', 'a_modulehandle', 'a_scriptstruct', 'a_threadid', 'a_zipcompressionlevel']; +export const builtin_variable_h = ['a_ahkdir', 'a_dlldir', 'a_dllpath', 'a_globalstruct', 'a_isdll', 'a_mainthreadid', 'a_memorymodule', 'a_modulehandle', 'a_scriptstruct', 'a_threadid']; export const builtin_ahkv1_commands = ['autotrim', 'blockinput', 'click', 'clipwait', 'control', 'controlclick', 'controlfocus', 'controlget', 'controlgetfocus', 'controlgetpos', 'controlgettext', 'controlmove', 'controlsend', 'controlsendraw', 'controlsettext', 'coordmode', 'critical', 'detecthiddentext', 'detecthiddenwindows', 'drive', 'driveget', 'drivespacefree', 'envadd', 'envdiv', 'envget', 'envmult', 'envset', 'envsub', 'envupdate', 'exit', 'exitapp', 'fileappend', 'filecopy', 'filecopydir', 'filecreatedir', 'filecreateshortcut', 'filedelete', 'fileencoding', 'filegetattrib', 'filegetshortcut', 'filegetsize', 'filegettime', 'filegetversion', 'fileinstall', 'filemove', 'filemovedir', 'fileopen', 'fileread', 'filereadline', 'filerecycle', 'filerecycleempty', 'fileremovedir', 'fileselectfile', 'fileselectfolder', 'filesetattrib', 'filesettime', 'format', 'formattime', 'getkeystate', 'gosub', 'groupactivate', 'groupadd', 'groupclose', 'groupdeactivate', 'gui', 'guicontrol', 'guicontrolget', 'hotkey', 'ifequal', 'ifexist', 'ifgreater', 'ifgreaterorequal', 'ifless', 'iflessorequal', 'ifmsgbox', 'ifnotequal', 'ifnotexist', 'ifwinactive', 'ifwinexist', 'ifwinnotactive', 'ifwinnotexist', 'imagesearch', 'inidelete', 'iniread', 'iniwrite', 'input', 'inputbox', 'keywait', 'listlines', 'menu', 'mouseclick', 'mouseclickdrag', 'mousegetpos', 'mousemove', 'msgbox', 'onerror', 'onexit', 'outputdebug', 'pause', 'pixelgetcolor', 'pixelsearch', 'postmessage', 'process', 'progress', 'random', 'regdelete', 'regread', 'regwrite', 'run', 'runas', 'runwait', 'send', 'sendevent', 'sendinput', 'sendlevel', 'sendmessage', 'sendmode', 'sendplay', 'sendraw', 'setbatchlines', 'setcapslockstate', 'setcontroldelay', 'setdefaultmousespeed', 'setenv', 'setformat', 'setkeydelay', 'setmousedelay', 'setnumlockstate', 'setregview', 'setscrolllockstate', 'setstorecapslockmode', 'settimer', 'settitlematchmode', 'setwindelay', 'setworkingdir', 'shutdown', 'sleep', 'sort', 'soundbeep', 'soundget', 'soundgetwavevolume', 'soundplay', 'soundset', 'soundsetwavevolume', 'splashimage', 'splashtextoff', 'splashtexton', 'splitpath', 'statusbargettext', 'statusbarwait', 'stringcasesense', 'stringleft', 'stringlower', 'stringright', 'stringtrimleft', 'stringtrimright', 'stringupper', 'suspend', 'sysget', 'thread', 'tooltip', 'transform', 'traytip', 'urldownloadtofile', 'winactivate', 'winactivatebottom', 'winclose', 'winget', 'wingetactivestats', 'wingetactivetitle', 'wingetclass', 'wingetpos', 'wingettext', 'wingettitle', 'winhide', 'winkill', 'winmaximize', 'winmenuselectitem', 'winminimize', 'winminimizeall', 'winminimizeallundo', 'winmove', 'winrestore', 'winset', 'winsettitle', 'winshow', 'winwait', 'winwaitactive', 'winwaitclose', 'winwaitnotactive']; -export const a_vars: { [key: string]: string } = { space: ' ', tab: '\t' }; +export const a_vars: Record = { space: ' ', tab: '\t' }; export const dllcalltpe = ['str', 'astr', 'wstr', 'int64', 'int', 'uint', 'short', 'ushort', 'char', 'uchar', 'float', 'double', 'ptr', 'uptr', 'hresult']; -export const chinese_punctuations: { [c: string]: string } = { +export const chinese_punctuations: Record = { ',': ',', '。': '.', ';': ';', diff --git a/server/src/localize.ts b/server/src/localize.ts index a42298bb..b3e95a44 100644 --- a/server/src/localize.ts +++ b/server/src/localize.ts @@ -1,7 +1,7 @@ import { rootdir, getlocalefile, getwebfile, isBrowser } from './common'; import { CfgKey } from './config'; -let loadedCollection: { [key: string]: string } = {}; +let loadedCollection: Record = {}; export const completionitem = { author: localize('completionitem.author', 'Add file infos about author, description, date, version.'), diff --git a/server/src/referencesProvider.ts b/server/src/referencesProvider.ts index 1522e3c4..506dc15c 100644 --- a/server/src/referencesProvider.ts +++ b/server/src/referencesProvider.ts @@ -13,13 +13,13 @@ export async function referenceProvider(params: ReferenceParams, token: Cancella return result; } -export function getAllReferences(doc: Lexer, context: Context, allow_builtin = true): { [uri: string]: Range[] } | null | undefined { +export function getAllReferences(doc: Lexer, context: Context, allow_builtin = true): Record | null | undefined { if (context.kind === SymbolKind.Null) return; const nodes = find_symbols(doc, context); if (nodes?.length !== 1) return; let name = context.text.toUpperCase(); - const references: { [uri: string]: Range[] } = {}; + const references: Record = {}; const { node, uri, scope, is_this, is_global } = nodes[0]; if (!uri || !node.selectionRange.end.character || is_this === false) return; @@ -87,7 +87,7 @@ export function getAllReferences(doc: Lexer, context: Context, allow_builtin = t else return; } const c = name.split('.'), l = c.length; - let i = 0, refs: { [uri: string]: Range[] } = {}; + let i = 0, refs: Record = {}; for (const uri of new Set([doc.uri, ...Object.keys(doc.relevance)])) refs[lexers[uri].document.uri] = findAllFromScope(lexers[uri] as unknown as AhkSymbol, c[0], SymbolKind.Variable); while (i < l) { @@ -137,7 +137,7 @@ export function getAllReferences(doc: Lexer, context: Context, allow_builtin = t } if (Object.keys(references).length) { for (const u in references) { - const m: { [k: string]: Range } = {}; + const m: Record = {}; for (const range of references[u]) m[`${range.start.line},${range.start.character}`] ??= range; references[u] = Object.values(m); diff --git a/server/src/renameProvider.ts b/server/src/renameProvider.ts index 7a98fcbf..aa8d8fde 100644 --- a/server/src/renameProvider.ts +++ b/server/src/renameProvider.ts @@ -2,7 +2,7 @@ import { CancellationToken, PrepareRenameParams, Range, RenameParams, WorkspaceE import { ResponseError } from 'vscode-jsonrpc'; import { Maybe, lexers, getAllReferences, response } from './common'; -let renameranges: { [uri: string]: Range[] } | null | undefined; +let renameranges: Record | null | undefined; export async function prepareRename(params: PrepareRenameParams, token: CancellationToken): Promise> { const doc = lexers[params.textDocument.uri.toLowerCase()]; diff --git a/server/src/semanticTokensProvider.ts b/server/src/semanticTokensProvider.ts index fed05156..459127a7 100644 --- a/server/src/semanticTokensProvider.ts +++ b/server/src/semanticTokensProvider.ts @@ -6,7 +6,7 @@ import { import { CfgKey, getCfg } from './config'; let curclass: ClassNode | undefined; -const memscache = new Map(); +const memscache = new Map>(); function resolve_sem(tk: Token, doc: Lexer) { const sem = tk.semantic; @@ -79,7 +79,7 @@ function resolveSemanticType(name: string, tk: Token, doc: Lexer) { case SemanticTokenTypes.method: case SemanticTokenTypes.property: if (curclass && !tk.ignore) { - let n = curclass.property[name], kind = n?.kind, temp: { [name: string]: AhkSymbol }; + let n = curclass.property[name], kind = n?.kind, temp: Record; if (!n || n.def === false) { const t = (temp = memscache.get(curclass) ?? (memscache.set(curclass, temp = get_class_members(doc, curclass)), temp))[name]; if (t) @@ -130,7 +130,8 @@ function resolveSemanticType(name: string, tk: Token, doc: Lexer) { if (ASSIGN_TYPE.includes(tt?.content)) { cls_add_prop(curclass, tk.content, tk.offset); } else if ((memscache.get(curclass) as _Flag)?.['#checkmember'] !== false) - ((curclass.undefined ??= {})[tk.content.toUpperCase()] ??= []).push(tk); + (curclass.undefined ??= {})[tk.content.toUpperCase()] ??= tk; + // doc.addDiagnostic(diagnostic.maybehavenotmember(curclass.name, tk.content), tk.offset, tk.length, 2); } } } @@ -172,12 +173,13 @@ function resolveSemanticType(name: string, tk: Token, doc: Lexer) { function resolve_class_undefined_member(doc: Lexer) { for (const cls of memscache.keys()) { - if (cls.undefined) { - const name = cls.name; - for (const tks of Object.values(cls.undefined)) - for (const tk of tks) - doc.addDiagnostic(diagnostic.maybehavenotmember(name, tk.content), tk.offset, tk.length, 2); - delete cls.undefined; - } + if (!cls.undefined) + continue; + const name = cls.name; + for (const tk of Object.values(cls.undefined)) + if (!tk.has_warned) { + tk.has_warned = true; + doc.addDiagnostic(diagnostic.maybehavenotmember(name, tk.content), tk.offset, tk.length, 2); + } } } \ No newline at end of file diff --git a/server/src/server.ts b/server/src/server.ts index 7b19b523..46d3b0f9 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -63,6 +63,10 @@ import { utils, winapis, workspaceSymbolProvider, + read_ahk_file, + getVersionInfo, + builtin_variable, + builtin_variable_h, } from './common'; import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; import { resolvePath, runscript } from './scriptrunner'; @@ -237,18 +241,33 @@ connection.onDidChangeConfiguration(async (change) => { } }); -documents.onDidOpen((e) => { +connection.onDidChangeWatchedFiles((change) => { + let uri, lex; + for (const c of change.changes) + switch (c.type) { + case 2: + if ((lex = lexers[c.uri.toLowerCase()])?.actived === false) + TextDocument.update(lex.document, [{ text: read_ahk_file(lex.fsPath) ?? '' }], 0), lex.update(); + break; + case 3: + if ((lex = lexers[uri = c.uri.toLowerCase()])) + lex.close(true), delete lexers[uri]; + break; + } +}); + +documents.onDidOpen(e => { const to_ahk2 = uri_switch_to_ahk2 === e.document.uri; const uri = e.document.uri.toLowerCase(); let doc = lexers[uri]; if (doc) doc.document = e.document; else { lexers[uri] = doc = new Lexer(e.document); - Object.defineProperty((doc.include = {}), '', { - value: '', - enumerable: false, - }); } + Object.defineProperty((doc.include = {}), '', { + value: '', + enumerable: false, + }); doc.actived = true; if (to_ahk2) doc.actionWhenV1Detected = 'Continue'; if (includeLocalLibrary(ahkppConfig.v2.general.librarySuggestions)) @@ -260,10 +279,8 @@ documents.onDidOpen((e) => { ); }); -documents.onDidClose((e) => lexers[e.document.uri.toLowerCase()]?.close()); -documents.onDidChangeContent((e) => - lexers[e.document.uri.toLowerCase()].update(), -); +documents.onDidClose(e => lexers[e.document.uri.toLowerCase()]?.close()); +documents.onDidChangeContent(e => lexers[e.document.uri.toLowerCase()]?.update()); connection.onCodeAction(codeActionProvider); connection.onCompletion(completionProvider); @@ -274,9 +291,7 @@ connection.onDocumentFormatting(documentFormatting); connection.onDocumentRangeFormatting(rangeFormatting); connection.onDocumentOnTypeFormatting(typeFormatting); connection.onDocumentSymbol(symbolProvider); -connection.onFoldingRanges( - (params) => lexers[params.textDocument.uri.toLowerCase()].foldingranges, -); +connection.onFoldingRanges(params => lexers[params.textDocument.uri.toLowerCase()]?.foldingranges); connection.onHover(hoverProvider); connection.onPrepareRename(prepareRename); connection.onReferences(referenceProvider); @@ -288,47 +303,20 @@ connection.languages.semanticTokens.on(semanticTokensOnFull); connection.languages.semanticTokens.onRange(semanticTokensOnRange); connection.onRequest('ahk2.exportSymbols', (uri: string) => exportSymbols(uri)); connection.onRequest('ahk2.getAHKversion', getAHKversion); -connection.onRequest('ahk2.getContent', (uri: string) => - lexers[uri.toLowerCase()]?.document.getText(), -); -connection.onRequest('ahk++.getVersionInfo', (uri: string) => { - const doc = lexers[uri.toLowerCase()]; - if (doc) { - const tk = doc.get_token(0); - if ( - (tk.type === 'TK_BLOCK_COMMENT' || tk.type === '') && - tk.content.match(/^\s*[;*]?\s*@(date|version)\b/im) - ) { - return { - uri: uri, - content: tk.content, - range: { - start: doc.document.positionAt(tk.offset), - end: doc.document.positionAt(tk.offset + tk.length), - }, - }; - } - } - return null; +connection.onRequest('ahk2.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); +connection.onRequest('ahk2.getVersionInfo', getVersionInfo); +connection.onNotification('onDidCloseTextDocument', (params: { uri: string, id: string }) => { + if (params.id === 'ahk2') + lexers[params.uri.toLowerCase()]?.close(true); + else uri_switch_to_ahk2 = params.uri; }); -connection.onNotification( - 'onDidCloseTextDocument', - (params: { uri: string; id: string }) => { - if (params.id === 'ahk2') lexers[params.uri.toLowerCase()]?.close(true); - else uri_switch_to_ahk2 = params.uri; - }, -); documents.listen(connection); connection.listen(); async function patherr(msg: string) { if (!ahkppConfig.commands?.includes('ahk2.executeCommand')) return connection.window.showErrorMessage(msg); - if ( - await connection.window.showErrorMessage(msg, { - title: 'Select Interpreter', - }) - ) + if (await connection.window.showErrorMessage(msg, { title: 'Select Interpreter' })) connection.sendRequest('ahk2.executeCommand', ['ahk++.setV2Interpreter']); } @@ -336,11 +324,11 @@ async function initpathenv(samefolder = false, retry = true): Promise { const script = ` #NoTrayIcon #Warn All, Off - s := "", _H := false, Append := SubStr(A_AhkVersion, 1, 1) = "1" ? "FileAppend2" : "FileAppend" - for _, p in ["a_ahkpath","a_appdata","a_appdatacommon","a_computername","a_comspec","a_desktop","a_desktopcommon","a_iscompiled","a_mydocuments","a_programfiles","a_programs","a_programscommon","a_startmenu","a_startmenucommon","a_startup","a_startupcommon","a_temp","a_username","a_windir","a_ahkversion"] - s .= SubStr(p, 3) "\`t" %p% "|" - try _H := !!A_ThreadID - %Append%(s "is64bit\`t" (A_PtrSize = 8) "|h\`t" _H "\`n", "*", "UTF-8") + s := "", Append := SubStr(A_AhkVersion, 1, 1) = "1" ? "FileAppend2" : "FileAppend" + for _, k in ${JSON.stringify([...builtin_variable, ...builtin_variable_h])} + try if SubStr(k, 1, 2) = "a_" && !IsObject(v := %k%) + s .= SubStr(k, 3) "|" v "\`n" + %Append%(s, "*", "utf-8") FileAppend2(text, file, encode) { FileAppend %text%, %file%, %encode% }`; @@ -375,18 +363,11 @@ async function initpathenv(samefolder = false, retry = true): Promise { connection.window.showErrorMessage(setting.getenverr()); return false; } - Object.assign( - a_vars, - Object.fromEntries( - data - .replace(/\t[A-Z]:\\/g, (m) => m.toLowerCase()) - .split('|') - .map((l) => l.split('\t')), - ), - ); - a_vars.ahkpath = interpreterPathV2; - set_version((a_vars.ahkversion ??= '2.0.0')); - if (a_vars.ahkversion.startsWith('1.')) patherr(setting.versionerr()); + Object.assign(a_vars, Object.fromEntries(data.replace(/|[A-Z]:\\/g, m => m.toLowerCase()).split('\n').map(l => l.split('|')))); + a_vars.ahkpath ??= interpreterPathV2; + set_version(a_vars.ahkversion ??= '2.0.0'); + if (a_vars.ahkversion.startsWith('1.')) + patherr(setting.versionerr()); if (!samefolder || !libdirs.length) { libdirs.length = 0; libdirs.push( @@ -396,14 +377,9 @@ async function initpathenv(samefolder = false, retry = true): Promise { let lb; for (lb of Object.values(libfuncs)) lb.islib = inlibdirs(lb.fsPath); } - a_vars.h = (a_vars.h ?? '0').slice(0, 1); - if (a_vars.h === '1') { - if (!isahk2_h) { - set_ahk_h(true); - samefolder = false; - loadahk2('ahk2_h'); - loadahk2('winapi', 4); - } + if (a_vars.threadid) { + if (!isahk2_h) + set_ahk_h(true), samefolder = false, loadahk2('ahk2_h'), loadahk2('winapi', 4); } else { if (isahk2_h) { set_ahk_h(false); @@ -412,6 +388,7 @@ async function initpathenv(samefolder = false, retry = true): Promise { loadahk2(); } } + Object.assign(a_vars, { index: '0', clipboard: '', threadid: '' }); await update_rcdata(); if (samefolder) return true; for (const uri in lexers) { @@ -567,16 +544,9 @@ async function getAHKversion(params: string[]) { } async function getDllExport(paths: string[] | Set, onlyone = false) { - const funcs: { [name: string]: true } = {}; + const funcs: Record = {}; for (const path of paths) { - const pe = await searchAndOpenPEFile( - path, - a_vars.is64bit === '1' - ? true - : a_vars.is64bit === '0' - ? false - : undefined, - ); + const pe = await searchAndOpenPEFile(path, a_vars.ptrsize === '8' ? true : a_vars.ptrsize === '4' ? false : undefined); if (!pe) continue; try { (await pe.getExport())?.Functions.forEach( @@ -591,7 +561,7 @@ async function getDllExport(paths: string[] | Set, onlyone = false) { return Object.keys(funcs); } -let curPERCDATA: { [key: string]: Buffer } | undefined = undefined; +let curPERCDATA: Record | undefined = undefined; function getRCDATA(name?: string) { const exe = resolvePath(interpreterPathV2, true); if (!exe) return; diff --git a/server/src/signatureProvider.ts b/server/src/signatureProvider.ts index de9e637d..e6980fff 100644 --- a/server/src/signatureProvider.ts +++ b/server/src/signatureProvider.ts @@ -91,7 +91,7 @@ export async function signatureProvider(params: SignatureHelpParams, token: Canc } fn = it as FuncNode; // fall through - case SymbolKind.Class: + default: add_cls(); break; } diff --git a/server/src/symbolProvider.ts b/server/src/symbolProvider.ts index d1d65230..4cbb8c8a 100644 --- a/server/src/symbolProvider.ts +++ b/server/src/symbolProvider.ts @@ -13,7 +13,7 @@ import { } from './common'; import { CfgKey, getCfg } from './config'; -export let globalsymbolcache: { [name: string]: AhkSymbol } = {}; +export let globalsymbolcache: Record = {}; export function symbolProvider(params: DocumentSymbolParams, token?: CancellationToken | null): SymbolInformation[] { let uri = params.textDocument.uri.toLowerCase(); @@ -22,8 +22,8 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio return []; if (token !== null && doc.symbolInformation) return doc.symbolInformation; - const gvar: { [name: string]: Variable } = globalsymbolcache = { ...ahkvars }; - let list = [uri, ...Object.keys(doc.relevance)], winapis: { [name: string]: AhkSymbol } = {}; + const gvar: Record = globalsymbolcache = { ...ahkvars }; + let list = [uri, ...Object.keys(doc.relevance)], winapis: Record = {}; list = list.map(u => lexers[u]?.d_uri).concat(list); for (const uri of list) { const lex = lexers[uri]; @@ -56,13 +56,15 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio } flatTree(doc); if (getCfg(ahkppConfig, CfgKey.VarUnset)) - for (const [k, v] of unset_vars) - k.assigned || doc.diagnostics.push({ message: warn.varisunset(v.name), range: v.selectionRange, severity: DiagnosticSeverity.Warning }); + for (const [k, v] of unset_vars) { + if (k.assigned) + continue; + doc.diagnostics.push({ message: warn.varisunset(v.name), range: v.selectionRange, severity: DiagnosticSeverity.Warning }); + } if (doc.actived) { checksamename(doc); doc.sendDiagnostics(false, true); } - doc.diags = doc.diagnostics.length; uri = doc.document.uri; return doc.symbolInformation = result.map(info => SymbolInformation.create(info.name, info.kind, info.range, uri)); @@ -70,7 +72,7 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio if (!(k.assigned ||= v.assigned) && v.returns === undefined) unset_vars.has(k) || unset_vars.set(k, v); } - function flatTree(node: { children?: AhkSymbol[] }, vars: { [key: string]: Variable } = {}, outer_is_global = false) { + function flatTree(node: { children?: AhkSymbol[] }, vars: Record = {}, outer_is_global = false) { const t: AhkSymbol[] = [], iscls = (node as AhkSymbol).kind === SymbolKind.Class; let tk: Token; node.children?.forEach((info: Variable) => { @@ -96,7 +98,7 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio result.push(info); }); for (const info of t) { - let inherit: { [key: string]: AhkSymbol } = {}, s: Variable; + let inherit: Record = {}, s: Variable; const oig = outer_is_global, fn = info as FuncNode; switch (info.kind) { case SymbolKind.Class: { @@ -186,18 +188,19 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio function checksamename(doc: Lexer) { if (doc.d) return; - const dec = { ...ahkvars }, lbs: { [k: string]: boolean } = {}; - let dd: Lexer; + const dec = { ...ahkvars }, lbs: Record = {}; + let dd: Lexer, sym: AhkSymbol; Object.keys(doc.labels).forEach(lb => lbs[lb] = true); for (const uri in doc.relevance) { if ((dd = lexers[uri])) { - dd.diagnostics.splice(dd.diags); + if (dd.d) continue; check_same_name_error(dec, Object.values(dd.declaration).filter(it => it.kind !== SymbolKind.Variable), dd.diagnostics); for (const lb in dd.labels) - if ((dd.labels[lb][0]).def) - if (lbs[lb]) - dd.diagnostics.push({ message: diagnostic.duplabel(), range: dd.labels[lb][0].selectionRange, severity: DiagnosticSeverity.Error }); - else lbs[lb] = true; + if ((sym = dd.labels[lb][0]).def) + if (lbs[lb]) { + sym.has_warned ??= + dd.diagnostics.push({ message: diagnostic.duplabel(), range: sym.selectionRange, severity: DiagnosticSeverity.Error }); + } else lbs[lb] = true; } } const t = Object.values(doc.declaration); @@ -230,9 +233,9 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio function err_extends(doc: Lexer, it: ClassNode, not_exist = true) { let o = doc.document.offsetAt(it.selectionRange.start), tk: Token; const tks = doc.tokens; - if (!(tk = tks[tks[o].next_token_offset]) || !(tk = tks[tk.next_token_offset])) + if (!(tk = tks[tks[o].next_token_offset]) || !(tk = tks[tk.next_token_offset]) || tk.has_warned) return; - o = tk.offset; + o = tk.offset, tk.has_warned = true; const rg: Range = { start: doc.document.positionAt(o), end: doc.document.positionAt(o + it.extends.length) }; doc.diagnostics.push({ message: not_exist ? diagnostic.unknown("class '" + it.extends) + "'" : diagnostic.unexpected(it.extends), range: rg, severity: DiagnosticSeverity.Warning }); } @@ -297,9 +300,9 @@ export function checkParams(doc: Lexer, node: FuncNode, info: CallSite) { if (!(params = node?.params)) return; const { max, min } = get_func_param_count(node), l = params.length - (node.variadic ? 1 : 0); - const _miss: { [index: number]: boolean } = {}; - // eslint-disable-next-line prefer-const + const _miss: Record = {}; let { count, miss } = paraminfo, index; + miss = [...miss]; while ((index = miss.pop()) !== undefined) { if (index !== --count) { count++, miss.push(index); @@ -384,12 +387,12 @@ export async function workspaceSymbolProvider(params: WorkspaceSymbolParams, tok } } } else { - const uris = (await connection.sendRequest('ahk2.getWorkspaceFiles', []) || []) as string[]; + const uris = (await connection?.sendRequest('ahk2.getWorkspaceFiles', []) || []) as string[]; for (const uri_ of uris) { const uri = uri_.toLowerCase(); let d: Lexer; if (!lexers[uri]) { - const content = (await connection.sendRequest('ahk2.getWorkspaceFileContent', [uri_])) as string; + const content = (await connection?.sendRequest('ahk2.getWorkspaceFileContent', [uri_])) as string; d = new Lexer(TextDocument.create(uri_, 'ahk2', -10, content)); d.parseScript(), lexers[uri] = d; if (filterSymbols(uri)) return symbols; diff --git a/syntaxes/ahk2.d.ahk b/syntaxes/ahk2.d.ahk index 855b5815..54368c06 100644 --- a/syntaxes/ahk2.d.ahk +++ b/syntaxes/ahk2.d.ahk @@ -2767,7 +2767,7 @@ ToolTip([Text, X, Y, WhichToolTip]) => Integer * @param IconNumber To use an icon group other than the first group of icons in the file, please specify its number in IconNumber (if omitted, it defaults to 1). For example, 2 will load the default icon in the second group of icons . If IconNumber is negative, it is assumed that its absolute value represents the resource ID of the icon in the executable file. * @param Freeze Specify 1 (true) to freeze the icon, or 0 (false) to unfreeze it (or leave it blank to keep the frozen/thawed state unchanged). When the icon is frozen, Pause and Suspend will not change it. Note : To freeze or unfreeze the current icon, please use 1 (true) or 0 (false), as shown in the following example: TraySetIcon(,, 1). */ -TraySetIcon(FileName: $FilePath, IconNumber := 1, Freeze := false) => void +TraySetIcon(FileName?: $FilePath, IconNumber := 1, Freeze := false) => void /** * Create a balloon prompt window near the tray icon. In Windows 10, a toast notification may be displayed instead. diff --git a/syntaxes/ahk2.tmLanguage.json b/syntaxes/ahk2.tmLanguage.json index e7697c49..8824da5f 100644 --- a/syntaxes/ahk2.tmLanguage.json +++ b/syntaxes/ahk2.tmLanguage.json @@ -1475,7 +1475,7 @@ "name": "keyword.operator.ahk2" }, { - "match": "(?<=(&[ \t]+|^[ \t]*))([<>$~*!+#^]*?)(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+|`[;{]|[\\x21-\\x3A\\x3C-\\x7E]|(?<=[^ \t]);)(?=([ \t]|$))", + "match": "(?<=(&[ \t]+|^[ \t]*))([<>$~*!+#^]*?)(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+|`[;{]|[\\x21-\\x3A\\x3C-\\x7E]|(?<=[^ \t]);)(?=([ \t]|$))", "name": "keyword.keys.ahk2" } ] @@ -1490,7 +1490,7 @@ "end": "(?=\\n)", "patterns": [ { - "match": "(?<=\\G[ \t]*)((?i:alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab)\\b|([<>]?[!+#^]){0,4}(`[{;]|(?<=\\G);|[^{;]|(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))(?=([ \t]+;.*|[ \t]*)\\n))", + "match": "(?<=\\G[ \t]*)((?i:alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab)\\b|([<>]?[!+#^]){0,4}(`[{;]|(?<=\\G);|[^{;]|(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))(?=([ \t]+;.*|[ \t]*)\\n))", "name": "keyword.keys.ahk2" }, { @@ -1663,7 +1663,7 @@ ] }, "keylist": { - "match": "\\b(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))\\b", + "match": "\\b(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))\\b", "name": "keyword.keys.ahk2" }, "line_continue": { diff --git a/syntaxes/ahk2_common.json b/syntaxes/ahk2_common.json index ee23a9c6..2a1739f5 100644 --- a/syntaxes/ahk2_common.json +++ b/syntaxes/ahk2_common.json @@ -35,6 +35,11 @@ "body": ";@format ${1|arrayStyle,objectStyle|}: ${2|collapse,expand,none|}", "prefix": "@format", "description": "Sets the object or array style of the current block for formatting" + }, + { + "body": ";@reference ${1:$TM_FILENAME_BASE.%A_Locale%.d.ahk}", + "prefix": "@reference", + "description": "Set the `.d.ahk` file associated with the current file. `%A_Locale%` is same as VS Code's locale." } ], "texts": [ diff --git a/tmgrammar-test/0-v2-demo.ahk b/tmgrammar-test/0-v2-demo.ahk new file mode 100644 index 00000000..6dd66f59 --- /dev/null +++ b/tmgrammar-test/0-v2-demo.ahk @@ -0,0 +1,3 @@ +#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle) +#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle +#HotIf diff --git a/tmgrammar-test/0-v2-demo.ahk.snap b/tmgrammar-test/0-v2-demo.ahk.snap new file mode 100644 index 00000000..e9f040a5 --- /dev/null +++ b/tmgrammar-test/0-v2-demo.ahk.snap @@ -0,0 +1,31 @@ +>#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle) +#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 +# ^^^^^ source.ahk2 keyword.control.directive.ahk2 +# ^ source.ahk2 +# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 +# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 +# ^^^^^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 +# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 +# ^ source.ahk2 +# ^^ source.ahk2 keyword.operator.expression.ahk2 +# ^ source.ahk2 +# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 +# ^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 variable.other.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 +>#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle +#^^^^^^ source.ahk2 hotkey.ahk2 keyword.keys.ahk2 +# ^^ source.ahk2 punctuation.definition.colon +# ^^^^^^ source.ahk2 variable.other.ahk2 support.function.ahk2 +# ^ source.ahk2 +# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.ahk2 string.quoted.ahk2 +# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 +# ^ source.ahk2 +# ^^^^^^^^^^^^^ source.ahk2 variable.other.ahk2 +>#HotIf +#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 +# ^^^^^ source.ahk2 keyword.control.directive.ahk2 +> \ No newline at end of file From b6bd720db8af7bdb365a46f52cc2fb976b223f0b Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 22 Sep 2024 23:37:59 -0700 Subject: [PATCH 30/60] Fixup validation errors (#28) --- .vscode-test.mjs | 14 ++- .vscode/launch.json | 4 +- client/src/test/runTest.ts | 36 ------ eslint.config.mjs | 68 ++++++------ package-lock.json | 11 +- package.nls.json | 2 +- package.nls.zh-cn.json | 2 +- readme.md | 189 ++++++++++++++++---------------- server/src/browserServerMain.ts | 15 +-- 9 files changed, 159 insertions(+), 182 deletions(-) delete mode 100644 client/src/test/runTest.ts diff --git a/.vscode-test.mjs b/.vscode-test.mjs index 5e9f9fbd..3613e4fc 100644 --- a/.vscode-test.mjs +++ b/.vscode-test.mjs @@ -4,14 +4,16 @@ import { execSync } from 'child_process'; let vscode_path = undefined; try { - const m = execSync('chcp 65001 && reg query HKCR\\vscode\\shell\\open\\command', { encoding: 'utf8' }) - .match(/REG_SZ\s+("([^"]+)"|\S+)/); + const m = execSync( + 'chcp 65001 && reg query HKCR\\vscode\\shell\\open\\command', + { encoding: 'utf8' }, + ).match(/REG_SZ\s+("([^"]+)"|\S+)/); vscode_path = m[2] || m[1]; -} catch { }; +} catch {} export default defineConfig({ files: 'client/dist/test/**/*.test.js', useInstallation: vscode_path && { - fromPath: vscode_path - } -}); \ No newline at end of file + fromPath: vscode_path, + }, +}); diff --git a/.vscode/launch.json b/.vscode/launch.json index 52f7f025..7aae83be 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -22,9 +22,9 @@ "preLaunchTask": "npm: watch", "args": [ "--disable-extensions", - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/client/dist/test/runTest" + "--extensionDevelopmentPath=${workspaceFolder}" ], + "testConfiguration": "${workspaceFolder}/.vscode-test.js", "outFiles": ["${workspaceFolder}/client/dist/test/**/*.js"] }, { diff --git a/client/src/test/runTest.ts b/client/src/test/runTest.ts deleted file mode 100644 index 856b58c4..00000000 --- a/client/src/test/runTest.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { resolve } from 'path'; -import * as Mocha from 'mocha'; -import { readdir } from 'fs'; - -export function run(): Promise { - // Create the mocha test - const mocha = new Mocha({ - ui: 'tdd', - timeout: 0 - }); - - return new Promise((c, e) => { - readdir(__dirname, (err, files) => { - if (err) { - return e(err); - } - - // Add files to the test suite - files.forEach(f => f.endsWith('.test.js') && mocha.addFile(resolve(__dirname, f))); - - try { - // Run the mocha test - mocha.run(failures => { - if (failures > 0) { - e(new Error(`${failures} tests failed.`)); - } else { - c(); - } - }); - } catch (err) { - console.error(err); - e(err); - } - }); - }); -} \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs index a805ba0e..7dc2a7b8 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -4,38 +4,38 @@ import tseslint from 'typescript-eslint'; /** @type {typeof tseslint.configs.recommended} */ export default [ - { - languageOptions: { - globals: { - ...globals.browser, - ...globals.node, - }, - }, - }, - pluginJs.configs.recommended, - ...tseslint.configs.recommended, - { - ignores: [ - '**/*.js', - '**/*.d.ts', - '**/.vscode-test-web/*', - '**/.vscode-test/*', - ], - }, - { - rules: { - 'no-control-regex': 'off', - 'no-empty': ['error', { allowEmptyCatch: true }], - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { - argsIgnorePattern: '^_', - varsIgnorePattern: '^_', - caughtErrors: 'none', - ignoreRestSiblings: true, - }, - ], - }, - }, + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + }, + }, + }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + ignores: [ + '**/*.js', + '**/*.d.ts', + '**/.vscode-test-web/*', + '**/.vscode-test/*', + ], + }, + { + rules: { + 'no-control-regex': 'off', + 'no-empty': ['error', { allowEmptyCatch: true }], + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrors: 'none', + ignoreRestSiblings: true, + }, + ], + }, + }, ]; diff --git a/package-lock.json b/package-lock.json index 996e9244..3d0f8aaf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-autohotkey2-lsp", - "version": "2.4.9", + "version": "2.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-autohotkey2-lsp", - "version": "2.4.9", + "version": "2.5.2", "license": "LGPLv3.0", "dependencies": { "vscode-languageclient": "^9.0.1", @@ -5774,6 +5774,13 @@ "dev": true, "license": "ISC" }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", diff --git a/package.nls.json b/package.nls.json index f82ad6af..c9049eeb 100644 --- a/package.nls.json +++ b/package.nls.json @@ -34,4 +34,4 @@ "ahk2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", "ahk2.update.versioninfo": "Update File Version Info", "ahk2.workingdirs": "Sets the working directory for the script" -} \ No newline at end of file +} diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index ed30b04f..97b62fc1 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -124,4 +124,4 @@ "setting.getenverr": "获取环境变量失败", "setting.uialimit": "由于安全限制, UIA可执行文件不允许重定向stdin/stdout, 因此依赖于此的一些功能将无法工作", "setting.versionerr": "当前AutoHotkey.exe不是v2版本, 无法获得正确的语法解析、补全等功能" -} \ No newline at end of file +} diff --git a/readme.md b/readme.md index 1a13cc0b..d7ba6748 100644 --- a/readme.md +++ b/readme.md @@ -11,34 +11,34 @@ AutoHotkey v2 Language support for VS Code, features realization based on v2 syntax analysis. Supports running on the Web, such as `Chrome/Edge`. https://vscode.dev or https://github.dev/github/dev -- [AutoHotkey v2 Language Support](#autohotkey-v2-language-support) - - [Language Features](#language-features) - - [Rename Symbol](#rename-symbol) - - [Diagnostics](#diagnostics) - - [IntelliSense](#intellisense) - - [Signature](#signature) - - [Document Symbol](#document-symbol) - - [Semantic Highlight](#semantic-highlight) - - [Tags](#tags) - - [Document Color](#document-color) - - [Hover](#hover) - - [Goto Definition](#goto-definition) - - [Find All References](#find-all-references) - - [CodeFormat](#codeformat) - - [Custom folding](#custom-folding) - - [Declaration document](#declaration-document) - - [Context Menu](#context-menu) - - [Quick Help](#quick-help) - - [Run Script](#run-script) - - [Run Selected Script](#run-selected-script) - - [Compile Script](#compile-script) - - [Debug Script](#debug-script) - - [Generate Comment](#generate-comment) - - [Use in other editors](#use-in-other-editors) - - [Sublime Text4](#sublime-text4) - - [Vim and Neovim](#vim-and-neovim) - - [Emacs](#Emacs) - - [Use in Web Browser](#use-in-web-browser) +- [AutoHotkey v2 Language Support](#autohotkey-v2-language-support) + - [Language Features](#language-features) + - [Rename Symbol](#rename-symbol) + - [Diagnostics](#diagnostics) + - [IntelliSense](#intellisense) + - [Signature](#signature) + - [Document Symbol](#document-symbol) + - [Semantic Highlight](#semantic-highlight) + - [Tags](#tags) + - [Document Color](#document-color) + - [Hover](#hover) + - [Goto Definition](#goto-definition) + - [Find All References](#find-all-references) + - [CodeFormat](#codeformat) + - [Custom folding](#custom-folding) + - [Declaration document](#declaration-document) + - [Context Menu](#context-menu) + - [Quick Help](#quick-help) + - [Run Script](#run-script) + - [Run Selected Script](#run-selected-script) + - [Compile Script](#compile-script) + - [Debug Script](#debug-script) + - [Generate Comment](#generate-comment) + - [Use in other editors](#use-in-other-editors) + - [Sublime Text4](#sublime-text4) + - [Vim and Neovim](#vim-and-neovim) + - [Emacs](#Emacs) + - [Use in Web Browser](#use-in-web-browser) ## Language Features @@ -141,10 +141,10 @@ See all the source code locations where a certain variable/function is being use usage: -- Right-click the popup menu and click "Format document". -- Press `Shift+Alt+F`. -- Supports formatting code blocks when typing '}', formatting lines and indenting lines when typing '\n'. (`editor.formatOnType` needs to be enabled) -- Supports the use of formatting instructions `;@format array_style: collapse, object_style: expand` to change the object style of different blocks +- Right-click the popup menu and click "Format document". +- Press `Shift+Alt+F`. +- Supports formatting code blocks when typing '}', formatting lines and indenting lines when typing '\n'. (`editor.formatOnType` needs to be enabled) +- Supports the use of formatting instructions `;@format array_style: collapse, object_style: expand` to change the object style of different blocks ![codeFormat](./pic/codeFormat.gif) @@ -227,87 +227,89 @@ node install.js ### Sublime Text4 -- `Package Control: Install Package`, and install [Sublime LSP](https://github.com/sublimelsp/LSP) plug-in. -- `Preferences: LSP Settings`, add lsp configuration, language selector, and syntax highlighting. This is a simple example [syntax highlighting](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), save the file in a similar path `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax`. +- `Package Control: Install Package`, and install [Sublime LSP](https://github.com/sublimelsp/LSP) plug-in. +- `Preferences: LSP Settings`, add lsp configuration, language selector, and syntax highlighting. This is a simple example [syntax highlighting](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), save the file in a similar path `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax`. ```json { - "clients": { - "lsp-ahk2": { - "enabled": true, - "command": [ - "node", - "/server/dist/server.js", - "--stdio" - ], // Update the path of node.exe(maybe it's already in PATH, so you don't need to set it) and the folder of vscode-autohotkey2-lsp - "selector": "source.ahk2", // Same as scope in AutoHotkey2.sublime-syntax - "schemes": ["file", "buffer", "res"], - "initializationOptions": { - "locale": "en-us", // or "zh-cn" - "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" - "CommentTags": "^;;\\s*(?.+)", - "CompleteFunctionParens": false, - "Diagnostics": { - "ClassStaticMemberCheck": true, - "ParamsCheck": true - }, - "ActionWhenV1IsDetected": "Continue", - "FormatOptions": { - "array_style": "none", // or "collapse" or "expand" - "break_chained_methods": false, - "ignore_comment": false, - "indent_string": "\t", - "max_preserve_newlines": 2, - "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" - "object_style": "none", // or "collapse" or "expand" - "preserve_newlines": true, - "space_after_double_colon": true, - "space_before_conditional": true, - "space_in_empty_paren": false, - "space_in_other": true, - "space_in_paren": false, - "wrap_line_length": 0 - }, - "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - "WorkingDirs": [], - "SymbolFoldingFromOpenBrace": false - } - } - }, - "semantic_highlighting": true + "clients": { + "lsp-ahk2": { + "enabled": true, + "command": [ + "node", + "/server/dist/server.js", + "--stdio" + ], // Update the path of node.exe(maybe it's already in PATH, so you don't need to set it) and the folder of vscode-autohotkey2-lsp + "selector": "source.ahk2", // Same as scope in AutoHotkey2.sublime-syntax + "schemes": ["file", "buffer", "res"], + "initializationOptions": { + "locale": "en-us", // or "zh-cn" + "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" + "CommentTags": "^;;\\s*(?.+)", + "CompleteFunctionParens": false, + "Diagnostics": { + "ClassStaticMemberCheck": true, + "ParamsCheck": true + }, + "ActionWhenV1IsDetected": "Continue", + "FormatOptions": { + "array_style": "none", // or "collapse" or "expand" + "break_chained_methods": false, + "ignore_comment": false, + "indent_string": "\t", + "max_preserve_newlines": 2, + "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" + "object_style": "none", // or "collapse" or "expand" + "preserve_newlines": true, + "space_after_double_colon": true, + "space_before_conditional": true, + "space_in_empty_paren": false, + "space_in_other": true, + "space_in_paren": false, + "wrap_line_length": 0 + }, + "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + "WorkingDirs": [], + "SymbolFoldingFromOpenBrace": false + } + } + }, + "semantic_highlighting": true } ``` ### Vim and Neovim #### COC -- Download [coc.nvim plugin](https://github.com/neoclide/coc.nvim). + +- Download [coc.nvim plugin](https://github.com/neoclide/coc.nvim). ```bat cd $VIMRUNTIME\plugin git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 ``` -- Open (n)vim and enter the command `:CocConfig` to enter the `coc.nvim` configuration file to add configuration information. +- Open (n)vim and enter the command `:CocConfig` to enter the `coc.nvim` configuration file to add configuration information. ```json { - "languageserver": { - "lsp-ahk2": { - "module": "/server/dist/server.js", - "filetypes": ["autohotkey"], - "args": ["--node-ipc"], - "initializationOptions": { - // Same as initializationOptions for Sublime Text4 - } - } - } + "languageserver": { + "lsp-ahk2": { + "module": "/server/dist/server.js", + "filetypes": ["autohotkey"], + "args": ["--node-ipc"], + "initializationOptions": { + // Same as initializationOptions for Sublime Text4 + } + } + } } ``` #### nvim-lspconfig -- Download [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). -- Add the following to your NVIM configuration (init.lua e.g.). Ensure that `cmd` points to the path of your vscode-autohotkey2-lsp installation and `InterpreterPath` points to your AHK exe. + +- Download [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). +- Add the following to your NVIM configuration (init.lua e.g.). Ensure that `cmd` points to the path of your vscode-autohotkey2-lsp installation and `InterpreterPath` points to your AHK exe. ```lua local function custom_attach(client, bufnr) @@ -349,9 +351,10 @@ nvim_lsp.ahk2.setup({}) ### Emacs #### Eglot -- Add the following lines to your emacs config file -``` emacs-lisp +- Add the following lines to your emacs config file + +```emacs-lisp (add-to-list 'eglot-server-programs '(ahk-mode "node" "/server/dist/server.js" "--stdio")) ``` diff --git a/server/src/browserServerMain.ts b/server/src/browserServerMain.ts index 49f248dd..c7c9bb29 100644 --- a/server/src/browserServerMain.ts +++ b/server/src/browserServerMain.ts @@ -8,13 +8,14 @@ import { InitializeResult, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver/browser'; import { - AHKLSSettings, chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, + chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, defintionProvider, documentFormatting, enumNames, executeCommandProvider, exportSymbols, getVersionInfo, hoverProvider, initahk2cache, Lexer, lexers, loadahk2, loadlocalize, prepareRename, rangeFormatting, referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, - signatureProvider, symbolProvider, typeFormatting, update_settings, workspaceSymbolProvider + signatureProvider, symbolProvider, typeFormatting, updateAhkppConfig, workspaceSymbolProvider } from './common'; +import { AhkppConfig } from './config'; const languageServer = 'ahk2-language-server'; const messageReader = new BrowserMessageReader(self); @@ -78,12 +79,12 @@ connection.onInitialize(params => { result.capabilities.workspace = { workspaceFolders: { supported: true } }; } - const configs: AHKLSSettings = params.initializationOptions; + const configs: AhkppConfig = params.initializationOptions; set_ahk_h(true); set_locale(params.locale); set_dirname(configs.extensionUri!); loadlocalize(); - update_settings(configs); + updateAhkppConfig(configs); set_WorkspaceFolders(workspaceFolders); set_version('3.0.0'); initahk2cache(); @@ -108,14 +109,14 @@ connection.onInitialized(() => { }); connection.onDidChangeConfiguration(async change => { - let newset: AHKLSSettings | undefined = change?.settings; + let newset: AhkppConfig | undefined = change?.settings; if (hasConfigurationCapability && !newset) newset = await connection.workspace.getConfiguration('AutoHotkey2'); if (!newset) { connection.window.showWarningMessage('Failed to obtain the configuration'); return; } - update_settings(newset); + updateAhkppConfig(newset); set_WorkspaceFolders(workspaceFolders); }); @@ -127,7 +128,7 @@ documents.onDidOpen(e => { else lexers[uri] = doc = new Lexer(e.document); doc.actived = true; if (to_ahk2) - doc.actionwhenv1 = 'Continue'; + doc.actionWhenV1Detected = 'Continue'; }); documents.onDidClose(e => lexers[e.document.uri.toLowerCase()]?.close()); From 0a11ed2ec49f0c6d54046207082b324559f5df78 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:00:50 -0700 Subject: [PATCH 31/60] Fixup CI (#29) --- .gitattributes | 1 + .github/workflows/prettier.yml | 41 ++++++++++++++++++++++++++++++++++ .gitignore | 4 +++- client/src/extension.ts | 4 ++-- package.json | 6 +++-- 5 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 .gitattributes create mode 100644 .github/workflows/prettier.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..94f480de --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf \ No newline at end of file diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml new file mode 100644 index 00000000..34665894 --- /dev/null +++ b/.github/workflows/prettier.yml @@ -0,0 +1,41 @@ +# Adapted from GitHub issue comment code by george-gca on 2024-01-16 +# https://github.com/prettier/prettier/issues/6885#issuecomment-1894252136 + +name: Prettier diff + +on: + push: + branches: ['main'] + pull_request: + branches: ['main'] + workflow_dispatch: + merge_group: + +jobs: + build: + strategy: + matrix: + # AHK is built for Windows only, so we only build on Windows + # As always, if community asks, community shall receive ;) + os: [windows-latest] + node-version: [20.x] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + - run: npm install + - name: Run Prettier + id: runPrettier + # format is just `prettier --check .` + run: npm run format + - name: + if: ${{ failure() }} + # format:fix is just `prettier --write .` + run: | + npm run format:fix + git diff diff --git a/.gitignore b/.gitignore index 921a5229..4ed6e072 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ node_modules *.vsix scripts/* *.js -*.js.map \ No newline at end of file +*.js.map +*.tsbuildinfo +**/dist/**/*.d.ts \ No newline at end of file diff --git a/client/src/extension.ts b/client/src/extension.ts index 251d7926..527e9c11 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -30,8 +30,8 @@ import { ServerOptions, TransportKind } from 'vscode-languageclient/node'; -import { resolve, basename } from 'path'; -import { ChildProcess, exec, execSync, spawn } from 'child_process'; +import { resolve } from 'path'; +import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, readFileSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config'; diff --git a/package.json b/package.json index 869afc31..2df08cbd 100644 --- a/package.json +++ b/package.json @@ -46,15 +46,17 @@ "format": "prettier --check .", "format:fix": "prettier --write .", "lint": "npm run format && npm run eslint && npm run sort-package-json", - "lint:ci": "npm run eslint && npm run sort-package-json", + "lint:fix": "npm run format:fix && npm run eslint:fix && npm run sort-package-json:fix", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", "test": "npm run test-unit", "pretest-unit": "npm run compile-ts", "test-unit": "cd client && vscode-test", + "test-unit//": "echo todo failing for now, will be adding pure unit tests soon", "test//": "Run unit tests, not grammar tests", "validate": "npm run lint && npm run test", - "validate:ci": "npm run lint:ci && npm run test", + "validate:ci": "npm run lint", + "validate:ci:fix": "npm run lint:fix", "watch": "tsc -b -w" }, "prettier": { From 52aa813616d3b69dfb3abf466208730392c81ec6 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:57:35 -0700 Subject: [PATCH 32/60] Add Vitest for unit tests (#30) --- .gitignore | 5 +- .vscode-test.mjs | 2 +- .vscode/extensions.json | 3 +- .vscode/settings.json | 3 +- .vscode/snippets.code-snippets | 40 + .../{extension.test.ts => extension.e2e.ts} | 0 client/src/extension.ts | 30 +- client/src/utils.test.ts | 29 + client/src/utils.ts | 33 + package-lock.json | 1692 +++++++++++++++-- package.json | 19 +- vitest.config.mjs | 13 + 12 files changed, 1683 insertions(+), 186 deletions(-) create mode 100644 .vscode/snippets.code-snippets rename client/src/{extension.test.ts => extension.e2e.ts} (100%) create mode 100644 client/src/utils.test.ts create mode 100644 client/src/utils.ts create mode 100644 vitest.config.mjs diff --git a/.gitignore b/.gitignore index 4ed6e072..0e373567 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,7 @@ scripts/* *.js *.js.map *.tsbuildinfo -**/dist/**/*.d.ts \ No newline at end of file +**/dist/**/*.d.ts + +# Vitest +coverage \ No newline at end of file diff --git a/.vscode-test.mjs b/.vscode-test.mjs index 3613e4fc..11029cf2 100644 --- a/.vscode-test.mjs +++ b/.vscode-test.mjs @@ -12,7 +12,7 @@ try { } catch {} export default defineConfig({ - files: 'client/dist/test/**/*.test.js', + files: 'client/dist/test/**/*.e2e.js', useInstallation: vscode_path && { fromPath: vscode_path, }, diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e22fcc88..bb3324e2 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ "recommendations": [ "aaron-bond.better-comments", "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode" + "esbenp.prettier-vscode", + "vitest.explorer" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index f494c7af..c09d1f5e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,5 @@ "editor.insertSpaces": false, "typescript.tsc.autoDetect": "off", "typescript.preferences.quoteStyle": "single", - "git.ignoreLimitWarning": true, - "editor.formatOnSave": false + "git.ignoreLimitWarning": true } diff --git a/.vscode/snippets.code-snippets b/.vscode/snippets.code-snippets new file mode 100644 index 00000000..3b6b41e3 --- /dev/null +++ b/.vscode/snippets.code-snippets @@ -0,0 +1,40 @@ +{ + // Place your ahk2 workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and + // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope + // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is + // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: + // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. + // Placeholders with the same ids are connected. + // Example: + // "Print to console": { + // "scope": "javascript,typescript", + // "prefix": "log", + // "body": [ + // "console.log('$1');", + // "$2" + // ], + // "description": "Log output to console" + // } + + "Add unit test": { + "scope": "typescript", + "prefix": "describe", + "body": [ + "describe('$1', () => {", + "\ttest.concurrent.each<", + "\t[", + "\t\tname: string,", + "\t\t\targs: Parameters,", + "\t\t\texpected: ReturnType,", + "\t\t]", + "\t>([", + "\t['$2', [$3], $4],", + "\t])('%s', (_name, args, expected) => {", + "\t\tconst result = $1(...args);", + "\t\texpect(result).toBe(expected);", + "\t});", + "});", + ], + "description": "Add Vitest test.concurrent.each in a describe block", + }, +} diff --git a/client/src/extension.test.ts b/client/src/extension.e2e.ts similarity index 100% rename from client/src/extension.test.ts rename to client/src/extension.e2e.ts diff --git a/client/src/extension.ts b/client/src/extension.ts index 527e9c11..112d1ade 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -34,12 +34,12 @@ import { resolve } from 'path'; import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, readFileSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config'; +import { resolvePath } from './utils'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); let v2Interpreter = getCfg(CfgKey.InterpreterPathV2), server_is_ready = false const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; -const isWindows = process.platform === 'win32'; let extlist: string[] = [], debugexts: Record = {}, langs: string[] = []; const loadedCollection = { 'ahk2.browse': 'Browse your file system to find AutoHotkey2 interpreter', @@ -623,34 +623,6 @@ async function onDidChangegetInterpreter() { } } -/** - * Returns the provided path as an absolute path. - * Resolves the provided path against the provided workspace. - * Resolves symbolic links by default. - * Returns empty string if resolution fails. - */ -export function resolvePath(path: string | undefined, workspace?: string, resolveSymbolicLink = true): string { - if (!path) - return ''; - const paths: string[] = []; - // If the path does not contain a colon, resolve it relative to the workspace - if (!path.includes(':')) - paths.push(resolve(workspace ?? '', path)); - // If there are no slashes or backslashes in the path and the platform is Windows - if (!/[\\/]/.test(path) && isWindows) - paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); - paths.push(path); - for (let path of paths) { - if (!path) continue; - try { - if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) - path = resolve(path, '..', readlinkSync(path)); - return path; - } catch { } - } - return ''; -} - /** * Returns whether the given path exists. * Only returns false if lstatSync give an ENOENT error. diff --git a/client/src/utils.test.ts b/client/src/utils.test.ts new file mode 100644 index 00000000..b40f75ba --- /dev/null +++ b/client/src/utils.test.ts @@ -0,0 +1,29 @@ +import { expect, test, describe, vi, beforeAll, afterAll } from 'vitest'; +import { resolvePath } from './utils'; + +describe('resolvePath', () => { + beforeAll(() => { + // Mock the behavior of fs.lstatSync + vi.mock('fs', () => ({ + lstatSync: (_path: string) => ({ isSymbolicLink: () => false }), + })); + }); + + afterAll(() => { + vi.restoreAllMocks(); + }); + + test.concurrent.each< + [ + name: string, + args: Parameters, + expected: ReturnType, + ] + >([ + ['empty string', [''], ''], + ['absolute path at drive root', ['C:/out.txt'], 'C:/out.txt'], + ])('%s', (_name, args, expected) => { + const result = resolvePath(...args); + expect(result).toBe(expected); + }); +}); diff --git a/client/src/utils.ts b/client/src/utils.ts new file mode 100644 index 00000000..96242b26 --- /dev/null +++ b/client/src/utils.ts @@ -0,0 +1,33 @@ +import { execSync } from 'child_process'; +import { lstatSync, readlinkSync } from 'fs'; +import { resolve } from 'path'; + +/** + * Returns the provided path as an absolute path. + * Resolves the provided path against the provided workspace. + * Resolves symbolic links by default. + * Returns empty string if resolution fails. + */ +export function resolvePath( + path: string | undefined, + workspace?: string, + resolveSymbolicLink = true, +): string { + if (!path) return ''; + const paths: string[] = []; + // If the path does not contain a colon, resolve it relative to the workspace + if (!path.includes(':')) paths.push(resolve(workspace ?? '', path)); + // If there are no slashes or backslashes in the path and the platform is Windows + if (!/[\\/]/.test(path) && process.platform === 'win32') + paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); + paths.push(path); + for (let path of paths) { + if (!path) continue; + try { + if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) + path = resolve(path, '..', readlinkSync(path)); + return path; + } catch {} + } + return ''; +} diff --git a/package-lock.json b/package-lock.json index 3d0f8aaf..efc81e67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", + "@vitest/coverage-v8": "^2.1.1", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", @@ -33,6 +34,7 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", + "vitest": "^2.1.1", "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" @@ -41,6 +43,20 @@ "vscode": "^1.82.0" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -55,6 +71,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { "version": "7.24.7", "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", @@ -81,6 +107,37 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -762,9 +819,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true, "license": "MIT" }, @@ -872,6 +929,230 @@ "node": ">=18" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", + "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", + "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", + "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", + "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", + "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", + "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", + "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", + "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", + "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", + "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", + "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", + "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", + "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", + "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", + "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", + "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -1137,30 +1418,40 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@vscode/test-cli": { - "version": "0.0.10", - "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", - "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", + "node_modules/@vitest/coverage-v8": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/coverage-v8/-/coverage-v8-2.1.1.tgz", + "integrity": "sha512-md/A7A3c42oTT8JUHSqjP5uKTWJejzUW4jalpvs+rZ27gsURsMU8DEb+8Jf8C6Kj2gwfSHJqobDNBuoqlm0cFw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/mocha": "^10.0.2", - "c8": "^9.1.0", - "chokidar": "^3.5.3", - "enhanced-resolve": "^5.15.0", - "glob": "^10.3.10", - "minimatch": "^9.0.3", - "mocha": "^10.2.0", - "supports-color": "^9.4.0", - "yargs": "^17.7.2" + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.6", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.11", + "magicast": "^0.3.4", + "std-env": "^3.7.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^1.2.0" }, - "bin": { - "vscode-test": "out/bin.mjs" + "funding": { + "url": "https://opencollective.com/vitest" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@vitest/browser": "2.1.1", + "vitest": "2.1.1" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, - "node_modules/@vscode/test-cli/node_modules/brace-expansion": { + "node_modules/@vitest/coverage-v8/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -1170,7 +1461,7 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@vscode/test-cli/node_modules/glob": { + "node_modules/@vitest/coverage-v8/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", @@ -1191,7 +1482,7 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vscode/test-cli/node_modules/minimatch": { + "node_modules/@vitest/coverage-v8/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", @@ -1207,53 +1498,252 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vscode/test-cli/node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "node_modules/@vitest/coverage-v8/node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "engines": { + "node": ">=18" } }, - "node_modules/@vscode/test-electron": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", - "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", + "node_modules/@vitest/expect": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/expect/-/expect-2.1.1.tgz", + "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", "dev": true, + "license": "MIT", "dependencies": { - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "jszip": "^3.10.1", - "ora": "^7.0.1", - "semver": "^7.6.2" + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" }, - "engines": { - "node": ">=16" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vscode/test-web": { - "version": "0.0.56", - "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", - "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", + "node_modules/@vitest/mocker": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/mocker/-/mocker-2.1.1.tgz", + "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", "dev": true, "license": "MIT", "dependencies": { - "@koa/cors": "^5.0.0", - "@koa/router": "^12.0.1", - "@playwright/browser-chromium": "^1.45.0", - "glob": "^10.4.2", - "gunzip-maybe": "^1.4.2", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.4", - "koa": "^2.15.3", - "koa-morgan": "^1.0.1", - "koa-mount": "^4.0.0", - "koa-static": "^5.0.0", + "@vitest/spy": "^2.1.0-beta.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.1", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", + "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/runner/-/runner-2.1.1.tgz", + "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.1", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/snapshot/-/snapshot-2.1.1.tgz", + "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.1", + "magic-string": "^0.30.11", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/spy/-/spy-2.1.1.tgz", + "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/utils/-/utils-2.1.1.tgz", + "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.1", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vscode/test-cli": { + "version": "0.0.10", + "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", + "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", + "dev": true, + "dependencies": { + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@vscode/test-cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vscode/test-cli/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-cli/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-cli/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", + "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^7.0.1", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@vscode/test-web": { + "version": "0.0.56", + "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", + "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@koa/cors": "^5.0.0", + "@koa/router": "^12.0.1", + "@playwright/browser-chromium": "^1.45.0", + "glob": "^10.4.2", + "gunzip-maybe": "^1.4.2", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.4", + "koa": "^2.15.3", + "koa-morgan": "^1.0.1", + "koa-mount": "^4.0.0", + "koa-static": "^5.0.0", "minimist": "^1.2.8", "playwright": "^1.45.0", "tar-fs": "^3.0.6", @@ -1732,6 +2222,16 @@ "node": ">=0.10.0" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmmirror.com/b4a/-/b4a-1.6.6.tgz", @@ -2029,6 +2529,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmmirror.com/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cache-content-type": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/cache-content-type/-/cache-content-type-1.0.1.tgz", @@ -2106,6 +2616,23 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", @@ -2121,6 +2648,16 @@ "node": ">=4" } }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", @@ -2439,13 +2976,13 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2506,6 +3043,16 @@ "node": ">=0.10.0" } }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.0.1.tgz", @@ -3223,6 +3770,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", @@ -3461,6 +4018,16 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/get-stdin": { "version": "9.0.0", "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-9.0.0.tgz", @@ -4167,6 +4734,21 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmmirror.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/istanbul-reports": { "version": "3.1.7", "resolved": "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz", @@ -4728,6 +5310,16 @@ "node": ">=8" } }, + "node_modules/loupe": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/loupe/-/loupe-3.1.1.tgz", + "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4741,6 +5333,28 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmmirror.com/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-4.0.0.tgz", @@ -5162,13 +5776,6 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/mocha/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", @@ -5340,16 +5947,35 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, @@ -5791,6 +6417,23 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/peek-stream": { "version": "1.1.3", "resolved": "https://registry.npmmirror.com/peek-stream/-/peek-stream-1.1.3.tgz", @@ -5804,9 +6447,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true, "license": "ISC" }, @@ -5868,6 +6511,35 @@ "node": ">=18" } }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6320,6 +6992,42 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.22.4.tgz", + "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.22.4", + "@rollup/rollup-android-arm64": "4.22.4", + "@rollup/rollup-darwin-arm64": "4.22.4", + "@rollup/rollup-darwin-x64": "4.22.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", + "@rollup/rollup-linux-arm-musleabihf": "4.22.4", + "@rollup/rollup-linux-arm64-gnu": "4.22.4", + "@rollup/rollup-linux-arm64-musl": "4.22.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", + "@rollup/rollup-linux-riscv64-gnu": "4.22.4", + "@rollup/rollup-linux-s390x-gnu": "4.22.4", + "@rollup/rollup-linux-x64-gnu": "4.22.4", + "@rollup/rollup-linux-x64-musl": "4.22.4", + "@rollup/rollup-win32-arm64-msvc": "4.22.4", + "@rollup/rollup-win32-ia32-msvc": "4.22.4", + "@rollup/rollup-win32-x64-msvc": "4.22.4", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6455,6 +7163,13 @@ "node": ">=8" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", @@ -6603,6 +7318,16 @@ "node": ">= 8" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", @@ -6660,6 +7385,13 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmmirror.com/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", @@ -6670,6 +7402,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmmirror.com/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true, + "license": "MIT" + }, "node_modules/stdin-discarder": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", @@ -7038,6 +7777,60 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7490,95 +8283,687 @@ "node": ">= 0.8" } }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "node_modules/vite": { + "version": "5.4.8", + "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.8.tgz", + "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", + "dev": true, "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, "engines": { - "node": ">=14.0.0" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/vscode-languageclient": { - "version": "9.0.1", - "resolved": "https://registry.npmmirror.com/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", - "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "node_modules/vite-node": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/vite-node/-/vite-node-2.1.1.tgz", + "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", + "dev": true, "license": "MIT", "dependencies": { - "minimatch": "^5.1.0", - "semver": "^7.3.7", - "vscode-languageserver-protocol": "3.17.5" + "cac": "^6.7.14", + "debug": "^4.3.6", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" }, "engines": { - "vscode": "^1.82.0" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/vscode-languageclient/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-languageclient/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/vscode-languageserver": { - "version": "9.0.1", - "resolved": "https://registry.npmmirror.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", - "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.17.5" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmmirror.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", - "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmmirror.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "license": "MIT" - }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/vscode-textmate": { - "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-7.0.4.tgz", - "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A==", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vitest": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/vitest/-/vitest-2.1.1.tgz", + "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.1", + "@vitest/mocker": "2.1.1", + "@vitest/pretty-format": "^2.1.1", + "@vitest/runner": "2.1.1", + "@vitest/snapshot": "2.1.1", + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "debug": "^4.3.6", + "magic-string": "^0.30.11", + "pathe": "^1.1.2", + "std-env": "^3.7.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", + "tinypool": "^1.0.0", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.1", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.1", + "@vitest/ui": "2.1.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "license": "MIT", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-textmate": { + "version": "7.0.4", + "resolved": "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-7.0.4.tgz", + "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A==", "dev": true, "license": "MIT" }, @@ -7789,6 +9174,23 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.1.tgz", diff --git a/package.json b/package.json index 2df08cbd..271be642 100644 --- a/package.json +++ b/package.json @@ -49,14 +49,17 @@ "lint:fix": "npm run format:fix && npm run eslint:fix && npm run sort-package-json:fix", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", - "test": "npm run test-unit", - "pretest-unit": "npm run compile-ts", - "test-unit": "cd client && vscode-test", - "test-unit//": "echo todo failing for now, will be adding pure unit tests soon", - "test//": "Run unit tests, not grammar tests", + "test": "npm run test:e2e", + "test//": "echo Run e2e tests (open VS Code), not grammar tests", + "test:ci": "npm run test:unit", + "pretest:e2e": "npm run compile-ts", + "test:e2e": "cd client && vscode-test", + "test:e2e//": "echo todo failing for now, will be adding pure unit tests soon", + "test:unit": "vitest --run", "validate": "npm run lint && npm run test", - "validate:ci": "npm run lint", - "validate:ci:fix": "npm run lint:fix", + "validate:ci": "npm run lint && npm run test:ci", + "validate:ci:fix": "npm run lint:fix && npm run test:ci", + "validate:ci:fix//": "echo Fix validation issues first, then run remaining checks until failure", "watch": "tsc -b -w" }, "prettier": { @@ -87,6 +90,7 @@ "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", + "@vitest/coverage-v8": "^2.1.1", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", @@ -101,6 +105,7 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", + "vitest": "^2.1.1", "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" diff --git a/vitest.config.mjs b/vitest.config.mjs new file mode 100644 index 00000000..1b0aa0f2 --- /dev/null +++ b/vitest.config.mjs @@ -0,0 +1,13 @@ +import { defineConfig } from 'vitest/config'; + +// https://vitest.dev/config +// https://vitest.dev/guide/improving-performance.html +export default defineConfig({ + test: { + isolate: false, + pool: 'threads', + coverage: { + enabled: true, + }, + }, +}); From aae4f9e45fda8447df3f8a52143aaa5286425cce Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Thu, 26 Sep 2024 20:54:42 -0700 Subject: [PATCH 33/60] Remove dupe config file (#31) --- client/.vscode-test.mjs | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 client/.vscode-test.mjs diff --git a/client/.vscode-test.mjs b/client/.vscode-test.mjs deleted file mode 100644 index efac995e..00000000 --- a/client/.vscode-test.mjs +++ /dev/null @@ -1,7 +0,0 @@ -// https://github.com/microsoft/vscode-test-cli -import { defineConfig } from '@vscode/test-cli'; -export default defineConfig({ - extensionDevelopmentPath: '..', - files: 'dist/**/*.test.js', - version: '1.92.0', -}); From b10a3ed9d8fff7b659c3d73de35412c60a3740a0 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 28 Sep 2024 11:56:05 -0700 Subject: [PATCH 34/60] Greatly cleanup and works towards ESM (#32) * Revert "Add Vitest for unit tests (#30)" This reverts commit 52aa813616d3b69dfb3abf466208730392c81ec6. * Revert "Remove dupe config file (#31)" This reverts commit aae4f9e45fda8447df3f8a52143aaa5286425cce. * Remove rootDirs from client * Remove rootDirs from server * Add compile-ts to client * Resolve modules via NodeNext * Make client an ESM module * Add compile-ts to server * Update module resolution of server * Make server an ESM module * Use bundler resolution in client * Remove unused tsconfig.json * Use NodeNext for compatibility with AHK++ * Add logs * Progress * ESM but still not quite working * More CJS building * Fix clean * Use server.cjs * Further cleanup * Ignore extension.cts when prettifying --- .gitignore | 6 +- .prettierignore | 2 +- .vscode-test.mjs | 19 - .vscode/extensions.json | 3 +- .vscode/launch.json | 2 +- .vscode/snippets.code-snippets | 40 - build.mjs | 6 +- client/package.json | 4 + client/src/browserClientMain.ts | 127 -- client/src/{config.ts => config.cts} | 0 client/src/{extension.ts => extension.cts} | 39 +- client/src/extension.e2e.ts | 234 --- client/src/utils.test.ts | 29 - client/src/utils.ts | 33 - client/tsconfig.json | 5 +- package-lock.json | 1530 +------------------- package.json | 20 +- server/cli/cli.ts | 6 +- server/package.json | 4 + server/src/Lexer.ts | 8 +- server/src/ahkProvider.ts | 6 +- server/src/browserServerMain.ts | 6 +- server/src/codeActionProvider.ts | 4 +- server/src/colorProvider.ts | 2 +- server/src/commandProvider.ts | 2 +- server/src/common.ts | 38 +- server/src/completionProvider.ts | 6 +- server/src/definitionProvider.ts | 2 +- server/src/formattingProvider.ts | 4 +- server/src/hoverProvider.ts | 2 +- server/src/localize.ts | 4 +- server/src/referencesProvider.ts | 2 +- server/src/renameProvider.ts | 2 +- server/src/scriptrunner.ts | 2 +- server/src/semanticTokensProvider.ts | 4 +- server/src/server.ts | 17 +- server/src/signatureProvider.ts | 2 +- server/src/symbolProvider.ts | 4 +- server/src/utils.ts | 2 +- server/tsconfig.json | 7 +- tsconfig.json | 14 - vitest.config.mjs | 13 - 42 files changed, 189 insertions(+), 2073 deletions(-) delete mode 100644 .vscode-test.mjs delete mode 100644 .vscode/snippets.code-snippets delete mode 100644 client/src/browserClientMain.ts rename client/src/{config.ts => config.cts} (100%) rename client/src/{extension.ts => extension.cts} (95%) delete mode 100644 client/src/extension.e2e.ts delete mode 100644 client/src/utils.test.ts delete mode 100644 client/src/utils.ts delete mode 100644 tsconfig.json delete mode 100644 vitest.config.mjs diff --git a/.gitignore b/.gitignore index 0e373567..db4e5649 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,7 @@ node_modules *.vsix scripts/* *.js +*.cjs *.js.map *.tsbuildinfo -**/dist/**/*.d.ts - -# Vitest -coverage \ No newline at end of file +**/dist/**/*.d.ts \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 2e589f88..e8bc4a40 100644 --- a/.prettierignore +++ b/.prettierignore @@ -9,7 +9,7 @@ scripts/* server/expr_parser/* client/src/browserClientMain.ts -client/src/extension.ts +client/src/extension.cts client/src/test/utils.ts server/src/ahkProvider.ts server/src/browserServerMain.ts diff --git a/.vscode-test.mjs b/.vscode-test.mjs deleted file mode 100644 index 11029cf2..00000000 --- a/.vscode-test.mjs +++ /dev/null @@ -1,19 +0,0 @@ -// https://github.com/microsoft/vscode-test-cli -import { defineConfig } from '@vscode/test-cli'; -import { execSync } from 'child_process'; - -let vscode_path = undefined; -try { - const m = execSync( - 'chcp 65001 && reg query HKCR\\vscode\\shell\\open\\command', - { encoding: 'utf8' }, - ).match(/REG_SZ\s+("([^"]+)"|\S+)/); - vscode_path = m[2] || m[1]; -} catch {} - -export default defineConfig({ - files: 'client/dist/test/**/*.e2e.js', - useInstallation: vscode_path && { - fromPath: vscode_path, - }, -}); diff --git a/.vscode/extensions.json b/.vscode/extensions.json index bb3324e2..e22fcc88 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,7 +2,6 @@ "recommendations": [ "aaron-bond.better-comments", "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode", - "vitest.explorer" + "esbenp.prettier-vscode" ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 7aae83be..aaee596a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -34,7 +34,7 @@ "runtimeExecutable": "${execPath}", "args": ["--extensionDevelopmentPath=${workspaceFolder}"], "env": { - "VSCODE_AHK_SERVER_PATH": "server/dist/server.js", + "VSCODE_AHK_SERVER_PATH": "server/dist/server.cjs", "SYNTAXES_PATH": "syntaxes" }, "outFiles": ["${workspaceFolder}/client/dist/**/*.js"], diff --git a/.vscode/snippets.code-snippets b/.vscode/snippets.code-snippets deleted file mode 100644 index 3b6b41e3..00000000 --- a/.vscode/snippets.code-snippets +++ /dev/null @@ -1,40 +0,0 @@ -{ - // Place your ahk2 workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and - // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope - // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is - // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: - // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. - // Placeholders with the same ids are connected. - // Example: - // "Print to console": { - // "scope": "javascript,typescript", - // "prefix": "log", - // "body": [ - // "console.log('$1');", - // "$2" - // ], - // "description": "Log output to console" - // } - - "Add unit test": { - "scope": "typescript", - "prefix": "describe", - "body": [ - "describe('$1', () => {", - "\ttest.concurrent.each<", - "\t[", - "\t\tname: string,", - "\t\t\targs: Parameters,", - "\t\t\texpected: ReturnType,", - "\t\t]", - "\t>([", - "\t['$2', [$3], $4],", - "\t])('%s', (_name, args, expected) => {", - "\t\tconst result = $1(...args);", - "\t\texpect(result).toBe(expected);", - "\t});", - "});", - ], - "description": "Add Vitest test.concurrent.each in a describe block", - }, -} diff --git a/build.mjs b/build.mjs index 0cd27f44..d6bc0ddc 100644 --- a/build.mjs +++ b/build.mjs @@ -14,7 +14,7 @@ console.log( build({ entryPoints: [path.join('./server/src/server.ts')], bundle: true, - outfile: path.join('./server/dist/server.js'), + outfile: path.join('./server/dist/server.cjs'), external: ['vscode'], format: 'cjs', platform: 'node', @@ -25,9 +25,9 @@ build({ // Node client (not necessary for AHK++, but super fast) // https://esbuild.github.io/api build({ - entryPoints: [path.join('./client/src/extension.ts')], + entryPoints: [path.join('./client/src/extension.cts')], bundle: true, - outfile: path.join('./client/dist/extension.js'), + outfile: path.join('./client/dist/extension.cjs'), external: ['vscode'], format: 'cjs', platform: 'node', diff --git a/client/package.json b/client/package.json index 4c7e43a8..e33d84ed 100644 --- a/client/package.json +++ b/client/package.json @@ -3,6 +3,10 @@ "description": "VSCode part of a language server", "license": "MIT", "version": "0.0.1", + "type": "module", + "scripts": { + "compile-ts": "tsc" + }, "engines": { "vscode": "^1.43.0" } diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts deleted file mode 100644 index 5e8e4267..00000000 --- a/client/src/browserClientMain.ts +++ /dev/null @@ -1,127 +0,0 @@ -//* ⚠️ Not currently used in AHK++ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { commands, ExtensionContext, languages, Range, RelativePattern, SnippetString, Uri, window, workspace, WorkspaceEdit } from 'vscode'; -import { LanguageClient } from 'vscode-languageclient/browser'; - -let client: LanguageClient; - -// this method is called when vs code is activated -export function activate(context: ExtensionContext) { - const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browserServerMain.js'); - /* eslint-disable-next-line */ - const request_handlers: Record any> = { - 'ahk2.getActiveTextEditorUriAndPosition': () => { - const editor = window.activeTextEditor; - if (!editor) return; - const uri = editor.document.uri.toString(), position = editor.selection.end; - return { uri, position }; - }, - 'ahk2.insertSnippet': async (params: [string, Range?]) => { - const editor = window.activeTextEditor; - if (!editor) return; - if (params[1]) { - const { start, end } = params[1]; - await editor.insertSnippet(new SnippetString(params[0]), new Range(start.line, start.character, end.line, end.character)); - } else - editor.insertSnippet(new SnippetString(params[0])); - }, - 'ahk2.setTextDocumentLanguage': async (params: [string, string?]) => { - const lang = params[1] || 'ahk'; - if (!(await languages.getLanguages()).includes(lang)) { - window.showErrorMessage(`Unknown language id: ${lang}`); - return; - } - const uri = params[0], it = workspace.textDocuments.find(it => it.uri.toString() === uri); - it && languages.setTextDocumentLanguage(it, lang); - }, - 'ahk2.getWorkspaceFiles': async (params: string[]) => { - const all = !params.length; - if (workspace.workspaceFolders) { - if (all) - return (await workspace.findFiles('**/*.{ahk,ah2,ahk2}')).forEach(it => it.toString()); - else { - const files: string[] = []; - for (const folder of workspace.workspaceFolders) - if (params.includes(folder.uri.toString().toLowerCase())) - files.push(...(await workspace.findFiles(new RelativePattern(folder, '*.{ahk,ah2,ahk2}'))).map(it => it.toString())); - return files; - } - } - }, - 'ahk2.getWorkspaceFileContent': async (params: string[]) => (await workspace.openTextDocument(Uri.parse(params[0]))).getText() - }; - - client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', { - documentSelector: [{ language: 'ahk2' }], - markdown: { isTrusted: true, supportHtml: true }, - initializationOptions: { - extensionUri: context.extensionUri.toString(), - commands: Object.keys(request_handlers), - ...JSON.parse(JSON.stringify(workspace.getConfiguration('AutoHotkey2'))) - } - }, new Worker(serverMain.toString())); - - context.subscriptions.push( - commands.registerTextEditorCommand('ahk2.update.versioninfo', async textEditor => { - const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); - if (!infos?.length) { - await textEditor.insertSnippet(new SnippetString([ - "/************************************************************************", - " * @description ${1:}", - " * @author ${2:}", - " * @date ${3:$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE}", - " * @version ${4:0.0.0}", - " ***********************************************************************/", - "", "" - ].join('\n')), new Range(0, 0, 0, 0)); - } else { - const d = new Date; - let contents: string[] = [], value: string | undefined; - for (const info of infos) { - if (info.single) - contents.push(info.content.replace( - /(?<=^;\s*@ahk2exe-setversion\s+)(\S+|(?=[\r\n]))/i, - s => (value ||= s, '\0'))); - else contents.push(info.content.replace( - /(?<=^\s*[;*]?\s*@date[:\s]\s*)(\S+|(?=[\r\n]))/im, - date => [d.getFullYear(), d.getMonth() + 1, d.getDate()].map( - n => n.toString().padStart(2, '0')).join(date.includes('.') ? '.' : '/') - ).replace(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S+|(?=[\r\n]))/im, s => (value ||= s, '\0'))); - } - if (value !== undefined) { - value = await window.showInputBox({ - value, prompt: 'Enter version info' - }); - if (!value) - return; - contents = contents.map(s => s.replace('\0', value!)); - } - const ed = new WorkspaceEdit(), uri = textEditor.document.uri; - infos.forEach(it => it.content !== (value = contents.shift()) && - ed.replace(uri, it.range, value!)); - ed.size && workspace.applyEdit(ed); - } - }), - commands.registerTextEditorCommand('ahk2.switch', textEditor => { - const doc = textEditor.document; - languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); - }), - workspace.onDidCloseTextDocument(e => { - client.sendNotification('onDidCloseTextDocument', e.isClosed ? - { uri: '', id: '' } : { uri: e.uri.toString(), id: e.languageId }); - }) - ); - - client.start().then(() => { - Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); - }); -} - -export function deactivate() { - return client?.stop(); -} \ No newline at end of file diff --git a/client/src/config.ts b/client/src/config.cts similarity index 100% rename from client/src/config.ts rename to client/src/config.cts diff --git a/client/src/extension.ts b/client/src/extension.cts similarity index 95% rename from client/src/extension.ts rename to client/src/extension.cts index 112d1ade..df10cbc5 100644 --- a/client/src/extension.ts +++ b/client/src/extension.cts @@ -29,17 +29,17 @@ import { LanguageClientOptions, ServerOptions, TransportKind -} from 'vscode-languageclient/node'; +} from 'vscode-languageclient/node.js'; import { resolve } from 'path'; import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, readFileSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; -import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config'; -import { resolvePath } from './utils'; +import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config.cjs'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); let v2Interpreter = getCfg(CfgKey.InterpreterPathV2), server_is_ready = false const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; +const isWindows = process.platform === 'win32'; let extlist: string[] = [], debugexts: Record = {}, langs: string[] = []; const loadedCollection = { 'ahk2.browse': 'Browse your file system to find AutoHotkey2 interpreter', @@ -61,8 +61,11 @@ const loadedCollection = { }; export function activate(context: ExtensionContext): Promise { + // when debugging, this goes into the Debug Console (Ctrl + Shift + Y) + console.log('Activating AHK v2 language server'); + /** Absolute path to `server.js` */ - const defaultServerModule = context.asAbsolutePath(`ahk2/server/dist/server.js`); + const defaultServerModule = context.asAbsolutePath(`ahk2/server/dist/server.cjs`); const serverModule = process.env.VSCODE_AHK_SERVER_PATH ? context.asAbsolutePath(process.env.VSCODE_AHK_SERVER_PATH) : defaultServerModule; // If the extension is launched in debug mode then the debug server options are used @@ -623,6 +626,34 @@ async function onDidChangegetInterpreter() { } } +/** + * Returns the provided path as an absolute path. + * Resolves the provided path against the provided workspace. + * Resolves symbolic links by default. + * Returns empty string if resolution fails. + */ +export function resolvePath(path: string | undefined, workspace?: string, resolveSymbolicLink = true): string { + if (!path) + return ''; + const paths: string[] = []; + // If the path does not contain a colon, resolve it relative to the workspace + if (!path.includes(':')) + paths.push(resolve(workspace ?? '', path)); + // If there are no slashes or backslashes in the path and the platform is Windows + if (!/[\\/]/.test(path) && isWindows) + paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); + paths.push(path); + for (let path of paths) { + if (!path) continue; + try { + if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) + path = resolve(path, '..', readlinkSync(path)); + return path; + } catch { } + } + return ''; +} + /** * Returns whether the given path exists. * Only returns false if lstatSync give an ENOENT error. diff --git a/client/src/extension.e2e.ts b/client/src/extension.e2e.ts deleted file mode 100644 index 38393599..00000000 --- a/client/src/extension.e2e.ts +++ /dev/null @@ -1,234 +0,0 @@ -import * as assert from 'assert'; -import * as vscode from 'vscode'; -import { resolve } from 'path'; -import { - LanguageClient, - CompletionRequest, - CompletionParams, - CompletionItem, - DocumentSymbolRequest, - DocumentSymbolParams, - SymbolInformation, - DefinitionRequest, - DefinitionParams, - LocationLink, - DocumentFormattingRequest, - DocumentFormattingParams, - TextEdit, - FoldingRangeRequest, - FoldingRangeParams, - FoldingRange, - HoverRequest, - HoverParams, - Hover, - PrepareRenameRequest, - PrepareRenameParams, - ReferencesRequest, - ReferenceParams, - Location, - RenameRequest, - RenameParams, - WorkspaceEdit, - SignatureHelpRequest, - SignatureHelpParams, - SignatureHelp, - SemanticTokensRequest, - SemanticTokensParams, - SemanticTokens, - WorkspaceSymbolRequest, - WorkspaceSymbolParams, - ExecuteCommandRequest, - ExecuteCommandParams, -} from 'vscode-languageclient/node'; - -suite('Start ahk language server', () => { - test('should be running', async () => { - await vscode.commands.executeCommand( - 'workbench.action.closeAllEditors', - ); - const client: LanguageClient = await vscode.extensions - .getExtension('thqby.vscode-autohotkey2-lsp') - ?.activate(); - assert.equal(client?.isRunning(), true); - - suite('Open ahk file', () => { - test('should be opened', async () => { - const path = resolve( - __dirname, - '../../../server/dist/ahkProvider.ahk', - ); - let document = ( - await vscode.window.showTextDocument( - await vscode.workspace.openTextDocument(path), - ) - ).document; - const uri = document.uri.toString(); - if (document.languageId !== 'ahk2') - document = await vscode.languages.setTextDocumentLanguage( - document, - 'ahk2', - ); - const content = (await client!.sendRequest( - 'ahk2.getContent', - uri, - )) as string; - assert.equal(document.getText() === content, true); - - suite('Test language server features', () => { - const textDocument = { uri }; - const position = { line: 10, character: 5 }; - - test(CompletionRequest.method, async function () { - const params: CompletionParams = { - textDocument, - position, - }; - const result: CompletionItem[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(DefinitionRequest.method, async function () { - const params: DefinitionParams = { - textDocument, - position, - }; - const result: LocationLink[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(DocumentFormattingRequest.method, async function () { - const params: DocumentFormattingParams = { - textDocument, - options: { insertSpaces: false, tabSize: 4 }, - }; - const result: TextEdit[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(DocumentSymbolRequest.method, async function () { - const params: DocumentSymbolParams = { textDocument }; - const result: SymbolInformation[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(FoldingRangeRequest.method, async function () { - const params: FoldingRangeParams = { textDocument }; - const result: FoldingRange[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(HoverRequest.method, async function () { - const params: HoverParams = { textDocument, position }; - const result: Hover | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.contents); - }); - - test(PrepareRenameRequest.method, async function () { - const params: PrepareRenameParams = { - textDocument, - position, - }; - const result: unknown | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result); - }); - - test(ReferencesRequest.method, async function () { - const params: ReferenceParams = { - textDocument, - position, - context: { includeDeclaration: true }, - }; - const result: Location[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(RenameRequest.method, async function () { - const params: RenameParams = { - textDocument, - position, - newName: '', - }; - const result: WorkspaceEdit | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.changes); - }); - - test(SignatureHelpRequest.method, async function () { - const params: SignatureHelpParams = { - textDocument, - position: { line: 8, character: 36 }, - }; - const result: SignatureHelp | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.signatures); - }); - - test(ExecuteCommandRequest.method, async function () { - const params: ExecuteCommandParams = { - command: 'ahk2.diagnose.all', - }; - await client.sendRequest(this.runnable().title, params); - }); - - test(WorkspaceSymbolRequest.method, async function () { - const params: WorkspaceSymbolParams = { query: 'msg' }; - const result: SymbolInformation[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(SemanticTokensRequest.method, async function () { - const params: SemanticTokensParams = { textDocument }; - const result: SemanticTokens | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.data); - }); - }); - }); - }); - }); -}); diff --git a/client/src/utils.test.ts b/client/src/utils.test.ts deleted file mode 100644 index b40f75ba..00000000 --- a/client/src/utils.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { expect, test, describe, vi, beforeAll, afterAll } from 'vitest'; -import { resolvePath } from './utils'; - -describe('resolvePath', () => { - beforeAll(() => { - // Mock the behavior of fs.lstatSync - vi.mock('fs', () => ({ - lstatSync: (_path: string) => ({ isSymbolicLink: () => false }), - })); - }); - - afterAll(() => { - vi.restoreAllMocks(); - }); - - test.concurrent.each< - [ - name: string, - args: Parameters, - expected: ReturnType, - ] - >([ - ['empty string', [''], ''], - ['absolute path at drive root', ['C:/out.txt'], 'C:/out.txt'], - ])('%s', (_name, args, expected) => { - const result = resolvePath(...args); - expect(result).toBe(expected); - }); -}); diff --git a/client/src/utils.ts b/client/src/utils.ts deleted file mode 100644 index 96242b26..00000000 --- a/client/src/utils.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { execSync } from 'child_process'; -import { lstatSync, readlinkSync } from 'fs'; -import { resolve } from 'path'; - -/** - * Returns the provided path as an absolute path. - * Resolves the provided path against the provided workspace. - * Resolves symbolic links by default. - * Returns empty string if resolution fails. - */ -export function resolvePath( - path: string | undefined, - workspace?: string, - resolveSymbolicLink = true, -): string { - if (!path) return ''; - const paths: string[] = []; - // If the path does not contain a colon, resolve it relative to the workspace - if (!path.includes(':')) paths.push(resolve(workspace ?? '', path)); - // If there are no slashes or backslashes in the path and the platform is Windows - if (!/[\\/]/.test(path) && process.platform === 'win32') - paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); - paths.push(path); - for (let path of paths) { - if (!path) continue; - try { - if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) - path = resolve(path, '..', readlinkSync(path)); - return path; - } catch {} - } - return ''; -} diff --git a/client/tsconfig.json b/client/tsconfig.json index 5f41caf1..0691600f 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -2,12 +2,11 @@ "compilerOptions": { "target": "ES2022", "lib": ["ES2022", "WebWorker"], - "module": "commonjs", - "moduleResolution": "node", + "module": "NodeNext", + "moduleResolution": "NodeNext", "sourceMap": true, "strict": true, "outDir": "dist", - "rootDirs": ["src", "../server/src"], "composite": true }, "include": ["src"], diff --git a/package-lock.json b/package-lock.json index efc81e67..3d0f8aaf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,6 @@ "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", - "@vitest/coverage-v8": "^2.1.1", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", @@ -34,7 +33,6 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", - "vitest": "^2.1.1", "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" @@ -43,20 +41,6 @@ "vscode": "^1.82.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -71,16 +55,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-validator-identifier": { "version": "7.24.7", "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", @@ -107,37 +81,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.6" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -819,9 +762,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.4.15", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true, "license": "MIT" }, @@ -929,230 +872,6 @@ "node": ">=18" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -1418,40 +1137,30 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@vitest/coverage-v8": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/coverage-v8/-/coverage-v8-2.1.1.tgz", - "integrity": "sha512-md/A7A3c42oTT8JUHSqjP5uKTWJejzUW4jalpvs+rZ27gsURsMU8DEb+8Jf8C6Kj2gwfSHJqobDNBuoqlm0cFw==", + "node_modules/@vscode/test-cli": { + "version": "0.0.10", + "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", + "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", "dev": true, - "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.6", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.6", - "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.11", - "magicast": "^0.3.4", - "std-env": "^3.7.0", - "test-exclude": "^7.0.1", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" }, - "peerDependencies": { - "@vitest/browser": "2.1.1", - "vitest": "2.1.1" + "bin": { + "vscode-test": "out/bin.mjs" }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } + "engines": { + "node": ">=18" } }, - "node_modules/@vitest/coverage-v8/node_modules/brace-expansion": { + "node_modules/@vscode/test-cli/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -1461,7 +1170,7 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@vitest/coverage-v8/node_modules/glob": { + "node_modules/@vscode/test-cli/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", @@ -1482,7 +1191,7 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vitest/coverage-v8/node_modules/minimatch": { + "node_modules/@vscode/test-cli/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", @@ -1498,238 +1207,39 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vitest/coverage-v8/node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "node_modules/@vscode/test-cli/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@vitest/expect": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/expect/-/expect-2.1.1.tgz", - "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", + "node_modules/@vscode/test-electron": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", + "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", "dev": true, - "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", - "chai": "^5.1.1", - "tinyrainbow": "^1.2.0" + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^7.0.1", + "semver": "^7.6.2" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">=16" } }, - "node_modules/@vitest/mocker": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/mocker/-/mocker-2.1.1.tgz", - "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "^2.1.0-beta.1", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/spy": "2.1.1", - "msw": "^2.3.5", - "vite": "^5.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", - "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/runner/-/runner-2.1.1.tgz", - "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "2.1.1", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/snapshot/-/snapshot-2.1.1.tgz", - "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.1", - "magic-string": "^0.30.11", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/spy/-/spy-2.1.1.tgz", - "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^3.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/utils/-/utils-2.1.1.tgz", - "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.1", - "loupe": "^3.1.1", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vscode/test-cli": { - "version": "0.0.10", - "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", - "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", - "dev": true, - "dependencies": { - "@types/mocha": "^10.0.2", - "c8": "^9.1.0", - "chokidar": "^3.5.3", - "enhanced-resolve": "^5.15.0", - "glob": "^10.3.10", - "minimatch": "^9.0.3", - "mocha": "^10.2.0", - "supports-color": "^9.4.0", - "yargs": "^17.7.2" - }, - "bin": { - "vscode-test": "out/bin.mjs" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@vscode/test-cli/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@vscode/test-cli/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/test-cli/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/test-cli/node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/@vscode/test-electron": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", - "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "jszip": "^3.10.1", - "ora": "^7.0.1", - "semver": "^7.6.2" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@vscode/test-web": { - "version": "0.0.56", - "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", - "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", + "node_modules/@vscode/test-web": { + "version": "0.0.56", + "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", + "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", "dev": true, "license": "MIT", "dependencies": { @@ -2222,16 +1732,6 @@ "node": ">=0.10.0" } }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmmirror.com/b4a/-/b4a-1.6.6.tgz", @@ -2529,16 +2029,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmmirror.com/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cache-content-type": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/cache-content-type/-/cache-content-type-1.0.1.tgz", @@ -2616,23 +2106,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", @@ -2648,16 +2121,6 @@ "node": ">=4" } }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", @@ -2976,13 +2439,13 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.3.5", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "ms": "2.1.2" }, "engines": { "node": ">=6.0" @@ -3043,16 +2506,6 @@ "node": ">=0.10.0" } }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmmirror.com/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.0.1.tgz", @@ -3770,16 +3223,6 @@ "node": ">=4.0" } }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", @@ -4018,16 +3461,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/get-stdin": { "version": "9.0.0", "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-9.0.0.tgz", @@ -4734,21 +4167,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmmirror.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/istanbul-reports": { "version": "3.1.7", "resolved": "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz", @@ -5310,16 +4728,6 @@ "node": ">=8" } }, - "node_modules/loupe": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/loupe/-/loupe-3.1.1.tgz", - "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", @@ -5333,28 +4741,6 @@ "node": ">=10" } }, - "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/magicast": { - "version": "0.3.5", - "resolved": "https://registry.npmmirror.com/magicast/-/magicast-0.3.5.tgz", - "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.4", - "@babel/types": "^7.25.4", - "source-map-js": "^1.2.0" - } - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-4.0.0.tgz", @@ -5776,6 +5162,13 @@ "node": ">=10" } }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/mocha/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", @@ -5947,31 +5340,12 @@ } }, "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, "license": "MIT" }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6417,23 +5791,6 @@ "node": ">=8" } }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, "node_modules/peek-stream": { "version": "1.1.3", "resolved": "https://registry.npmmirror.com/peek-stream/-/peek-stream-1.1.3.tgz", @@ -6447,9 +5804,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true, "license": "ISC" }, @@ -6511,35 +5868,6 @@ "node": ">=18" } }, - "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6992,42 +6320,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", - "fsevents": "~2.3.2" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7163,13 +6455,6 @@ "node": ">=8" } }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", @@ -7318,16 +6603,6 @@ "node": ">= 8" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", @@ -7385,13 +6660,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmmirror.com/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", @@ -7402,13 +6670,6 @@ "node": ">= 0.8" } }, - "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmmirror.com/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true, - "license": "MIT" - }, "node_modules/stdin-discarder": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", @@ -7777,60 +7038,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmmirror.com/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinypool": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/tinypool/-/tinypool-1.0.1.tgz", - "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8283,598 +7490,6 @@ "node": ">= 0.8" } }, - "node_modules/vite": { - "version": "5.4.8", - "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.8.tgz", - "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/vite-node/-/vite-node-2.1.1.tgz", - "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.6", - "pathe": "^1.1.2", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vite/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/vitest": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/vitest/-/vitest-2.1.1.tgz", - "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.1", - "@vitest/mocker": "2.1.1", - "@vitest/pretty-format": "^2.1.1", - "@vitest/runner": "2.1.1", - "@vitest/snapshot": "2.1.1", - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", - "chai": "^5.1.1", - "debug": "^4.3.6", - "magic-string": "^0.30.11", - "pathe": "^1.1.2", - "std-env": "^3.7.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.0", - "tinypool": "^1.0.0", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.1", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.1", - "@vitest/ui": "2.1.1", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", @@ -9174,23 +7789,6 @@ "node": ">= 8" } }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.1.tgz", diff --git a/package.json b/package.json index 271be642..7dabd667 100644 --- a/package.json +++ b/package.json @@ -34,10 +34,10 @@ "build:dev": "node build.mjs", "build:old": "webpack", "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", - "clean": "del-cli client/dist server/dist/*.js*", + "clean": "del-cli client/dist server/dist/*.js* server/dist/*.cjs", "clean//": "Remove both the compiled extension and compiled test files", "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", - "compile-ts": "cd client && tsc && cd ../server && tsc", + "compile-ts": "cd client && npm run compile-ts && cd ../server && npm run compile-ts", "compile-ts//": "Compile TS files", "compile//": "Compile the extension for packaging and publishing", "eslint": "npm run eslint:files -- client server && echo No ESLint problems", @@ -49,17 +49,9 @@ "lint:fix": "npm run format:fix && npm run eslint:fix && npm run sort-package-json:fix", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", - "test": "npm run test:e2e", - "test//": "echo Run e2e tests (open VS Code), not grammar tests", - "test:ci": "npm run test:unit", - "pretest:e2e": "npm run compile-ts", - "test:e2e": "cd client && vscode-test", - "test:e2e//": "echo todo failing for now, will be adding pure unit tests soon", - "test:unit": "vitest --run", - "validate": "npm run lint && npm run test", - "validate:ci": "npm run lint && npm run test:ci", - "validate:ci:fix": "npm run lint:fix && npm run test:ci", - "validate:ci:fix//": "echo Fix validation issues first, then run remaining checks until failure", + "validate": "npm run lint", + "validate:ci": "npm run lint", + "validate:ci:fix": "npm run lint:fix", "watch": "tsc -b -w" }, "prettier": { @@ -90,7 +82,6 @@ "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", - "@vitest/coverage-v8": "^2.1.1", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", @@ -105,7 +96,6 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", - "vitest": "^2.1.1", "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" diff --git a/server/cli/cli.ts b/server/cli/cli.ts index 71a29d2a..c3624475 100644 --- a/server/cli/cli.ts +++ b/server/cli/cli.ts @@ -1,6 +1,6 @@ -import { openFile } from '../src/common'; -import { newFormatterConfig } from '../src/config'; -import { Lexer } from '../src/Lexer'; +import { openFile } from '../src/common.js'; +import { newFormatterConfig } from '../src/config.js'; +import { Lexer } from '../src/Lexer.js'; function main() { const options: Record = {}; diff --git a/server/package.json b/server/package.json index 403a1a88..f3d001a0 100644 --- a/server/package.json +++ b/server/package.json @@ -2,6 +2,10 @@ "name": "vscode-autohotkey2-server", "description": "Autohotkey2 Language Server using vscode-lsp.", "license": "LGPLv3.0", + "type": "module", + "scripts": { + "compile-ts": "tsc" + }, "engines": { "node": "*" }, diff --git a/server/src/Lexer.ts b/server/src/Lexer.ts index c0d1b59a..7f1550a2 100644 --- a/server/src/Lexer.ts +++ b/server/src/Lexer.ts @@ -18,14 +18,14 @@ import { import { TextDocument } from 'vscode-languageserver-textdocument'; import { URI } from 'vscode-uri'; -import { builtin_ahkv1_commands, builtin_variable, builtin_variable_h } from './constants'; -import { action, completionitem, diagnostic, warn } from './localize'; +import { builtin_ahkv1_commands, builtin_variable, builtin_variable_h } from './constants.js'; +import { action, completionitem, diagnostic, warn } from './localize.js'; import { a_vars, ahk_version, ahkuris, ahkvars, alpha_3, connection, ahkppConfig, hoverCache, isBrowser, isahk2_h, lexers, libdirs, libfuncs, locale, openAndParse, openFile, restorePath, rootdir, setTextDocumentLanguage, symbolProvider, utils, workspaceFolders -} from './common'; -import { newFormatterConfig, FormatterConfig, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses, getCfg, CfgKey } from './config'; +} from './common.js'; +import { newFormatterConfig, FormatterConfig, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses, getCfg, CfgKey } from './config.js'; export interface ParamInfo { offset: number diff --git a/server/src/ahkProvider.ts b/server/src/ahkProvider.ts index 6531fbaa..0958723a 100644 --- a/server/src/ahkProvider.ts +++ b/server/src/ahkProvider.ts @@ -1,7 +1,7 @@ -import { createClientSocketTransport, createMessageConnection, createServerSocketTransport, MessageConnection } from 'vscode-languageserver/node'; +import { createClientSocketTransport, createMessageConnection, createServerSocketTransport, MessageConnection } from 'vscode-languageserver/node.js'; import { spawn } from 'child_process'; -import { resolvePath } from './scriptrunner'; -import { interpreterPathV2, isWindows, rootdir } from './common'; +import { resolvePath } from './scriptrunner.js'; +import { interpreterPathV2, isWindows, rootdir } from './common.js'; let ahk_server: MessageConnection | undefined | null; async function get_ahkProvider_port(): Promise { diff --git a/server/src/browserServerMain.ts b/server/src/browserServerMain.ts index c7c9bb29..32995e3e 100644 --- a/server/src/browserServerMain.ts +++ b/server/src/browserServerMain.ts @@ -6,7 +6,7 @@ import { TextDocument } from 'vscode-languageserver-textdocument'; import { createConnection, BrowserMessageReader, BrowserMessageWriter, DidChangeConfigurationNotification, InitializeResult, TextDocuments, TextDocumentSyncKind -} from 'vscode-languageserver/browser'; +} from 'vscode-languageserver/browser.js'; import { chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, defintionProvider, documentFormatting, enumNames, executeCommandProvider, exportSymbols, getVersionInfo, @@ -14,8 +14,8 @@ import { referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, signatureProvider, symbolProvider, typeFormatting, updateAhkppConfig, workspaceSymbolProvider -} from './common'; -import { AhkppConfig } from './config'; +} from './common.js'; +import { AhkppConfig } from './config.js'; const languageServer = 'ahk2-language-server'; const messageReader = new BrowserMessageReader(self); diff --git a/server/src/codeActionProvider.ts b/server/src/codeActionProvider.ts index 602ec3c0..bc82986b 100644 --- a/server/src/codeActionProvider.ts +++ b/server/src/codeActionProvider.ts @@ -1,7 +1,7 @@ import { readdirSync } from 'fs'; import { CancellationToken, CodeAction, CodeActionKind, CodeActionParams, TextEdit } from 'vscode-languageserver'; -import { codeaction, diagnostic } from './localize'; -import { Maybe, lexers, restorePath, warn } from './common'; +import { codeaction, diagnostic } from './localize.js'; +import { Maybe, lexers, restorePath, warn } from './common.js'; export async function codeActionProvider(params: CodeActionParams, token: CancellationToken): Promise> { const uri = params.textDocument.uri, lex = lexers[uri.toLowerCase()], document = lex?.document; diff --git a/server/src/colorProvider.ts b/server/src/colorProvider.ts index 38177f0b..d44fa0fe 100644 --- a/server/src/colorProvider.ts +++ b/server/src/colorProvider.ts @@ -1,5 +1,5 @@ import { CancellationToken, ColorInformation, ColorPresentation, ColorPresentationParams, DocumentColorParams } from 'vscode-languageserver'; -import { Maybe, lexers } from './common'; +import { Maybe, lexers } from './common.js'; export async function colorPresentation(params: ColorPresentationParams, token: CancellationToken): Promise> { const { range, color, textDocument: { uri } } = params, text = lexers[uri.toLowerCase()]?.document.getText(range); diff --git a/server/src/commandProvider.ts b/server/src/commandProvider.ts index 1ee3f571..aeeb167e 100644 --- a/server/src/commandProvider.ts +++ b/server/src/commandProvider.ts @@ -4,7 +4,7 @@ import { connection, ahkppConfig, find_class, generate_type_annotation, join_types, lexers, parse_include, restorePath, semanticTokensOnFull, traverse_include, update_include_cache -} from './common'; +} from './common.js'; function checkCommand(cmd: string) { if (ahkppConfig.commands?.includes(cmd)) diff --git a/server/src/common.ts b/server/src/common.ts index b9274c62..51391d0d 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -4,25 +4,25 @@ import { readdirSync, readFileSync, existsSync, statSync, promises as fs } from import { Connection, MessageConnection } from 'vscode-languageserver'; import { TextDocument } from 'vscode-languageserver-textdocument'; import { CompletionItem, CompletionItemKind, Hover, InsertTextFormat, Range, SymbolKind } from 'vscode-languageserver-types'; -import { AhkSymbol, Lexer, setCommentTagRegex } from './Lexer'; -import { diagnostic } from './localize'; -import { isBrowser, jsDocTagNames } from './constants'; -import { AhkppConfig, CfgKey, getCfg, newAhkppConfig } from './config'; -export * from './codeActionProvider'; -export * from './colorProvider'; -export * from './commandProvider'; -export * from './completionProvider'; -export * from './constants'; -export * from './definitionProvider'; -export * from './formattingProvider'; -export * from './hoverProvider'; -export * from './Lexer'; -export * from './localize'; -export * from './referencesProvider'; -export * from './renameProvider'; -export * from './semanticTokensProvider'; -export * from './signatureProvider'; -export * from './symbolProvider'; +import { AhkSymbol, Lexer, setCommentTagRegex } from './Lexer.js'; +import { diagnostic } from './localize.js'; +import { isBrowser, jsDocTagNames } from './constants.js'; +import { AhkppConfig, CfgKey, getCfg, newAhkppConfig } from './config.js'; +export * from './codeActionProvider.js'; +export * from './colorProvider.js'; +export * from './commandProvider.js'; +export * from './completionProvider.js'; +export * from './constants.js'; +export * from './definitionProvider.js'; +export * from './formattingProvider.js'; +export * from './hoverProvider.js'; +export * from './Lexer.js'; +export * from './localize.js'; +export * from './referencesProvider.js'; +export * from './renameProvider.js'; +export * from './semanticTokensProvider.js'; +export * from './signatureProvider.js'; +export * from './symbolProvider.js'; export const winapis: string[] = []; export const lexers: Record = {}; diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index 3ba3144f..02863510 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -11,9 +11,9 @@ import { decltype_expr, dllcalltpe, ahkppConfig, find_class, find_symbol, find_symbols, get_detail, generate_fn_comment, get_callinfo, get_class_constructor, get_class_member, get_class_members, isBrowser, lexers, libfuncs, make_search_re, sendAhkRequest, utils, winapis, -} from './common'; -import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; -import { BraceStyle, CompletionCommitCharacters, CfgKey, FormatterConfig, getCfg } from './config'; +} from './common.js'; +import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils.js'; +import { BraceStyle, CompletionCommitCharacters, CfgKey, FormatterConfig, getCfg } from './config.js'; export async function completionProvider(params: CompletionParams, _token: CancellationToken): Promise> { let { position, textDocument: { uri } } = params; diff --git a/server/src/definitionProvider.ts b/server/src/definitionProvider.ts index a9af1520..99f3bfb0 100644 --- a/server/src/definitionProvider.ts +++ b/server/src/definitionProvider.ts @@ -1,5 +1,5 @@ import { DefinitionParams, LocationLink, SymbolKind, Range, CancellationToken } from 'vscode-languageserver'; -import { AhkSymbol, lexers, restorePath, find_symbols, Token } from './common'; +import { AhkSymbol, lexers, restorePath, find_symbols, Token } from './common.js'; import { URI } from 'vscode-uri'; export async function defintionProvider(params: DefinitionParams, token: CancellationToken): Promise { diff --git a/server/src/formattingProvider.ts b/server/src/formattingProvider.ts index 1c7fa8ad..f6c50915 100644 --- a/server/src/formattingProvider.ts +++ b/server/src/formattingProvider.ts @@ -1,6 +1,6 @@ import { DocumentFormattingParams, DocumentOnTypeFormattingParams, DocumentRangeFormattingParams, Position, Range, TextEdit } from 'vscode-languageserver'; -import { chinese_punctuations, ahkppConfig, lexers, Token } from './common'; -import { FormatterConfig } from './config'; +import { chinese_punctuations, ahkppConfig, lexers, Token } from './common.js'; +import { FormatterConfig } from './config.js'; export async function documentFormatting(params: DocumentFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], range = Range.create(0, 0, doc.document.lineCount, 0); diff --git a/server/src/hoverProvider.ts b/server/src/hoverProvider.ts index 7007ee03..731f8c1e 100644 --- a/server/src/hoverProvider.ts +++ b/server/src/hoverProvider.ts @@ -2,7 +2,7 @@ import { CancellationToken, Hover, HoverParams, SymbolKind } from 'vscode-langua import { AhkSymbol, FuncNode, Maybe, SemanticTokenTypes, Variable, get_detail, hoverCache, join_types, lexers, find_symbols -} from './common'; +} from './common.js'; export async function hoverProvider(params: HoverParams, token: CancellationToken): Promise> { if (token.isCancellationRequested) return; diff --git a/server/src/localize.ts b/server/src/localize.ts index b3e95a44..11ba9a6d 100644 --- a/server/src/localize.ts +++ b/server/src/localize.ts @@ -1,5 +1,5 @@ -import { rootdir, getlocalefile, getwebfile, isBrowser } from './common'; -import { CfgKey } from './config'; +import { rootdir, getlocalefile, getwebfile, isBrowser } from './common.js'; +import { CfgKey } from './config.js'; let loadedCollection: Record = {}; diff --git a/server/src/referencesProvider.ts b/server/src/referencesProvider.ts index 506dc15c..a82796aa 100644 --- a/server/src/referencesProvider.ts +++ b/server/src/referencesProvider.ts @@ -2,7 +2,7 @@ import { CancellationToken, Location, Range, ReferenceParams, SymbolKind } from import { AhkSymbol, ClassNode, Context, FuncNode, FuncScope, Lexer, Property, Variable, ahkuris, ahkvars, find_symbol, find_symbols, lexers -} from './common'; +} from './common.js'; export async function referenceProvider(params: ReferenceParams, token: CancellationToken): Promise { const result: Location[] = [], doc = lexers[params.textDocument.uri.toLowerCase()]; diff --git a/server/src/renameProvider.ts b/server/src/renameProvider.ts index aa8d8fde..647bc716 100644 --- a/server/src/renameProvider.ts +++ b/server/src/renameProvider.ts @@ -1,6 +1,6 @@ import { CancellationToken, PrepareRenameParams, Range, RenameParams, WorkspaceEdit } from 'vscode-languageserver'; import { ResponseError } from 'vscode-jsonrpc'; -import { Maybe, lexers, getAllReferences, response } from './common'; +import { Maybe, lexers, getAllReferences, response } from './common.js'; let renameranges: Record | null | undefined; diff --git a/server/src/scriptrunner.ts b/server/src/scriptrunner.ts index 68900eef..be247232 100644 --- a/server/src/scriptrunner.ts +++ b/server/src/scriptrunner.ts @@ -1,5 +1,5 @@ import { execSync, spawnSync } from 'child_process'; -import { interpreterPathV2, isWindows } from './common'; +import { interpreterPathV2, isWindows } from './common.js'; import { lstatSync, readlinkSync } from 'fs'; import { resolve } from 'path'; diff --git a/server/src/semanticTokensProvider.ts b/server/src/semanticTokensProvider.ts index 459127a7..cdb4fa4a 100644 --- a/server/src/semanticTokensProvider.ts +++ b/server/src/semanticTokensProvider.ts @@ -2,8 +2,8 @@ import { CancellationToken, DocumentSymbol, Range, SemanticTokens, SemanticToken import { ASSIGN_TYPE, AhkSymbol, ClassNode, FuncNode, Lexer, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, Token, Variable, checkParams, diagnostic, ahkppConfig, get_class_member, get_class_members, globalsymbolcache, lexers, symbolProvider -} from './common'; -import { CfgKey, getCfg } from './config'; +} from './common.js'; +import { CfgKey, getCfg } from './config.js'; let curclass: ClassNode | undefined; const memscache = new Map>(); diff --git a/server/src/server.ts b/server/src/server.ts index 46d3b0f9..764aa163 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -8,9 +8,9 @@ import { SymbolKind, TextDocuments, TextDocumentSyncKind, -} from 'vscode-languageserver/node'; +} from 'vscode-languageserver/node.js'; import { URI } from 'vscode-uri'; -import { get_ahkProvider } from './ahkProvider'; +import { get_ahkProvider } from './ahkProvider.js'; import { a_vars, interpreterPathV2, @@ -67,12 +67,12 @@ import { getVersionInfo, builtin_variable, builtin_variable_h, -} from './common'; -import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; -import { resolvePath, runscript } from './scriptrunner'; +} from './common.js'; +import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile.js'; +import { resolvePath, runscript } from './scriptrunner.js'; import { TextDecoder } from 'util'; -import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; -import { AhkppConfig, CfgKey, getCfg, LibrarySuggestions } from './config'; +import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils.js'; +import { AhkppConfig, CfgKey, getCfg, LibrarySuggestions } from './config.js'; const languageServer = 'ahk2-language-server'; const documents = new TextDocuments(TextDocument); @@ -86,6 +86,9 @@ commands['ahk++.v2.setIntepreterPath'] = (args: string[]) => setInterpreter(args[0].replace(/^[A-Z]:/, (m) => m.toLowerCase())); connection.onInitialize(async (params) => { + // Shows up in extension development host + // Output > AHK++ + connection.console.log(`Initializing language server`); const capabilities = params.capabilities; hasConfigurationCapability = !!( capabilities.workspace && !!capabilities.workspace.configuration diff --git a/server/src/signatureProvider.ts b/server/src/signatureProvider.ts index e6980fff..fe23e14a 100644 --- a/server/src/signatureProvider.ts +++ b/server/src/signatureProvider.ts @@ -4,7 +4,7 @@ import { ANY, AhkSymbol, ClassNode, FuncNode, Lexer, Maybe, Variable, ahkuris, decltype_expr, decltype_invoke, decltype_returns, get_detail, get_callinfo, get_class_constructor, get_class_member, lexers -} from './common'; +} from './common.js'; let cache: { index?: number, diff --git a/server/src/symbolProvider.ts b/server/src/symbolProvider.ts index 4cbb8c8a..cacb259c 100644 --- a/server/src/symbolProvider.ts +++ b/server/src/symbolProvider.ts @@ -10,8 +10,8 @@ import { ahkuris, ahkvars, check_same_name_error, connection, decltype_expr, diagnostic, enum_ahkfiles, ahkppConfig, find_class, get_class_constructor, isBrowser, is_line_continue, lexers, make_same_name_error, openFile, warn, workspaceFolders -} from './common'; -import { CfgKey, getCfg } from './config'; +} from './common.js'; +import { CfgKey, getCfg } from './config.js'; export let globalsymbolcache: Record = {}; diff --git a/server/src/utils.ts b/server/src/utils.ts index 30ff2ff0..831071ad 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -1,4 +1,4 @@ -import { LibrarySuggestions } from './config'; +import { LibrarySuggestions } from './config.js'; export function includeUserAndStandardLibrary( librarySuggestions: LibrarySuggestions, diff --git a/server/tsconfig.json b/server/tsconfig.json index b4758cd2..f219a5b1 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -2,12 +2,11 @@ "compilerOptions": { "target": "ES2022", "lib": ["ES2022", "WebWorker"], - "module": "commonjs", - "moduleResolution": "node", + "module": "NodeNext", + "moduleResolution": "NodeNext", "sourceMap": true, "strict": true, - "outDir": "out", - "rootDirs": ["src", "../client/src"] + "outDir": "out" }, "include": ["src"], "exclude": ["node_modules", ".vscode-test", ".vscode-test-web"] diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index f1057913..00000000 --- a/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "ES2021", - "lib": ["ES2021"], - "outDir": "out", - "rootDir": "src", - "sourceMap": true, - "composite": true - }, - "include": ["src"], - "exclude": ["node_modules", ".vscode-test"], - "references": [{ "path": "./client" }, { "path": "./server" }] -} diff --git a/vitest.config.mjs b/vitest.config.mjs deleted file mode 100644 index 1b0aa0f2..00000000 --- a/vitest.config.mjs +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from 'vitest/config'; - -// https://vitest.dev/config -// https://vitest.dev/guide/improving-performance.html -export default defineConfig({ - test: { - isolate: false, - pool: 'threads', - coverage: { - enabled: true, - }, - }, -}); From 6e22b4279bc294b1b61b82c2b0e28428aeb4cd5e Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 28 Sep 2024 14:38:38 -0700 Subject: [PATCH 35/60] Revert "Greatly cleanup and works towards ESM" (#33) This reverts commit b10a3ed9d8fff7b659c3d73de35412c60a3740a0. --- .gitignore | 6 +- .prettierignore | 2 +- .vscode-test.mjs | 19 + .vscode/extensions.json | 3 +- .vscode/launch.json | 2 +- .vscode/snippets.code-snippets | 40 + build.mjs | 6 +- client/package.json | 4 - client/src/browserClientMain.ts | 127 ++ client/src/{config.cts => config.ts} | 0 client/src/extension.e2e.ts | 234 +++ client/src/{extension.cts => extension.ts} | 39 +- client/src/utils.test.ts | 29 + client/src/utils.ts | 33 + client/tsconfig.json | 5 +- package-lock.json | 1692 ++++++++++++++++++-- package.json | 20 +- server/cli/cli.ts | 6 +- server/package.json | 4 - server/src/Lexer.ts | 8 +- server/src/ahkProvider.ts | 6 +- server/src/browserServerMain.ts | 6 +- server/src/codeActionProvider.ts | 4 +- server/src/colorProvider.ts | 2 +- server/src/commandProvider.ts | 2 +- server/src/common.ts | 38 +- server/src/completionProvider.ts | 6 +- server/src/definitionProvider.ts | 2 +- server/src/formattingProvider.ts | 4 +- server/src/hoverProvider.ts | 2 +- server/src/localize.ts | 4 +- server/src/referencesProvider.ts | 2 +- server/src/renameProvider.ts | 2 +- server/src/scriptrunner.ts | 2 +- server/src/semanticTokensProvider.ts | 4 +- server/src/server.ts | 17 +- server/src/signatureProvider.ts | 2 +- server/src/symbolProvider.ts | 4 +- server/src/utils.ts | 2 +- server/tsconfig.json | 7 +- tsconfig.json | 14 + vitest.config.mjs | 13 + 42 files changed, 2154 insertions(+), 270 deletions(-) create mode 100644 .vscode-test.mjs create mode 100644 .vscode/snippets.code-snippets create mode 100644 client/src/browserClientMain.ts rename client/src/{config.cts => config.ts} (100%) create mode 100644 client/src/extension.e2e.ts rename client/src/{extension.cts => extension.ts} (95%) create mode 100644 client/src/utils.test.ts create mode 100644 client/src/utils.ts create mode 100644 tsconfig.json create mode 100644 vitest.config.mjs diff --git a/.gitignore b/.gitignore index db4e5649..0e373567 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,9 @@ node_modules *.vsix scripts/* *.js -*.cjs *.js.map *.tsbuildinfo -**/dist/**/*.d.ts \ No newline at end of file +**/dist/**/*.d.ts + +# Vitest +coverage \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index e8bc4a40..2e589f88 100644 --- a/.prettierignore +++ b/.prettierignore @@ -9,7 +9,7 @@ scripts/* server/expr_parser/* client/src/browserClientMain.ts -client/src/extension.cts +client/src/extension.ts client/src/test/utils.ts server/src/ahkProvider.ts server/src/browserServerMain.ts diff --git a/.vscode-test.mjs b/.vscode-test.mjs new file mode 100644 index 00000000..11029cf2 --- /dev/null +++ b/.vscode-test.mjs @@ -0,0 +1,19 @@ +// https://github.com/microsoft/vscode-test-cli +import { defineConfig } from '@vscode/test-cli'; +import { execSync } from 'child_process'; + +let vscode_path = undefined; +try { + const m = execSync( + 'chcp 65001 && reg query HKCR\\vscode\\shell\\open\\command', + { encoding: 'utf8' }, + ).match(/REG_SZ\s+("([^"]+)"|\S+)/); + vscode_path = m[2] || m[1]; +} catch {} + +export default defineConfig({ + files: 'client/dist/test/**/*.e2e.js', + useInstallation: vscode_path && { + fromPath: vscode_path, + }, +}); diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e22fcc88..bb3324e2 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ "recommendations": [ "aaron-bond.better-comments", "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode" + "esbenp.prettier-vscode", + "vitest.explorer" ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index aaee596a..7aae83be 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -34,7 +34,7 @@ "runtimeExecutable": "${execPath}", "args": ["--extensionDevelopmentPath=${workspaceFolder}"], "env": { - "VSCODE_AHK_SERVER_PATH": "server/dist/server.cjs", + "VSCODE_AHK_SERVER_PATH": "server/dist/server.js", "SYNTAXES_PATH": "syntaxes" }, "outFiles": ["${workspaceFolder}/client/dist/**/*.js"], diff --git a/.vscode/snippets.code-snippets b/.vscode/snippets.code-snippets new file mode 100644 index 00000000..3b6b41e3 --- /dev/null +++ b/.vscode/snippets.code-snippets @@ -0,0 +1,40 @@ +{ + // Place your ahk2 workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and + // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope + // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is + // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: + // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. + // Placeholders with the same ids are connected. + // Example: + // "Print to console": { + // "scope": "javascript,typescript", + // "prefix": "log", + // "body": [ + // "console.log('$1');", + // "$2" + // ], + // "description": "Log output to console" + // } + + "Add unit test": { + "scope": "typescript", + "prefix": "describe", + "body": [ + "describe('$1', () => {", + "\ttest.concurrent.each<", + "\t[", + "\t\tname: string,", + "\t\t\targs: Parameters,", + "\t\t\texpected: ReturnType,", + "\t\t]", + "\t>([", + "\t['$2', [$3], $4],", + "\t])('%s', (_name, args, expected) => {", + "\t\tconst result = $1(...args);", + "\t\texpect(result).toBe(expected);", + "\t});", + "});", + ], + "description": "Add Vitest test.concurrent.each in a describe block", + }, +} diff --git a/build.mjs b/build.mjs index d6bc0ddc..0cd27f44 100644 --- a/build.mjs +++ b/build.mjs @@ -14,7 +14,7 @@ console.log( build({ entryPoints: [path.join('./server/src/server.ts')], bundle: true, - outfile: path.join('./server/dist/server.cjs'), + outfile: path.join('./server/dist/server.js'), external: ['vscode'], format: 'cjs', platform: 'node', @@ -25,9 +25,9 @@ build({ // Node client (not necessary for AHK++, but super fast) // https://esbuild.github.io/api build({ - entryPoints: [path.join('./client/src/extension.cts')], + entryPoints: [path.join('./client/src/extension.ts')], bundle: true, - outfile: path.join('./client/dist/extension.cjs'), + outfile: path.join('./client/dist/extension.js'), external: ['vscode'], format: 'cjs', platform: 'node', diff --git a/client/package.json b/client/package.json index e33d84ed..4c7e43a8 100644 --- a/client/package.json +++ b/client/package.json @@ -3,10 +3,6 @@ "description": "VSCode part of a language server", "license": "MIT", "version": "0.0.1", - "type": "module", - "scripts": { - "compile-ts": "tsc" - }, "engines": { "vscode": "^1.43.0" } diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts new file mode 100644 index 00000000..5e8e4267 --- /dev/null +++ b/client/src/browserClientMain.ts @@ -0,0 +1,127 @@ +//* ⚠️ Not currently used in AHK++ + +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { commands, ExtensionContext, languages, Range, RelativePattern, SnippetString, Uri, window, workspace, WorkspaceEdit } from 'vscode'; +import { LanguageClient } from 'vscode-languageclient/browser'; + +let client: LanguageClient; + +// this method is called when vs code is activated +export function activate(context: ExtensionContext) { + const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browserServerMain.js'); + /* eslint-disable-next-line */ + const request_handlers: Record any> = { + 'ahk2.getActiveTextEditorUriAndPosition': () => { + const editor = window.activeTextEditor; + if (!editor) return; + const uri = editor.document.uri.toString(), position = editor.selection.end; + return { uri, position }; + }, + 'ahk2.insertSnippet': async (params: [string, Range?]) => { + const editor = window.activeTextEditor; + if (!editor) return; + if (params[1]) { + const { start, end } = params[1]; + await editor.insertSnippet(new SnippetString(params[0]), new Range(start.line, start.character, end.line, end.character)); + } else + editor.insertSnippet(new SnippetString(params[0])); + }, + 'ahk2.setTextDocumentLanguage': async (params: [string, string?]) => { + const lang = params[1] || 'ahk'; + if (!(await languages.getLanguages()).includes(lang)) { + window.showErrorMessage(`Unknown language id: ${lang}`); + return; + } + const uri = params[0], it = workspace.textDocuments.find(it => it.uri.toString() === uri); + it && languages.setTextDocumentLanguage(it, lang); + }, + 'ahk2.getWorkspaceFiles': async (params: string[]) => { + const all = !params.length; + if (workspace.workspaceFolders) { + if (all) + return (await workspace.findFiles('**/*.{ahk,ah2,ahk2}')).forEach(it => it.toString()); + else { + const files: string[] = []; + for (const folder of workspace.workspaceFolders) + if (params.includes(folder.uri.toString().toLowerCase())) + files.push(...(await workspace.findFiles(new RelativePattern(folder, '*.{ahk,ah2,ahk2}'))).map(it => it.toString())); + return files; + } + } + }, + 'ahk2.getWorkspaceFileContent': async (params: string[]) => (await workspace.openTextDocument(Uri.parse(params[0]))).getText() + }; + + client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', { + documentSelector: [{ language: 'ahk2' }], + markdown: { isTrusted: true, supportHtml: true }, + initializationOptions: { + extensionUri: context.extensionUri.toString(), + commands: Object.keys(request_handlers), + ...JSON.parse(JSON.stringify(workspace.getConfiguration('AutoHotkey2'))) + } + }, new Worker(serverMain.toString())); + + context.subscriptions.push( + commands.registerTextEditorCommand('ahk2.update.versioninfo', async textEditor => { + const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); + if (!infos?.length) { + await textEditor.insertSnippet(new SnippetString([ + "/************************************************************************", + " * @description ${1:}", + " * @author ${2:}", + " * @date ${3:$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE}", + " * @version ${4:0.0.0}", + " ***********************************************************************/", + "", "" + ].join('\n')), new Range(0, 0, 0, 0)); + } else { + const d = new Date; + let contents: string[] = [], value: string | undefined; + for (const info of infos) { + if (info.single) + contents.push(info.content.replace( + /(?<=^;\s*@ahk2exe-setversion\s+)(\S+|(?=[\r\n]))/i, + s => (value ||= s, '\0'))); + else contents.push(info.content.replace( + /(?<=^\s*[;*]?\s*@date[:\s]\s*)(\S+|(?=[\r\n]))/im, + date => [d.getFullYear(), d.getMonth() + 1, d.getDate()].map( + n => n.toString().padStart(2, '0')).join(date.includes('.') ? '.' : '/') + ).replace(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S+|(?=[\r\n]))/im, s => (value ||= s, '\0'))); + } + if (value !== undefined) { + value = await window.showInputBox({ + value, prompt: 'Enter version info' + }); + if (!value) + return; + contents = contents.map(s => s.replace('\0', value!)); + } + const ed = new WorkspaceEdit(), uri = textEditor.document.uri; + infos.forEach(it => it.content !== (value = contents.shift()) && + ed.replace(uri, it.range, value!)); + ed.size && workspace.applyEdit(ed); + } + }), + commands.registerTextEditorCommand('ahk2.switch', textEditor => { + const doc = textEditor.document; + languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); + }), + workspace.onDidCloseTextDocument(e => { + client.sendNotification('onDidCloseTextDocument', e.isClosed ? + { uri: '', id: '' } : { uri: e.uri.toString(), id: e.languageId }); + }) + ); + + client.start().then(() => { + Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); + }); +} + +export function deactivate() { + return client?.stop(); +} \ No newline at end of file diff --git a/client/src/config.cts b/client/src/config.ts similarity index 100% rename from client/src/config.cts rename to client/src/config.ts diff --git a/client/src/extension.e2e.ts b/client/src/extension.e2e.ts new file mode 100644 index 00000000..38393599 --- /dev/null +++ b/client/src/extension.e2e.ts @@ -0,0 +1,234 @@ +import * as assert from 'assert'; +import * as vscode from 'vscode'; +import { resolve } from 'path'; +import { + LanguageClient, + CompletionRequest, + CompletionParams, + CompletionItem, + DocumentSymbolRequest, + DocumentSymbolParams, + SymbolInformation, + DefinitionRequest, + DefinitionParams, + LocationLink, + DocumentFormattingRequest, + DocumentFormattingParams, + TextEdit, + FoldingRangeRequest, + FoldingRangeParams, + FoldingRange, + HoverRequest, + HoverParams, + Hover, + PrepareRenameRequest, + PrepareRenameParams, + ReferencesRequest, + ReferenceParams, + Location, + RenameRequest, + RenameParams, + WorkspaceEdit, + SignatureHelpRequest, + SignatureHelpParams, + SignatureHelp, + SemanticTokensRequest, + SemanticTokensParams, + SemanticTokens, + WorkspaceSymbolRequest, + WorkspaceSymbolParams, + ExecuteCommandRequest, + ExecuteCommandParams, +} from 'vscode-languageclient/node'; + +suite('Start ahk language server', () => { + test('should be running', async () => { + await vscode.commands.executeCommand( + 'workbench.action.closeAllEditors', + ); + const client: LanguageClient = await vscode.extensions + .getExtension('thqby.vscode-autohotkey2-lsp') + ?.activate(); + assert.equal(client?.isRunning(), true); + + suite('Open ahk file', () => { + test('should be opened', async () => { + const path = resolve( + __dirname, + '../../../server/dist/ahkProvider.ahk', + ); + let document = ( + await vscode.window.showTextDocument( + await vscode.workspace.openTextDocument(path), + ) + ).document; + const uri = document.uri.toString(); + if (document.languageId !== 'ahk2') + document = await vscode.languages.setTextDocumentLanguage( + document, + 'ahk2', + ); + const content = (await client!.sendRequest( + 'ahk2.getContent', + uri, + )) as string; + assert.equal(document.getText() === content, true); + + suite('Test language server features', () => { + const textDocument = { uri }; + const position = { line: 10, character: 5 }; + + test(CompletionRequest.method, async function () { + const params: CompletionParams = { + textDocument, + position, + }; + const result: CompletionItem[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(DefinitionRequest.method, async function () { + const params: DefinitionParams = { + textDocument, + position, + }; + const result: LocationLink[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(DocumentFormattingRequest.method, async function () { + const params: DocumentFormattingParams = { + textDocument, + options: { insertSpaces: false, tabSize: 4 }, + }; + const result: TextEdit[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(DocumentSymbolRequest.method, async function () { + const params: DocumentSymbolParams = { textDocument }; + const result: SymbolInformation[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(FoldingRangeRequest.method, async function () { + const params: FoldingRangeParams = { textDocument }; + const result: FoldingRange[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(HoverRequest.method, async function () { + const params: HoverParams = { textDocument, position }; + const result: Hover | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.contents); + }); + + test(PrepareRenameRequest.method, async function () { + const params: PrepareRenameParams = { + textDocument, + position, + }; + const result: unknown | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result); + }); + + test(ReferencesRequest.method, async function () { + const params: ReferenceParams = { + textDocument, + position, + context: { includeDeclaration: true }, + }; + const result: Location[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(RenameRequest.method, async function () { + const params: RenameParams = { + textDocument, + position, + newName: '', + }; + const result: WorkspaceEdit | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.changes); + }); + + test(SignatureHelpRequest.method, async function () { + const params: SignatureHelpParams = { + textDocument, + position: { line: 8, character: 36 }, + }; + const result: SignatureHelp | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.signatures); + }); + + test(ExecuteCommandRequest.method, async function () { + const params: ExecuteCommandParams = { + command: 'ahk2.diagnose.all', + }; + await client.sendRequest(this.runnable().title, params); + }); + + test(WorkspaceSymbolRequest.method, async function () { + const params: WorkspaceSymbolParams = { query: 'msg' }; + const result: SymbolInformation[] | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(SemanticTokensRequest.method, async function () { + const params: SemanticTokensParams = { textDocument }; + const result: SemanticTokens | undefined = + await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.data); + }); + }); + }); + }); + }); +}); diff --git a/client/src/extension.cts b/client/src/extension.ts similarity index 95% rename from client/src/extension.cts rename to client/src/extension.ts index df10cbc5..112d1ade 100644 --- a/client/src/extension.cts +++ b/client/src/extension.ts @@ -29,17 +29,17 @@ import { LanguageClientOptions, ServerOptions, TransportKind -} from 'vscode-languageclient/node.js'; +} from 'vscode-languageclient/node'; import { resolve } from 'path'; import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, readFileSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; -import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config.cjs'; +import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config'; +import { resolvePath } from './utils'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); let v2Interpreter = getCfg(CfgKey.InterpreterPathV2), server_is_ready = false const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; -const isWindows = process.platform === 'win32'; let extlist: string[] = [], debugexts: Record = {}, langs: string[] = []; const loadedCollection = { 'ahk2.browse': 'Browse your file system to find AutoHotkey2 interpreter', @@ -61,11 +61,8 @@ const loadedCollection = { }; export function activate(context: ExtensionContext): Promise { - // when debugging, this goes into the Debug Console (Ctrl + Shift + Y) - console.log('Activating AHK v2 language server'); - /** Absolute path to `server.js` */ - const defaultServerModule = context.asAbsolutePath(`ahk2/server/dist/server.cjs`); + const defaultServerModule = context.asAbsolutePath(`ahk2/server/dist/server.js`); const serverModule = process.env.VSCODE_AHK_SERVER_PATH ? context.asAbsolutePath(process.env.VSCODE_AHK_SERVER_PATH) : defaultServerModule; // If the extension is launched in debug mode then the debug server options are used @@ -626,34 +623,6 @@ async function onDidChangegetInterpreter() { } } -/** - * Returns the provided path as an absolute path. - * Resolves the provided path against the provided workspace. - * Resolves symbolic links by default. - * Returns empty string if resolution fails. - */ -export function resolvePath(path: string | undefined, workspace?: string, resolveSymbolicLink = true): string { - if (!path) - return ''; - const paths: string[] = []; - // If the path does not contain a colon, resolve it relative to the workspace - if (!path.includes(':')) - paths.push(resolve(workspace ?? '', path)); - // If there are no slashes or backslashes in the path and the platform is Windows - if (!/[\\/]/.test(path) && isWindows) - paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); - paths.push(path); - for (let path of paths) { - if (!path) continue; - try { - if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) - path = resolve(path, '..', readlinkSync(path)); - return path; - } catch { } - } - return ''; -} - /** * Returns whether the given path exists. * Only returns false if lstatSync give an ENOENT error. diff --git a/client/src/utils.test.ts b/client/src/utils.test.ts new file mode 100644 index 00000000..b40f75ba --- /dev/null +++ b/client/src/utils.test.ts @@ -0,0 +1,29 @@ +import { expect, test, describe, vi, beforeAll, afterAll } from 'vitest'; +import { resolvePath } from './utils'; + +describe('resolvePath', () => { + beforeAll(() => { + // Mock the behavior of fs.lstatSync + vi.mock('fs', () => ({ + lstatSync: (_path: string) => ({ isSymbolicLink: () => false }), + })); + }); + + afterAll(() => { + vi.restoreAllMocks(); + }); + + test.concurrent.each< + [ + name: string, + args: Parameters, + expected: ReturnType, + ] + >([ + ['empty string', [''], ''], + ['absolute path at drive root', ['C:/out.txt'], 'C:/out.txt'], + ])('%s', (_name, args, expected) => { + const result = resolvePath(...args); + expect(result).toBe(expected); + }); +}); diff --git a/client/src/utils.ts b/client/src/utils.ts new file mode 100644 index 00000000..96242b26 --- /dev/null +++ b/client/src/utils.ts @@ -0,0 +1,33 @@ +import { execSync } from 'child_process'; +import { lstatSync, readlinkSync } from 'fs'; +import { resolve } from 'path'; + +/** + * Returns the provided path as an absolute path. + * Resolves the provided path against the provided workspace. + * Resolves symbolic links by default. + * Returns empty string if resolution fails. + */ +export function resolvePath( + path: string | undefined, + workspace?: string, + resolveSymbolicLink = true, +): string { + if (!path) return ''; + const paths: string[] = []; + // If the path does not contain a colon, resolve it relative to the workspace + if (!path.includes(':')) paths.push(resolve(workspace ?? '', path)); + // If there are no slashes or backslashes in the path and the platform is Windows + if (!/[\\/]/.test(path) && process.platform === 'win32') + paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); + paths.push(path); + for (let path of paths) { + if (!path) continue; + try { + if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) + path = resolve(path, '..', readlinkSync(path)); + return path; + } catch {} + } + return ''; +} diff --git a/client/tsconfig.json b/client/tsconfig.json index 0691600f..5f41caf1 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -2,11 +2,12 @@ "compilerOptions": { "target": "ES2022", "lib": ["ES2022", "WebWorker"], - "module": "NodeNext", - "moduleResolution": "NodeNext", + "module": "commonjs", + "moduleResolution": "node", "sourceMap": true, "strict": true, "outDir": "dist", + "rootDirs": ["src", "../server/src"], "composite": true }, "include": ["src"], diff --git a/package-lock.json b/package-lock.json index 3d0f8aaf..efc81e67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", + "@vitest/coverage-v8": "^2.1.1", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", @@ -33,6 +34,7 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", + "vitest": "^2.1.1", "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" @@ -41,6 +43,20 @@ "vscode": "^1.82.0" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -55,6 +71,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { "version": "7.24.7", "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", @@ -81,6 +107,37 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -762,9 +819,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true, "license": "MIT" }, @@ -872,6 +929,230 @@ "node": ">=18" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", + "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", + "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", + "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", + "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", + "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", + "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", + "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", + "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", + "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", + "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", + "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", + "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", + "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", + "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", + "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", + "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -1137,30 +1418,40 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@vscode/test-cli": { - "version": "0.0.10", - "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", - "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", + "node_modules/@vitest/coverage-v8": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/coverage-v8/-/coverage-v8-2.1.1.tgz", + "integrity": "sha512-md/A7A3c42oTT8JUHSqjP5uKTWJejzUW4jalpvs+rZ27gsURsMU8DEb+8Jf8C6Kj2gwfSHJqobDNBuoqlm0cFw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/mocha": "^10.0.2", - "c8": "^9.1.0", - "chokidar": "^3.5.3", - "enhanced-resolve": "^5.15.0", - "glob": "^10.3.10", - "minimatch": "^9.0.3", - "mocha": "^10.2.0", - "supports-color": "^9.4.0", - "yargs": "^17.7.2" + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.6", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.11", + "magicast": "^0.3.4", + "std-env": "^3.7.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^1.2.0" }, - "bin": { - "vscode-test": "out/bin.mjs" + "funding": { + "url": "https://opencollective.com/vitest" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@vitest/browser": "2.1.1", + "vitest": "2.1.1" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, - "node_modules/@vscode/test-cli/node_modules/brace-expansion": { + "node_modules/@vitest/coverage-v8/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -1170,7 +1461,7 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@vscode/test-cli/node_modules/glob": { + "node_modules/@vitest/coverage-v8/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", @@ -1191,7 +1482,7 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vscode/test-cli/node_modules/minimatch": { + "node_modules/@vitest/coverage-v8/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", @@ -1207,53 +1498,252 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vscode/test-cli/node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "node_modules/@vitest/coverage-v8/node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "engines": { + "node": ">=18" } }, - "node_modules/@vscode/test-electron": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", - "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", + "node_modules/@vitest/expect": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/expect/-/expect-2.1.1.tgz", + "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", "dev": true, + "license": "MIT", "dependencies": { - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "jszip": "^3.10.1", - "ora": "^7.0.1", - "semver": "^7.6.2" + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" }, - "engines": { - "node": ">=16" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vscode/test-web": { - "version": "0.0.56", - "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", - "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", + "node_modules/@vitest/mocker": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/mocker/-/mocker-2.1.1.tgz", + "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", "dev": true, "license": "MIT", "dependencies": { - "@koa/cors": "^5.0.0", - "@koa/router": "^12.0.1", - "@playwright/browser-chromium": "^1.45.0", - "glob": "^10.4.2", - "gunzip-maybe": "^1.4.2", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.4", - "koa": "^2.15.3", - "koa-morgan": "^1.0.1", - "koa-mount": "^4.0.0", - "koa-static": "^5.0.0", + "@vitest/spy": "^2.1.0-beta.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.1", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", + "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/runner/-/runner-2.1.1.tgz", + "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.1", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/snapshot/-/snapshot-2.1.1.tgz", + "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.1", + "magic-string": "^0.30.11", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/spy/-/spy-2.1.1.tgz", + "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@vitest/utils/-/utils-2.1.1.tgz", + "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.1", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vscode/test-cli": { + "version": "0.0.10", + "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", + "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", + "dev": true, + "dependencies": { + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@vscode/test-cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vscode/test-cli/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-cli/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-cli/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", + "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^7.0.1", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@vscode/test-web": { + "version": "0.0.56", + "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", + "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@koa/cors": "^5.0.0", + "@koa/router": "^12.0.1", + "@playwright/browser-chromium": "^1.45.0", + "glob": "^10.4.2", + "gunzip-maybe": "^1.4.2", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.4", + "koa": "^2.15.3", + "koa-morgan": "^1.0.1", + "koa-mount": "^4.0.0", + "koa-static": "^5.0.0", "minimist": "^1.2.8", "playwright": "^1.45.0", "tar-fs": "^3.0.6", @@ -1732,6 +2222,16 @@ "node": ">=0.10.0" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmmirror.com/b4a/-/b4a-1.6.6.tgz", @@ -2029,6 +2529,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmmirror.com/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cache-content-type": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/cache-content-type/-/cache-content-type-1.0.1.tgz", @@ -2106,6 +2616,23 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", @@ -2121,6 +2648,16 @@ "node": ">=4" } }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", @@ -2439,13 +2976,13 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2506,6 +3043,16 @@ "node": ">=0.10.0" } }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.0.1.tgz", @@ -3223,6 +3770,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", @@ -3461,6 +4018,16 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/get-stdin": { "version": "9.0.0", "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-9.0.0.tgz", @@ -4167,6 +4734,21 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmmirror.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/istanbul-reports": { "version": "3.1.7", "resolved": "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz", @@ -4728,6 +5310,16 @@ "node": ">=8" } }, + "node_modules/loupe": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/loupe/-/loupe-3.1.1.tgz", + "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4741,6 +5333,28 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmmirror.com/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-4.0.0.tgz", @@ -5162,13 +5776,6 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/mocha/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", @@ -5340,16 +5947,35 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, @@ -5791,6 +6417,23 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/peek-stream": { "version": "1.1.3", "resolved": "https://registry.npmmirror.com/peek-stream/-/peek-stream-1.1.3.tgz", @@ -5804,9 +6447,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true, "license": "ISC" }, @@ -5868,6 +6511,35 @@ "node": ">=18" } }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6320,6 +6992,42 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.22.4.tgz", + "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.22.4", + "@rollup/rollup-android-arm64": "4.22.4", + "@rollup/rollup-darwin-arm64": "4.22.4", + "@rollup/rollup-darwin-x64": "4.22.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", + "@rollup/rollup-linux-arm-musleabihf": "4.22.4", + "@rollup/rollup-linux-arm64-gnu": "4.22.4", + "@rollup/rollup-linux-arm64-musl": "4.22.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", + "@rollup/rollup-linux-riscv64-gnu": "4.22.4", + "@rollup/rollup-linux-s390x-gnu": "4.22.4", + "@rollup/rollup-linux-x64-gnu": "4.22.4", + "@rollup/rollup-linux-x64-musl": "4.22.4", + "@rollup/rollup-win32-arm64-msvc": "4.22.4", + "@rollup/rollup-win32-ia32-msvc": "4.22.4", + "@rollup/rollup-win32-x64-msvc": "4.22.4", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6455,6 +7163,13 @@ "node": ">=8" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", @@ -6603,6 +7318,16 @@ "node": ">= 8" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", @@ -6660,6 +7385,13 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmmirror.com/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", @@ -6670,6 +7402,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmmirror.com/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true, + "license": "MIT" + }, "node_modules/stdin-discarder": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", @@ -7038,6 +7777,60 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7490,95 +8283,687 @@ "node": ">= 0.8" } }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "node_modules/vite": { + "version": "5.4.8", + "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.8.tgz", + "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", + "dev": true, "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, "engines": { - "node": ">=14.0.0" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/vscode-languageclient": { - "version": "9.0.1", - "resolved": "https://registry.npmmirror.com/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", - "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "node_modules/vite-node": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/vite-node/-/vite-node-2.1.1.tgz", + "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", + "dev": true, "license": "MIT", "dependencies": { - "minimatch": "^5.1.0", - "semver": "^7.3.7", - "vscode-languageserver-protocol": "3.17.5" + "cac": "^6.7.14", + "debug": "^4.3.6", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" }, "engines": { - "vscode": "^1.82.0" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/vscode-languageclient/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-languageclient/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/vscode-languageserver": { - "version": "9.0.1", - "resolved": "https://registry.npmmirror.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", - "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.17.5" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmmirror.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", - "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmmirror.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "license": "MIT" - }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/vscode-textmate": { - "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-7.0.4.tgz", - "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A==", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vitest": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/vitest/-/vitest-2.1.1.tgz", + "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.1", + "@vitest/mocker": "2.1.1", + "@vitest/pretty-format": "^2.1.1", + "@vitest/runner": "2.1.1", + "@vitest/snapshot": "2.1.1", + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "debug": "^4.3.6", + "magic-string": "^0.30.11", + "pathe": "^1.1.2", + "std-env": "^3.7.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", + "tinypool": "^1.0.0", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.1", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.1", + "@vitest/ui": "2.1.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "license": "MIT", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-textmate": { + "version": "7.0.4", + "resolved": "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-7.0.4.tgz", + "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A==", "dev": true, "license": "MIT" }, @@ -7789,6 +9174,23 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.1.tgz", diff --git a/package.json b/package.json index 7dabd667..271be642 100644 --- a/package.json +++ b/package.json @@ -34,10 +34,10 @@ "build:dev": "node build.mjs", "build:old": "webpack", "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", - "clean": "del-cli client/dist server/dist/*.js* server/dist/*.cjs", + "clean": "del-cli client/dist server/dist/*.js*", "clean//": "Remove both the compiled extension and compiled test files", "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", - "compile-ts": "cd client && npm run compile-ts && cd ../server && npm run compile-ts", + "compile-ts": "cd client && tsc && cd ../server && tsc", "compile-ts//": "Compile TS files", "compile//": "Compile the extension for packaging and publishing", "eslint": "npm run eslint:files -- client server && echo No ESLint problems", @@ -49,9 +49,17 @@ "lint:fix": "npm run format:fix && npm run eslint:fix && npm run sort-package-json:fix", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", - "validate": "npm run lint", - "validate:ci": "npm run lint", - "validate:ci:fix": "npm run lint:fix", + "test": "npm run test:e2e", + "test//": "echo Run e2e tests (open VS Code), not grammar tests", + "test:ci": "npm run test:unit", + "pretest:e2e": "npm run compile-ts", + "test:e2e": "cd client && vscode-test", + "test:e2e//": "echo todo failing for now, will be adding pure unit tests soon", + "test:unit": "vitest --run", + "validate": "npm run lint && npm run test", + "validate:ci": "npm run lint && npm run test:ci", + "validate:ci:fix": "npm run lint:fix && npm run test:ci", + "validate:ci:fix//": "echo Fix validation issues first, then run remaining checks until failure", "watch": "tsc -b -w" }, "prettier": { @@ -82,6 +90,7 @@ "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", + "@vitest/coverage-v8": "^2.1.1", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", @@ -96,6 +105,7 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", + "vitest": "^2.1.1", "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" diff --git a/server/cli/cli.ts b/server/cli/cli.ts index c3624475..71a29d2a 100644 --- a/server/cli/cli.ts +++ b/server/cli/cli.ts @@ -1,6 +1,6 @@ -import { openFile } from '../src/common.js'; -import { newFormatterConfig } from '../src/config.js'; -import { Lexer } from '../src/Lexer.js'; +import { openFile } from '../src/common'; +import { newFormatterConfig } from '../src/config'; +import { Lexer } from '../src/Lexer'; function main() { const options: Record = {}; diff --git a/server/package.json b/server/package.json index f3d001a0..403a1a88 100644 --- a/server/package.json +++ b/server/package.json @@ -2,10 +2,6 @@ "name": "vscode-autohotkey2-server", "description": "Autohotkey2 Language Server using vscode-lsp.", "license": "LGPLv3.0", - "type": "module", - "scripts": { - "compile-ts": "tsc" - }, "engines": { "node": "*" }, diff --git a/server/src/Lexer.ts b/server/src/Lexer.ts index 7f1550a2..c0d1b59a 100644 --- a/server/src/Lexer.ts +++ b/server/src/Lexer.ts @@ -18,14 +18,14 @@ import { import { TextDocument } from 'vscode-languageserver-textdocument'; import { URI } from 'vscode-uri'; -import { builtin_ahkv1_commands, builtin_variable, builtin_variable_h } from './constants.js'; -import { action, completionitem, diagnostic, warn } from './localize.js'; +import { builtin_ahkv1_commands, builtin_variable, builtin_variable_h } from './constants'; +import { action, completionitem, diagnostic, warn } from './localize'; import { a_vars, ahk_version, ahkuris, ahkvars, alpha_3, connection, ahkppConfig, hoverCache, isBrowser, isahk2_h, lexers, libdirs, libfuncs, locale, openAndParse, openFile, restorePath, rootdir, setTextDocumentLanguage, symbolProvider, utils, workspaceFolders -} from './common.js'; -import { newFormatterConfig, FormatterConfig, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses, getCfg, CfgKey } from './config.js'; +} from './common'; +import { newFormatterConfig, FormatterConfig, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses, getCfg, CfgKey } from './config'; export interface ParamInfo { offset: number diff --git a/server/src/ahkProvider.ts b/server/src/ahkProvider.ts index 0958723a..6531fbaa 100644 --- a/server/src/ahkProvider.ts +++ b/server/src/ahkProvider.ts @@ -1,7 +1,7 @@ -import { createClientSocketTransport, createMessageConnection, createServerSocketTransport, MessageConnection } from 'vscode-languageserver/node.js'; +import { createClientSocketTransport, createMessageConnection, createServerSocketTransport, MessageConnection } from 'vscode-languageserver/node'; import { spawn } from 'child_process'; -import { resolvePath } from './scriptrunner.js'; -import { interpreterPathV2, isWindows, rootdir } from './common.js'; +import { resolvePath } from './scriptrunner'; +import { interpreterPathV2, isWindows, rootdir } from './common'; let ahk_server: MessageConnection | undefined | null; async function get_ahkProvider_port(): Promise { diff --git a/server/src/browserServerMain.ts b/server/src/browserServerMain.ts index 32995e3e..c7c9bb29 100644 --- a/server/src/browserServerMain.ts +++ b/server/src/browserServerMain.ts @@ -6,7 +6,7 @@ import { TextDocument } from 'vscode-languageserver-textdocument'; import { createConnection, BrowserMessageReader, BrowserMessageWriter, DidChangeConfigurationNotification, InitializeResult, TextDocuments, TextDocumentSyncKind -} from 'vscode-languageserver/browser.js'; +} from 'vscode-languageserver/browser'; import { chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, defintionProvider, documentFormatting, enumNames, executeCommandProvider, exportSymbols, getVersionInfo, @@ -14,8 +14,8 @@ import { referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, signatureProvider, symbolProvider, typeFormatting, updateAhkppConfig, workspaceSymbolProvider -} from './common.js'; -import { AhkppConfig } from './config.js'; +} from './common'; +import { AhkppConfig } from './config'; const languageServer = 'ahk2-language-server'; const messageReader = new BrowserMessageReader(self); diff --git a/server/src/codeActionProvider.ts b/server/src/codeActionProvider.ts index bc82986b..602ec3c0 100644 --- a/server/src/codeActionProvider.ts +++ b/server/src/codeActionProvider.ts @@ -1,7 +1,7 @@ import { readdirSync } from 'fs'; import { CancellationToken, CodeAction, CodeActionKind, CodeActionParams, TextEdit } from 'vscode-languageserver'; -import { codeaction, diagnostic } from './localize.js'; -import { Maybe, lexers, restorePath, warn } from './common.js'; +import { codeaction, diagnostic } from './localize'; +import { Maybe, lexers, restorePath, warn } from './common'; export async function codeActionProvider(params: CodeActionParams, token: CancellationToken): Promise> { const uri = params.textDocument.uri, lex = lexers[uri.toLowerCase()], document = lex?.document; diff --git a/server/src/colorProvider.ts b/server/src/colorProvider.ts index d44fa0fe..38177f0b 100644 --- a/server/src/colorProvider.ts +++ b/server/src/colorProvider.ts @@ -1,5 +1,5 @@ import { CancellationToken, ColorInformation, ColorPresentation, ColorPresentationParams, DocumentColorParams } from 'vscode-languageserver'; -import { Maybe, lexers } from './common.js'; +import { Maybe, lexers } from './common'; export async function colorPresentation(params: ColorPresentationParams, token: CancellationToken): Promise> { const { range, color, textDocument: { uri } } = params, text = lexers[uri.toLowerCase()]?.document.getText(range); diff --git a/server/src/commandProvider.ts b/server/src/commandProvider.ts index aeeb167e..1ee3f571 100644 --- a/server/src/commandProvider.ts +++ b/server/src/commandProvider.ts @@ -4,7 +4,7 @@ import { connection, ahkppConfig, find_class, generate_type_annotation, join_types, lexers, parse_include, restorePath, semanticTokensOnFull, traverse_include, update_include_cache -} from './common.js'; +} from './common'; function checkCommand(cmd: string) { if (ahkppConfig.commands?.includes(cmd)) diff --git a/server/src/common.ts b/server/src/common.ts index 51391d0d..b9274c62 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -4,25 +4,25 @@ import { readdirSync, readFileSync, existsSync, statSync, promises as fs } from import { Connection, MessageConnection } from 'vscode-languageserver'; import { TextDocument } from 'vscode-languageserver-textdocument'; import { CompletionItem, CompletionItemKind, Hover, InsertTextFormat, Range, SymbolKind } from 'vscode-languageserver-types'; -import { AhkSymbol, Lexer, setCommentTagRegex } from './Lexer.js'; -import { diagnostic } from './localize.js'; -import { isBrowser, jsDocTagNames } from './constants.js'; -import { AhkppConfig, CfgKey, getCfg, newAhkppConfig } from './config.js'; -export * from './codeActionProvider.js'; -export * from './colorProvider.js'; -export * from './commandProvider.js'; -export * from './completionProvider.js'; -export * from './constants.js'; -export * from './definitionProvider.js'; -export * from './formattingProvider.js'; -export * from './hoverProvider.js'; -export * from './Lexer.js'; -export * from './localize.js'; -export * from './referencesProvider.js'; -export * from './renameProvider.js'; -export * from './semanticTokensProvider.js'; -export * from './signatureProvider.js'; -export * from './symbolProvider.js'; +import { AhkSymbol, Lexer, setCommentTagRegex } from './Lexer'; +import { diagnostic } from './localize'; +import { isBrowser, jsDocTagNames } from './constants'; +import { AhkppConfig, CfgKey, getCfg, newAhkppConfig } from './config'; +export * from './codeActionProvider'; +export * from './colorProvider'; +export * from './commandProvider'; +export * from './completionProvider'; +export * from './constants'; +export * from './definitionProvider'; +export * from './formattingProvider'; +export * from './hoverProvider'; +export * from './Lexer'; +export * from './localize'; +export * from './referencesProvider'; +export * from './renameProvider'; +export * from './semanticTokensProvider'; +export * from './signatureProvider'; +export * from './symbolProvider'; export const winapis: string[] = []; export const lexers: Record = {}; diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index 02863510..3ba3144f 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -11,9 +11,9 @@ import { decltype_expr, dllcalltpe, ahkppConfig, find_class, find_symbol, find_symbols, get_detail, generate_fn_comment, get_callinfo, get_class_constructor, get_class_member, get_class_members, isBrowser, lexers, libfuncs, make_search_re, sendAhkRequest, utils, winapis, -} from './common.js'; -import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils.js'; -import { BraceStyle, CompletionCommitCharacters, CfgKey, FormatterConfig, getCfg } from './config.js'; +} from './common'; +import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; +import { BraceStyle, CompletionCommitCharacters, CfgKey, FormatterConfig, getCfg } from './config'; export async function completionProvider(params: CompletionParams, _token: CancellationToken): Promise> { let { position, textDocument: { uri } } = params; diff --git a/server/src/definitionProvider.ts b/server/src/definitionProvider.ts index 99f3bfb0..a9af1520 100644 --- a/server/src/definitionProvider.ts +++ b/server/src/definitionProvider.ts @@ -1,5 +1,5 @@ import { DefinitionParams, LocationLink, SymbolKind, Range, CancellationToken } from 'vscode-languageserver'; -import { AhkSymbol, lexers, restorePath, find_symbols, Token } from './common.js'; +import { AhkSymbol, lexers, restorePath, find_symbols, Token } from './common'; import { URI } from 'vscode-uri'; export async function defintionProvider(params: DefinitionParams, token: CancellationToken): Promise { diff --git a/server/src/formattingProvider.ts b/server/src/formattingProvider.ts index f6c50915..1c7fa8ad 100644 --- a/server/src/formattingProvider.ts +++ b/server/src/formattingProvider.ts @@ -1,6 +1,6 @@ import { DocumentFormattingParams, DocumentOnTypeFormattingParams, DocumentRangeFormattingParams, Position, Range, TextEdit } from 'vscode-languageserver'; -import { chinese_punctuations, ahkppConfig, lexers, Token } from './common.js'; -import { FormatterConfig } from './config.js'; +import { chinese_punctuations, ahkppConfig, lexers, Token } from './common'; +import { FormatterConfig } from './config'; export async function documentFormatting(params: DocumentFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], range = Range.create(0, 0, doc.document.lineCount, 0); diff --git a/server/src/hoverProvider.ts b/server/src/hoverProvider.ts index 731f8c1e..7007ee03 100644 --- a/server/src/hoverProvider.ts +++ b/server/src/hoverProvider.ts @@ -2,7 +2,7 @@ import { CancellationToken, Hover, HoverParams, SymbolKind } from 'vscode-langua import { AhkSymbol, FuncNode, Maybe, SemanticTokenTypes, Variable, get_detail, hoverCache, join_types, lexers, find_symbols -} from './common.js'; +} from './common'; export async function hoverProvider(params: HoverParams, token: CancellationToken): Promise> { if (token.isCancellationRequested) return; diff --git a/server/src/localize.ts b/server/src/localize.ts index 11ba9a6d..b3e95a44 100644 --- a/server/src/localize.ts +++ b/server/src/localize.ts @@ -1,5 +1,5 @@ -import { rootdir, getlocalefile, getwebfile, isBrowser } from './common.js'; -import { CfgKey } from './config.js'; +import { rootdir, getlocalefile, getwebfile, isBrowser } from './common'; +import { CfgKey } from './config'; let loadedCollection: Record = {}; diff --git a/server/src/referencesProvider.ts b/server/src/referencesProvider.ts index a82796aa..506dc15c 100644 --- a/server/src/referencesProvider.ts +++ b/server/src/referencesProvider.ts @@ -2,7 +2,7 @@ import { CancellationToken, Location, Range, ReferenceParams, SymbolKind } from import { AhkSymbol, ClassNode, Context, FuncNode, FuncScope, Lexer, Property, Variable, ahkuris, ahkvars, find_symbol, find_symbols, lexers -} from './common.js'; +} from './common'; export async function referenceProvider(params: ReferenceParams, token: CancellationToken): Promise { const result: Location[] = [], doc = lexers[params.textDocument.uri.toLowerCase()]; diff --git a/server/src/renameProvider.ts b/server/src/renameProvider.ts index 647bc716..aa8d8fde 100644 --- a/server/src/renameProvider.ts +++ b/server/src/renameProvider.ts @@ -1,6 +1,6 @@ import { CancellationToken, PrepareRenameParams, Range, RenameParams, WorkspaceEdit } from 'vscode-languageserver'; import { ResponseError } from 'vscode-jsonrpc'; -import { Maybe, lexers, getAllReferences, response } from './common.js'; +import { Maybe, lexers, getAllReferences, response } from './common'; let renameranges: Record | null | undefined; diff --git a/server/src/scriptrunner.ts b/server/src/scriptrunner.ts index be247232..68900eef 100644 --- a/server/src/scriptrunner.ts +++ b/server/src/scriptrunner.ts @@ -1,5 +1,5 @@ import { execSync, spawnSync } from 'child_process'; -import { interpreterPathV2, isWindows } from './common.js'; +import { interpreterPathV2, isWindows } from './common'; import { lstatSync, readlinkSync } from 'fs'; import { resolve } from 'path'; diff --git a/server/src/semanticTokensProvider.ts b/server/src/semanticTokensProvider.ts index cdb4fa4a..459127a7 100644 --- a/server/src/semanticTokensProvider.ts +++ b/server/src/semanticTokensProvider.ts @@ -2,8 +2,8 @@ import { CancellationToken, DocumentSymbol, Range, SemanticTokens, SemanticToken import { ASSIGN_TYPE, AhkSymbol, ClassNode, FuncNode, Lexer, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, Token, Variable, checkParams, diagnostic, ahkppConfig, get_class_member, get_class_members, globalsymbolcache, lexers, symbolProvider -} from './common.js'; -import { CfgKey, getCfg } from './config.js'; +} from './common'; +import { CfgKey, getCfg } from './config'; let curclass: ClassNode | undefined; const memscache = new Map>(); diff --git a/server/src/server.ts b/server/src/server.ts index 764aa163..46d3b0f9 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -8,9 +8,9 @@ import { SymbolKind, TextDocuments, TextDocumentSyncKind, -} from 'vscode-languageserver/node.js'; +} from 'vscode-languageserver/node'; import { URI } from 'vscode-uri'; -import { get_ahkProvider } from './ahkProvider.js'; +import { get_ahkProvider } from './ahkProvider'; import { a_vars, interpreterPathV2, @@ -67,12 +67,12 @@ import { getVersionInfo, builtin_variable, builtin_variable_h, -} from './common.js'; -import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile.js'; -import { resolvePath, runscript } from './scriptrunner.js'; +} from './common'; +import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; +import { resolvePath, runscript } from './scriptrunner'; import { TextDecoder } from 'util'; -import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils.js'; -import { AhkppConfig, CfgKey, getCfg, LibrarySuggestions } from './config.js'; +import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; +import { AhkppConfig, CfgKey, getCfg, LibrarySuggestions } from './config'; const languageServer = 'ahk2-language-server'; const documents = new TextDocuments(TextDocument); @@ -86,9 +86,6 @@ commands['ahk++.v2.setIntepreterPath'] = (args: string[]) => setInterpreter(args[0].replace(/^[A-Z]:/, (m) => m.toLowerCase())); connection.onInitialize(async (params) => { - // Shows up in extension development host - // Output > AHK++ - connection.console.log(`Initializing language server`); const capabilities = params.capabilities; hasConfigurationCapability = !!( capabilities.workspace && !!capabilities.workspace.configuration diff --git a/server/src/signatureProvider.ts b/server/src/signatureProvider.ts index fe23e14a..e6980fff 100644 --- a/server/src/signatureProvider.ts +++ b/server/src/signatureProvider.ts @@ -4,7 +4,7 @@ import { ANY, AhkSymbol, ClassNode, FuncNode, Lexer, Maybe, Variable, ahkuris, decltype_expr, decltype_invoke, decltype_returns, get_detail, get_callinfo, get_class_constructor, get_class_member, lexers -} from './common.js'; +} from './common'; let cache: { index?: number, diff --git a/server/src/symbolProvider.ts b/server/src/symbolProvider.ts index cacb259c..4cbb8c8a 100644 --- a/server/src/symbolProvider.ts +++ b/server/src/symbolProvider.ts @@ -10,8 +10,8 @@ import { ahkuris, ahkvars, check_same_name_error, connection, decltype_expr, diagnostic, enum_ahkfiles, ahkppConfig, find_class, get_class_constructor, isBrowser, is_line_continue, lexers, make_same_name_error, openFile, warn, workspaceFolders -} from './common.js'; -import { CfgKey, getCfg } from './config.js'; +} from './common'; +import { CfgKey, getCfg } from './config'; export let globalsymbolcache: Record = {}; diff --git a/server/src/utils.ts b/server/src/utils.ts index 831071ad..30ff2ff0 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -1,4 +1,4 @@ -import { LibrarySuggestions } from './config.js'; +import { LibrarySuggestions } from './config'; export function includeUserAndStandardLibrary( librarySuggestions: LibrarySuggestions, diff --git a/server/tsconfig.json b/server/tsconfig.json index f219a5b1..b4758cd2 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -2,11 +2,12 @@ "compilerOptions": { "target": "ES2022", "lib": ["ES2022", "WebWorker"], - "module": "NodeNext", - "moduleResolution": "NodeNext", + "module": "commonjs", + "moduleResolution": "node", "sourceMap": true, "strict": true, - "outDir": "out" + "outDir": "out", + "rootDirs": ["src", "../client/src"] }, "include": ["src"], "exclude": ["node_modules", ".vscode-test", ".vscode-test-web"] diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..f1057913 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "ES2021", + "lib": ["ES2021"], + "outDir": "out", + "rootDir": "src", + "sourceMap": true, + "composite": true + }, + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"], + "references": [{ "path": "./client" }, { "path": "./server" }] +} diff --git a/vitest.config.mjs b/vitest.config.mjs new file mode 100644 index 00000000..1b0aa0f2 --- /dev/null +++ b/vitest.config.mjs @@ -0,0 +1,13 @@ +import { defineConfig } from 'vitest/config'; + +// https://vitest.dev/config +// https://vitest.dev/guide/improving-performance.html +export default defineConfig({ + test: { + isolate: false, + pool: 'threads', + coverage: { + enabled: true, + }, + }, +}); From 09132813f437ef030bd7cdb19610e91934c128fe Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 28 Sep 2024 14:56:10 -0700 Subject: [PATCH 36/60] Revert "Remove dupe config file" (#34) This reverts commit aae4f9e45fda8447df3f8a52143aaa5286425cce. --- client/.vscode-test.mjs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 client/.vscode-test.mjs diff --git a/client/.vscode-test.mjs b/client/.vscode-test.mjs new file mode 100644 index 00000000..efac995e --- /dev/null +++ b/client/.vscode-test.mjs @@ -0,0 +1,7 @@ +// https://github.com/microsoft/vscode-test-cli +import { defineConfig } from '@vscode/test-cli'; +export default defineConfig({ + extensionDevelopmentPath: '..', + files: 'dist/**/*.test.js', + version: '1.92.0', +}); From ef355855a3e50458c3eebf66ecd64ba641387d9d Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 28 Sep 2024 14:57:22 -0700 Subject: [PATCH 37/60] Revert "Add Vitest for unit tests" (#35) This reverts commit 52aa813616d3b69dfb3abf466208730392c81ec6. --- .gitignore | 5 +- .vscode-test.mjs | 2 +- .vscode/extensions.json | 3 +- .vscode/settings.json | 3 +- .vscode/snippets.code-snippets | 40 - .../{extension.e2e.ts => extension.test.ts} | 0 client/src/extension.ts | 30 +- client/src/utils.test.ts | 29 - client/src/utils.ts | 33 - package-lock.json | 1530 +---------------- package.json | 19 +- vitest.config.mjs | 13 - 12 files changed, 105 insertions(+), 1602 deletions(-) delete mode 100644 .vscode/snippets.code-snippets rename client/src/{extension.e2e.ts => extension.test.ts} (100%) delete mode 100644 client/src/utils.test.ts delete mode 100644 client/src/utils.ts delete mode 100644 vitest.config.mjs diff --git a/.gitignore b/.gitignore index 0e373567..4ed6e072 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,4 @@ scripts/* *.js *.js.map *.tsbuildinfo -**/dist/**/*.d.ts - -# Vitest -coverage \ No newline at end of file +**/dist/**/*.d.ts \ No newline at end of file diff --git a/.vscode-test.mjs b/.vscode-test.mjs index 11029cf2..3613e4fc 100644 --- a/.vscode-test.mjs +++ b/.vscode-test.mjs @@ -12,7 +12,7 @@ try { } catch {} export default defineConfig({ - files: 'client/dist/test/**/*.e2e.js', + files: 'client/dist/test/**/*.test.js', useInstallation: vscode_path && { fromPath: vscode_path, }, diff --git a/.vscode/extensions.json b/.vscode/extensions.json index bb3324e2..e22fcc88 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,7 +2,6 @@ "recommendations": [ "aaron-bond.better-comments", "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode", - "vitest.explorer" + "esbenp.prettier-vscode" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index c09d1f5e..f494c7af 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,5 +2,6 @@ "editor.insertSpaces": false, "typescript.tsc.autoDetect": "off", "typescript.preferences.quoteStyle": "single", - "git.ignoreLimitWarning": true + "git.ignoreLimitWarning": true, + "editor.formatOnSave": false } diff --git a/.vscode/snippets.code-snippets b/.vscode/snippets.code-snippets deleted file mode 100644 index 3b6b41e3..00000000 --- a/.vscode/snippets.code-snippets +++ /dev/null @@ -1,40 +0,0 @@ -{ - // Place your ahk2 workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and - // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope - // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is - // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: - // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. - // Placeholders with the same ids are connected. - // Example: - // "Print to console": { - // "scope": "javascript,typescript", - // "prefix": "log", - // "body": [ - // "console.log('$1');", - // "$2" - // ], - // "description": "Log output to console" - // } - - "Add unit test": { - "scope": "typescript", - "prefix": "describe", - "body": [ - "describe('$1', () => {", - "\ttest.concurrent.each<", - "\t[", - "\t\tname: string,", - "\t\t\targs: Parameters,", - "\t\t\texpected: ReturnType,", - "\t\t]", - "\t>([", - "\t['$2', [$3], $4],", - "\t])('%s', (_name, args, expected) => {", - "\t\tconst result = $1(...args);", - "\t\texpect(result).toBe(expected);", - "\t});", - "});", - ], - "description": "Add Vitest test.concurrent.each in a describe block", - }, -} diff --git a/client/src/extension.e2e.ts b/client/src/extension.test.ts similarity index 100% rename from client/src/extension.e2e.ts rename to client/src/extension.test.ts diff --git a/client/src/extension.ts b/client/src/extension.ts index 112d1ade..527e9c11 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -34,12 +34,12 @@ import { resolve } from 'path'; import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, readFileSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config'; -import { resolvePath } from './utils'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); let v2Interpreter = getCfg(CfgKey.InterpreterPathV2), server_is_ready = false const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; +const isWindows = process.platform === 'win32'; let extlist: string[] = [], debugexts: Record = {}, langs: string[] = []; const loadedCollection = { 'ahk2.browse': 'Browse your file system to find AutoHotkey2 interpreter', @@ -623,6 +623,34 @@ async function onDidChangegetInterpreter() { } } +/** + * Returns the provided path as an absolute path. + * Resolves the provided path against the provided workspace. + * Resolves symbolic links by default. + * Returns empty string if resolution fails. + */ +export function resolvePath(path: string | undefined, workspace?: string, resolveSymbolicLink = true): string { + if (!path) + return ''; + const paths: string[] = []; + // If the path does not contain a colon, resolve it relative to the workspace + if (!path.includes(':')) + paths.push(resolve(workspace ?? '', path)); + // If there are no slashes or backslashes in the path and the platform is Windows + if (!/[\\/]/.test(path) && isWindows) + paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); + paths.push(path); + for (let path of paths) { + if (!path) continue; + try { + if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) + path = resolve(path, '..', readlinkSync(path)); + return path; + } catch { } + } + return ''; +} + /** * Returns whether the given path exists. * Only returns false if lstatSync give an ENOENT error. diff --git a/client/src/utils.test.ts b/client/src/utils.test.ts deleted file mode 100644 index b40f75ba..00000000 --- a/client/src/utils.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { expect, test, describe, vi, beforeAll, afterAll } from 'vitest'; -import { resolvePath } from './utils'; - -describe('resolvePath', () => { - beforeAll(() => { - // Mock the behavior of fs.lstatSync - vi.mock('fs', () => ({ - lstatSync: (_path: string) => ({ isSymbolicLink: () => false }), - })); - }); - - afterAll(() => { - vi.restoreAllMocks(); - }); - - test.concurrent.each< - [ - name: string, - args: Parameters, - expected: ReturnType, - ] - >([ - ['empty string', [''], ''], - ['absolute path at drive root', ['C:/out.txt'], 'C:/out.txt'], - ])('%s', (_name, args, expected) => { - const result = resolvePath(...args); - expect(result).toBe(expected); - }); -}); diff --git a/client/src/utils.ts b/client/src/utils.ts deleted file mode 100644 index 96242b26..00000000 --- a/client/src/utils.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { execSync } from 'child_process'; -import { lstatSync, readlinkSync } from 'fs'; -import { resolve } from 'path'; - -/** - * Returns the provided path as an absolute path. - * Resolves the provided path against the provided workspace. - * Resolves symbolic links by default. - * Returns empty string if resolution fails. - */ -export function resolvePath( - path: string | undefined, - workspace?: string, - resolveSymbolicLink = true, -): string { - if (!path) return ''; - const paths: string[] = []; - // If the path does not contain a colon, resolve it relative to the workspace - if (!path.includes(':')) paths.push(resolve(workspace ?? '', path)); - // If there are no slashes or backslashes in the path and the platform is Windows - if (!/[\\/]/.test(path) && process.platform === 'win32') - paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); - paths.push(path); - for (let path of paths) { - if (!path) continue; - try { - if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) - path = resolve(path, '..', readlinkSync(path)); - return path; - } catch {} - } - return ''; -} diff --git a/package-lock.json b/package-lock.json index efc81e67..3d0f8aaf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,6 @@ "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", - "@vitest/coverage-v8": "^2.1.1", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", @@ -34,7 +33,6 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", - "vitest": "^2.1.1", "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" @@ -43,20 +41,6 @@ "vscode": "^1.82.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -71,16 +55,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-validator-identifier": { "version": "7.24.7", "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", @@ -107,37 +81,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.6" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -819,9 +762,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.4.15", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true, "license": "MIT" }, @@ -929,230 +872,6 @@ "node": ">=18" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -1418,40 +1137,30 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@vitest/coverage-v8": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/coverage-v8/-/coverage-v8-2.1.1.tgz", - "integrity": "sha512-md/A7A3c42oTT8JUHSqjP5uKTWJejzUW4jalpvs+rZ27gsURsMU8DEb+8Jf8C6Kj2gwfSHJqobDNBuoqlm0cFw==", + "node_modules/@vscode/test-cli": { + "version": "0.0.10", + "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", + "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", "dev": true, - "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.6", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.6", - "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.11", - "magicast": "^0.3.4", - "std-env": "^3.7.0", - "test-exclude": "^7.0.1", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" }, - "peerDependencies": { - "@vitest/browser": "2.1.1", - "vitest": "2.1.1" + "bin": { + "vscode-test": "out/bin.mjs" }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } + "engines": { + "node": ">=18" } }, - "node_modules/@vitest/coverage-v8/node_modules/brace-expansion": { + "node_modules/@vscode/test-cli/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -1461,7 +1170,7 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@vitest/coverage-v8/node_modules/glob": { + "node_modules/@vscode/test-cli/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", @@ -1482,7 +1191,7 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vitest/coverage-v8/node_modules/minimatch": { + "node_modules/@vscode/test-cli/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", @@ -1498,238 +1207,39 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vitest/coverage-v8/node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "node_modules/@vscode/test-cli/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@vitest/expect": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/expect/-/expect-2.1.1.tgz", - "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", + "node_modules/@vscode/test-electron": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", + "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", "dev": true, - "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", - "chai": "^5.1.1", - "tinyrainbow": "^1.2.0" + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^7.0.1", + "semver": "^7.6.2" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">=16" } }, - "node_modules/@vitest/mocker": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/mocker/-/mocker-2.1.1.tgz", - "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "^2.1.0-beta.1", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/spy": "2.1.1", - "msw": "^2.3.5", - "vite": "^5.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", - "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/runner/-/runner-2.1.1.tgz", - "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "2.1.1", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/snapshot/-/snapshot-2.1.1.tgz", - "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.1", - "magic-string": "^0.30.11", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/spy/-/spy-2.1.1.tgz", - "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^3.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/@vitest/utils/-/utils-2.1.1.tgz", - "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.1", - "loupe": "^3.1.1", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vscode/test-cli": { - "version": "0.0.10", - "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", - "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", - "dev": true, - "dependencies": { - "@types/mocha": "^10.0.2", - "c8": "^9.1.0", - "chokidar": "^3.5.3", - "enhanced-resolve": "^5.15.0", - "glob": "^10.3.10", - "minimatch": "^9.0.3", - "mocha": "^10.2.0", - "supports-color": "^9.4.0", - "yargs": "^17.7.2" - }, - "bin": { - "vscode-test": "out/bin.mjs" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@vscode/test-cli/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@vscode/test-cli/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/test-cli/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/test-cli/node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/@vscode/test-electron": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", - "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "jszip": "^3.10.1", - "ora": "^7.0.1", - "semver": "^7.6.2" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@vscode/test-web": { - "version": "0.0.56", - "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", - "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", + "node_modules/@vscode/test-web": { + "version": "0.0.56", + "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", + "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", "dev": true, "license": "MIT", "dependencies": { @@ -2222,16 +1732,6 @@ "node": ">=0.10.0" } }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmmirror.com/b4a/-/b4a-1.6.6.tgz", @@ -2529,16 +2029,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmmirror.com/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cache-content-type": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/cache-content-type/-/cache-content-type-1.0.1.tgz", @@ -2616,23 +2106,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", @@ -2648,16 +2121,6 @@ "node": ">=4" } }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", @@ -2976,13 +2439,13 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.3.5", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "ms": "2.1.2" }, "engines": { "node": ">=6.0" @@ -3043,16 +2506,6 @@ "node": ">=0.10.0" } }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmmirror.com/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.0.1.tgz", @@ -3770,16 +3223,6 @@ "node": ">=4.0" } }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", @@ -4018,16 +3461,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/get-stdin": { "version": "9.0.0", "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-9.0.0.tgz", @@ -4734,21 +4167,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmmirror.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/istanbul-reports": { "version": "3.1.7", "resolved": "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz", @@ -5310,16 +4728,6 @@ "node": ">=8" } }, - "node_modules/loupe": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/loupe/-/loupe-3.1.1.tgz", - "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", @@ -5333,28 +4741,6 @@ "node": ">=10" } }, - "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/magicast": { - "version": "0.3.5", - "resolved": "https://registry.npmmirror.com/magicast/-/magicast-0.3.5.tgz", - "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.4", - "@babel/types": "^7.25.4", - "source-map-js": "^1.2.0" - } - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-4.0.0.tgz", @@ -5776,6 +5162,13 @@ "node": ">=10" } }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/mocha/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", @@ -5947,31 +5340,12 @@ } }, "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, "license": "MIT" }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6417,23 +5791,6 @@ "node": ">=8" } }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, "node_modules/peek-stream": { "version": "1.1.3", "resolved": "https://registry.npmmirror.com/peek-stream/-/peek-stream-1.1.3.tgz", @@ -6447,9 +5804,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true, "license": "ISC" }, @@ -6511,35 +5868,6 @@ "node": ">=18" } }, - "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6992,42 +6320,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", - "fsevents": "~2.3.2" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7163,13 +6455,6 @@ "node": ">=8" } }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", @@ -7318,16 +6603,6 @@ "node": ">= 8" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", @@ -7385,13 +6660,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmmirror.com/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", @@ -7402,13 +6670,6 @@ "node": ">= 0.8" } }, - "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmmirror.com/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true, - "license": "MIT" - }, "node_modules/stdin-discarder": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", @@ -7777,60 +7038,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmmirror.com/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinypool": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/tinypool/-/tinypool-1.0.1.tgz", - "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8283,598 +7490,6 @@ "node": ">= 0.8" } }, - "node_modules/vite": { - "version": "5.4.8", - "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.8.tgz", - "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/vite-node/-/vite-node-2.1.1.tgz", - "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.6", - "pathe": "^1.1.2", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vite/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/vitest": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/vitest/-/vitest-2.1.1.tgz", - "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.1", - "@vitest/mocker": "2.1.1", - "@vitest/pretty-format": "^2.1.1", - "@vitest/runner": "2.1.1", - "@vitest/snapshot": "2.1.1", - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", - "chai": "^5.1.1", - "debug": "^4.3.6", - "magic-string": "^0.30.11", - "pathe": "^1.1.2", - "std-env": "^3.7.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.0", - "tinypool": "^1.0.0", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.1", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.1", - "@vitest/ui": "2.1.1", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", @@ -9174,23 +7789,6 @@ "node": ">= 8" } }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.1.tgz", diff --git a/package.json b/package.json index 271be642..2df08cbd 100644 --- a/package.json +++ b/package.json @@ -49,17 +49,14 @@ "lint:fix": "npm run format:fix && npm run eslint:fix && npm run sort-package-json:fix", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", - "test": "npm run test:e2e", - "test//": "echo Run e2e tests (open VS Code), not grammar tests", - "test:ci": "npm run test:unit", - "pretest:e2e": "npm run compile-ts", - "test:e2e": "cd client && vscode-test", - "test:e2e//": "echo todo failing for now, will be adding pure unit tests soon", - "test:unit": "vitest --run", + "test": "npm run test-unit", + "pretest-unit": "npm run compile-ts", + "test-unit": "cd client && vscode-test", + "test-unit//": "echo todo failing for now, will be adding pure unit tests soon", + "test//": "Run unit tests, not grammar tests", "validate": "npm run lint && npm run test", - "validate:ci": "npm run lint && npm run test:ci", - "validate:ci:fix": "npm run lint:fix && npm run test:ci", - "validate:ci:fix//": "echo Fix validation issues first, then run remaining checks until failure", + "validate:ci": "npm run lint", + "validate:ci:fix": "npm run lint:fix", "watch": "tsc -b -w" }, "prettier": { @@ -90,7 +87,6 @@ "@types/node": "^20.16.0", "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", - "@vitest/coverage-v8": "^2.1.1", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/test-web": "^0.0.56", @@ -105,7 +101,6 @@ "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", - "vitest": "^2.1.1", "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" diff --git a/vitest.config.mjs b/vitest.config.mjs deleted file mode 100644 index 1b0aa0f2..00000000 --- a/vitest.config.mjs +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from 'vitest/config'; - -// https://vitest.dev/config -// https://vitest.dev/guide/improving-performance.html -export default defineConfig({ - test: { - isolate: false, - pool: 'threads', - coverage: { - enabled: true, - }, - }, -}); From 9d6e8123ae6adae2d8d8ee0d3cac043ed09ea94b Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 28 Sep 2024 15:23:19 -0700 Subject: [PATCH 38/60] Fix unhandled commands (#36) --- client/src/browserClientMain.ts | 6 +++--- client/src/extension.ts | 26 +++++++++++++------------- package.json | 1 + server/src/commandProvider.ts | 20 ++++++++++---------- server/src/server.ts | 14 +++++++------- 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts index 5e8e4267..09f3312b 100644 --- a/client/src/browserClientMain.ts +++ b/client/src/browserClientMain.ts @@ -15,13 +15,13 @@ export function activate(context: ExtensionContext) { const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browserServerMain.js'); /* eslint-disable-next-line */ const request_handlers: Record any> = { - 'ahk2.getActiveTextEditorUriAndPosition': () => { + 'ahk++.getActiveTextEditorUriAndPosition': () => { const editor = window.activeTextEditor; if (!editor) return; const uri = editor.document.uri.toString(), position = editor.selection.end; return { uri, position }; }, - 'ahk2.insertSnippet': async (params: [string, Range?]) => { + 'ahk++.insertSnippet': async (params: [string, Range?]) => { const editor = window.activeTextEditor; if (!editor) return; if (params[1]) { @@ -30,7 +30,7 @@ export function activate(context: ExtensionContext) { } else editor.insertSnippet(new SnippetString(params[0])); }, - 'ahk2.setTextDocumentLanguage': async (params: [string, string?]) => { + 'ahk++.setTextDocumentLanguage': async (params: [string, string?]) => { const lang = params[1] || 'ahk'; if (!(await languages.getLanguages()).includes(lang)) { window.showErrorMessage(`Unknown language id: ${lang}`); diff --git a/client/src/extension.ts b/client/src/extension.ts index 527e9c11..9d982751 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -78,14 +78,14 @@ export function activate(context: ExtensionContext): Promise { // eslint-disable-next-line @typescript-eslint/no-explicit-any const request_handlers: Record = { - 'ahk2.executeCommand': (params: string[]) => commands.executeCommand(params.shift() as string, ...params), - 'ahk2.getActiveTextEditorUriAndPosition': () => { + 'ahk++.executeCommand': (params: string[]) => commands.executeCommand(params.shift() as string, ...params), + 'ahk++.getActiveTextEditorUriAndPosition': () => { const editor = window.activeTextEditor; if (!editor) return; const uri = editor.document.uri.toString(), position = editor.selection.end; return { uri, position }; }, - 'ahk2.insertSnippet': async (params: [string, Range?]) => { + 'ahk++.insertSnippet': async (params: [string, Range?]) => { const editor = window.activeTextEditor; if (!editor) return; if (params[1]) { @@ -94,7 +94,7 @@ export function activate(context: ExtensionContext): Promise { } else editor.insertSnippet(new SnippetString(params[0])); }, - 'ahk2.setTextDocumentLanguage': async (params: [string, string?]) => { + 'ahk++.setTextDocumentLanguage': async (params: [string, string?]) => { const lang = params[1] || 'ahk'; if (!langs.includes(lang)) { window.showErrorMessage(`Unknown language id: ${lang}`); @@ -103,7 +103,7 @@ export function activate(context: ExtensionContext): Promise { const uri = params[0], it = workspace.textDocuments.find(it => it.uri.toString() === uri); it && languages.setTextDocumentLanguage(it, lang); }, - 'ahk2.updateStatusBar': async (params: [string]) => { + 'ahk++.updateStatusBar': async (params: [string]) => { v2Interpreter = params[0]; onDidChangegetInterpreter(); } @@ -204,7 +204,7 @@ export function activate(context: ExtensionContext): Promise { ahkStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 75); ahkStatusBarItem.command = 'ahk++.setv2Interpreter'; for (const it of [ - { text: '$(folder)syntaxes', command: { title: localize('ahk2.select'), command: 'ahk2.select.syntaxes' } }, + { text: '$(folder)syntaxes', command: { title: localize('ahk2.select'), command: 'ahk++.select.syntaxes' } }, ]) context.subscriptions.push(Object.assign(languages.createLanguageStatusItem(it.command.command, { language: 'ahk2' }), it)); const ahkLanguageStatusItem = languages.createLanguageStatusItem('ahk++', { language: 'ahk2' }); @@ -216,10 +216,10 @@ export function activate(context: ExtensionContext): Promise { commands.registerTextEditorCommand('ahk++.run', textEditor => runScript(textEditor)), commands.registerTextEditorCommand('ahk++.runSelection', textEditor => runScript(textEditor, true)), commands.registerCommand('ahk++.stop', stopRunningScript), - commands.registerCommand('ahk2.debug.file', () => beginDebug('f')), - commands.registerCommand('ahk2.debug.configs', () => beginDebug('c')), - commands.registerCommand('ahk2.debug.params', () => beginDebug('p')), - commands.registerCommand('ahk2.debug.attach', () => beginDebug('a')), + commands.registerCommand('ahk++.debug.file', () => beginDebug('f')), + commands.registerCommand('ahk++.debug.configs', () => beginDebug('c')), + commands.registerCommand('ahk++.debug.params', () => beginDebug('p')), + commands.registerCommand('ahk++.debug.attach', () => beginDebug('a')), commands.registerCommand('ahk++.selectSyntaxes', selectSyntaxes), commands.registerTextEditorCommand('ahk++.updateVersionInfo', async textEditor => { if (!server_is_ready) @@ -271,7 +271,7 @@ export function activate(context: ExtensionContext): Promise { const doc = textEditor.document; if (doc.languageId !== 'ahk2') return; - client.sendRequest('ahk2.exportSymbols', doc.uri.toString()) + client.sendRequest('ahk++.exportSymbols', doc.uri.toString()) .then(result => workspace.openTextDocument({ language: 'json', content: JSON.stringify(result, undefined, 2) }).then(d => window.showTextDocument(d, 2))); @@ -280,7 +280,7 @@ export function activate(context: ExtensionContext): Promise { provideTextDocumentContent(uri, token) { if (token.isCancellationRequested) return; - return client.sendRequest('ahk2.getContent', uri.toString()).then(content => { + return client.sendRequest('ahk++.getContent', uri.toString()).then(content => { setTimeout(() => { const it = workspace.textDocuments.find(it => it.uri.scheme === 'ahkres' && it.uri.path === uri.path); it && it.languageId !== 'ahk2' && languages.setTextDocumentLanguage(it, 'ahk2'); @@ -585,7 +585,7 @@ async function selectSyntaxes() { } function getAHKversion(paths: string[]): Thenable { - return client.sendRequest('ahk2.getAHKversion', paths.map(p => resolvePath(p, undefined, true) || p)); + return client.sendRequest('ahk++.getAHKversion', paths.map(p => resolvePath(p, undefined, true) || p)); } /** diff --git a/package.json b/package.json index 2df08cbd..03fa3be6 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "publisher": "mark-wiemer", "main": "./client/dist/extension", "scripts": { + "prebuild": "npm run clean", "build": "node build.mjs --mode=production", "prebuild:dev": "npm run clean", "build:dev": "node build.mjs", diff --git a/server/src/commandProvider.ts b/server/src/commandProvider.ts index 1ee3f571..5ab62303 100644 --- a/server/src/commandProvider.ts +++ b/server/src/commandProvider.ts @@ -19,15 +19,15 @@ function trim_jsdoc(detail?: string) { } function insertSnippet(value: string, range?: Range) { - if (!checkCommand('ahk2.insertSnippet')) + if (!checkCommand('ahk++.insertSnippet')) return; - connection?.sendRequest('ahk2.insertSnippet', [value, range]); + connection?.sendRequest('ahk++.insertSnippet', [value, range]); } export function setTextDocumentLanguage(uri: string, lang?: string) { - if (!checkCommand('ahk2.setTextDocumentLanguage')) + if (!checkCommand('ahk++.setTextDocumentLanguage')) return; - return connection?.sendRequest('ahk2.setTextDocumentLanguage', [uri, lang]); + return connection?.sendRequest('ahk++.setTextDocumentLanguage', [uri, lang]); } export function generate_fn_comment(doc: Lexer, fn: FuncNode, detail?: string) { @@ -76,9 +76,9 @@ export function generate_fn_comment(doc: Lexer, fn: FuncNode, detail?: string) { /** Add a function header comment for the currently active function */ async function generateComment() { - if (!checkCommand('ahk2.getActiveTextEditorUriAndPosition') || !checkCommand('ahk2.insertSnippet')) + if (!checkCommand('ahk++.getActiveTextEditorUriAndPosition') || !checkCommand('ahk++.insertSnippet')) return; - const { uri, position } = await connection?.sendRequest('ahk2.getActiveTextEditorUriAndPosition') as { uri: string, position: Position }; + const { uri, position } = await connection?.sendRequest('ahk++.getActiveTextEditorUriAndPosition') as { uri: string, position: Position }; const doc = lexers[uri.toLowerCase()]; let scope = doc.searchScopedNode(position); const ts = scope?.children || doc.children; @@ -207,9 +207,9 @@ export function exportSymbols(uri: string) { } async function diagnoseAll() { - if (!checkCommand('ahk2.getActiveTextEditorUriAndPosition')) + if (!checkCommand('ahk++.getActiveTextEditorUriAndPosition')) return; - const { uri } = await connection?.sendRequest('ahk2.getActiveTextEditorUriAndPosition') as { uri: string }; + const { uri } = await connection?.sendRequest('ahk++.getActiveTextEditorUriAndPosition') as { uri: string }; const doc = lexers[uri.toLowerCase()]; if (!doc) return; update_include_cache(); @@ -219,9 +219,9 @@ async function diagnoseAll() { } async function setscriptdir() { - if (!checkCommand('ahk2.getActiveTextEditorUriAndPosition')) + if (!checkCommand('ahk++.getActiveTextEditorUriAndPosition')) return; - const { uri } = await connection?.sendRequest('ahk2.getActiveTextEditorUriAndPosition') as { uri: string }; + const { uri } = await connection?.sendRequest('ahk++.getActiveTextEditorUriAndPosition') as { uri: string }; const lex = lexers[uri.toLowerCase()]; if (!lex) return; if (lex.scriptdir !== lex.scriptpath) diff --git a/server/src/server.ts b/server/src/server.ts index 46d3b0f9..c7be99ea 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -220,7 +220,7 @@ connection.onDidChangeConfiguration(async (change) => { const newInterpreterPath: string = getCfg(newCfg, CfgKey.InterpreterPath); if (getCfg(oldCfg, CfgKey.InterpreterPath) !== newInterpreterPath) { if (await setInterpreter(resolvePath(newInterpreterPath))) - connection.sendRequest('ahk2.updateStatusBar', [newInterpreterPath]); + connection.sendRequest('ahk++.updateStatusBar', [newInterpreterPath]); } const oldLibSuggestions: LibrarySuggestions = getCfg(oldCfg, CfgKey.LibrarySuggestions); @@ -301,10 +301,10 @@ connection.onExecuteCommand(executeCommandProvider); connection.onWorkspaceSymbol(workspaceSymbolProvider); connection.languages.semanticTokens.on(semanticTokensOnFull); connection.languages.semanticTokens.onRange(semanticTokensOnRange); -connection.onRequest('ahk2.exportSymbols', (uri: string) => exportSymbols(uri)); -connection.onRequest('ahk2.getAHKversion', getAHKversion); -connection.onRequest('ahk2.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); -connection.onRequest('ahk2.getVersionInfo', getVersionInfo); +connection.onRequest('ahk++.exportSymbols', (uri: string) => exportSymbols(uri)); +connection.onRequest('ahk++.getAHKversion', getAHKversion); +connection.onRequest('ahk++.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); +connection.onRequest('ahk++.getVersionInfo', getVersionInfo); connection.onNotification('onDidCloseTextDocument', (params: { uri: string, id: string }) => { if (params.id === 'ahk2') lexers[params.uri.toLowerCase()]?.close(true); @@ -314,10 +314,10 @@ documents.listen(connection); connection.listen(); async function patherr(msg: string) { - if (!ahkppConfig.commands?.includes('ahk2.executeCommand')) + if (!ahkppConfig.commands?.includes('ahk++.executeCommand')) return connection.window.showErrorMessage(msg); if (await connection.window.showErrorMessage(msg, { title: 'Select Interpreter' })) - connection.sendRequest('ahk2.executeCommand', ['ahk++.setV2Interpreter']); + connection.sendRequest('ahk++.executeCommand', ['ahk++.setV2Interpreter']); } async function initpathenv(samefolder = false, retry = true): Promise { From 02004de0983a982850dd8086ca8b06035b807fb7 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:25:53 -0700 Subject: [PATCH 39/60] Remove automated tests for clarity (#37) * Remove e2e test config file * Remove references to e2e tests --- .vscode-test.mjs | 19 --- client/src/extension.test.ts | 234 ----------------------------------- package.json | 7 +- 3 files changed, 1 insertion(+), 259 deletions(-) delete mode 100644 .vscode-test.mjs delete mode 100644 client/src/extension.test.ts diff --git a/.vscode-test.mjs b/.vscode-test.mjs deleted file mode 100644 index 3613e4fc..00000000 --- a/.vscode-test.mjs +++ /dev/null @@ -1,19 +0,0 @@ -// https://github.com/microsoft/vscode-test-cli -import { defineConfig } from '@vscode/test-cli'; -import { execSync } from 'child_process'; - -let vscode_path = undefined; -try { - const m = execSync( - 'chcp 65001 && reg query HKCR\\vscode\\shell\\open\\command', - { encoding: 'utf8' }, - ).match(/REG_SZ\s+("([^"]+)"|\S+)/); - vscode_path = m[2] || m[1]; -} catch {} - -export default defineConfig({ - files: 'client/dist/test/**/*.test.js', - useInstallation: vscode_path && { - fromPath: vscode_path, - }, -}); diff --git a/client/src/extension.test.ts b/client/src/extension.test.ts deleted file mode 100644 index 38393599..00000000 --- a/client/src/extension.test.ts +++ /dev/null @@ -1,234 +0,0 @@ -import * as assert from 'assert'; -import * as vscode from 'vscode'; -import { resolve } from 'path'; -import { - LanguageClient, - CompletionRequest, - CompletionParams, - CompletionItem, - DocumentSymbolRequest, - DocumentSymbolParams, - SymbolInformation, - DefinitionRequest, - DefinitionParams, - LocationLink, - DocumentFormattingRequest, - DocumentFormattingParams, - TextEdit, - FoldingRangeRequest, - FoldingRangeParams, - FoldingRange, - HoverRequest, - HoverParams, - Hover, - PrepareRenameRequest, - PrepareRenameParams, - ReferencesRequest, - ReferenceParams, - Location, - RenameRequest, - RenameParams, - WorkspaceEdit, - SignatureHelpRequest, - SignatureHelpParams, - SignatureHelp, - SemanticTokensRequest, - SemanticTokensParams, - SemanticTokens, - WorkspaceSymbolRequest, - WorkspaceSymbolParams, - ExecuteCommandRequest, - ExecuteCommandParams, -} from 'vscode-languageclient/node'; - -suite('Start ahk language server', () => { - test('should be running', async () => { - await vscode.commands.executeCommand( - 'workbench.action.closeAllEditors', - ); - const client: LanguageClient = await vscode.extensions - .getExtension('thqby.vscode-autohotkey2-lsp') - ?.activate(); - assert.equal(client?.isRunning(), true); - - suite('Open ahk file', () => { - test('should be opened', async () => { - const path = resolve( - __dirname, - '../../../server/dist/ahkProvider.ahk', - ); - let document = ( - await vscode.window.showTextDocument( - await vscode.workspace.openTextDocument(path), - ) - ).document; - const uri = document.uri.toString(); - if (document.languageId !== 'ahk2') - document = await vscode.languages.setTextDocumentLanguage( - document, - 'ahk2', - ); - const content = (await client!.sendRequest( - 'ahk2.getContent', - uri, - )) as string; - assert.equal(document.getText() === content, true); - - suite('Test language server features', () => { - const textDocument = { uri }; - const position = { line: 10, character: 5 }; - - test(CompletionRequest.method, async function () { - const params: CompletionParams = { - textDocument, - position, - }; - const result: CompletionItem[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(DefinitionRequest.method, async function () { - const params: DefinitionParams = { - textDocument, - position, - }; - const result: LocationLink[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(DocumentFormattingRequest.method, async function () { - const params: DocumentFormattingParams = { - textDocument, - options: { insertSpaces: false, tabSize: 4 }, - }; - const result: TextEdit[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(DocumentSymbolRequest.method, async function () { - const params: DocumentSymbolParams = { textDocument }; - const result: SymbolInformation[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(FoldingRangeRequest.method, async function () { - const params: FoldingRangeParams = { textDocument }; - const result: FoldingRange[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(HoverRequest.method, async function () { - const params: HoverParams = { textDocument, position }; - const result: Hover | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.contents); - }); - - test(PrepareRenameRequest.method, async function () { - const params: PrepareRenameParams = { - textDocument, - position, - }; - const result: unknown | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result); - }); - - test(ReferencesRequest.method, async function () { - const params: ReferenceParams = { - textDocument, - position, - context: { includeDeclaration: true }, - }; - const result: Location[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(RenameRequest.method, async function () { - const params: RenameParams = { - textDocument, - position, - newName: '', - }; - const result: WorkspaceEdit | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.changes); - }); - - test(SignatureHelpRequest.method, async function () { - const params: SignatureHelpParams = { - textDocument, - position: { line: 8, character: 36 }, - }; - const result: SignatureHelp | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.signatures); - }); - - test(ExecuteCommandRequest.method, async function () { - const params: ExecuteCommandParams = { - command: 'ahk2.diagnose.all', - }; - await client.sendRequest(this.runnable().title, params); - }); - - test(WorkspaceSymbolRequest.method, async function () { - const params: WorkspaceSymbolParams = { query: 'msg' }; - const result: SymbolInformation[] | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.length); - }); - - test(SemanticTokensRequest.method, async function () { - const params: SemanticTokensParams = { textDocument }; - const result: SemanticTokens | undefined = - await client.sendRequest( - this.runnable().title, - params, - ); - assert.ok(result?.data); - }); - }); - }); - }); - }); -}); diff --git a/package.json b/package.json index 03fa3be6..f9dd4e87 100644 --- a/package.json +++ b/package.json @@ -50,12 +50,7 @@ "lint:fix": "npm run format:fix && npm run eslint:fix && npm run sort-package-json:fix", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", - "test": "npm run test-unit", - "pretest-unit": "npm run compile-ts", - "test-unit": "cd client && vscode-test", - "test-unit//": "echo todo failing for now, will be adding pure unit tests soon", - "test//": "Run unit tests, not grammar tests", - "validate": "npm run lint && npm run test", + "validate": "npm run lint", "validate:ci": "npm run lint", "validate:ci:fix": "npm run lint:fix", "watch": "tsc -b -w" From b1057d6513318cd30f2012f98793d085a5f2ac43 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 28 Sep 2024 20:49:56 -0700 Subject: [PATCH 40/60] Add unit tests (#38) * Remove dupe rootDirs, use `out` for compile-ts * Add unit test script and move to out folder consistently * Extract resolvePath into a unit-tested thingamabob --- .gitignore | 2 +- client/src/extension.ts | 30 +----------------------------- client/src/utils.test.ts | 9 +++++++++ client/src/utils.ts | 33 +++++++++++++++++++++++++++++++++ client/tsconfig.json | 3 +-- package.json | 21 ++++++++++++++------- server/tsconfig.json | 3 +-- 7 files changed, 60 insertions(+), 41 deletions(-) create mode 100644 client/src/utils.test.ts create mode 100644 client/src/utils.ts diff --git a/.gitignore b/.gitignore index 4ed6e072..96a5e3e3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ scripts/* *.js *.js.map *.tsbuildinfo -**/dist/**/*.d.ts \ No newline at end of file +**/out/**/*.d.ts \ No newline at end of file diff --git a/client/src/extension.ts b/client/src/extension.ts index 9d982751..28fc4343 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -34,12 +34,12 @@ import { resolve } from 'path'; import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, readFileSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config'; +import { resolvePath } from './utils'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); let v2Interpreter = getCfg(CfgKey.InterpreterPathV2), server_is_ready = false const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; -const isWindows = process.platform === 'win32'; let extlist: string[] = [], debugexts: Record = {}, langs: string[] = []; const loadedCollection = { 'ahk2.browse': 'Browse your file system to find AutoHotkey2 interpreter', @@ -623,34 +623,6 @@ async function onDidChangegetInterpreter() { } } -/** - * Returns the provided path as an absolute path. - * Resolves the provided path against the provided workspace. - * Resolves symbolic links by default. - * Returns empty string if resolution fails. - */ -export function resolvePath(path: string | undefined, workspace?: string, resolveSymbolicLink = true): string { - if (!path) - return ''; - const paths: string[] = []; - // If the path does not contain a colon, resolve it relative to the workspace - if (!path.includes(':')) - paths.push(resolve(workspace ?? '', path)); - // If there are no slashes or backslashes in the path and the platform is Windows - if (!/[\\/]/.test(path) && isWindows) - paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); - paths.push(path); - for (let path of paths) { - if (!path) continue; - try { - if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) - path = resolve(path, '..', readlinkSync(path)); - return path; - } catch { } - } - return ''; -} - /** * Returns whether the given path exists. * Only returns false if lstatSync give an ENOENT error. diff --git a/client/src/utils.test.ts b/client/src/utils.test.ts new file mode 100644 index 00000000..b27833b2 --- /dev/null +++ b/client/src/utils.test.ts @@ -0,0 +1,9 @@ +import * as assert from 'assert'; +import { suite, test } from 'mocha'; +import { resolvePath } from './utils'; + +suite('resolvePath', () => { + test('empty string', () => { + assert.strictEqual(resolvePath(''), ''); + }); +}); diff --git a/client/src/utils.ts b/client/src/utils.ts new file mode 100644 index 00000000..96242b26 --- /dev/null +++ b/client/src/utils.ts @@ -0,0 +1,33 @@ +import { execSync } from 'child_process'; +import { lstatSync, readlinkSync } from 'fs'; +import { resolve } from 'path'; + +/** + * Returns the provided path as an absolute path. + * Resolves the provided path against the provided workspace. + * Resolves symbolic links by default. + * Returns empty string if resolution fails. + */ +export function resolvePath( + path: string | undefined, + workspace?: string, + resolveSymbolicLink = true, +): string { + if (!path) return ''; + const paths: string[] = []; + // If the path does not contain a colon, resolve it relative to the workspace + if (!path.includes(':')) paths.push(resolve(workspace ?? '', path)); + // If there are no slashes or backslashes in the path and the platform is Windows + if (!/[\\/]/.test(path) && process.platform === 'win32') + paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); + paths.push(path); + for (let path of paths) { + if (!path) continue; + try { + if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) + path = resolve(path, '..', readlinkSync(path)); + return path; + } catch {} + } + return ''; +} diff --git a/client/tsconfig.json b/client/tsconfig.json index 5f41caf1..564016b0 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -6,8 +6,7 @@ "moduleResolution": "node", "sourceMap": true, "strict": true, - "outDir": "dist", - "rootDirs": ["src", "../server/src"], + "outDir": "out", "composite": true }, "include": ["src"], diff --git a/package.json b/package.json index f9dd4e87..dca2e131 100644 --- a/package.json +++ b/package.json @@ -29,16 +29,17 @@ "publisher": "mark-wiemer", "main": "./client/dist/extension", "scripts": { - "prebuild": "npm run clean", + "prebuild": "npm run clean:dist", "build": "node build.mjs --mode=production", "prebuild:dev": "npm run clean", "build:dev": "node build.mjs", "build:old": "webpack", "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", - "clean": "del-cli client/dist server/dist/*.js*", - "clean//": "Remove both the compiled extension and compiled test files", + "clean:dist": "del-cli client/dist server/dist/*.js*", + "clean:out": "del-cli client/out server/out", "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", - "compile-ts": "cd client && tsc && cd ../server && tsc", + "precompile-ts": "npm run clean:out", + "compile-ts": "tsc -b", "compile-ts//": "Compile TS files", "compile//": "Compile the extension for packaging and publishing", "eslint": "npm run eslint:files -- client server && echo No ESLint problems", @@ -50,9 +51,12 @@ "lint:fix": "npm run format:fix && npm run eslint:fix && npm run sort-package-json:fix", "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", - "validate": "npm run lint", - "validate:ci": "npm run lint", - "validate:ci:fix": "npm run lint:fix", + "pretest-unit": "npm run compile-ts", + "test-unit": "mocha", + "validate": "npm run lint && npm run test-unit", + "validate:ci": "npm run lint && npm run test-unit", + "validate:ci:fix": "npm run lint:fix && npm run test-unit", + "validate:fix": "npm run lint:fix && npm run test-unit", "watch": "tsc -b -w" }, "prettier": { @@ -72,6 +76,9 @@ } ] }, + "mocha": { + "spec": "./**/out/**/*.test.js" + }, "dependencies": { "vscode-languageclient": "^9.0.1", "vscode-languageserver": "^9.0.1", diff --git a/server/tsconfig.json b/server/tsconfig.json index b4758cd2..e156e410 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -6,8 +6,7 @@ "moduleResolution": "node", "sourceMap": true, "strict": true, - "outDir": "out", - "rootDirs": ["src", "../client/src"] + "outDir": "out" }, "include": ["src"], "exclude": ["node_modules", ".vscode-test", ".vscode-test-web"] From c2ba5f2722c08576a16356bfe6c8e04730bb4e09 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 28 Sep 2024 21:41:03 -0700 Subject: [PATCH 41/60] Fix debug commands, remove unused stuffs (#39) --- .gitignore | 2 +- .vscode/launch.json | 61 - client/src/browserClientMain.ts | 127 -- client/src/extension.ts | 9 +- package-lock.json | 2835 +---------------------------- package.json | 8 +- package.nls.json | 37 - package.nls.zh-cn.json | 127 -- readme.md | 363 +--- server/cli/cli.ts | 24 - server/src/browserServerMain.ts | 165 -- test-data/.gitignore | 1 - tmgrammar-test/0-v2-demo.ahk | 3 - tmgrammar-test/0-v2-demo.ahk.snap | 31 - tools/install.js | 1325 -------------- 15 files changed, 43 insertions(+), 5075 deletions(-) delete mode 100644 .vscode/launch.json delete mode 100644 client/src/browserClientMain.ts delete mode 100644 package.nls.json delete mode 100644 package.nls.zh-cn.json delete mode 100644 server/cli/cli.ts delete mode 100644 server/src/browserServerMain.ts delete mode 100644 test-data/.gitignore delete mode 100644 tmgrammar-test/0-v2-demo.ahk delete mode 100644 tmgrammar-test/0-v2-demo.ahk.snap delete mode 100644 tools/install.js diff --git a/.gitignore b/.gitignore index 96a5e3e3..6ff933f9 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ scripts/* *.js *.js.map *.tsbuildinfo -**/out/**/*.d.ts \ No newline at end of file +**/out/**/*.d.ts diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 7aae83be..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,61 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Run Web Extension in VS Code", - "type": "pwa-extensionHost", - "debugWebWorkerHost": true, - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionDevelopmentKind=web" - ], - "outFiles": ["${workspaceFolder}/client/dist/**/*.js"], - "preLaunchTask": "npm: build:watch" - }, - { - "name": "Extension Tests", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "preLaunchTask": "npm: watch", - "args": [ - "--disable-extensions", - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "testConfiguration": "${workspaceFolder}/.vscode-test.js", - "outFiles": ["${workspaceFolder}/client/dist/test/**/*.js"] - }, - { - "type": "extensionHost", - "request": "launch", - "name": "Launch Client", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceFolder}"], - "env": { - "VSCODE_AHK_SERVER_PATH": "server/dist/server.js", - "SYNTAXES_PATH": "syntaxes" - }, - "outFiles": ["${workspaceFolder}/client/dist/**/*.js"], - "preLaunchTask": "npm: build:dev" - }, - { - "type": "node", - "request": "attach", - "name": "Attach to Server", - "port": 6009, - "restart": true, - "outFiles": [ - "${workspaceFolder}/server/out/**/*.js", - "${workspaceFolder}/server/dist/**/*.js" - ] - } - ], - "compounds": [ - { - "name": "Client + Server", - "configurations": ["Launch Client", "Attach to Server"] - } - ] -} diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts deleted file mode 100644 index 09f3312b..00000000 --- a/client/src/browserClientMain.ts +++ /dev/null @@ -1,127 +0,0 @@ -//* ⚠️ Not currently used in AHK++ - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { commands, ExtensionContext, languages, Range, RelativePattern, SnippetString, Uri, window, workspace, WorkspaceEdit } from 'vscode'; -import { LanguageClient } from 'vscode-languageclient/browser'; - -let client: LanguageClient; - -// this method is called when vs code is activated -export function activate(context: ExtensionContext) { - const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browserServerMain.js'); - /* eslint-disable-next-line */ - const request_handlers: Record any> = { - 'ahk++.getActiveTextEditorUriAndPosition': () => { - const editor = window.activeTextEditor; - if (!editor) return; - const uri = editor.document.uri.toString(), position = editor.selection.end; - return { uri, position }; - }, - 'ahk++.insertSnippet': async (params: [string, Range?]) => { - const editor = window.activeTextEditor; - if (!editor) return; - if (params[1]) { - const { start, end } = params[1]; - await editor.insertSnippet(new SnippetString(params[0]), new Range(start.line, start.character, end.line, end.character)); - } else - editor.insertSnippet(new SnippetString(params[0])); - }, - 'ahk++.setTextDocumentLanguage': async (params: [string, string?]) => { - const lang = params[1] || 'ahk'; - if (!(await languages.getLanguages()).includes(lang)) { - window.showErrorMessage(`Unknown language id: ${lang}`); - return; - } - const uri = params[0], it = workspace.textDocuments.find(it => it.uri.toString() === uri); - it && languages.setTextDocumentLanguage(it, lang); - }, - 'ahk2.getWorkspaceFiles': async (params: string[]) => { - const all = !params.length; - if (workspace.workspaceFolders) { - if (all) - return (await workspace.findFiles('**/*.{ahk,ah2,ahk2}')).forEach(it => it.toString()); - else { - const files: string[] = []; - for (const folder of workspace.workspaceFolders) - if (params.includes(folder.uri.toString().toLowerCase())) - files.push(...(await workspace.findFiles(new RelativePattern(folder, '*.{ahk,ah2,ahk2}'))).map(it => it.toString())); - return files; - } - } - }, - 'ahk2.getWorkspaceFileContent': async (params: string[]) => (await workspace.openTextDocument(Uri.parse(params[0]))).getText() - }; - - client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', { - documentSelector: [{ language: 'ahk2' }], - markdown: { isTrusted: true, supportHtml: true }, - initializationOptions: { - extensionUri: context.extensionUri.toString(), - commands: Object.keys(request_handlers), - ...JSON.parse(JSON.stringify(workspace.getConfiguration('AutoHotkey2'))) - } - }, new Worker(serverMain.toString())); - - context.subscriptions.push( - commands.registerTextEditorCommand('ahk2.update.versioninfo', async textEditor => { - const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); - if (!infos?.length) { - await textEditor.insertSnippet(new SnippetString([ - "/************************************************************************", - " * @description ${1:}", - " * @author ${2:}", - " * @date ${3:$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE}", - " * @version ${4:0.0.0}", - " ***********************************************************************/", - "", "" - ].join('\n')), new Range(0, 0, 0, 0)); - } else { - const d = new Date; - let contents: string[] = [], value: string | undefined; - for (const info of infos) { - if (info.single) - contents.push(info.content.replace( - /(?<=^;\s*@ahk2exe-setversion\s+)(\S+|(?=[\r\n]))/i, - s => (value ||= s, '\0'))); - else contents.push(info.content.replace( - /(?<=^\s*[;*]?\s*@date[:\s]\s*)(\S+|(?=[\r\n]))/im, - date => [d.getFullYear(), d.getMonth() + 1, d.getDate()].map( - n => n.toString().padStart(2, '0')).join(date.includes('.') ? '.' : '/') - ).replace(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S+|(?=[\r\n]))/im, s => (value ||= s, '\0'))); - } - if (value !== undefined) { - value = await window.showInputBox({ - value, prompt: 'Enter version info' - }); - if (!value) - return; - contents = contents.map(s => s.replace('\0', value!)); - } - const ed = new WorkspaceEdit(), uri = textEditor.document.uri; - infos.forEach(it => it.content !== (value = contents.shift()) && - ed.replace(uri, it.range, value!)); - ed.size && workspace.applyEdit(ed); - } - }), - commands.registerTextEditorCommand('ahk2.switch', textEditor => { - const doc = textEditor.document; - languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); - }), - workspace.onDidCloseTextDocument(e => { - client.sendNotification('onDidCloseTextDocument', e.isClosed ? - { uri: '', id: '' } : { uri: e.uri.toString(), id: e.languageId }); - }) - ); - - client.start().then(() => { - Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); - }); -} - -export function deactivate() { - return client?.stop(); -} \ No newline at end of file diff --git a/client/src/extension.ts b/client/src/extension.ts index 28fc4343..224f116c 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -125,7 +125,7 @@ export function activate(context: ExtensionContext): Promise { }; // Create the language client and start the client. - client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', serverOptions, clientOptions); + client = new LanguageClient('AHK++', 'AHK++', serverOptions, clientOptions); loadlocalize(context.extensionPath + '/package.nls'); textdecoders.push(new TextDecoder(env.language.startsWith('zh-') ? 'gbk' : 'windows-1252')); @@ -216,10 +216,9 @@ export function activate(context: ExtensionContext): Promise { commands.registerTextEditorCommand('ahk++.run', textEditor => runScript(textEditor)), commands.registerTextEditorCommand('ahk++.runSelection', textEditor => runScript(textEditor, true)), commands.registerCommand('ahk++.stop', stopRunningScript), - commands.registerCommand('ahk++.debug.file', () => beginDebug('f')), - commands.registerCommand('ahk++.debug.configs', () => beginDebug('c')), - commands.registerCommand('ahk++.debug.params', () => beginDebug('p')), - commands.registerCommand('ahk++.debug.attach', () => beginDebug('a')), + commands.registerCommand('ahk++.debugConfigs', () => beginDebug('c')), + commands.registerCommand('ahk++.debugParams', () => beginDebug('p')), + commands.registerCommand('ahk++.debugAttach', () => beginDebug('a')), commands.registerCommand('ahk++.selectSyntaxes', selectSyntaxes), commands.registerTextEditorCommand('ahk++.updateVersionInfo', async textEditor => { if (!server_is_ready) diff --git a/package-lock.json b/package-lock.json index 3d0f8aaf..59244092 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,24 +16,19 @@ }, "devDependencies": { "@eslint/js": "^9.4.0", + "@types/mocha": "^10.0.8", "@types/node": "^20.16.0", - "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", - "@vscode/test-cli": "^0.0.10", - "@vscode/test-electron": "^2.4.1", - "@vscode/test-web": "^0.0.56", "del-cli": "^5.1.0", "esbuild": "^0.23.1", "eslint": "^9.4.0", "globals": "^15.4.0", "mocha": "^10.7.0", "prettier": "3.3.3", - "sinon": "^18.0.0", "sort-package-json": "^2.10.0", "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", - "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" }, @@ -81,13 +76,6 @@ "node": ">=6.9.0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" - }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -658,63 +646,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmmirror.com/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -779,36 +710,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@koa/cors": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/@koa/cors/-/cors-5.0.0.tgz", - "integrity": "sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@koa/router": { - "version": "12.0.1", - "resolved": "https://registry.npmmirror.com/@koa/router/-/router-12.0.1.tgz", - "integrity": "sha512-ribfPYfHb+Uw3b27Eiw6NPqjhIhTpVFzEWLwyc/1Xp+DCdwRRyIlAUODX+9bPARF6aQtUu1+/PHzdNvRzcs/+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "http-errors": "^2.0.0", - "koa-compose": "^4.1.0", - "methods": "^1.1.2", - "path-to-regexp": "^6.2.1" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -847,80 +748,6 @@ "node": ">= 8" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmmirror.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@playwright/browser-chromium": { - "version": "1.45.3", - "resolved": "https://registry.npmmirror.com/@playwright/browser-chromium/-/browser-chromium-1.45.3.tgz", - "integrity": "sha512-UVPW8HveE8SghaahoMy8CfG0QdJ2mO0BZLOcPT8nlQh7Z97Gkv4e3Ad69D1oCqM3m3zYkDPAiGB+hOASNS0d/g==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.45.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "11.2.2", - "resolved": "https://registry.npmmirror.com/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", - "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/@sinonjs/samsam/-/samsam-8.0.0.tgz", - "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmmirror.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true, - "license": "(Unlicense OR Apache-2.0)" - }, "node_modules/@types/eslint": { "version": "8.56.10", "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.10.tgz", @@ -950,13 +777,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -972,9 +792,9 @@ "license": "MIT" }, "node_modules/@types/mocha": { - "version": "10.0.7", - "resolved": "https://registry.npmmirror.com/@types/mocha/-/mocha-10.0.7.tgz", - "integrity": "sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==", + "version": "10.0.8", + "resolved": "https://registry.npmmirror.com/@types/mocha/-/mocha-10.0.8.tgz", + "integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==", "dev": true, "license": "MIT" }, @@ -995,23 +815,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/sinon": { - "version": "17.0.3", - "resolved": "https://registry.npmmirror.com/@types/sinon/-/sinon-17.0.3.tgz", - "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/sinonjs__fake-timers": "*" - } - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmmirror.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/vscode": { "version": "1.90.0", "resolved": "https://registry.npmmirror.com/@types/vscode/-/vscode-1.90.0.tgz", @@ -1137,209 +940,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@vscode/test-cli": { - "version": "0.0.10", - "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", - "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", - "dev": true, - "dependencies": { - "@types/mocha": "^10.0.2", - "c8": "^9.1.0", - "chokidar": "^3.5.3", - "enhanced-resolve": "^5.15.0", - "glob": "^10.3.10", - "minimatch": "^9.0.3", - "mocha": "^10.2.0", - "supports-color": "^9.4.0", - "yargs": "^17.7.2" - }, - "bin": { - "vscode-test": "out/bin.mjs" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@vscode/test-cli/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@vscode/test-cli/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/test-cli/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/test-cli/node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/@vscode/test-electron": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", - "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "jszip": "^3.10.1", - "ora": "^7.0.1", - "semver": "^7.6.2" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@vscode/test-web": { - "version": "0.0.56", - "resolved": "https://registry.npmmirror.com/@vscode/test-web/-/test-web-0.0.56.tgz", - "integrity": "sha512-lR688n+D6A9odw+IZ5cU8CYr2YXLB61bGgyZpPVJe/sJy4/DYX5CAxPb7Wj9ZMYL41CTvWq5DeXtfCjlabPcYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@koa/cors": "^5.0.0", - "@koa/router": "^12.0.1", - "@playwright/browser-chromium": "^1.45.0", - "glob": "^10.4.2", - "gunzip-maybe": "^1.4.2", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.4", - "koa": "^2.15.3", - "koa-morgan": "^1.0.1", - "koa-mount": "^4.0.0", - "koa-static": "^5.0.0", - "minimist": "^1.2.8", - "playwright": "^1.45.0", - "tar-fs": "^3.0.6", - "vscode-uri": "^3.0.8" - }, - "bin": { - "vscode-test-web": "out/index.js" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@vscode/test-web/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@vscode/test-web/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/test-web/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vscode/test-web/node_modules/tar-fs": { - "version": "3.0.6", - "resolved": "https://registry.npmmirror.com/tar-fs/-/tar-fs-3.0.6.tgz", - "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^2.1.1", - "bare-path": "^2.1.0" - } - }, - "node_modules/@vscode/test-web/node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -1554,20 +1154,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.11.3.tgz", @@ -1601,19 +1187,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/aggregate-error": { "version": "4.0.1", "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-4.0.1.tgz", @@ -1732,130 +1305,24 @@ "node": ">=0.10.0" } }, - "node_modules/b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmmirror.com/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, - "node_modules/bare-events": { - "version": "2.4.2", - "resolved": "https://registry.npmmirror.com/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, - "license": "Apache-2.0", - "optional": true - }, - "node_modules/bare-fs": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/bare-fs/-/bare-fs-2.3.1.tgz", - "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-events": "^2.0.0", - "bare-path": "^2.0.0", - "bare-stream": "^2.0.0" - } - }, - "node_modules/bare-os": { - "version": "2.4.0", - "resolved": "https://registry.npmmirror.com/bare-os/-/bare-os-2.4.0.tgz", - "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", - "dev": true, - "license": "Apache-2.0", - "optional": true - }, - "node_modules/bare-path": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/bare-path/-/bare-path-2.1.3.tgz", - "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-os": "^2.1.0" - } - }, - "node_modules/bare-stream": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/bare-stream/-/bare-stream-2.1.3.tgz", - "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "streamx": "^2.18.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bottleneck": { - "version": "2.19.5", - "resolved": "https://registry.npmmirror.com/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", - "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/brace-expansion": { "version": "1.1.11", @@ -1888,16 +1355,6 @@ "dev": true, "license": "ISC" }, - "node_modules/browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "pako": "~0.2.0" - } - }, "node_modules/browserslist": { "version": "4.23.0", "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.23.0.tgz", @@ -1938,111 +1395,6 @@ "dev": true, "license": "MIT" }, - "node_modules/c8": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/c8/-/c8-9.1.0.tgz", - "integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^3.1.1", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.1.6", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=14.14.0" - } - }, - "node_modules/c8/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/c8/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/c8/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/c8/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cache-content-type": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/cache-content-type/-/cache-content-type-1.0.1.tgz", - "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "^2.1.18", - "ylru": "^1.2.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", @@ -2198,124 +1550,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cliui/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz", @@ -2331,17 +1565,6 @@ "node": ">=6" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmmirror.com/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", @@ -2373,56 +1596,6 @@ "dev": true, "license": "MIT" }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookies": { - "version": "0.9.1", - "resolved": "https://registry.npmmirror.com/cookies/-/cookies-0.9.1.tgz", - "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "keygrip": "~1.1.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2506,13 +1679,6 @@ "node": ">=0.10.0" } }, - "node_modules/deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", - "dev": true, - "license": "MIT" - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", @@ -2610,34 +1776,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/detect-indent": { "version": "7.0.1", "resolved": "https://registry.npmmirror.com/detect-indent/-/detect-indent-7.0.1.tgz", @@ -2684,66 +1822,6 @@ "node": ">=8" } }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmmirror.com/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/duplexify/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/duplexify/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/duplexify/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true, - "license": "MIT" - }, "node_modules/electron-to-chromium": { "version": "1.4.796", "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.796.tgz", @@ -2751,33 +1829,6 @@ "dev": true, "license": "ISC" }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/enhanced-resolve": { "version": "5.17.0", "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", @@ -2872,13 +1923,6 @@ "node": ">=6" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, - "license": "MIT" - }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -3250,13 +2294,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmmirror.com/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "dev": true, - "license": "MIT" - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz", @@ -3392,33 +2429,6 @@ "dev": true, "license": "ISC" }, - "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3574,24 +2584,6 @@ "dev": true, "license": "MIT" }, - "node_modules/gunzip-maybe": { - "version": "1.4.2", - "resolved": "https://registry.npmmirror.com/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", - "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "browserify-zlib": "^0.1.4", - "is-deflate": "^1.0.0", - "is-gzip": "^1.0.0", - "peek-stream": "^1.1.0", - "pumpify": "^1.3.3", - "through2": "^2.0.3" - }, - "bin": { - "gunzip-maybe": "bin.js" - } - }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -3612,35 +2604,6 @@ "node": ">=4" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", @@ -3671,136 +2634,12 @@ "dev": true, "license": "ISC", "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-assert": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/http-assert/-/http-assert-1.5.0.tgz", - "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-equal": "~1.0.1", - "http-errors": "~1.8.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-assert/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-assert/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-assert/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">=10" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.1.tgz", @@ -3811,12 +2650,6 @@ "node": ">= 4" } }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true - }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz", @@ -3949,13 +2782,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-deflate": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-deflate/-/is-deflate-1.0.0.tgz", - "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", - "dev": true, - "license": "MIT" - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3976,22 +2802,6 @@ "node": ">=8" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmmirror.com/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", @@ -4005,28 +2815,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-gzip": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-gzip/-/is-gzip-1.0.0.tgz", - "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", @@ -4096,12 +2884,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", @@ -4119,84 +2901,6 @@ "node": ">=0.10.0" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", @@ -4286,75 +2990,6 @@ "dev": true, "license": "MIT" }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmmirror.com/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dev": true, - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/jszip/node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true, - "license": "(MIT AND Zlib)" - }, - "node_modules/jszip/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/jszip/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/jszip/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/just-extend": { - "version": "6.2.0", - "resolved": "https://registry.npmmirror.com/just-extend/-/just-extend-6.2.0.tgz", - "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true, - "license": "MIT" - }, - "node_modules/keygrip": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/keygrip/-/keygrip-1.1.0.tgz", - "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "tsscmp": "1.0.6" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", @@ -4375,199 +3010,6 @@ "node": ">=0.10.0" } }, - "node_modules/koa": { - "version": "2.15.3", - "resolved": "https://registry.npmmirror.com/koa/-/koa-2.15.3.tgz", - "integrity": "sha512-j/8tY9j5t+GVMLeioLaxweJiKUayFhlGqNTzf2ZGwL0ZCQijd2RLHK0SLW5Tsko8YyyqCZC2cojIb0/s62qTAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.9.0", - "debug": "^4.3.2", - "delegates": "^1.0.0", - "depd": "^2.0.0", - "destroy": "^1.0.4", - "encodeurl": "^1.0.2", - "escape-html": "^1.0.3", - "fresh": "~0.5.2", - "http-assert": "^1.3.0", - "http-errors": "^1.6.3", - "is-generator-function": "^1.0.7", - "koa-compose": "^4.1.0", - "koa-convert": "^2.0.0", - "on-finished": "^2.3.0", - "only": "~0.0.2", - "parseurl": "^1.3.2", - "statuses": "^1.5.0", - "type-is": "^1.6.16", - "vary": "^1.1.2" - }, - "engines": { - "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" - } - }, - "node_modules/koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", - "dev": true, - "license": "MIT" - }, - "node_modules/koa-convert": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/koa-convert/-/koa-convert-2.0.0.tgz", - "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", - "dev": true, - "license": "MIT", - "dependencies": { - "co": "^4.6.0", - "koa-compose": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/koa-morgan": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/koa-morgan/-/koa-morgan-1.0.1.tgz", - "integrity": "sha512-JOUdCNlc21G50afBXfErUrr1RKymbgzlrO5KURY+wmDG1Uvd2jmxUJcHgylb/mYXy2SjiNZyYim/ptUBGsIi3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "morgan": "^1.6.1" - } - }, - "node_modules/koa-mount": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/koa-mount/-/koa-mount-4.0.0.tgz", - "integrity": "sha512-rm71jaA/P+6HeCpoRhmCv8KVBIi0tfGuO/dMKicbQnQW/YJntJ6MnnspkodoA4QstMVEZArsCphmd0bJEtoMjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.0.1", - "koa-compose": "^4.1.0" - }, - "engines": { - "node": ">= 7.6.0" - } - }, - "node_modules/koa-send": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/koa-send/-/koa-send-5.0.1.tgz", - "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "resolve-path": "^1.4.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/koa-send/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa-send/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa-send/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa-static": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/koa-static/-/koa-static-5.0.0.tgz", - "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.1.0", - "koa-send": "^5.0.0" - }, - "engines": { - "node": ">= 7.6.0" - } - }, - "node_modules/koa-static/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/koa/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa/node_modules/http-errors/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", @@ -4582,15 +3024,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dev": true, - "dependencies": { - "immediate": "~3.0.5" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -4621,13 +3054,6 @@ "node": ">=8" } }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmmirror.com/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4730,31 +3156,15 @@ }, "node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "semver": "^7.5.3" + "yallist": "^4.0.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/map-obj": { @@ -4770,16 +3180,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/meow": { "version": "10.1.5", "resolved": "https://registry.npmmirror.com/meow/-/meow-10.1.5.tgz", @@ -4847,16 +3247,6 @@ "node": ">= 8" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/micromatch": { "version": "4.0.7", "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.7.tgz", @@ -4894,15 +3284,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz", @@ -4926,16 +3307,6 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/minimist-options": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/minimist-options/-/minimist-options-4.1.0.tgz", @@ -4961,16 +3332,6 @@ "node": ">=0.10.0" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/mocha": { "version": "10.7.3", "resolved": "https://registry.npmmirror.com/mocha/-/mocha-10.7.3.tgz", @@ -5292,53 +3653,6 @@ "node": ">=10" } }, - "node_modules/morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmmirror.com/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/morgan/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/morgan/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/morgan/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", @@ -5353,16 +3667,6 @@ "dev": true, "license": "MIT" }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", @@ -5370,20 +3674,6 @@ "dev": true, "license": "MIT" }, - "node_modules/nise": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/nise/-/nise-6.0.0.tgz", - "integrity": "sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^11.2.2", - "@sinonjs/text-encoding": "^0.7.2", - "just-extend": "^6.2.0", - "path-to-regexp": "^6.2.1" - } - }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz", @@ -5417,29 +3707,6 @@ "node": ">=0.10.0" } }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", @@ -5450,27 +3717,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/only": { - "version": "0.0.2", - "resolved": "https://registry.npmmirror.com/only/-/only-0.0.2.tgz", - "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==", - "dev": true - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", @@ -5489,119 +3735,6 @@ "node": ">= 0.8.0" } }, - "node_modules/ora": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/ora/-/ora-7.0.1.tgz", - "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==", - "dev": true, - "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^4.0.0", - "cli-spinners": "^2.9.0", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^1.3.0", - "log-symbols": "^5.1.0", - "stdin-discarder": "^0.1.0", - "string-width": "^6.1.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true - }, - "node_modules/ora/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/log-symbols": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-5.1.0.tgz", - "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", - "dev": true, - "dependencies": { - "chalk": "^5.0.0", - "is-unicode-supported": "^1.1.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/string-width": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-6.1.0.tgz", - "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^10.2.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", @@ -5657,20 +3790,6 @@ "node": ">=6" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmmirror.com/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", - "dev": true, - "license": "MIT" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", @@ -5703,16 +3822,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", @@ -5750,37 +3859,6 @@ "dev": true, "license": "MIT" }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true, - "license": "MIT" - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", @@ -5791,18 +3869,6 @@ "node": ">=8" } }, - "node_modules/peek-stream": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/peek-stream/-/peek-stream-1.1.3.tgz", - "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "duplexify": "^3.5.0", - "through2": "^2.0.3" - } - }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz", @@ -5836,38 +3902,6 @@ "node": ">=8" } }, - "node_modules/playwright": { - "version": "1.45.3", - "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.45.3.tgz", - "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.45.3" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.45.3", - "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.45.3.tgz", - "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5878,60 +3912,20 @@ "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmmirror.com/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/punycode": { @@ -5965,13 +3959,6 @@ ], "license": "MIT" }, - "node_modules/queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true, - "license": "MIT" - }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz", @@ -6097,21 +4084,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", @@ -6206,92 +4178,6 @@ "node": ">=8" } }, - "node_modules/resolve-path": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/resolve-path/-/resolve-path-1.4.0.tgz", - "integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "http-errors": "~1.6.2", - "path-is-absolute": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/resolve-path/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/resolve-path/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/resolve-path/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true, - "license": "ISC" - }, - "node_modules/resolve-path/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/resolve-path/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz", @@ -6406,19 +4292,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "license": "ISC" - }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -6455,61 +4328,6 @@ "node": ">=8" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sinon": { - "version": "18.0.0", - "resolved": "https://registry.npmmirror.com/sinon/-/sinon-18.0.0.tgz", - "integrity": "sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^11.2.2", - "@sinonjs/samsam": "^8.0.0", - "diff": "^5.2.0", - "nise": "^6.0.0", - "supports-color": "^7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", @@ -6660,168 +4478,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stdin-discarder": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", - "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", - "dev": true, - "dependencies": { - "bl": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stdin-discarder/node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/stdin-discarder/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/stream-shift": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/streamx": { - "version": "2.18.0", - "resolved": "https://registry.npmmirror.com/streamx/-/streamx-2.18.0.tgz", - "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.3.2", - "queue-tick": "^1.0.1", - "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -6835,20 +4491,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-indent": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-4.0.0.tgz", @@ -6958,34 +4600,9 @@ "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/text-decoder/-/text-decoder-1.1.1.tgz", - "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "b4a": "^1.6.4" - } + "license": "MIT" }, "node_modules/text-table": { "version": "0.2.0", @@ -6994,50 +4611,6 @@ "dev": true, "license": "MIT" }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7051,16 +4624,6 @@ "node": ">=8.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, "node_modules/trim-newlines": { "version": "4.1.1", "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-4.1.1.tgz", @@ -7184,16 +4747,6 @@ "node": ">=8" } }, - "node_modules/tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6.x" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", @@ -7207,16 +4760,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmmirror.com/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz", @@ -7230,20 +4773,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.4.5.tgz", @@ -7447,28 +4976,6 @@ "punycode": "^2.1.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmmirror.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -7480,16 +4987,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", @@ -7568,60 +5065,6 @@ "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", "license": "MIT" }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-textmate": { - "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-7.0.4.tgz", - "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-tmgrammar-test": { - "version": "0.1.3", - "resolved": "https://registry.npmmirror.com/vscode-tmgrammar-test/-/vscode-tmgrammar-test-0.1.3.tgz", - "integrity": "sha512-Wg6Pz+ePAT1O+F/A1Fc4wS5vY2X+HNtgN4qMdL+65NLQYd1/zdDWH4fhwsLjX8wTzeXkMy49Cr4ZqWTJ7VnVxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bottleneck": "^2.19.5", - "chalk": "^2.4.2", - "commander": "^9.2.0", - "diff": "^4.0.2", - "glob": "^7.1.6", - "vscode-oniguruma": "^1.5.1", - "vscode-textmate": "^7.0.1" - }, - "bin": { - "vscode-tmgrammar-snap": "dist/snapshot.js", - "vscode-tmgrammar-test": "dist/unit.js" - } - }, - "node_modules/vscode-tmgrammar-test/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/vscode-tmgrammar-test/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/vscode-uri": { "version": "3.0.8", "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.0.8.tgz", @@ -7813,143 +5256,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", @@ -7957,16 +5263,6 @@ "dev": true, "license": "ISC" }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", @@ -7984,35 +5280,6 @@ "dev": true, "license": "ISC" }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz", @@ -8029,38 +5296,6 @@ "node": ">=10" } }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ylru": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/ylru/-/ylru-1.4.0.tgz", - "integrity": "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index dca2e131..338be832 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "prebuild:dev": "npm run clean", "build:dev": "node build.mjs", "build:old": "webpack", - "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./test-data", "clean:dist": "del-cli client/dist server/dist/*.js*", "clean:out": "del-cli client/out server/out", "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", @@ -87,24 +86,19 @@ }, "devDependencies": { "@eslint/js": "^9.4.0", + "@types/mocha": "^10.0.8", "@types/node": "^20.16.0", - "@types/sinon": "^17.0.3", "@types/vscode": "^1.82.0", - "@vscode/test-cli": "^0.0.10", - "@vscode/test-electron": "^2.4.1", - "@vscode/test-web": "^0.0.56", "del-cli": "^5.1.0", "esbuild": "^0.23.1", "eslint": "^9.4.0", "globals": "^15.4.0", "mocha": "^10.7.0", "prettier": "3.3.3", - "sinon": "^18.0.0", "sort-package-json": "^2.10.0", "ts-loader": "^9.4.0", "typescript": "^5.3.2", "typescript-eslint": "^7.12.0", - "vscode-tmgrammar-test": "^0.1.3", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" }, diff --git a/package.nls.json b/package.nls.json deleted file mode 100644 index c9049eeb..00000000 --- a/package.nls.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "ahk2.actionwhenv1isdetected": "Action when v1 script is detected", - "ahk2.autolibinclude": "Provide completion and automatic include from User and Standard library, Local library", - "ahk2.commenttags": "A regular expression used to extract named tags from comments and generate module symbols", - "ahk2.compile": "Compile Script", - "ahk2.compilercmd": "Compiler command line options. If ahk2exe.exe is not specified, the default path will be used. `${execPath}` is equal to the currently selected AutoHotkey.exe", - "ahk2.completefunctionparens": "Parentheses are added to function completion when there is no `(` or `[` on the right; otherwise move the cursor to the right", - "ahk2.completioncommitcharacters": "Characters which commit auto completion, such as `.(`", - "ahk2.debug.attach": "Attach to ahk process", - "ahk2.debug.configs": "Debug ahk File using launch.json", - "ahk2.debug.file": "Debug ahk File", - "ahk2.debug.params": "Debug ahk File with Params", - "ahk2.debugconfiguration": "Append debugging configuration to the currently started debugger, same as launch.json configuration", - "ahk2.description": "Autohotkey2 Language Support using vscode-lsp", - "ahk2.diagnose.all": "Diagnostic All", - "ahk2.diagnostics.class-non-dynamic-member-check": "Check whether non-dynamic members of class exist", - "ahk2.diagnostics.paramscheck": "Check that the function call has the correct number of arguments", - "ahk2.warn.varunset": "Display warnings for each variable that has never been directly assigned or used with the reference operator", - "ahk2.warn.localsameasglobal": "Display warnings for each undeclared local variable which has the same name as a global variable", - "ahk2.warn.callwithoutparentheses": "Display warnings for each function or method call without parentheses", - "ahk2.extract.symbols": "Extract Symbol Information", - "ahk2.files.exclude": "Configure glob patterns for excluding files and folders when scanning ahk files.", - "ahk2.files.scanmaxdepth": "Controls the depth when scanning ahk files.", - "ahk2.generate.comment": "Generate Comment Template", - "ahk2.help": "Quick Help", - "ahk2.interpreterpath": "The path of the `AutoHotkey.exe` executable file. If `AutoHotkeyUX.exe` is selected, the script will be launched using UX Launcher.", - "ahk2.run": "Run ahk File", - "ahk2.run.selection": "Run Selected Script", - "ahk2.select.syntaxes": "Select Language Definition Folder", - "ahk2.set.interpreter": "Select AutoHotkey2 Interpreter", - "ahk2.set.scriptdir": "Set Here as A_ScriptDir", - "ahk2.stop": "Stop Running Script", - "ahk2.symbolfoldingfromopenbrace": "Forced symbol folding starts at open brace", - "ahk2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", - "ahk2.update.versioninfo": "Update File Version Info", - "ahk2.workingdirs": "Sets the working directory for the script" -} diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json deleted file mode 100644 index 97b62fc1..00000000 --- a/package.nls.zh-cn.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "ahk2.actionwhenv1isdetected": "检测到v1脚本时的行为", - "ahk2.autolibinclude": "对用户库和标准库, 本地库提供补全和自动include", - "ahk2.browse": "浏览文件系统来选择一个 AutoHotkey2 解释器", - "ahk2.commenttags": "用来从注释中提取命名标记的正则表达式, 并生成模块符号", - "ahk2.compile": "编译脚本", - "ahk2.compiledfailed": "编译失败!", - "ahk2.compiledsuccessfully": "编译成功!", - "ahk2.compilercmd": "编译器命令行选项. 如果未指定ahk2exe.exe, 将使用默认路径. `${execPath}`等价于当前选择的AutoHotkey.exe", - "ahk2.completefunctionparens": "当右侧不存在`(`或`[`时, 给函数补全添加括号; 否则向右移动光标", - "ahk2.completioncommitcharacters": "提交自动完成的字符, 例如`.(`", - "ahk2.current": "当前: {0}", - "ahk2.debug.attach": "附加到ahk进程", - "ahk2.debug.configs": "使用launch.json调试ahk文件", - "ahk2.debug.file": "调试ahk文件", - "ahk2.debug.params": "带参数调试", - "ahk2.debugconfiguration": "追加调试配置到当前启动的调试器, 与launch.json配置相同", - "ahk2.debugextnotexist": "未找到debug扩展, 请先安装debug扩展!", - "ahk2.description": "基于 vscode-lsp 协议的 Autohotkey2 语言支持", - "ahk2.diagnose.all": "诊断全部", - "ahk2.diagnostics.class-non-dynamic-member-check": "检查类非动态成员是否存在", - "ahk2.diagnostics.paramscheck": "检查函数调用参数个数是否正确", - "ahk2.enterahkpath": "请输入 AutoHotkey2 解释器的路径", - "ahk2.entercmd": "输入需要传递的命令行参数", - "ahk2.enterorfind": "输入路径或选择一个现有的解释器", - "ahk2.enterversion": "输入版本号", - "ahk2.filenotexist": "'{0}'文件不存在", - "ahk2.files.exclude": "配置 glob 模式以在扫描ahk文件时排除文件和文件夹.", - "ahk2.files.scanmaxdepth": "控制扫描ahk文件时的深度.", - "ahk2.find": "浏览...", - "ahk2.generate.comment": "生成注释模板", - "ahk2.help": "快捷帮助", - "ahk2.interpreterpath": "`AutoHotkey.exe`可执行文件的路径. 如果选择`AutoHotkeyUX.exe`, 将使用UX Launcher启动脚本.", - "ahk2.extract.symbols": "提取符号信息", - "ahk2.run": "运行ahk文件", - "ahk2.run.selection": "运行选择的脚本", - "ahk2.savebeforecompilation": "编译前请先保存脚本", - "ahk2.select": "选择", - "ahk2.select.syntaxes": "选择语言定义文件夹", - "ahk2.set.interpreter": "选择AutoHotkey2解释器", - "ahk2.set.scriptdir": "设置此处为A_ScriptDir", - "ahk2.stop": "停止运行中的脚本", - "ahk2.symbolfoldingfromopenbrace": "强制符号折叠从大括号处开始", - "ahk2.syntaxes": "指定用于智能感知的`ahk2.json`, `*.snippet.json`和`ahk2.d.ahk`文件的文件夹路径.", - "ahk2.unknownversion": "未知版本", - "ahk2.update.versioninfo": "更新文件版本信息", - "ahk2.warn.callwithoutparentheses": "为每个不带括号的函数或方法调用显示警告", - "ahk2.warn.localsameasglobal": "为每个与全局变量同名的未声明的局部变量显示警告", - "ahk2.warn.varunset": "为每个从未直接赋值或与引用操作符一起使用的变量的显示警告", - "ahk2.workingdirs": "设置脚本的工作目录", - "action.skipline": "跳过行", - "action.stopparsing": "停止解析", - "action.switchtov1": "切换到ahk v1", - "codeaction.include": "导入 '{0}'", - "completionitem.author": "添加作者, 描述, 日期, 版本等文件信息.", - "completionitem.generatecomment": "生成当前作用域函数/方法的注释模板.", - "completionitem.include": "从'{0}'自动导入", - "completionitem.new": "构造类的新实例.", - "completionitem.prototype": "检索或设置类的所有实例所基于的对象.", - "completionitem.super": "在继承类中, super 可以代替 this 来访问在派生类中被重写的方法或属性的超类版本.", - "completionitem.this": "在类中, 通过 this 访问该类的其他实例变量和方法.", - "completionitem.thishotkey": "热键函数的隐藏参数.", - "completionitem.value": "在动态属性 set 中, Value 包含被分配的值.", - "diagnostic.acceptparams": "'{0}' 接受{1}个参数", - "diagnostic.assignerr": "{0} '{1}'不能用作输出变量", - "diagnostic.classinfuncerr": "函数不能包含类", - "diagnostic.classuseerr": "类不能用作输出变量", - "diagnostic.conflictserr": "{0} '{2}'声明和已存在的{1}冲突", - "diagnostic.declarationerr": "意外的声明", - "diagnostic.defaultvalmissing": "'{0}' 需要参数默认值", - "diagnostic.deprecated": "使用'{0}'而不是'{1}'", - "diagnostic.didyoumean": "你是想用'{0}'吗?", - "diagnostic.dupdeclaration": "重复声明", - "diagnostic.duplabel": "重复的标签声明", - "diagnostic.filenotexist": "'{0}'文件不存在", - "diagnostic.funccallerr": "函数调用需要空格或'(', 仅在参数之间使用逗号", - "diagnostic.funccallerr2": "在表达式中, 函数调用需要括号", - "diagnostic.hotdeferr": "热键/热字串不能在函数/类中定义", - "diagnostic.hotmissbrace": "热键或热字符串缺少左括号", - "diagnostic.invaliddefinition": "无效的{0}定义", - "diagnostic.invalidencoding": "'{0}' 无效的文件编码", - "diagnostic.invalidhotdef": "无效的热键定义", - "diagnostic.invalidparam": "无效的参数定义", - "diagnostic.invalidprop": "不是有效的getter/setter属性", - "diagnostic.invalidpropname": "对象字面量中的属性名无效", - "diagnostic.invalidsymbolname": "无效的符号命名 '{0}'", - "diagnostic.invalidscope": "'{0}'不能在函数/类中使用", - "diagnostic.invalidsuper": "'super'仅在类内部有效", - "diagnostic.maybehavenotmember": "类'{0}'可能没有成员'{1}'", - "diagnostic.maybev1": "这可能是一个v1脚本, lexer停止解析.", - "diagnostic.missing": "丢失对应的 '{0}'", - "diagnostic.missingparam": "缺少必需的参数", - "diagnostic.missingoperand": "缺少操作数", - "diagnostic.missingretval": "函数缺少返回值", - "diagnostic.missingspace": "前面缺少空格或运算符", - "diagnostic.objectliteralerr": "对象字面量存在错误", - "diagnostic.outofloop": "Break/Continue必须被循环包围", - "diagnostic.paramcounterr": "应有 {0} 个参数, 但获得 {1} 个", - "diagnostic.pathinvalid": "无效的文件路径", - "diagnostic.propdeclaraerr": "不是有效的方法, 类或属性定义", - "diagnostic.propemptyparams": "动态属性不允许使用空[]", - "diagnostic.propnotinit": "属性声明未初始化", - "diagnostic.requirev1": "此脚本需要AutoHotkey v1, lexer停止解析.", - "diagnostic.requirevariable": "'&'需要一个变量", - "diagnostic.requireversion": "该特性需要AutoHotkey版本 >= v{0}", - "diagnostic.reservedworderr": "保留字'{0}'不得用作变量名", - "diagnostic.resourcenotfound": "未找到或无法解析资源", - "diagnostic.skipline": "该行被跳过且未解析", - "diagnostic.syntaxerror": "语法错误. 具体为: {0}", - "diagnostic.tryswitchtov1": "尝试切换到AutoHotkey v1.", - "diagnostic.typemaybenot": "类型可能不是 '{0}'", - "diagnostic.unexpected": "意外的'{0}'", - "diagnostic.unknown": "未知的{0}", - "diagnostic.unknownoperatoruse": "未知的操作符使用", - "diagnostic.unknowntoken": "未知的Token '{0}'", - "diagnostic.unsupportinclude": "函数、类中的#include无法正确地推导作用域和代码补全", - "diagnostic.unterminated": "未终止的字符串文本", - "warn.varisunset": "变量'{0}'似乎从未被赋值", - "warn.localsameasglobal": "局部变量'{0}'与全局变量具有相同的名称", - "warn.callwithoutparentheses": "函数或方法调用没有使用括号", - "response.cannotrename": "无法重命名此元素。", - "response.cannotrenamestdlib": "不能重命名标准AutoHotkey库中定义的元素。", - "setting.ahkpatherr": "AutoHotkey解释器不存在, 在'设置-AutoHotkey2.InterpreterPath'中重新指定", - "setting.getenverr": "获取环境变量失败", - "setting.uialimit": "由于安全限制, UIA可执行文件不允许重定向stdin/stdout, 因此依赖于此的一些功能将无法工作", - "setting.versionerr": "当前AutoHotkey.exe不是v2版本, 无法获得正确的语法解析、补全等功能" -} diff --git a/readme.md b/readme.md index d7ba6748..6e4d1702 100644 --- a/readme.md +++ b/readme.md @@ -1,364 +1,5 @@ -**English** | [中文](./README.zh-CN.md) - # AutoHotkey v2 Language Support -[![installs](https://img.shields.io/visual-studio-marketplace/i/thqby.vscode-autohotkey2-lsp?label=Extension%20Install&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) -[![version](https://img.shields.io/visual-studio-marketplace/v/thqby.vscode-autohotkey2-lsp?label=Extension%20Version&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) -[![](https://img.shields.io/badge/Compatibility-autohotkey%20v2.0+-green?style=for-the-badge&logo=autohotkey)](https://www.autohotkey.com/) - -**Repositories**: [Github](https://github.com/thqby/vscode-autohotkey2-lsp) | [Gitee](https://gitee.com/orz707/vscode-autohotkey2-lsp) - -AutoHotkey v2 Language support for VS Code, features realization based on v2 syntax analysis. -Supports running on the Web, such as `Chrome/Edge`. https://vscode.dev or https://github.dev/github/dev - -- [AutoHotkey v2 Language Support](#autohotkey-v2-language-support) - - [Language Features](#language-features) - - [Rename Symbol](#rename-symbol) - - [Diagnostics](#diagnostics) - - [IntelliSense](#intellisense) - - [Signature](#signature) - - [Document Symbol](#document-symbol) - - [Semantic Highlight](#semantic-highlight) - - [Tags](#tags) - - [Document Color](#document-color) - - [Hover](#hover) - - [Goto Definition](#goto-definition) - - [Find All References](#find-all-references) - - [CodeFormat](#codeformat) - - [Custom folding](#custom-folding) - - [Declaration document](#declaration-document) - - [Context Menu](#context-menu) - - [Quick Help](#quick-help) - - [Run Script](#run-script) - - [Run Selected Script](#run-selected-script) - - [Compile Script](#compile-script) - - [Debug Script](#debug-script) - - [Generate Comment](#generate-comment) - - [Use in other editors](#use-in-other-editors) - - [Sublime Text4](#sublime-text4) - - [Vim and Neovim](#vim-and-neovim) - - [Emacs](#Emacs) - - [Use in Web Browser](#use-in-web-browser) - -## Language Features - -### Rename Symbol - -Rename variables and function names in the scope in batches. - -![rename](./pic/rename.gif) - -### Diagnostics - -Simple syntax error diagnosis. - -![diagnostics](./pic/diagnostics2.png) - -### IntelliSense - -Supports intelligent completion of variables, functions, parameters, class names, and method names within the scope (by simple type deduction), and supports the completion of include files and function libraries. - -![snippet1](./pic/snippet.png) - -![snippet2](./pic/snippet.gif) - -### Signature - -Support for intelligent prompts for function parameters. - -![signature](./pic/signature.gif) - -### Document Symbol - -1. Displays class, method, function, variable, label, hotkey, hot string, block information in the left outline column. -2. press Ctrl + P, Input @symbol_name to retrieve and jump -3. You can comment a method with a semicolon or /\* \*/ on the top line of a function, variable. Jsdoc-style annotations can mark variable types. - - - -```js -/** - * @param {Array} a - a param - * @return {Integer} - */ -fn(a*) { - /** @type {Map} */ - d := Map() - /** - * @var {Map} e - * @var {Object} f - */ - e := Map(), f := {} - /** @type {(a,b)=>Integer} */ - cb := (a, b) => a + b - /** @type {ComObject} */ - wb := ComObject('Excel.Sheet.12') - return a[1] + a[2] -} -class abc { - /** @type {Map} */ - p := dosomethingandreturnmap() -} -``` - -### Semantic Highlight - -Semantic highlighting is an addition to syntax highlighting, resolves symbols in the context of a project. The editor applies the highlighting from semantic tokens on top of the highlighting from grammars. - -![semanticTokens](./pic/semanticTokens.png) - -### Tags - -usage: Add `;;`(default) or `; TODO ` to the comment code Tags. - -![codeSymbole](./pic/codeSymbol.png) - -### Document Color - -Compute and resolve colors inside a document to provide color picker in editor. - -![documentcolor](./pic/documentcolor.png) - -### Hover - -Supports hover prompts and comments for scoped variables, functions, global classes, and labels. -usage: Move the mouse over the symbol. - -![hover](./pic/hover.png) - -### Goto Definition - -1. Support for jumping to the declaration location of scoped variables, functions, global classes, and labels. -2. usage: Press ctrl Then move the mouse over to the code and click. - -![gotoDefinition](./pic/gotoDefinition.png) - -### Find All References - -See all the source code locations where a certain variable/function is being used. - -### CodeFormat - -usage: - -- Right-click the popup menu and click "Format document". -- Press `Shift+Alt+F`. -- Supports formatting code blocks when typing '}', formatting lines and indenting lines when typing '\n'. (`editor.formatOnType` needs to be enabled) -- Supports the use of formatting instructions `;@format array_style: collapse, object_style: expand` to change the object style of different blocks - -![codeFormat](./pic/codeFormat.gif) - -### Custom folding - -Fold the part between `;@region tag` and `;@endregion`, `;{` and `;}` - -```ini -;#region tag -code -;#endregion -``` - -### Declaration document - -The declaration file is a file with the suffix of `.d.ahk` as the file name, which is used to describe the implemented functions or classes, etc., does not contain the implementation part of the code, and is referenced by the ahk file with the same name by default, and the syntax refers to `ahk2.d.ahk` provided by the extension. The declaration file can extend or rewrite the declaration of ahk built-in functions or classes, and the annotation document can be separated from the source code to provide a multilingual version of intellisense. - -``` -; array.d.ahk -; #ClsName represents the ahk built-in class -/** @extends {#Array} */ -class Array { - /** jsdoc-default */ - Filter(FilterFunc) => Array -} - -; array.zh-cn.d.ahk -; #ClsName 表示ahk内置类 -/** @extends {#Array} */ -class Array { - /** jsdoc-zh */ - Filter(FilterFunc) => Array -} - -; array.ahk -; %A_Locale% is VSCode's Display Language -;@reference array.%A_Locale%.d.ahk -Array.Prototype.DefineProp('Filter', { call: Array_Filter_impl }) -``` - -## Context Menu - -### Quick Help - -Open the help file and navigate to the keyword at the current cursor. - -### Run Script - -Run the currently open script. - -### Run Selected Script - -Run the code snippet at the cursor selection. - -### Compile Script - -Compile the script to generate executable EXE files. - -### Debug Script - -No additional configuration is required to start the installed Debug extensions, and support debugging with parameters. - -### Generate Comment - -Generate JSDOC-style comments for a function or method. - -## Use in other editors - -1. Install [Node.js](https://nodejs.org/en/download/). -2. Download vscode-autohotkey2-lsp server using command line, or download and unpack through [vscode marketplace](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp). - -```shell -mkdir vscode-autohotkey2-lsp -cd vscode-autohotkey2-lsp -curl.exe -L -o install.js https://raw.githubusercontent.com/thqby/vscode-autohotkey2-lsp/main/tools/install.js -node install.js -``` - -3. Set the LSP configuration of the editor that support [LSP(Language Server Protocol)](https://microsoft.github.io/language-server-protocol/), such as Sublime Text4, Vim, Neovim, Emacs, [etc](https://microsoft.github.io/language-server-protocol/implementors/tools/). - -### Sublime Text4 - -- `Package Control: Install Package`, and install [Sublime LSP](https://github.com/sublimelsp/LSP) plug-in. -- `Preferences: LSP Settings`, add lsp configuration, language selector, and syntax highlighting. This is a simple example [syntax highlighting](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), save the file in a similar path `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax`. - -```json -{ - "clients": { - "lsp-ahk2": { - "enabled": true, - "command": [ - "node", - "/server/dist/server.js", - "--stdio" - ], // Update the path of node.exe(maybe it's already in PATH, so you don't need to set it) and the folder of vscode-autohotkey2-lsp - "selector": "source.ahk2", // Same as scope in AutoHotkey2.sublime-syntax - "schemes": ["file", "buffer", "res"], - "initializationOptions": { - "locale": "en-us", // or "zh-cn" - "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" - "CommentTags": "^;;\\s*(?.+)", - "CompleteFunctionParens": false, - "Diagnostics": { - "ClassStaticMemberCheck": true, - "ParamsCheck": true - }, - "ActionWhenV1IsDetected": "Continue", - "FormatOptions": { - "array_style": "none", // or "collapse" or "expand" - "break_chained_methods": false, - "ignore_comment": false, - "indent_string": "\t", - "max_preserve_newlines": 2, - "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" - "object_style": "none", // or "collapse" or "expand" - "preserve_newlines": true, - "space_after_double_colon": true, - "space_before_conditional": true, - "space_in_empty_paren": false, - "space_in_other": true, - "space_in_paren": false, - "wrap_line_length": 0 - }, - "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - "WorkingDirs": [], - "SymbolFoldingFromOpenBrace": false - } - } - }, - "semantic_highlighting": true -} -``` - -### Vim and Neovim - -#### COC - -- Download [coc.nvim plugin](https://github.com/neoclide/coc.nvim). - -```bat -cd $VIMRUNTIME\plugin -git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 -``` - -- Open (n)vim and enter the command `:CocConfig` to enter the `coc.nvim` configuration file to add configuration information. - -```json -{ - "languageserver": { - "lsp-ahk2": { - "module": "/server/dist/server.js", - "filetypes": ["autohotkey"], - "args": ["--node-ipc"], - "initializationOptions": { - // Same as initializationOptions for Sublime Text4 - } - } - } -} -``` - -#### nvim-lspconfig - -- Download [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). -- Add the following to your NVIM configuration (init.lua e.g.). Ensure that `cmd` points to the path of your vscode-autohotkey2-lsp installation and `InterpreterPath` points to your AHK exe. - -```lua -local function custom_attach(client, bufnr) - require("lsp_signature").on_attach({ - bind = true, - use_lspsaga = false, - floating_window = true, - fix_pos = true, - hint_enable = true, - hi_parameter = "Search", - handler_opts = { "double" }, - }) -end - -local ahk2_configs = { - autostart = true, - cmd = { - "node", - vim.fn.expand("$HOME/vscode-autohotkey2-lsp/server/dist/server.js"), - "--stdio" - }, - filetypes = { "ahk", "autohotkey", "ah2" }, - init_options = { - locale = "en-us", - InterpreterPath = "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - -- Same as initializationOptions for Sublime Text4, convert json literal to lua dictionary literal - }, - single_file_support = true, - flags = { debounce_text_changes = 500 }, - capabilities = capabilities, - on_attach = custom_attach, -} -local configs = require "lspconfig.configs" -configs["ahk2"] = { default_config = ahk2_configs } -local nvim_lsp = require("lspconfig") -nvim_lsp.ahk2.setup({}) -``` - -### Emacs - -#### Eglot - -- Add the following lines to your emacs config file - -```emacs-lisp -(add-to-list 'eglot-server-programs '(ahk-mode "node" "/server/dist/server.js" "--stdio")) - -``` - -## Use in Web Browser +This codebase is not meant for independent use, but rather as a submodule of [AHK++](https://github.com/mark-wiemer-org/ahkpp). -visit https://github.dev or https://vscode.dev in `Chrome/Edge`, and install `thqby.vscode-autohotkey2-lsp` +It provides AHK v2 language support via the [Language Server Protocol](https://microsoft.github.io/language-server-protocol). diff --git a/server/cli/cli.ts b/server/cli/cli.ts deleted file mode 100644 index 71a29d2a..00000000 --- a/server/cli/cli.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { openFile } from '../src/common'; -import { newFormatterConfig } from '../src/config'; -import { Lexer } from '../src/Lexer'; - -function main() { - const options: Record = {}; - process.argv.slice(2).forEach((s) => { - const arr = s.split('='); - options[arr[0]] = arr[1]; - }); - let path: string = options.path ?? ''; - path = path.replace(/^(['"])(.*)\1$/, '$2'); - if (!path) return; - try { - const td = openFile(path, false); - if (!td) return; - const sc = new Lexer(td).beautify(newFormatterConfig()); - console.log(sc); - } catch (e) { - console.error(e); - } -} - -main(); diff --git a/server/src/browserServerMain.ts b/server/src/browserServerMain.ts deleted file mode 100644 index c7c9bb29..00000000 --- a/server/src/browserServerMain.ts +++ /dev/null @@ -1,165 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { - createConnection, BrowserMessageReader, BrowserMessageWriter, DidChangeConfigurationNotification, - InitializeResult, TextDocuments, TextDocumentSyncKind -} from 'vscode-languageserver/browser'; -import { - chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, - defintionProvider, documentFormatting, enumNames, executeCommandProvider, exportSymbols, getVersionInfo, - hoverProvider, initahk2cache, Lexer, lexers, loadahk2, loadlocalize, prepareRename, rangeFormatting, - referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, - SemanticTokenTypes, set_ahk_h, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, - signatureProvider, symbolProvider, typeFormatting, updateAhkppConfig, workspaceSymbolProvider -} from './common'; -import { AhkppConfig } from './config'; - -const languageServer = 'ahk2-language-server'; -const messageReader = new BrowserMessageReader(self); -const messageWriter = new BrowserMessageWriter(self); -const documents = new TextDocuments(TextDocument); -const workspaceFolders = new Set(); -const connection = set_Connection(createConnection(messageReader, messageWriter)); - -let hasConfigurationCapability = false, hasWorkspaceFolderCapability = false; -let uri_switch_to_ahk2 = ''; - -connection.onInitialize(params => { - const capabilities = params.capabilities; - hasConfigurationCapability = !!( - capabilities.workspace && !!capabilities.workspace.configuration - ); - hasWorkspaceFolderCapability = !!( - capabilities.workspace && !!capabilities.workspace.workspaceFolders - ); - - const result: InitializeResult = { - serverInfo: { - name: languageServer, - }, - capabilities: { - textDocumentSync: { - change: TextDocumentSyncKind.Incremental, - openClose: true - }, - completionProvider: { - resolveProvider: false, - triggerCharacters: ['.', '#', '*', '@'] - }, - signatureHelpProvider: { - triggerCharacters: ['(', ',', ' '] - }, - documentSymbolProvider: true, - definitionProvider: true, - documentFormattingProvider: true, - documentRangeFormattingProvider: true, - documentOnTypeFormattingProvider: { firstTriggerCharacter: '}', moreTriggerCharacter: ['\n', ...Object.keys(chinese_punctuations)] }, - executeCommandProvider: { commands: Object.keys(commands) }, - hoverProvider: true, - foldingRangeProvider: true, - colorProvider: true, - renameProvider: { prepareProvider: true }, - referencesProvider: { workDoneProgress: true }, - semanticTokensProvider: { - legend: { - tokenTypes: enumNames(SemanticTokenTypes), - tokenModifiers: enumNames(SemanticTokenModifiers) - }, - full: true, - range: true - }, - workspaceSymbolProvider: true - } - }; - if (hasWorkspaceFolderCapability) { - params.workspaceFolders?.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); - result.capabilities.workspace = { workspaceFolders: { supported: true } }; - } - - const configs: AhkppConfig = params.initializationOptions; - set_ahk_h(true); - set_locale(params.locale); - set_dirname(configs.extensionUri!); - loadlocalize(); - updateAhkppConfig(configs); - set_WorkspaceFolders(workspaceFolders); - set_version('3.0.0'); - initahk2cache(); - loadahk2(); - loadahk2('ahk2_h'); - loadahk2('winapi', 4); - return result; -}); - -connection.onInitialized(() => { - if (hasConfigurationCapability) { - // Register for all configuration changes. - connection.client.register(DidChangeConfigurationNotification.type); - } - if (hasWorkspaceFolderCapability) { - connection.workspace.onDidChangeWorkspaceFolders(event => { - event.removed.forEach(it => workspaceFolders.delete(it.uri.toLowerCase() + '/')); - event.added.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); - set_WorkspaceFolders(workspaceFolders); - }); - } -}); - -connection.onDidChangeConfiguration(async change => { - let newset: AhkppConfig | undefined = change?.settings; - if (hasConfigurationCapability && !newset) - newset = await connection.workspace.getConfiguration('AutoHotkey2'); - if (!newset) { - connection.window.showWarningMessage('Failed to obtain the configuration'); - return; - } - updateAhkppConfig(newset); - set_WorkspaceFolders(workspaceFolders); -}); - -documents.onDidOpen(e => { - const to_ahk2 = uri_switch_to_ahk2 === e.document.uri; - const uri = e.document.uri.toLowerCase(); - let doc = lexers[uri]; - if (doc) doc.document = e.document; - else lexers[uri] = doc = new Lexer(e.document); - doc.actived = true; - if (to_ahk2) - doc.actionWhenV1Detected = 'Continue'; -}); - -documents.onDidClose(e => lexers[e.document.uri.toLowerCase()]?.close()); -documents.onDidChangeContent(e => lexers[e.document.uri.toLowerCase()].update()); - -connection.onCompletion(completionProvider); -connection.onColorPresentation(colorPresentation); -connection.onDocumentColor(colorProvider); -connection.onDefinition(defintionProvider); -connection.onDocumentFormatting(documentFormatting); -connection.onDocumentRangeFormatting(rangeFormatting); -connection.onDocumentOnTypeFormatting(typeFormatting); -connection.onDocumentSymbol(symbolProvider); -connection.onFoldingRanges(params => lexers[params.textDocument.uri.toLowerCase()].foldingranges); -connection.onHover(hoverProvider); -connection.onPrepareRename(prepareRename); -connection.onReferences(referenceProvider); -connection.onRenameRequest(renameProvider); -connection.onSignatureHelp(signatureProvider); -connection.onExecuteCommand(executeCommandProvider); -connection.onWorkspaceSymbol(workspaceSymbolProvider); -connection.languages.semanticTokens.on(semanticTokensOnFull); -connection.languages.semanticTokens.onRange(semanticTokensOnRange); -connection.onRequest('ahk2.exportSymbols', exportSymbols); -connection.onRequest('ahk2.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); -connection.onRequest('ahk2.getVersionInfo', getVersionInfo); -connection.onNotification('onDidCloseTextDocument', - (params: { uri: string, id: string }) => { - if (params.id === 'ahk2') - lexers[params.uri.toLowerCase()]?.close(true); - else uri_switch_to_ahk2 = params.uri; - }); -documents.listen(connection); -connection.listen(); diff --git a/test-data/.gitignore b/test-data/.gitignore deleted file mode 100644 index ac456bfc..00000000 --- a/test-data/.gitignore +++ /dev/null @@ -1 +0,0 @@ -# this file is present so the test-data folder is present when others clone the repo \ No newline at end of file diff --git a/tmgrammar-test/0-v2-demo.ahk b/tmgrammar-test/0-v2-demo.ahk deleted file mode 100644 index 6dd66f59..00000000 --- a/tmgrammar-test/0-v2-demo.ahk +++ /dev/null @@ -1,3 +0,0 @@ -#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle) -#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle -#HotIf diff --git a/tmgrammar-test/0-v2-demo.ahk.snap b/tmgrammar-test/0-v2-demo.ahk.snap deleted file mode 100644 index e9f040a5..00000000 --- a/tmgrammar-test/0-v2-demo.ahk.snap +++ /dev/null @@ -1,31 +0,0 @@ ->#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle) -#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 -# ^^^^^ source.ahk2 keyword.control.directive.ahk2 -# ^ source.ahk2 -# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 -# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 -# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 -# ^^^^^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 -# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 -# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 -# ^ source.ahk2 -# ^^ source.ahk2 keyword.operator.expression.ahk2 -# ^ source.ahk2 -# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 -# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 -# ^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 variable.other.ahk2 -# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 ->#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle -#^^^^^^ source.ahk2 hotkey.ahk2 keyword.keys.ahk2 -# ^^ source.ahk2 punctuation.definition.colon -# ^^^^^^ source.ahk2 variable.other.ahk2 support.function.ahk2 -# ^ source.ahk2 -# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.ahk2 string.quoted.ahk2 -# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 -# ^ source.ahk2 -# ^^^^^^^^^^^^^ source.ahk2 variable.other.ahk2 ->#HotIf -#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 -# ^^^^^ source.ahk2 keyword.control.directive.ahk2 -> \ No newline at end of file diff --git a/tools/install.js b/tools/install.js deleted file mode 100644 index 197ebcc5..00000000 --- a/tools/install.js +++ /dev/null @@ -1,1325 +0,0 @@ -/** - * @license node-stream-zip | (c) 2020 Antelle | https://github.com/antelle/node-stream-zip/blob/master/LICENSE - * Portions copyright https://github.com/cthackers/adm-zip | https://raw.githubusercontent.com/cthackers/adm-zip/master/LICENSE - */ -/* eslint-disable */ -let fs = require('fs'); -const path = require('path'); -const events = require('events'); -const zlib = require('zlib'); -const stream = require('stream'); - -const consts = { - /* The local file header */ - LOCHDR: 30, // LOC header size - LOCSIG: 0x04034b50, // "PK\003\004" - LOCVER: 4, // version needed to extract - LOCFLG: 6, // general purpose bit flag - LOCHOW: 8, // compression method - LOCTIM: 10, // modification time (2 bytes time, 2 bytes date) - LOCCRC: 14, // uncompressed file crc-32 value - LOCSIZ: 18, // compressed size - LOCLEN: 22, // uncompressed size - LOCNAM: 26, // filename length - LOCEXT: 28, // extra field length - - /* The Data descriptor */ - EXTSIG: 0x08074b50, // "PK\007\008" - EXTHDR: 16, // EXT header size - EXTCRC: 4, // uncompressed file crc-32 value - EXTSIZ: 8, // compressed size - EXTLEN: 12, // uncompressed size - - /* The central directory file header */ - CENHDR: 46, // CEN header size - CENSIG: 0x02014b50, // "PK\001\002" - CENVEM: 4, // version made by - CENVER: 6, // version needed to extract - CENFLG: 8, // encrypt, decrypt flags - CENHOW: 10, // compression method - CENTIM: 12, // modification time (2 bytes time, 2 bytes date) - CENCRC: 16, // uncompressed file crc-32 value - CENSIZ: 20, // compressed size - CENLEN: 24, // uncompressed size - CENNAM: 28, // filename length - CENEXT: 30, // extra field length - CENCOM: 32, // file comment length - CENDSK: 34, // volume number start - CENATT: 36, // internal file attributes - CENATX: 38, // external file attributes (host system dependent) - CENOFF: 42, // LOC header offset - - /* The entries in the end of central directory */ - ENDHDR: 22, // END header size - ENDSIG: 0x06054b50, // "PK\005\006" - ENDSIGFIRST: 0x50, - ENDSUB: 8, // number of entries on this disk - ENDTOT: 10, // total number of entries - ENDSIZ: 12, // central directory size in bytes - ENDOFF: 16, // offset of first CEN header - ENDCOM: 20, // zip file comment length - MAXFILECOMMENT: 0xffff, - - /* The entries in the end of ZIP64 central directory locator */ - ENDL64HDR: 20, // ZIP64 end of central directory locator header size - ENDL64SIG: 0x07064b50, // ZIP64 end of central directory locator signature - ENDL64SIGFIRST: 0x50, - ENDL64OFS: 8, // ZIP64 end of central directory offset - - /* The entries in the end of ZIP64 central directory */ - END64HDR: 56, // ZIP64 end of central directory header size - END64SIG: 0x06064b50, // ZIP64 end of central directory signature - END64SIGFIRST: 0x50, - END64SUB: 24, // number of entries on this disk - END64TOT: 32, // total number of entries - END64SIZ: 40, - END64OFF: 48, - - /* Compression methods */ - STORED: 0, // no compression - SHRUNK: 1, // shrunk - REDUCED1: 2, // reduced with compression factor 1 - REDUCED2: 3, // reduced with compression factor 2 - REDUCED3: 4, // reduced with compression factor 3 - REDUCED4: 5, // reduced with compression factor 4 - IMPLODED: 6, // imploded - // 7 reserved - DEFLATED: 8, // deflated - ENHANCED_DEFLATED: 9, // deflate64 - PKWARE: 10, // PKWare DCL imploded - // 11 reserved - BZIP2: 12, // compressed using BZIP2 - // 13 reserved - LZMA: 14, // LZMA - // 15-17 reserved - IBM_TERSE: 18, // compressed using IBM TERSE - IBM_LZ77: 19, //IBM LZ77 z - - /* General purpose bit flag */ - FLG_ENC: 0, // encrypted file - FLG_COMP1: 1, // compression option - FLG_COMP2: 2, // compression option - FLG_DESC: 4, // data descriptor - FLG_ENH: 8, // enhanced deflation - FLG_STR: 16, // strong encryption - FLG_LNG: 1024, // language encoding - FLG_MSK: 4096, // mask header values - FLG_ENTRY_ENC: 1, - - /* 4.5 Extensible data fields */ - EF_ID: 0, - EF_SIZE: 2, - - /* Header IDs */ - ID_ZIP64: 0x0001, - ID_AVINFO: 0x0007, - ID_PFS: 0x0008, - ID_OS2: 0x0009, - ID_NTFS: 0x000a, - ID_OPENVMS: 0x000c, - ID_UNIX: 0x000d, - ID_FORK: 0x000e, - ID_PATCH: 0x000f, - ID_X509_PKCS7: 0x0014, - ID_X509_CERTID_F: 0x0015, - ID_X509_CERTID_C: 0x0016, - ID_STRONGENC: 0x0017, - ID_RECORD_MGT: 0x0018, - ID_X509_PKCS7_RL: 0x0019, - ID_IBM1: 0x0065, - ID_IBM2: 0x0066, - ID_POSZIP: 0x4690, - - EF_ZIP64_OR_32: 0xffffffff, - EF_ZIP64_OR_16: 0xffff, -}; - -class StreamZip extends events.EventEmitter { - constructor(config) { - super(); - let fd, fileSize, chunkSize, op, centralDirectory, closed; - const ready = false, - that = this, - entries = config.storeEntries !== false ? {} : null, - textDecoder = config.nameEncoding - ? new TextDecoder(config.nameEncoding) - : null; - - fd = config.buffer; - fileSize = fd.byteLength; - chunkSize = config.chunkSize || Math.round(fileSize / 1000); - chunkSize = Math.max( - Math.min(chunkSize, Math.min(128 * 1024, fileSize)), - Math.min(1024, fileSize), - ); - setImmediate(readCentralDirectory); - - function readUntilFoundCallback(err, bytesRead) { - if (err || !bytesRead) { - return that.emit( - 'error', - err || new Error('Archive read error'), - ); - } - let pos = op.lastPos; - let bufferPosition = pos - op.win.position; - const buffer = op.win.buffer; - const minPos = op.minPos; - while (--pos >= minPos && --bufferPosition >= 0) { - if ( - buffer.length - bufferPosition >= 4 && - buffer[bufferPosition] === op.firstByte - ) { - // quick check first signature byte - if (buffer.readUInt32LE(bufferPosition) === op.sig) { - op.lastBufferPosition = bufferPosition; - op.lastBytesRead = bytesRead; - op.complete(); - return; - } - } - } - if (pos === minPos) { - return that.emit('error', new Error('Bad archive')); - } - op.lastPos = pos + 1; - op.chunkSize *= 2; - if (pos <= minPos) { - return that.emit('error', new Error('Bad archive')); - } - const expandLength = Math.min(op.chunkSize, pos - minPos); - op.win.expandLeft(expandLength, readUntilFoundCallback); - } - - function readCentralDirectory() { - const totalReadLength = Math.min( - consts.ENDHDR + consts.MAXFILECOMMENT, - fileSize, - ); - op = { - win: new FileWindowBuffer(fd), - totalReadLength, - minPos: fileSize - totalReadLength, - lastPos: fileSize, - chunkSize: Math.min(1024, chunkSize), - firstByte: consts.ENDSIGFIRST, - sig: consts.ENDSIG, - complete: readCentralDirectoryComplete, - }; - op.win.read( - fileSize - op.chunkSize, - op.chunkSize, - readUntilFoundCallback, - ); - } - - function readCentralDirectoryComplete() { - const buffer = op.win.buffer; - const pos = op.lastBufferPosition; - try { - centralDirectory = new CentralDirectoryHeader(); - centralDirectory.read(buffer.slice(pos, pos + consts.ENDHDR)); - centralDirectory.headerOffset = op.win.position + pos; - if (centralDirectory.commentLength) { - that.comment = buffer - .slice( - pos + consts.ENDHDR, - pos + - consts.ENDHDR + - centralDirectory.commentLength, - ) - .toString(); - } else { - that.comment = null; - } - that.entriesCount = centralDirectory.volumeEntries; - that.centralDirectory = centralDirectory; - if ( - (centralDirectory.volumeEntries === consts.EF_ZIP64_OR_16 && - centralDirectory.totalEntries === - consts.EF_ZIP64_OR_16) || - centralDirectory.size === consts.EF_ZIP64_OR_32 || - centralDirectory.offset === consts.EF_ZIP64_OR_32 - ) { - readZip64CentralDirectoryLocator(); - } else { - op = {}; - readEntries(); - } - } catch (err) { - that.emit('error', err); - } - } - - function readZip64CentralDirectoryLocator() { - const length = consts.ENDL64HDR; - if (op.lastBufferPosition > length) { - op.lastBufferPosition -= length; - readZip64CentralDirectoryLocatorComplete(); - } else { - op = { - win: op.win, - totalReadLength: length, - minPos: op.win.position - length, - lastPos: op.win.position, - chunkSize: op.chunkSize, - firstByte: consts.ENDL64SIGFIRST, - sig: consts.ENDL64SIG, - complete: readZip64CentralDirectoryLocatorComplete, - }; - op.win.read( - op.lastPos - op.chunkSize, - op.chunkSize, - readUntilFoundCallback, - ); - } - } - - function readZip64CentralDirectoryLocatorComplete() { - const buffer = op.win.buffer; - const locHeader = new CentralDirectoryLoc64Header(); - locHeader.read( - buffer.slice( - op.lastBufferPosition, - op.lastBufferPosition + consts.ENDL64HDR, - ), - ); - const readLength = fileSize - locHeader.headerOffset; - op = { - win: op.win, - totalReadLength: readLength, - minPos: locHeader.headerOffset, - lastPos: op.lastPos, - chunkSize: op.chunkSize, - firstByte: consts.END64SIGFIRST, - sig: consts.END64SIG, - complete: readZip64CentralDirectoryComplete, - }; - op.win.read( - fileSize - op.chunkSize, - op.chunkSize, - readUntilFoundCallback, - ); - } - - function readZip64CentralDirectoryComplete() { - const buffer = op.win.buffer; - const zip64cd = new CentralDirectoryZip64Header(); - zip64cd.read( - buffer.slice( - op.lastBufferPosition, - op.lastBufferPosition + consts.END64HDR, - ), - ); - that.centralDirectory.volumeEntries = zip64cd.volumeEntries; - that.centralDirectory.totalEntries = zip64cd.totalEntries; - that.centralDirectory.size = zip64cd.size; - that.centralDirectory.offset = zip64cd.offset; - that.entriesCount = zip64cd.volumeEntries; - op = {}; - readEntries(); - } - - function readEntries() { - op = { - win: new FileWindowBuffer(fd), - pos: centralDirectory.offset, - chunkSize, - entriesLeft: centralDirectory.volumeEntries, - }; - op.win.read( - op.pos, - Math.min(chunkSize, fileSize - op.pos), - readEntriesCallback, - ); - } - - function readEntriesCallback(err, bytesRead) { - if (err || !bytesRead) { - return that.emit( - 'error', - err || new Error('Entries read error'), - ); - } - let bufferPos = op.pos - op.win.position; - let entry = op.entry; - const buffer = op.win.buffer; - const bufferLength = buffer.length; - try { - while (op.entriesLeft > 0) { - if (!entry) { - entry = new ZipEntry(); - entry.readHeader(buffer, bufferPos); - entry.headerOffset = op.win.position + bufferPos; - op.entry = entry; - op.pos += consts.CENHDR; - bufferPos += consts.CENHDR; - } - const entryHeaderSize = - entry.fnameLen + entry.extraLen + entry.comLen; - const advanceBytes = - entryHeaderSize + - (op.entriesLeft > 1 ? consts.CENHDR : 0); - if (bufferLength - bufferPos < advanceBytes) { - op.win.moveRight( - chunkSize, - readEntriesCallback, - bufferPos, - ); - op.move = true; - return; - } - entry.read(buffer, bufferPos, textDecoder); - if (!config.skipEntryNameValidation) { - entry.validateName(); - } - if (entries) { - entries[entry.name] = entry; - } - that.emit('entry', entry); - op.entry = entry = null; - op.entriesLeft--; - op.pos += entryHeaderSize; - bufferPos += entryHeaderSize; - } - that.emit('ready'); - } catch (err) { - that.emit('error', err); - } - } - - function checkEntriesExist() { - if (!entries) { - throw new Error('storeEntries disabled'); - } - } - - Object.defineProperty(this, 'ready', { - get() { - return ready; - }, - }); - - this.entry = function (name) { - checkEntriesExist(); - return entries[name]; - }; - - this.entries = function () { - checkEntriesExist(); - return entries; - }; - - this.stream = function (entry, callback) { - return this.openEntry( - entry, - (err, entry) => { - if (err) { - return callback(err); - } - const offset = dataOffset(entry); - let entryStream = new EntryDataReaderStream( - fd, - offset, - entry.compressedSize, - ); - if (entry.method === consts.STORED) { - // nothing to do - } else if (entry.method === consts.DEFLATED) { - entryStream = entryStream.pipe(zlib.createInflateRaw()); - } else { - return callback( - new Error( - 'Unknown compression method: ' + entry.method, - ), - ); - } - if (canVerifyCrc(entry)) { - entryStream = entryStream.pipe( - new EntryVerifyStream( - entryStream, - entry.crc, - entry.size, - ), - ); - } - callback(null, entryStream); - }, - false, - ); - }; - - this.entryDataSync = function (entry) { - let err = null; - this.openEntry( - entry, - (e, en) => { - err = e; - entry = en; - }, - true, - ); - if (err) { - throw err; - } - let data = Buffer.alloc(entry.compressedSize); - new BufRead( - fd, - data, - 0, - entry.compressedSize, - dataOffset(entry), - (e) => { - err = e; - }, - ).read(true); - if (err) { - throw err; - } - if (entry.method === consts.STORED) { - // nothing to do - } else if ( - entry.method === consts.DEFLATED || - entry.method === consts.ENHANCED_DEFLATED - ) { - data = zlib.inflateRawSync(data); - } else { - throw new Error('Unknown compression method: ' + entry.method); - } - if (data.length !== entry.size) { - throw new Error('Invalid size'); - } - if (canVerifyCrc(entry)) { - const verify = new CrcVerify(entry.crc, entry.size); - verify.data(data); - } - return data; - }; - - this.openEntry = function (entry, callback, sync) { - if (typeof entry === 'string') { - checkEntriesExist(); - entry = entries[entry]; - if (!entry) { - return callback(new Error('Entry not found')); - } - } - if (!entry.isFile) { - return callback(new Error('Entry is not file')); - } - if (!fd) { - return callback(new Error('Archive closed')); - } - const buffer = Buffer.alloc(consts.LOCHDR); - new BufRead(fd, buffer, 0, buffer.length, entry.offset, (err) => { - if (err) { - return callback(err); - } - let readEx; - try { - entry.readDataHeader(buffer); - if (entry.encrypted) { - readEx = new Error('Entry encrypted'); - } - } catch (ex) { - readEx = ex; - } - callback(readEx, entry); - }).read(sync); - }; - - function dataOffset(entry) { - return ( - entry.offset + consts.LOCHDR + entry.fnameLen + entry.extraLen - ); - } - - function canVerifyCrc(entry) { - // if bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written - return (entry.flags & 0x8) !== 0x8; - } - - function extract(entry, outPath, callback) { - that.stream(entry, (err, stm) => { - if (err) { - callback(err); - } else { - let fsStm, errThrown; - stm.on('error', (err) => { - errThrown = err; - if (fsStm) { - stm.unpipe(fsStm); - fsStm.close(() => { - callback(err); - }); - } - }); - fs.open(outPath, 'w', (err, fdFile) => { - if (err) { - return callback(err); - } - if (errThrown) { - fs.close(fd, () => { - callback(errThrown); - }); - return; - } - fsStm = fs.createWriteStream(outPath, { fd: fdFile }); - fsStm.on('finish', () => { - that.emit('extract', entry, outPath); - if (!errThrown) { - callback(); - } - }); - stm.pipe(fsStm); - }); - } - }); - } - - function createDirectories(baseDir, dirs, callback) { - if (!dirs.length) { - return callback(); - } - let dir = dirs.shift(); - dir = path.join(baseDir, path.join(...dir)); - fs.mkdir(dir, { recursive: true }, (err) => { - if (err && err.code !== 'EEXIST') { - return callback(err); - } - createDirectories(baseDir, dirs, callback); - }); - } - - function extractFiles( - baseDir, - baseRelPath, - files, - callback, - extractedCount, - ) { - if (!files.length) { - return callback(null, extractedCount); - } - const file = files.shift(); - const targetPath = path.join( - baseDir, - file.name.replace(baseRelPath, ''), - ); - extract(file, targetPath, (err) => { - if (err) { - return callback(err, extractedCount); - } - extractFiles( - baseDir, - baseRelPath, - files, - callback, - extractedCount + 1, - ); - }); - } - - this.extract = function (entry, outPath, callback, filter) { - let entryName = entry || ''; - if (typeof entry === 'string') { - entry = this.entry(entry); - if (entry) { - entryName = entry.name; - } else { - if ( - entryName.length && - entryName[entryName.length - 1] !== '/' - ) { - entryName += '/'; - } - } - } - if (!entry || entry.isDirectory) { - const files = [], - dirs = [], - allDirs = {}; - for (const e in entries) { - if ( - Object.prototype.hasOwnProperty.call(entries, e) && - e.lastIndexOf(entryName, 0) === 0 - ) { - let relPath = e.replace(entryName, ''); - const childEntry = entries[e]; - if (filter && !filter(childEntry)) continue; - if (childEntry.isFile) { - files.push(childEntry); - relPath = path.dirname(relPath); - } - if (relPath && !allDirs[relPath] && relPath !== '.') { - allDirs[relPath] = true; - let parts = relPath.split('/').filter((f) => { - return f; - }); - if (parts.length) { - dirs.push(parts); - } - while (parts.length > 1) { - parts = parts.slice(0, parts.length - 1); - const partsPath = parts.join('/'); - if (allDirs[partsPath] || partsPath === '.') { - break; - } - allDirs[partsPath] = true; - dirs.push(parts); - } - } - } - } - dirs.sort((x, y) => { - return x.length - y.length; - }); - if (dirs.length) { - createDirectories(outPath, dirs, (err) => { - if (err) { - callback(err); - } else { - extractFiles( - outPath, - entryName, - files, - callback, - 0, - ); - } - }); - } else { - extractFiles(outPath, entryName, files, callback, 0); - } - } else { - fs.stat(outPath, (err, stat) => { - if (stat && stat.isDirectory()) { - extract( - entry, - path.join(outPath, path.basename(entry.name)), - callback, - ); - } else { - extract(entry, outPath, callback); - } - }); - } - }; - - this.close = function (callback) { - if (closed || !fd || (BufRead === BufRead && !(fd = null))) { - closed = true; - if (callback) { - callback(); - } - } else { - closed = true; - fs.close(fd, (err) => { - fd = null; - if (callback) { - callback(err); - } - }); - } - }; - - const originalEmit = events.EventEmitter.prototype.emit; - this.emit = function (...args) { - if (!closed) { - return originalEmit.call(this, ...args); - } - }; - } -} - -class CentralDirectoryHeader { - read(data) { - if ( - data.length !== consts.ENDHDR || - data.readUInt32LE(0) !== consts.ENDSIG - ) { - throw new Error('Invalid central directory'); - } - // number of entries on this volume - this.volumeEntries = data.readUInt16LE(consts.ENDSUB); - // total number of entries - this.totalEntries = data.readUInt16LE(consts.ENDTOT); - // central directory size in bytes - this.size = data.readUInt32LE(consts.ENDSIZ); - // offset of first CEN header - this.offset = data.readUInt32LE(consts.ENDOFF); - // zip file comment length - this.commentLength = data.readUInt16LE(consts.ENDCOM); - } -} - -class CentralDirectoryLoc64Header { - read(data) { - if ( - data.length !== consts.ENDL64HDR || - data.readUInt32LE(0) !== consts.ENDL64SIG - ) { - throw new Error('Invalid zip64 central directory locator'); - } - // ZIP64 EOCD header offset - this.headerOffset = readUInt64LE(data, consts.ENDSUB); - } -} - -class CentralDirectoryZip64Header { - read(data) { - if ( - data.length !== consts.END64HDR || - data.readUInt32LE(0) !== consts.END64SIG - ) { - throw new Error('Invalid central directory'); - } - // number of entries on this volume - this.volumeEntries = readUInt64LE(data, consts.END64SUB); - // total number of entries - this.totalEntries = readUInt64LE(data, consts.END64TOT); - // central directory size in bytes - this.size = readUInt64LE(data, consts.END64SIZ); - // offset of first CEN header - this.offset = readUInt64LE(data, consts.END64OFF); - } -} - -class ZipEntry { - readHeader(data, offset) { - // data should be 46 bytes and start with "PK 01 02" - if ( - data.length < offset + consts.CENHDR || - data.readUInt32LE(offset) !== consts.CENSIG - ) { - throw new Error('Invalid entry header'); - } - // version made by - this.verMade = data.readUInt16LE(offset + consts.CENVEM); - // version needed to extract - this.version = data.readUInt16LE(offset + consts.CENVER); - // encrypt, decrypt flags - this.flags = data.readUInt16LE(offset + consts.CENFLG); - // compression method - this.method = data.readUInt16LE(offset + consts.CENHOW); - // modification time (2 bytes time, 2 bytes date) - const timebytes = data.readUInt16LE(offset + consts.CENTIM); - const datebytes = data.readUInt16LE(offset + consts.CENTIM + 2); - this.time = parseZipTime(timebytes, datebytes); - - // uncompressed file crc-32 value - this.crc = data.readUInt32LE(offset + consts.CENCRC); - // compressed size - this.compressedSize = data.readUInt32LE(offset + consts.CENSIZ); - // uncompressed size - this.size = data.readUInt32LE(offset + consts.CENLEN); - // filename length - this.fnameLen = data.readUInt16LE(offset + consts.CENNAM); - // extra field length - this.extraLen = data.readUInt16LE(offset + consts.CENEXT); - // file comment length - this.comLen = data.readUInt16LE(offset + consts.CENCOM); - // volume number start - this.diskStart = data.readUInt16LE(offset + consts.CENDSK); - // internal file attributes - this.inattr = data.readUInt16LE(offset + consts.CENATT); - // external file attributes - this.attr = data.readUInt32LE(offset + consts.CENATX); - // LOC header offset - this.offset = data.readUInt32LE(offset + consts.CENOFF); - } - - readDataHeader(data) { - // 30 bytes and should start with "PK\003\004" - if (data.readUInt32LE(0) !== consts.LOCSIG) { - throw new Error('Invalid local header'); - } - // version needed to extract - this.version = data.readUInt16LE(consts.LOCVER); - // general purpose bit flag - this.flags = data.readUInt16LE(consts.LOCFLG); - // compression method - this.method = data.readUInt16LE(consts.LOCHOW); - // modification time (2 bytes time ; 2 bytes date) - const timebytes = data.readUInt16LE(consts.LOCTIM); - const datebytes = data.readUInt16LE(consts.LOCTIM + 2); - this.time = parseZipTime(timebytes, datebytes); - - // uncompressed file crc-32 value - this.crc = data.readUInt32LE(consts.LOCCRC) || this.crc; - // compressed size - const compressedSize = data.readUInt32LE(consts.LOCSIZ); - if (compressedSize && compressedSize !== consts.EF_ZIP64_OR_32) { - this.compressedSize = compressedSize; - } - // uncompressed size - const size = data.readUInt32LE(consts.LOCLEN); - if (size && size !== consts.EF_ZIP64_OR_32) { - this.size = size; - } - // filename length - this.fnameLen = data.readUInt16LE(consts.LOCNAM); - // extra field length - this.extraLen = data.readUInt16LE(consts.LOCEXT); - } - - read(data, offset, textDecoder) { - const nameData = data.slice(offset, (offset += this.fnameLen)); - this.name = textDecoder - ? textDecoder.decode(new Uint8Array(nameData)) - : nameData.toString('utf8'); - const lastChar = data[offset - 1]; - this.isDirectory = lastChar === 47 || lastChar === 92; - - if (this.extraLen) { - this.readExtra(data, offset); - offset += this.extraLen; - } - this.comment = this.comLen - ? data.slice(offset, offset + this.comLen).toString() - : null; - } - - validateName() { - if (/\\|^\w+:|^\/|(^|\/)\.\.(\/|$)/.test(this.name)) { - throw new Error('Malicious entry: ' + this.name); - } - } - - readExtra(data, offset) { - let signature, size; - const maxPos = offset + this.extraLen; - while (offset < maxPos) { - signature = data.readUInt16LE(offset); - offset += 2; - size = data.readUInt16LE(offset); - offset += 2; - if (consts.ID_ZIP64 === signature) { - this.parseZip64Extra(data, offset, size); - } - offset += size; - } - } - - parseZip64Extra(data, offset, length) { - if (length >= 8 && this.size === consts.EF_ZIP64_OR_32) { - this.size = readUInt64LE(data, offset); - offset += 8; - length -= 8; - } - if (length >= 8 && this.compressedSize === consts.EF_ZIP64_OR_32) { - this.compressedSize = readUInt64LE(data, offset); - offset += 8; - length -= 8; - } - if (length >= 8 && this.offset === consts.EF_ZIP64_OR_32) { - this.offset = readUInt64LE(data, offset); - offset += 8; - length -= 8; - } - if (length >= 4 && this.diskStart === consts.EF_ZIP64_OR_16) { - this.diskStart = data.readUInt32LE(offset); - // offset += 4; length -= 4; - } - } - - get encrypted() { - return (this.flags & consts.FLG_ENTRY_ENC) === consts.FLG_ENTRY_ENC; - } - - get isFile() { - return !this.isDirectory; - } -} - -class BufRead { - constructor(fd, buffer, offset, length, position, callback) { - /** @type Buffer */ - this.fd = fd; - this.buffer = buffer; - this.offset = offset; - this.length = length; - this.position = position; - this.callback = callback; - this.bytesRead = 0; - this.waiting = false; - } - - read(sync) { - this.waiting = true; - let err; - let bytesRead = this.fd.copy( - this.buffer, - this.offset + this.bytesRead, - this.position + this.bytesRead, - ); - this.readCallback(sync, err, !sync || err ? bytesRead : null); - } - - readCallback(sync, err, bytesRead) { - if (typeof bytesRead === 'number') { - this.bytesRead += bytesRead; - } - if (err || !bytesRead || this.bytesRead === this.length) { - this.waiting = false; - return this.callback(err, this.bytesRead); - } else { - this.read(sync); - } - } -} - -class FileWindowBuffer { - constructor(fd) { - this.position = 0; - this.buffer = Buffer.alloc(0); - this.fd = fd; - this.fsOp = null; - } - - checkOp() { - if (this.fsOp && this.fsOp.waiting) { - throw new Error('Operation in progress'); - } - } - - read(pos, length, callback) { - this.checkOp(); - if (this.buffer.length < length) { - this.buffer = Buffer.alloc(length); - } - this.position = pos; - this.fsOp = new BufRead( - this.fd, - this.buffer, - 0, - length, - this.position, - callback, - ).read(); - } - - expandLeft(length, callback) { - this.checkOp(); - this.buffer = Buffer.concat([Buffer.alloc(length), this.buffer]); - this.position -= length; - if (this.position < 0) { - this.position = 0; - } - this.fsOp = new BufRead( - this.fd, - this.buffer, - 0, - length, - this.position, - callback, - ).read(); - } - - expandRight(length, callback) { - this.checkOp(); - const offset = this.buffer.length; - this.buffer = Buffer.concat([this.buffer, Buffer.alloc(length)]); - this.fsOp = new BufRead( - this.fd, - this.buffer, - offset, - length, - this.position + offset, - callback, - ).read(); - } - - moveRight(length, callback, shift) { - this.checkOp(); - if (shift) { - this.buffer.copy(this.buffer, 0, shift); - } else { - shift = 0; - } - this.position += shift; - this.fsOp = new BufRead( - this.fd, - this.buffer, - this.buffer.length - shift, - shift, - this.position + this.buffer.length - shift, - callback, - ).read(); - } -} - -class EntryDataReaderStream extends stream.Readable { - constructor(fd, offset, length) { - super(); - this.fd = fd; - this.offset = offset; - this.length = length; - this.pos = 0; - } - - _read(n) { - const buffer = Buffer.alloc(Math.min(n, this.length - this.pos)); - if (buffer.length) { - this.readCallback( - undefined, - this.fd.copy(buffer, 0, this.offset + this.pos), - buffer, - ); - } else { - this.push(null); - } - } - - readCallback(err, bytesRead, buffer) { - this.pos += bytesRead; - if (err) { - this.emit('error', err); - this.push(null); - } else if (!bytesRead) { - this.push(null); - } else { - if (bytesRead !== buffer.length) { - buffer = buffer.slice(0, bytesRead); - } - this.push(buffer); - } - } -} - -class EntryVerifyStream extends stream.Transform { - constructor(baseStm, crc, size) { - super(); - this.verify = new CrcVerify(crc, size); - baseStm.on('error', (e) => { - this.emit('error', e); - }); - } - - _transform(data, encoding, callback) { - let err; - try { - this.verify.data(data); - } catch (e) { - err = e; - } - callback(err, data); - } -} - -class CrcVerify { - constructor(crc, size) { - this.crc = crc; - this.size = size; - this.state = { - crc: ~0, - size: 0, - }; - } - - data(data) { - const crcTable = CrcVerify.getCrcTable(); - let crc = this.state.crc; - let off = 0; - let len = data.length; - while (--len >= 0) { - crc = crcTable[(crc ^ data[off++]) & 0xff] ^ (crc >>> 8); - } - this.state.crc = crc; - this.state.size += data.length; - if (this.state.size >= this.size) { - const buf = Buffer.alloc(4); - buf.writeInt32LE(~this.state.crc & 0xffffffff, 0); - crc = buf.readUInt32LE(0); - if (crc !== this.crc) { - throw new Error('Invalid CRC'); - } - if (this.state.size !== this.size) { - throw new Error('Invalid size'); - } - } - } - - static getCrcTable() { - let crcTable = CrcVerify.crcTable; - if (!crcTable) { - CrcVerify.crcTable = crcTable = []; - const b = Buffer.alloc(4); - for (let n = 0; n < 256; n++) { - let c = n; - for (let k = 8; --k >= 0; ) { - if ((c & 1) !== 0) { - c = 0xedb88320 ^ (c >>> 1); - } else { - c = c >>> 1; - } - } - if (c < 0) { - b.writeInt32LE(c, 0); - c = b.readUInt32LE(0); - } - crcTable[n] = c; - } - } - return crcTable; - } -} - -function parseZipTime(timebytes, datebytes) { - const timebits = toBits(timebytes, 16); - const datebits = toBits(datebytes, 16); - - const mt = { - h: parseInt(timebits.slice(0, 5).join(''), 2), - m: parseInt(timebits.slice(5, 11).join(''), 2), - s: parseInt(timebits.slice(11, 16).join(''), 2) * 2, - Y: parseInt(datebits.slice(0, 7).join(''), 2) + 1980, - M: parseInt(datebits.slice(7, 11).join(''), 2), - D: parseInt(datebits.slice(11, 16).join(''), 2), - }; - const dt_str = - [mt.Y, mt.M, mt.D].join('-') + - ' ' + - [mt.h, mt.m, mt.s].join(':') + - ' GMT+0'; - return new Date(dt_str).getTime(); -} - -function toBits(dec, size) { - let b = (dec >>> 0).toString(2); - while (b.length < size) { - b = '0' + b; - } - return b.split(''); -} - -function readUInt64LE(buffer, offset) { - return ( - buffer.readUInt32LE(offset + 4) * 0x0000000100000000 + - buffer.readUInt32LE(offset) - ); -} - -const https = require('https'); -function https_request(url, data, headers) { - return new Promise((resolve, reject) => { - let req = https.request( - url, - { method: data ? 'POST' : 'GET', headers }, - (msg) => { - let body = Buffer.alloc(0); - let isgzip = msg.headers['content-encoding'] === 'gzip'; - msg.on( - 'data', - (chunk) => (body = Buffer.concat([body, chunk])), - ); - msg.on('end', () => { - if (isgzip) - zlib.gunzip(body, (err, buf) => - resolve(err ? body : buf), - ); - else resolve(body); - }); - }, - ); - data && req.write(data); - req.end(); - req.on('error', (err) => reject(err)); - req.on('timeout', () => reject('timeout')); - }); -} - -function get_latest_ahk2lsp() { - https_request( - 'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery', - '{"assetTypes":null,"filters":[{"criteria":[{"filterType":7,"value":"thqby.vscode-autohotkey2-lsp"}],"direction":2,"pageSize":100,"pageNumber":1,"sortBy":0,"sortOrder":0,"pagingToken":null}],"flags":2151}', - { - 'content-type': 'application/json', - accept: 'application/json;api-version=7.1-preview.1;excludeUrls=true', - }, - ) - .catch((err) => console.error(err)) - .then((info) => { - let ext = JSON.parse(info).results[0].extensions[0].versions[0]; - let version = ext.version; - fs.readFile('./package.json', (err, buf) => { - let update = !buf; - if (buf) { - try { - let curver = JSON.parse(buf).version.split('.'), - ver = version.split('.'); - for (let n in curver) { - if (parseInt(curver[n]) < parseInt(ver[n])) { - update = true; - break; - } - } - } catch (e) { - update = true; - } - } - if (update) download_ahk2lsp(); - else - console.log( - `thqby.vscode-autohotkey2-lsp v${version} is the latest version.`, - ); - - function download_ahk2lsp(url) { - https_request( - url ?? - `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/thqby/vsextensions/vscode-autohotkey2-lsp/${version}/vspackage`, - ) - .then((buffer) => { - if (buffer[0] === 123) { - if (!url) { - for (let f of ext.files) - if ( - f.assetType.endsWith('.VSIXPackage') - ) - return download_ahk2lsp(f.source); - } - return console.error(buffer.toString()); - } - let zip = new StreamZip({ buffer }); - let extract_count = 0, - has_extract_count = 0; - zip.on('ready', () => - zip.extract( - 'extension/', - './', - (err) => err && console.error(err), - (entry) => { - let name = entry.name.toLowerCase(); - if ( - name.includes('/client/') || - name.includes('/browser') - ) - return false; - if ( - name.endsWith( - '/ahk2.configuration.json', - ) || - name.endsWith('.png') || - name.endsWith('.tmlanguage.json') - ) - return false; - extract_count++; - return true; - }, - ), - ); - zip.on('error', (err) => console.error(err)); - zip.on('extract', (entry, outPath) => { - if (++has_extract_count === extract_count) - console.log( - `thqby.vscode-autohotkey2-lsp v${version} has been installed.`, - ); - }); - }) - .catch((err) => console.error(err)); - } - }); - }); -} - -get_latest_ahk2lsp(); From 2ca259623cb38a29e05eabdaa110d634c6a89763 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 28 Sep 2024 22:22:28 -0700 Subject: [PATCH 42/60] Stop running prettier check (#40) --- .github/workflows/prettier.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml index 34665894..1976c27d 100644 --- a/.github/workflows/prettier.yml +++ b/.github/workflows/prettier.yml @@ -4,12 +4,12 @@ name: Prettier diff on: - push: - branches: ['main'] - pull_request: - branches: ['main'] + # push: + # branches: ['main'] + # pull_request: + # branches: ['main'] workflow_dispatch: - merge_group: + # merge_group: jobs: build: From f95c66833e2c10f1a138a9601fb495e247085d1c Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Mon, 30 Sep 2024 20:05:25 -0700 Subject: [PATCH 43/60] Merge thqby@2.5.3 (#41) Co-authored-by: thqby <294633707@qq.com> --- .github/workflows/node.js.yml | 8 +- .vscode-test.mjs | 25 + .vscode/extensions.json | 7 +- .vscode/launch.json | 70 + .vscode/tasks.json | 19 + CHANGELOG.md | 13 +- client/.vscode-test.mjs | 7 - client/package-lock.json | 5 - client/package.json | 9 - client/src/browserClientMain.ts | 125 + client/src/config.ts | 17 +- client/src/extension.ts | 8 +- client/src/test/extension.test.ts | 154 + .../test/formatting/array_object_style.ahk | 26 + client/tsconfig.json | 14 - esbuild.mjs | 116 + eslint.config.mjs | 58 +- package-lock.json | 5676 +++++++++-------- package.json | 723 ++- package.nls.json | 37 + package.nls.zh-cn.json | 127 + server/cli/cli.ts | 25 + server/package-lock.json | 4 - server/package.json | 14 +- server/src/Lexer.ts | 126 +- server/src/ahkProvider.ts | 4 +- server/src/browserServerMain.ts | 161 + server/src/common.ts | 30 +- server/src/completionProvider.ts | 16 +- server/src/config.ts | 76 +- server/src/constants.ts | 3 - server/src/formattingProvider.ts | 8 +- server/src/localize.ts | 4 +- server/src/scriptrunner.ts | 4 +- server/src/semanticTokensProvider.ts | 7 +- server/src/server.ts | 17 +- server/src/symbolProvider.ts | 4 +- server/tsconfig.json | 13 - syntaxes/ahk2.tmLanguage.json | 4718 +++++++------- tmgrammar-test/0-v2-demo.ahk | 3 + tmgrammar-test/0-v2-demo.ahk.snap | 31 + tsconfig.json | 17 +- webpack.config.cli.js | 53 - webpack.config.js | 92 - 44 files changed, 7057 insertions(+), 5617 deletions(-) create mode 100644 .vscode-test.mjs create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json delete mode 100644 client/.vscode-test.mjs delete mode 100644 client/package-lock.json delete mode 100644 client/package.json create mode 100644 client/src/browserClientMain.ts create mode 100644 client/src/test/extension.test.ts create mode 100644 client/src/test/formatting/array_object_style.ahk delete mode 100644 client/tsconfig.json create mode 100644 esbuild.mjs create mode 100644 package.nls.json create mode 100644 package.nls.zh-cn.json create mode 100644 server/cli/cli.ts delete mode 100644 server/package-lock.json create mode 100644 server/src/browserServerMain.ts delete mode 100644 server/tsconfig.json create mode 100644 tmgrammar-test/0-v2-demo.ahk create mode 100644 tmgrammar-test/0-v2-demo.ahk.snap delete mode 100644 webpack.config.cli.js delete mode 100644 webpack.config.js diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 1649bbfa..cabc9139 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -5,9 +5,9 @@ name: Build on: push: - branches: ['main'] + branches: ["main"] pull_request: - branches: ['main'] + branches: ["main"] workflow_dispatch: merge_group: @@ -27,6 +27,6 @@ jobs: uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - cache: 'npm' + cache: "npm" - run: npm install - - run: npm run validate:ci + - run: npm run vscode:prepublish diff --git a/.vscode-test.mjs b/.vscode-test.mjs new file mode 100644 index 00000000..15777653 --- /dev/null +++ b/.vscode-test.mjs @@ -0,0 +1,25 @@ +// https://github.com/microsoft/vscode-test-cli +import { defineConfig } from '@vscode/test-cli'; +import { execSync } from 'child_process'; + +let timeout, vscode_path; +if (process.execPath.toLowerCase().endsWith('code.exe')) + timeout = 0; +else { + try { + const m = execSync('chcp 65001 && reg query HKCR\\vscode\\shell\\open\\command', { encoding: 'utf8' }) + .match(/REG_SZ\s+("([^"]+)"|\S+)/); + vscode_path = m[2] || m[1]; + } catch { } +} + +export default defineConfig({ + files: 'client/dist/test/**/*.test.js', + mocha: { + failZero: true, + timeout + }, + useInstallation: vscode_path && { + fromPath: vscode_path + } +}); \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e22fcc88..6a3c7b3e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,6 @@ { "recommendations": [ - "aaron-bond.better-comments", - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode" + "connor4312.esbuild-problem-matchers", + "dbaeumer.vscode-eslint" ] -} +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..38a800c4 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,70 @@ +// A launch configuration that compiles the extension and then opens it inside a new window +{ + "version": "0.2.0", + "configurations": [ + { + "type": "extensionHost", + "request": "launch", + "name": "Launch Client", + "runtimeExecutable": "${execPath}", + "preLaunchTask": "npm: watch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/client/dist/**/*.js" + ] + }, + { + "type": "node", + "request": "attach", + "name": "Attach to Server", + "port": 6009, + "restart": true, + "outFiles": [ + "${workspaceFolder}/server/out/**/*.js", + "${workspaceFolder}/server/dist/**/*.js" + ] + }, + { + "name": "Extension Tests", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "preLaunchTask": "npm: watch", + "args": [ + "--disable-extensions", + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/client/dist/test/**/*.js" + ], + "testConfiguration": "${workspaceFolder}/.vscode-test.mjs" + }, + { + "name": "Run Web Extension", + "type": "extensionHost", + "debugWebWorkerHost": true, + "request": "launch", + "args": [ + "--disable-extensions", + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionDevelopmentKind=web" + ], + "outFiles": [ + "${workspaceFolder}/client/dist/**/*.js", + "${workspaceFolder}/server/dist/**/*.js" + ], + "preLaunchTask": "npm: watch-web" + } + ], + "compounds": [ + { + "name": "Client + Server", + "configurations": [ + "Launch Client", + "Attach to Server" + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..6670d29e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,19 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "watch", + "group": "build", + "isBackground": true, + "problemMatcher": "$esbuild-watch" + }, + { + "type": "npm", + "script": "watch-web", + "group": "build", + "isBackground": true, + "problemMatcher": "$esbuild-watch" + } + ] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ad6c8d0..765d366c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.5.3 +- 修复[#603](https://github.com/thqby/vscode-autohotkey2-lsp/issues/603) +- 修复[#605](https://github.com/thqby/vscode-autohotkey2-lsp/issues/605) + ## 2.5.2 - 修复[#591](https://github.com/thqby/vscode-autohotkey2-lsp/issues/591) @@ -6,11 +10,10 @@ - 修复[#596](https://github.com/thqby/vscode-autohotkey2-lsp/issues/596) ## 2.5.1 - -- 修复[#584](https://github.com/thqby/vscode-autohotkey2-lsp/issues/584) - -57](https://github.com/thqby/vscode-autohotkey2-lsp/issues/587) -- [FR #565](https://github.com/thqby/vscode-autohotkey2-lsp/issues/565) -- 修复一些bug +- 修复[#584](https://github.com/thqby/vscode-autohotkey2-lsp/issues/584) +- 修复[#587](https://github.com/thqby/vscode-autohotkey2-lsp/issues/587) +- [FR #565](https://github.com/thqby/vscode-autohotkey2-lsp/issues/565) +- 修复一些bug ## 2.5.0 diff --git a/client/.vscode-test.mjs b/client/.vscode-test.mjs deleted file mode 100644 index efac995e..00000000 --- a/client/.vscode-test.mjs +++ /dev/null @@ -1,7 +0,0 @@ -// https://github.com/microsoft/vscode-test-cli -import { defineConfig } from '@vscode/test-cli'; -export default defineConfig({ - extensionDevelopmentPath: '..', - files: 'dist/**/*.test.js', - version: '1.92.0', -}); diff --git a/client/package-lock.json b/client/package-lock.json deleted file mode 100644 index c861ba72..00000000 --- a/client/package-lock.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "vscode-autohotkey2-client", - "version": "0.0.1", - "lockfileVersion": 1 -} diff --git a/client/package.json b/client/package.json deleted file mode 100644 index 4c7e43a8..00000000 --- a/client/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "vscode-autohotkey2-client", - "description": "VSCode part of a language server", - "license": "MIT", - "version": "0.0.1", - "engines": { - "vscode": "^1.43.0" - } -} diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts new file mode 100644 index 00000000..7b9a2408 --- /dev/null +++ b/client/src/browserClientMain.ts @@ -0,0 +1,125 @@ +import { commands, ExtensionContext, languages, Range, RelativePattern, SnippetString, Uri, window, workspace, WorkspaceEdit } from 'vscode'; +import { LanguageClient } from 'vscode-languageclient/browser'; + +let client: LanguageClient; + +// this method is called when vs code is activated +export function activate(context: ExtensionContext) { + const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browserServerMain.js'); + /* eslint-disable-next-line */ + const request_handlers: Record any> = { + 'ahk2.getActiveTextEditorUriAndPosition': () => { + const editor = window.activeTextEditor; + if (!editor) return; + const uri = editor.document.uri.toString(), position = editor.selection.end; + return { uri, position: { line: position.line, character: position.character } }; + }, + 'ahk2.insertSnippet': async (params: [string, Range?]) => { + const editor = window.activeTextEditor; + if (!editor) return; + if (params[1]) { + const { start, end } = params[1]; + await editor.insertSnippet(new SnippetString(params[0]), new Range(start.line, start.character, end.line, end.character)); + } else + editor.insertSnippet(new SnippetString(params[0])); + }, + 'ahk2.setTextDocumentLanguage': async (params: [string, string?]) => { + const lang = params[1] || 'ahk'; + if (!(await languages.getLanguages()).includes(lang)) { + window.showErrorMessage(`Unknown language id: ${lang}`); + return; + } + const uri = params[0], it = workspace.textDocuments.find(it => it.uri.toString() === uri); + it && languages.setTextDocumentLanguage(it, lang); + }, + 'ahk2.getWorkspaceFiles': async (params: string[]) => { + const all = !params.length; + if (workspace.workspaceFolders) { + if (all) + return (await workspace.findFiles('**/*.{ahk,ah2,ahk2}')).forEach(it => it.toString()); + else { + const files: string[] = []; + for (const folder of workspace.workspaceFolders) + if (params.includes(folder.uri.toString().toLowerCase())) + files.push(...(await workspace.findFiles(new RelativePattern(folder, '*.{ahk,ah2,ahk2}'))).map(it => it.toString())); + return files; + } + } + }, + 'ahk2.getWorkspaceFileContent': async (params: string[]) => (await workspace.openTextDocument(Uri.parse(params[0]))).getText() + }; + + client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', { + documentSelector: [{ language: 'ahk2' }], + markdown: { isTrusted: true, supportHtml: true }, + initializationOptions: { + extensionUri: !process.env.DEBUG ? context.extensionUri.toString() : unpkg_url(context), + commands: Object.keys(request_handlers), + ...JSON.parse(JSON.stringify(workspace.getConfiguration('AutoHotkey2'))) + } + }, new Worker(serverMain.toString())); + + context.subscriptions.push( + commands.registerTextEditorCommand('ahk2.update.versioninfo', async textEditor => { + const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); + if (!infos?.length) { + await textEditor.insertSnippet(new SnippetString([ + "/************************************************************************", + " * @description ${1:}", + " * @author ${2:}", + " * @date ${3:$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE}", + " * @version ${4:0.0.0}", + " ***********************************************************************/", + "", "" + ].join('\n')), new Range(0, 0, 0, 0)); + } else { + const d = new Date; + let contents: string[] = [], value: string | undefined; + for (const info of infos) { + if (info.single) + contents.push(info.content.replace( + /(?<=^;\s*@ahk2exe-setversion\s+)(\S+|(?=[\r\n]))/i, + s => (value ||= s, '\0'))); + else contents.push(info.content.replace( + /(?<=^\s*[;*]?\s*@date[:\s]\s*)(\S+|(?=[\r\n]))/im, + date => [d.getFullYear(), d.getMonth() + 1, d.getDate()].map( + n => n.toString().padStart(2, '0')).join(date.includes('.') ? '.' : '/') + ).replace(/(?<=^\s*[;*]?\s*@version[:\s]\s*)(\S+|(?=[\r\n]))/im, s => (value ||= s, '\0'))); + } + if (value !== undefined) { + value = await window.showInputBox({ + value, prompt: 'Enter version info' + }); + if (!value) + return; + contents = contents.map(s => s.replace('\0', value!)); + } + const ed = new WorkspaceEdit(), uri = textEditor.document.uri; + infos.forEach(it => it.content !== (value = contents.shift()) && + ed.replace(uri, it.range, value!)); + ed.size && workspace.applyEdit(ed); + } + }), + commands.registerTextEditorCommand('ahk2.switch', textEditor => { + const doc = textEditor.document; + languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); + }), + workspace.onDidCloseTextDocument(e => { + client.sendNotification('onDidCloseTextDocument', e.isClosed ? + { uri: '', id: '' } : { uri: e.uri.toString(), id: e.languageId }); + }) + ); + + client.start().then(() => { + Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); + }); +} + +export function deactivate() { + return client?.stop(); +} + +function unpkg_url(context: ExtensionContext) { + const pk = context.extension.packageJSON; + return `https://${pk.publisher}.vscode-unpkg.net/${pk.publisher}/${pk.name}/${pk.version}/extension/`; +} \ No newline at end of file diff --git a/client/src/config.ts b/client/src/config.ts index 573c6bd6..4ec36c0d 100644 --- a/client/src/config.ts +++ b/client/src/config.ts @@ -7,14 +7,23 @@ import * as vscode from 'vscode'; export type ShowOutput = 'always' | 'never'; export enum CfgKey { - DebugConfiguration = 'v2.debugConfiguration', + //* AHK++ values + // DebugConfiguration = 'v2.debugConfiguration', InterpreterPathV1 = 'v1.file.interpreterPath', - InterpreterPathV2 = 'v2.file.interpreterPath', + // InterpreterPathV2 = 'v2.file.interpreterPath', ShowOutput = 'general.showOutput', - Syntaxes = 'v2.general.syntaxes', + // Syntaxes = 'v2.general.syntaxes', + + //* thqby values + DebugConfiguration = 'debugConfiguration', + // InterpreterPathV1 = 'v1.file.interpreterPath', + InterpreterPathV2 = 'InterpreterPath', + // ShowOutput = 'general.showOutput', + Syntaxes = 'Syntaxes', } -const configPrefix = 'AHK++'; +// const configPrefix = 'AHK++'; // AHK++ +const configPrefix = 'AutoHotkey2'; // thqby /** * Gets AHK++ config value from VS Code. diff --git a/client/src/extension.ts b/client/src/extension.ts index 224f116c..4b368742 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -1,8 +1,3 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ - import { commands, ConfigurationTarget, @@ -62,7 +57,8 @@ const loadedCollection = { export function activate(context: ExtensionContext): Promise { /** Absolute path to `server.js` */ - const defaultServerModule = context.asAbsolutePath(`ahk2/server/dist/server.js`); + // todo needs to start with `ahk2` for compatibility with AHK++ + const defaultServerModule = context.asAbsolutePath(`server/dist/server.js`); const serverModule = process.env.VSCODE_AHK_SERVER_PATH ? context.asAbsolutePath(process.env.VSCODE_AHK_SERVER_PATH) : defaultServerModule; // If the extension is launched in debug mode then the debug server options are used diff --git a/client/src/test/extension.test.ts b/client/src/test/extension.test.ts new file mode 100644 index 00000000..c75dfabc --- /dev/null +++ b/client/src/test/extension.test.ts @@ -0,0 +1,154 @@ +import * as assert from 'assert'; +import * as vscode from 'vscode'; +import { resolve } from 'path'; +import { + LanguageClient, + CompletionRequest, CompletionParams, CompletionItem, + DocumentSymbolRequest, DocumentSymbolParams, SymbolInformation, + DefinitionRequest, DefinitionParams, LocationLink, + DocumentFormattingRequest, DocumentFormattingParams, TextEdit, + FoldingRangeRequest, FoldingRangeParams, FoldingRange, + HoverRequest, HoverParams, Hover, + PrepareRenameRequest, PrepareRenameParams, + ReferencesRequest, ReferenceParams, Location, + RenameRequest, RenameParams, WorkspaceEdit, + SignatureHelpRequest, SignatureHelpParams, SignatureHelp, + SemanticTokensRequest, SemanticTokensParams, SemanticTokens, + WorkspaceSymbolRequest, WorkspaceSymbolParams, + ExecuteCommandRequest, ExecuteCommandParams, + DidChangeConfigurationNotification, +} from 'vscode-languageclient/node'; +import { readdirSync } from 'fs'; + +suite('Start ahk language server', () => { + test('should be running', async () => { + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); + const client: LanguageClient = await vscode.extensions.getExtension('thqby.vscode-autohotkey2-lsp')?.activate(); + assert.equal(client?.isRunning(), true); + + suite('Open ahk file', () => { + test('should be opened', async () => { + const path = resolve(__dirname, '../../../server/dist/ahkProvider.ahk'); + let document = await vscode.workspace.openTextDocument(path); + const uri = document.uri.toString(); + await vscode.window.showTextDocument(document); + if (document.languageId !== 'ahk2') + document = await vscode.languages.setTextDocumentLanguage(document, 'ahk2'); + const content = await client.sendRequest('ahk++.getContent', uri) as string; + assert.equal(document.getText() === content, true); + + suite('Test language server features', () => { + const textDocument = { uri }; + const position = { line: 10, character: 5 }; + + test.skip(CompletionRequest.method, async function () { + const params: CompletionParams = { textDocument, position }; + const result: CompletionItem[] | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.length); + }); + + test.skip(DefinitionRequest.method, async function () { + const params: DefinitionParams = { textDocument, position }; + const result: LocationLink[] | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.length); + }); + + test.skip(DocumentFormattingRequest.method, async function () { + const params: DocumentFormattingParams = { textDocument, options: { insertSpaces: false, tabSize: 4 } }; + const result: TextEdit[] | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.length); + }); + + test.skip(DocumentSymbolRequest.method, async function () { + const params: DocumentSymbolParams = { textDocument }; + const result: SymbolInformation[] | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.length); + }); + + test.skip(FoldingRangeRequest.method, async function () { + const params: FoldingRangeParams = { textDocument }; + const result: FoldingRange[] | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.length); + }); + + test.skip(HoverRequest.method, async function () { + const params: HoverParams = { textDocument, position }; + const result: Hover | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.contents); + }); + + test.skip(PrepareRenameRequest.method, async function () { + const params: PrepareRenameParams = { textDocument, position }; + const result: unknown | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result); + }); + + test.skip(ReferencesRequest.method, async function () { + const params: ReferenceParams = { textDocument, position, context: { includeDeclaration: true } }; + const result: Location[] | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.length); + }); + + test.skip(RenameRequest.method, async function () { + const params: RenameParams = { textDocument, position, newName: '' }; + const result: WorkspaceEdit | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.changes); + }); + + test.skip(SignatureHelpRequest.method, async function () { + const params: SignatureHelpParams = { textDocument, position: { line: 8, character: 36 } }; + const result: SignatureHelp | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.signatures); + }); + + test.skip(ExecuteCommandRequest.method, async function () { + const params: ExecuteCommandParams = { command: 'ahk++.diagnostic.full' }; + await client.sendRequest(this.runnable().title, params); + }); + + test.skip(WorkspaceSymbolRequest.method, async function () { + const params: WorkspaceSymbolParams = { query: 'msg' }; + const result: SymbolInformation[] | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.length); + }); + + test.skip(SemanticTokensRequest.method, async function () { + const params: SemanticTokensParams = { textDocument }; + const result: SemanticTokens | undefined = await client.sendRequest(this.runnable().title, params); + assert.ok(result?.data); + }); + }); + + await client.sendNotification( + DidChangeConfigurationNotification.method, + { settings: { FormatOptions: {} } }); + test_formatting(client); + }); + }); + }); +}); + +// todo AHK++ does not handle formatter directives yet +function test_formatting(client: LanguageClient) { + suite('Test formatting', () => { + const dir = resolve(__dirname, '../../src/test/formatting'); + const files = readdirSync(dir); + for (const file of files) { + if (!file.endsWith('.ahk')) + continue; + test.skip(file.slice(0, -4), async function () { + let document = await vscode.workspace.openTextDocument(resolve(dir, file)); + if (document.languageId !== 'ahk2') + document = await vscode.languages.setTextDocumentLanguage(document, 'ahk2'); + const uri = document.uri.toString(); + const params: DocumentFormattingParams = { + textDocument: { uri }, + options: { insertSpaces: false, tabSize: 4 } + }; + const content = document.getText().replaceAll('\r\n', '\n'); + const result: TextEdit[] | undefined = await client.sendRequest(DocumentFormattingRequest.method, params); + assert.ok(result?.[0].newText === content); + }); + } + }); +} \ No newline at end of file diff --git a/client/src/test/formatting/array_object_style.ahk b/client/src/test/formatting/array_object_style.ahk new file mode 100644 index 00000000..896273f9 --- /dev/null +++ b/client/src/test/formatting/array_object_style.ahk @@ -0,0 +1,26 @@ +;@format array_style: expand, object_style: expand +list := [ + { + name: 1, + age: 2 + }, + { + name: 2, + age: 3 + } +] +;@format array_style: collapse, object_style: expand +list := [{ + name: 1, + age: 2 +}, { + name: 2, + age: 3 +}] +;@format array_style: expand, object_style: collapse +list := [ + { name: 1, age: 2 }, + { name: 2, age: 3 } +] +;@format array_style: collapse, object_style: collapse +list := [{ name: 1, age: 2 }, { name: 2, age: 3 }] \ No newline at end of file diff --git a/client/tsconfig.json b/client/tsconfig.json deleted file mode 100644 index 564016b0..00000000 --- a/client/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2022", "WebWorker"], - "module": "commonjs", - "moduleResolution": "node", - "sourceMap": true, - "strict": true, - "outDir": "out", - "composite": true - }, - "include": ["src"], - "exclude": ["node_modules", ".vscode-test", ".vscode-test-web"] -} diff --git a/esbuild.mjs b/esbuild.mjs new file mode 100644 index 00000000..ae90771a --- /dev/null +++ b/esbuild.mjs @@ -0,0 +1,116 @@ +import { build, context } from 'esbuild'; + +/** @type {import('esbuild').BuildOptions} */ +const server_opt = { + define: { + 'process.env.BROWSER': 'false', + 'process.env.DEBUG': 'false', + }, + entryPoints: ['server/src/server.ts'], + format: 'cjs', + logLevel: 'error', + outbase: 'server/src', + outdir: 'server/dist', + platform: 'node', + sourcemap: true, +}; +const client_opt = { + ...server_opt, + entryPoints: ['client/src/extension.ts', 'client/src/test/*.ts'], + outbase: 'client/src', + outdir: 'client/dist', +}; + +switch (process.argv[2]) { + case '--cli': build_cli(); break; + case '--dev': build_watch(); break; + case '--web': build_watch(true); break; + default: build_prod(); break; +} + +async function build_cli() { + server_opt.bundle = true; + server_opt.minify = true; + server_opt.outdir = 'server/cli'; + const start = new Date; + await build(server_opt); + console.log(`build finished in ${new Date - start} ms`); +} + +async function build_prod() { + const opts = [ + client_opt, server_opt, + { ...client_opt, entryPoints: [client_opt.entryPoints.pop()] } + ]; + client_opt.external = ['vscode']; + client_opt.bundle = server_opt.bundle = true; + client_opt.minify = server_opt.minify = true; + opts.push(...browser_opts(true)); + const start = new Date; + await Promise.all(opts.map(o => build(o))); + console.log(`build finished in ${new Date - start} ms`); +} + +function build_watch(web = false) { + let start, timer, opts; + /** @type {import('esbuild').Plugin} */ + const plugin = { + name: 'esbuild-problem-matcher', + setup(build) { + build.onStart(() => { + start ??= (console.log('\x1bc[watch] build started'), new Date); + }); + build.onEnd(result => { + const end = new Date; + result.errors.forEach(({ text, location }) => { + console.error(`✘ [ERROR] ${text}`); + console.error(` ${location.file}:${location.line}:${location.column}:`); + }); + timer && clearTimeout(timer); + timer = setTimeout(() => { + console.log(`[watch] build finished in ${end - start} ms`); + start = timer = undefined; + }, 500); + }); + } + }; + client_opt.logLevel = server_opt.logLevel = 'silent'; + server_opt.define['process.env.DEBUG'] = 'true'; + if (web) + opts = browser_opts(false); + else { + server_opt.entryPoints = ['server/src/*.ts']; + server_opt.outdir = 'server/out'; + opts = [client_opt, server_opt]; + } + for (const opt of opts) { + opt.plugins = [plugin]; + context(opt).then(ctx => ctx.watch()); + } +} +/** @returns {Array} */ +function browser_opts(minify) { + const browser_opt = { + bundle: true, + define: { + ...server_opt.define, + 'process.cwd': 'process_cwd', + 'process.env.BROWSER': 'true', + }, + minify, + platform: 'browser', + }; + return [{ + ...client_opt, + ...browser_opt, + entryPoints: ['client/src/browserClientMain.ts'], + external: ['vscode'], + }, { + ...server_opt, + ...browser_opt, + entryPoints: ['server/src/browserServerMain.ts'], + footer: { + js: 'function process_cwd(){return""}' + }, + }]; +} \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs index 7dc2a7b8..449991df 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,41 +1,25 @@ -import globals from 'globals'; -import pluginJs from '@eslint/js'; -import tseslint from 'typescript-eslint'; +import pluginJs from "@eslint/js"; +import tseslint from "typescript-eslint"; /** @type {typeof tseslint.configs.recommended} */ export default [ - { - languageOptions: { - globals: { - ...globals.browser, - ...globals.node, - }, - }, - }, - pluginJs.configs.recommended, - ...tseslint.configs.recommended, - { - ignores: [ - '**/*.js', - '**/*.d.ts', - '**/.vscode-test-web/*', - '**/.vscode-test/*', - ], - }, - { - rules: { - 'no-control-regex': 'off', - 'no-empty': ['error', { allowEmptyCatch: true }], - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { - argsIgnorePattern: '^_', - varsIgnorePattern: '^_', - caughtErrors: 'none', - ignoreRestSiblings: true, - }, - ], - }, - }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + ignores: ['**/*.{js,mjs}', '**/*.d.ts', '**/.vscode-test-web/*', '**/.vscode-test/*'], + }, + { + rules: { + 'no-control-regex': 'off', + 'no-empty': 'off', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-expressions': 'off', + '@typescript-eslint/no-unused-vars': ['error', { + args: 'none', + varsIgnorePattern: '^_', + caughtErrors: 'none', + ignoreRestSiblings: true + }], + } + } ]; diff --git a/package-lock.json b/package-lock.json index 59244092..b0025a8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,491 +1,258 @@ { "name": "vscode-autohotkey2-lsp", - "version": "2.5.2", + "version": "2.5.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-autohotkey2-lsp", - "version": "2.5.2", + "version": "2.5.3", "license": "LGPLv3.0", "dependencies": { + "path-browserify": "^1.0.1", "vscode-languageclient": "^9.0.1", "vscode-languageserver": "^9.0.1", - "vscode-languageserver-textdocument": "^1.0.11", + "vscode-languageserver-textdocument": "^1.0.12", "vscode-uri": "^3.0.8" }, "devDependencies": { - "@eslint/js": "^9.4.0", - "@types/mocha": "^10.0.8", - "@types/node": "^20.16.0", - "@types/vscode": "^1.82.0", - "del-cli": "^5.1.0", - "esbuild": "^0.23.1", - "eslint": "^9.4.0", - "globals": "^15.4.0", - "mocha": "^10.7.0", - "prettier": "3.3.3", - "sort-package-json": "^2.10.0", - "ts-loader": "^9.4.0", - "typescript": "^5.3.2", - "typescript-eslint": "^7.12.0", - "webpack": "^5.74.0", - "webpack-cli": "^4.10.0" + "@types/node": "^20.14.0", + "@types/vscode": "1.93.0", + "@vscode/test-cli": "^0.0.10", + "@vscode/test-electron": "^2.4.1", + "@vscode/vsce": "^2.32.0", + "esbuild": "^0.24.0", + "eslint": "^9.11.0", + "typescript": "5.5.4", + "typescript-eslint": "^8.7.0", + "vscode-tmgrammar-test": "^0.1.3" }, "engines": { "vscode": "^1.82.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "node_modules/@azure/abort-controller": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz", + "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" + "tslib": "^2.2.0" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" + "node": ">=12.0.0" } }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "node_modules/@azure/core-auth": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/@azure/core-auth/-/core-auth-1.8.0.tgz", + "integrity": "sha512-YvFMowkXzLbXNM11yZtVLhUCmuG0ex7JKOH366ipjmHBhL3vpDcPAeWF+jf0X+jVXwFqo3UhsWUq4kH0ZPdu/g==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", - "cpu": [ - "arm64" - ], + "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", - "cpu": [ - "ia32" - ], + "node_modules/@azure/core-client": { + "version": "1.9.2", + "resolved": "https://registry.npmmirror.com/@azure/core-client/-/core-client-1.9.2.tgz", + "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-rest-pipeline": "^1.9.1", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.6.1", + "@azure/logger": "^1.0.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", - "cpu": [ - "loong64" - ], + "node_modules/@azure/core-client/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", - "cpu": [ - "mips64el" - ], + "node_modules/@azure/core-rest-pipeline": { + "version": "1.17.0", + "resolved": "https://registry.npmmirror.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.17.0.tgz", + "integrity": "sha512-62Vv8nC+uPId3j86XJ0WI+sBf0jlqTqPUFCBNrGtlaUeQUIXWV/D8GE5A1d+Qx8H7OQojn2WguC8kChD6v0shA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.8.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.9.0", + "@azure/logger": "^1.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", - "cpu": [ - "ppc64" - ], + "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", - "cpu": [ - "riscv64" - ], + "node_modules/@azure/core-tracing": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@azure/core-tracing/-/core-tracing-1.1.2.tgz", + "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", - "cpu": [ - "s390x" - ], + "node_modules/@azure/core-util": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/@azure/core-util/-/core-util-1.10.0.tgz", + "integrity": "sha512-dqLWQsh9Nro1YQU+405POVtXnwrIVqPyfUzc4zXCbThTg7+vNNaiMkwbX9AMXKyoFYFClxmB3s25ZFr3+jZkww==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", - "cpu": [ - "x64" - ], + "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", - "cpu": [ - "x64" - ], + "node_modules/@azure/identity": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/@azure/identity/-/identity-4.4.1.tgz", + "integrity": "sha512-DwnG4cKFEM7S3T+9u05NstXU/HN0dk45kPOinUyNKsn5VWwpXd9sbPKEg6kgJzGbm1lMuhx9o31PVbCtM5sfBA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-auth": "^1.5.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.1.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.3.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^3.14.0", + "@azure/msal-node": "^2.9.2", + "events": "^3.0.0", + "jws": "^4.0.0", + "open": "^8.0.0", + "stoppable": "^1.1.0", + "tslib": "^2.2.0" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], + "node_modules/@azure/logger": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/@azure/logger/-/logger-1.1.4.tgz", + "integrity": "sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", - "cpu": [ - "x64" - ], + "node_modules/@azure/msal-browser": { + "version": "3.24.0", + "resolved": "https://registry.npmmirror.com/@azure/msal-browser/-/msal-browser-3.24.0.tgz", + "integrity": "sha512-JGNV9hTYAa7lsum9IMIibn2kKczAojNihGo1hi7pG0kNrcKej530Fl6jxwM05A44/6I079CSn6WxYxbVhKUmWg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@azure/msal-common": "14.15.0" + }, "engines": { - "node": ">=18" + "node": ">=0.8.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", - "cpu": [ - "x64" - ], + "node_modules/@azure/msal-common": { + "version": "14.15.0", + "resolved": "https://registry.npmmirror.com/@azure/msal-common/-/msal-common-14.15.0.tgz", + "integrity": "sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], "engines": { - "node": ">=18" + "node": ">=0.8.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", - "cpu": [ - "arm64" - ], + "node_modules/@azure/msal-node": { + "version": "2.14.0", + "resolved": "https://registry.npmmirror.com/@azure/msal-node/-/msal-node-2.14.0.tgz", + "integrity": "sha512-rrfzIpG3Q1rHjVYZmHAEDidWAZZ2cgkxlIcMQ8dHebRISaZ2KCV33Q8Vs+uaV6lxweROabNxKFlR2lIKagZqYg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@azure/msal-common": "14.15.0", + "jsonwebtoken": "^9.0.0", + "uuid": "^8.3.0" + }, "engines": { - "node": ">=18" + "node": ">=16" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true }, "node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "win32" @@ -499,7 +266,6 @@ "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, - "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -515,7 +281,6 @@ "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -524,26 +289,55 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "version": "4.11.1", + "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, - "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { - "version": "0.15.1", - "resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.15.1.tgz", - "integrity": "sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==", + "version": "0.18.0", + "resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.3", + "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", - "minimatch": "^3.0.5" + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -553,7 +347,6 @@ "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, - "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -572,12 +365,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -585,35 +387,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "brace-expansion": "^1.1.7" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "*" } }, "node_modules/@eslint/js": { - "version": "9.4.0", - "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.4.0.tgz", - "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", + "version": "9.11.1", + "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.11.1.tgz", + "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", "dev": true, - "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.3.tgz", - "integrity": "sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw==", + "version": "2.1.4", + "resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -623,7 +435,6 @@ "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -637,7 +448,6 @@ "resolved": "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.3.0.tgz", "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -646,65 +456,79 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=12" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, - "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=6.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmmirror.com/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "engines": { + "node": ">=8" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -715,7 +539,6 @@ "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -729,7 +552,6 @@ "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } @@ -739,7 +561,6 @@ "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -748,106 +569,164 @@ "node": ">= 8" } }, - "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmmirror.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "optional": true, + "engines": { + "node": ">=14" } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/mocha": { "version": "10.0.8", "resolved": "https://registry.npmmirror.com/@types/mocha/-/mocha-10.0.8.tgz", "integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/node": { - "version": "20.16.0", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.16.0.tgz", - "integrity": "sha512-vDxceJcoZhIVh67S568bm1UGZO0DX0hpplJZxzeXMKwIPLn190ec5RRxQ69BKhX44SUGIxxgMdDY557lGLKprQ==", + "version": "20.16.10", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "dev": true, - "license": "MIT", "dependencies": { "undici-types": "~6.19.2" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "node_modules/@types/vscode": { + "version": "1.93.0", + "resolved": "https://registry.npmmirror.com/@types/vscode/-/vscode-1.93.0.tgz", + "integrity": "sha512-kUK6jAHSR5zY8ps42xuW89NLcBpw1kOabah7yv38J8MyiYuOHxLQBi0e7zeXbQgVefDy/mZZetqEFC+Fl5eIEQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.7.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", + "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", "dev": true, - "license": "MIT" + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/type-utils": "8.7.0", + "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } }, - "node_modules/@types/vscode": { - "version": "1.90.0", - "resolved": "https://registry.npmmirror.com/@types/vscode/-/vscode-1.90.0.tgz", - "integrity": "sha512-oT+ZJL7qHS9Z8bs0+WKf/kQ27qWYR3trsXpq46YDjFqBsMLG4ygGGjPaJ2tyrH0wJzjOEmDyg9PDJBBhWg9pkQ==", + "node_modules/@typescript-eslint/parser": { + "version": "8.7.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.7.0.tgz", + "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", "dev": true, - "license": "MIT" + "dependencies": { + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/typescript-estree": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", - "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", + "version": "8.7.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", + "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.7.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", + "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0" + "@typescript-eslint/typescript-estree": "8.7.0", + "@typescript-eslint/utils": "8.7.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/types": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-7.12.0.tgz", - "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", + "version": "8.7.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.7.0.tgz", + "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", "dev": true, - "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -855,23 +734,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", - "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", + "version": "8.7.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", + "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -883,44 +761,39 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "node_modules/@typescript-eslint/utils": { + "version": "8.7.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.7.0.tgz", + "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", "dev": true, - "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/typescript-estree": "8.7.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", - "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", + "version": "8.7.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", + "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/types": "8.7.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -932,7 +805,6 @@ "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -940,226 +812,165 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "node_modules/@vscode/test-cli": { + "version": "0.0.10", + "resolved": "https://registry.npmmirror.com/@vscode/test-cli/-/test-cli-0.0.10.tgz", + "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "@xtuc/long": "4.2.2" + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "node_modules/@vscode/test-electron": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/@vscode/test-electron/-/test-electron-2.4.1.tgz", + "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", "dev": true, - "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^7.0.1", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=16" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "node_modules/@vscode/vsce": { + "version": "2.32.0", + "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-2.32.0.tgz", + "integrity": "sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==", "dev": true, - "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@azure/identity": "^4.1.0", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^6.2.1", + "form-data": "^4.0.0", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^12.3.2", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^7.5.2", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 16" + }, + "optionalDependencies": { + "keytar": "^7.7.0" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "node_modules/@vscode/vsce-sign": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign/-/vsce-sign-2.0.4.tgz", + "integrity": "sha512-0uL32egStKYfy60IqnynAChMTbL0oqpqk0Ew0YHiIb+fayuGZWADuIPHWUcY1GCnAA+VgchOPDMxnc2R3XGWEA==", "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "hasInstallScript": true, + "optionalDependencies": { + "@vscode/vsce-sign-alpine-arm64": "2.0.2", + "@vscode/vsce-sign-alpine-x64": "2.0.2", + "@vscode/vsce-sign-darwin-arm64": "2.0.2", + "@vscode/vsce-sign-darwin-x64": "2.0.2", + "@vscode/vsce-sign-linux-arm": "2.0.2", + "@vscode/vsce-sign-linux-arm64": "2.0.2", + "@vscode/vsce-sign-linux-x64": "2.0.2", + "@vscode/vsce-sign-win32-arm64": "2.0.2", + "@vscode/vsce-sign-win32-x64": "2.0.2" + } + }, + "node_modules/@vscode/vsce-sign-win32-x64": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.2.tgz", + "integrity": "sha512-pAiRN6qSAhDM5SVOIxgx+2xnoVUePHbRNC7OD2aOR3WltTKxxF25OfpK8h8UQ7A0BuRkSgREbB59DBlFk4iAeg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "node_modules/@vscode/vsce/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz", - "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@webpack-cli/info": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/@webpack-cli/info/-/info-1.5.0.tgz", - "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", + "node_modules/@vscode/vsce/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", "dependencies": { - "envinfo": "^7.7.3" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, - "peerDependencies": { - "webpack-cli": "4.x.x" + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@webpack-cli/serve": { - "version": "1.7.0", - "resolved": "https://registry.npmmirror.com/@webpack-cli/serve/-/serve-1.7.0.tgz", - "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "node_modules/@vscode/vsce/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", - "peerDependencies": { - "webpack-cli": "4.x.x" + "dependencies": { + "brace-expansion": "^1.1.7" }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } + "engines": { + "node": "*" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, - "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1167,41 +978,25 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmmirror.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, - "license": "MIT", "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" + "debug": "^4.3.4" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 14" } }, "node_modules/ajv": { @@ -1209,7 +1004,6 @@ "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1221,22 +1015,11 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -1246,7 +1029,6 @@ "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -1256,7 +1038,6 @@ "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -1269,7 +1050,6 @@ "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, - "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1282,41 +1062,54 @@ "version": "2.0.1", "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" + "dev": true }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "node_modules/azure-devops-node-api": { + "version": "12.5.0", + "resolved": "https://registry.npmmirror.com/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", + "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" } }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" }, @@ -1324,15 +1117,49 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", "dev": true, - "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmmirror.com/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -1340,7 +1167,6 @@ "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, - "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -1352,55 +1178,96 @@ "version": "1.3.1", "resolved": "https://registry.npmmirror.com/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true, - "license": "ISC" + "dev": true }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "type": "patreon", + "url": "https://www.patreon.com/feross" }, { - "type": "github", - "url": "https://github.com/sponsors/ai" + "type": "consulting", + "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true + }, + "node_modules/c8": { + "version": "9.1.0", + "resolved": "https://registry.npmmirror.com/c8/-/c8-9.1.0.tgz", + "integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" }, "bin": { - "browserslist": "cli.js" + "c8": "bin/c8.js" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=14.14.0" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, - "license": "MIT" + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -1410,7 +1277,6 @@ "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -1418,52 +1284,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001629", - "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001629.tgz", - "integrity": "sha512-c3dl911slnQhmxUIT4HhYzT7wnBK/XYpGnYLOj4nJBaRiw52Ibe7YxlDaAeRECvA786zCuExhxIUJ2K7nHMrBw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -1473,12 +1298,65 @@ "node": ">=4" } }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cheerio": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/cheerio/-/cheerio-1.0.0.tgz", + "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", + "dev": true, + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "encoding-sniffer": "^0.2.0", + "htmlparser2": "^9.1.0", + "parse5": "^7.1.2", + "parse5-htmlparser2-tree-adapter": "^7.0.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^6.19.5", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=18.17" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1498,37 +1376,50 @@ "fsevents": "~2.3.2" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true, - "license": "ISC", + "optional": true + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "restore-cursor": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=6.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT", "dependencies": { - "escape-string-regexp": "5.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { "node": ">=12" @@ -1537,32 +1428,83 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clean-stack/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6" + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "dev": true, + "engines": { + "node": ">=16" } }, "node_modules/color-convert": { @@ -1570,7 +1512,6 @@ "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -1579,29 +1520,52 @@ "version": "1.1.3", "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "license": "MIT" + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true, - "license": "MIT" + "engines": { + "node": ">= 6" + } }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1611,14 +1575,41 @@ "node": ">= 8" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, - "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1634,7 +1625,6 @@ "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -1642,199 +1632,197 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, - "license": "MIT", + "optional": true, "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" + "mimic-response": "^3.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decamelize-keys/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, - "license": "MIT", + "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" } }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" + "dev": true }, - "node_modules/del": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/del/-/del-7.1.0.tgz", - "integrity": "sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, - "license": "MIT", "dependencies": { - "globby": "^13.1.2", - "graceful-fs": "^4.2.10", - "is-glob": "^4.0.3", - "is-path-cwd": "^3.0.0", - "is-path-inside": "^4.0.0", - "p-map": "^5.5.0", - "rimraf": "^3.0.2", - "slash": "^4.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { - "node": ">=14.16" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/del-cli": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/del-cli/-/del-cli-5.1.0.tgz", - "integrity": "sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==", + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "dev": true, - "license": "MIT", - "dependencies": { - "del": "^7.1.0", - "meow": "^10.1.3" - }, - "bin": { - "del": "cli.js", - "del-cli": "cli.js" - }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/del/node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmmirror.com/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, - "license": "MIT", - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.4.0" } }, - "node_modules/del/node_modules/is-path-inside": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-4.0.0.tgz", - "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "dev": true, - "license": "MIT", + "optional": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/del/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, - "license": "MIT", "engines": { - "node": ">=12" + "node": ">=0.3.1" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/detect-indent": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/detect-indent/-/detect-indent-7.0.1.tgz", - "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, "engines": { - "node": ">=12.20" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/detect-newline": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/detect-newline/-/detect-newline-4.0.1.tgz", - "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" + "dependencies": { + "safe-buffer": "^5.0.1" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/encoding-sniffer": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", + "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", "dev": true, "license": "MIT", "dependencies": { - "path-type": "^4.0.0" + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.796", - "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.796.tgz", - "integrity": "sha512-NglN/xprcM+SHD2XCli4oC6bWe6kHoytcyLKCWXmRL854F0qhPhaYgUswUsglnPxYaNQIg2uMY4BvaomIf3kLA==", + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, - "license": "ISC" + "optional": true, + "dependencies": { + "once": "^1.4.0" + } }, "node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "version": "5.17.1", + "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -1843,43 +1831,68 @@ "node": ">=10.13.0" } }, - "node_modules/envinfo": { - "version": "7.13.0", - "resolved": "https://registry.npmmirror.com/envinfo/-/envinfo-7.13.0.tgz", - "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, - "license": "MIT", - "bin": { - "envinfo": "dist/cli.js" - }, "engines": { - "node": ">=4" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, - "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-module-lexer": { - "version": "1.5.3", - "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.5.3.tgz", - "integrity": "sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg==", + "get-intrinsic": "^1.2.4" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "license": "MIT" + "engines": { + "node": ">= 0.4" + } }, "node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", "dev": true, "hasInstallScript": true, - "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -1887,38 +1900,37 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -1928,35 +1940,37 @@ "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/eslint": { - "version": "9.4.0", - "resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.4.0.tgz", - "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", + "version": "9.11.1", + "resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.11.1.tgz", + "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/config-array": "^0.15.1", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.4.0", + "@eslint/js": "9.11.1", + "@eslint/plugin-kit": "^0.2.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.1", + "eslint-scope": "^8.0.2", "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", - "esquery": "^1.4.2", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -1967,7 +1981,6 @@ "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", @@ -1982,29 +1995,38 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "8.0.2", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -2017,7 +2039,6 @@ "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2028,12 +2049,21 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2050,7 +2080,6 @@ "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2062,15 +2091,13 @@ "version": "1.1.4", "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -2078,48 +2105,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.0.1", - "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.0.1.tgz", - "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10.13.0" } }, "node_modules/eslint/node_modules/has-flag": { @@ -2127,57 +2122,20 @@ "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "*" } }, "node_modules/eslint/node_modules/supports-color": { @@ -2185,7 +2143,6 @@ "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -2194,15 +2151,14 @@ } }, "node_modules/espree": { - "version": "10.0.1", - "resolved": "https://registry.npmmirror.com/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.11.3", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2210,28 +2166,17 @@ "funding": { "url": "https://opencollective.com/eslint" } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, "engines": { - "node": ">=4.0" + "node": ">=0.10" } }, "node_modules/esrecurse": { @@ -2239,7 +2184,6 @@ "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2247,22 +2191,11 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -2272,7 +2205,6 @@ "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -2282,24 +2214,31 @@ "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.x" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -2311,59 +2250,41 @@ "node": ">=8.6.0" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmmirror.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } + "dev": true }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, - "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -2376,7 +2297,6 @@ "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2385,17 +2305,19 @@ } }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { @@ -2403,7 +2325,6 @@ "resolved": "https://registry.npmmirror.com/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } @@ -2413,7 +2334,6 @@ "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, - "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -2426,37 +2346,56 @@ "version": "3.3.1", "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.1.tgz", "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true, - "license": "ISC" + "dev": true }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, - "license": "ISC" + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">= 6" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "optional": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2466,150 +2405,142 @@ "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, - "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/git-hooks-list": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/git-hooks-list/-/git-hooks-list-3.1.0.tgz", - "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmmirror.com/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/fisker/git-hooks-list?sponsor=1" - } + "optional": true }, "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "version": "10.4.5", + "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "*" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "ISC", "dependencies": { - "is-glob": "^4.0.3" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/globals": { - "version": "15.4.0", - "resolved": "https://registry.npmmirror.com/globals/-/globals-15.4.0.tgz", - "integrity": "sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, - "license": "MIT", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" + "get-intrinsic": "^1.1.3" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "dev": true }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, - "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -2622,7 +2553,6 @@ "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "license": "MIT", "bin": { "he": "bin/he" } @@ -2632,7 +2562,6 @@ "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, - "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2640,58 +2569,115 @@ "node": ">=10" } }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", "dev": true, - "license": "MIT", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, "engines": { - "node": ">= 4" + "node": ">= 14" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, - "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "agent-base": "^7.0.2", + "debug": "4" }, "engines": { - "node": ">=6" + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, - "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 4" } }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, - "license": "MIT", "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2702,31 +2688,16 @@ "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, - "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2736,32 +2707,20 @@ "version": "2.0.4", "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } + "dev": true }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, - "license": "MIT" + "optional": true }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -2769,17 +2728,19 @@ "node": ">=8" } }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-extglob": { @@ -2787,7 +2748,6 @@ "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2797,7 +2757,6 @@ "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -2807,7 +2766,6 @@ "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -2815,35 +2773,32 @@ "node": ">=0.10.0" } }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } }, - "node_modules/is-path-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-path-cwd/-/is-path-cwd-3.0.0.tgz", - "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -2853,30 +2808,15 @@ "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -2884,77 +2824,107 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" + "dev": true }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, - "license": "MIT", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">=10" } }, - "node_modules/jest-worker/node_modules/has-flag": { + "node_modules/istanbul-lib-report/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "license": "MIT" + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2966,48 +2936,130 @@ "version": "3.0.1", "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "dev": true, - "license": "MIT" + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmmirror.com/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "dev": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dev": true, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmmirror.com/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "node_modules/levn": { @@ -3015,7 +3067,6 @@ "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -3024,49 +3075,93 @@ "node": ">= 0.8.0" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.11.5" + "dependencies": { + "uc.micro": "^1.0.1" } }, "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -3083,7 +3178,6 @@ "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3099,7 +3193,6 @@ "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3116,7 +3209,6 @@ "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -3128,15 +3220,13 @@ "version": "1.1.4", "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/log-symbols/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -3146,7 +3236,6 @@ "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3159,7 +3248,6 @@ "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -3167,98 +3255,84 @@ "node": ">=10" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow": { - "version": "10.1.5", - "resolved": "https://registry.npmmirror.com/meow/-/meow-10.1.5.tgz", - "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, - "license": "MIT", "dependencies": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^7.0.0", - "decamelize": "^5.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.2", - "read-pkg-up": "^8.0.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^1.2.2", - "yargs-parser": "^20.2.9" + "semver": "^7.5.3" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/meow/node_modules/decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "markdown-it": "bin/markdown-it.js" } }, - "node_modules/meow/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, - "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { - "node": ">=8.6" + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" } }, "node_modules/mime-db": { @@ -3266,7 +3340,6 @@ "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3276,7 +3349,6 @@ "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, - "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -3284,60 +3356,74 @@ "node": ">= 0.6" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "optional": true, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 6" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minimist-options/node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmmirror.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "optional": true + }, "node_modules/mocha": { "version": "10.7.3", "resolved": "https://registry.npmmirror.com/mocha/-/mocha-10.7.3.tgz", "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", "dev": true, - "license": "MIT", "dependencies": { "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", @@ -3373,7 +3459,6 @@ "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3384,22 +3469,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/mocha/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -3411,7 +3485,6 @@ "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -3423,39 +3496,19 @@ "version": "1.1.4", "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/mocha/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, "engines": { "node": ">=10" }, @@ -3469,7 +3522,6 @@ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3489,33 +3541,15 @@ "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mocha/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -3523,51 +3557,11 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mocha/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3577,25 +3571,11 @@ "node": ">=8" } }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3611,7 +3591,6 @@ "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3629,7 +3608,6 @@ "resolved": "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -3648,154 +3626,306 @@ "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmmirror.com/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "dev": true, - "license": "MIT" + "optional": true }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" + "dev": true }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "node_modules/node-abi": { + "version": "3.68.0", + "resolved": "https://registry.npmmirror.com/node-abi/-/node-abi-3.68.0.tgz", + "integrity": "sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==", "dev": true, - "license": "MIT" - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "license": "BSD-2-Clause", + "optional": true, "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "semver": "^7.3.5" }, "engines": { "node": ">=10" } }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, + "optional": true + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/ora/-/ora-7.0.1.tgz", + "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==", + "dev": true, + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.3.0", + "log-symbols": "^5.1.0", + "stdin-discarder": "^0.1.0", + "string-width": "^6.1.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/ora/node_modules/log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", "dev": true, - "license": "MIT", "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/ora/node_modules/string-width": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-6.1.0.tgz", + "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", "dev": true, - "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^10.2.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=6" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmmirror.com/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "license": "MIT", "dependencies": { - "aggregate-error": "^4.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -3803,31 +3933,71 @@ "node": ">=6" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", + "dev": true, + "dependencies": { + "semver": "^5.1.0" + } + }, + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "entities": "^4.4.0" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dev": true, + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -3837,7 +4007,6 @@ "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3847,41 +4016,43 @@ "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, - "license": "MIT", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true, - "license": "ISC" + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.6" }, @@ -3889,17 +4060,31 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "dev": true, - "license": "MIT", + "optional": true, "dependencies": { - "find-up": "^4.0.0" + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/prelude-ls": { @@ -3907,17 +4092,22 @@ "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, - "license": "MIT", + "optional": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -3933,11 +4123,25 @@ "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3956,140 +4160,81 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + ] }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, - "node_modules/read-pkg": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-6.0.0.tgz", - "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-8.0.0.tgz", - "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, - "license": "MIT", + "optional": true, "dependencies": { - "find-up": "^5.0.0", - "read-pkg": "^6.0.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "rc": "cli.js" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "optional": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", "dev": true, - "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" + "mute-stream": "~0.0.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8" } }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, - "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -4097,115 +4242,56 @@ "node": ">=8.10.0" } }, - "node_modules/rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmmirror.com/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.9.0" - }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/redent": { + "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "license": "MIT", - "dependencies": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, - "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4225,7 +4311,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -4248,33 +4333,25 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "dev": true }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "license": "ISC", + "version": "7.6.3", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -4287,30 +4364,38 @@ "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, - "license": "MIT", "dependencies": { - "kind-of": "^6.0.2" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -4323,60 +4408,95 @@ "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, - "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sort-object-keys": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz", - "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/sort-package-json": { - "version": "2.10.0", - "resolved": "https://registry.npmmirror.com/sort-package-json/-/sort-package-json-2.10.0.tgz", - "integrity": "sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g==", + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true, "dependencies": { - "detect-indent": "^7.0.1", - "detect-newline": "^4.0.0", - "get-stdin": "^9.0.0", - "git-hooks-list": "^3.0.0", - "globby": "^13.1.2", - "is-plain-obj": "^4.1.0", - "semver": "^7.6.0", - "sort-object-keys": "^1.1.3" - }, - "bin": { - "sort-package-json": "cli.js" + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, - "node_modules/sort-package-json/node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmmirror.com/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "node_modules/stdin-discarder": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", + "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", "dev": true, "license": "MIT", "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "bl": "^5.0.0" }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -4385,25 +4505,41 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sort-package-json/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", "dev": true, - "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4", + "npm": ">=6" } }, - "node_modules/sort-package-json/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, - "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, "engines": { "node": ">=12" }, @@ -4411,79 +4547,72 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "license": "BSD-3-Clause", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, - "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.18", - "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", - "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/strip-ansi": { + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", "version": "6.0.1", "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -4491,46 +4620,28 @@ "node": ">=8" } }, - "node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "license": "MIT", - "dependencies": { - "min-indent": "^1.0.1" - }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "version": "9.4.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/tapable": { @@ -4538,85 +4649,169 @@ "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=6" + "node": ">=6" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/tar-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/terser": { - "version": "5.31.1", - "resolved": "https://registry.npmmirror.com/terser/-/terser-5.31.1.tgz", - "integrity": "sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==", + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": "*" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT" + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=14.14" + } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -4624,25 +4819,11 @@ "node": ">=8.0" } }, - "node_modules/trim-newlines": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-4.1.1.tgz", - "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=16" }, @@ -4650,101 +4831,32 @@ "typescript": ">=4.2.0" } }, - "node_modules/ts-loader": { - "version": "9.5.1", - "resolved": "https://registry.npmmirror.com/ts-loader/-/ts-loader-9.5.1.tgz", - "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4", - "source-map": "^0.7.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/ts-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ts-loader/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ts-loader/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ts-loader/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true }, - "node_modules/ts-loader/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmmirror.com/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" } }, - "node_modules/ts-loader/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, - "license": "MIT", + "optional": true, "dependencies": { - "has-flag": "^4.0.0" + "safe-buffer": "^5.0.1" }, "engines": { - "node": ">=8" + "node": "*" } }, "node_modules/type-check": { @@ -4752,7 +4864,6 @@ "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -4760,25 +4871,22 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmmirror.com/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.4", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4788,210 +4896,104 @@ } }, "node_modules/typescript-eslint": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-7.12.0.tgz", - "integrity": "sha512-D6HKNbQcnNu3BaN4HkQCR16tgG8Q2AMUWPgvhrJksOXu+d6ys07yC06ONiV2kcsEfWC22voB6C3PvK2MqlBZ7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "7.12.0", - "@typescript-eslint/parser": "7.12.0", - "@typescript-eslint/utils": "7.12.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz", - "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==", + "version": "8.7.0", + "resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.7.0.tgz", + "integrity": "sha512-nEHbEYJyHwsuf7c3V3RS7Saq+1+la3i0ieR3qP0yjqWSzVmh8Drp47uOl9LjbPANac4S7EFSqvcYIKXUUwIfIQ==", "dev": true, - "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/type-utils": "7.12.0", - "@typescript-eslint/utils": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/eslint-plugin": "8.7.0", + "@typescript-eslint/parser": "8.7.0", + "@typescript-eslint/utils": "8.7.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz", - "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/utils": "7.12.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-7.12.0.tgz", - "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmmirror.com/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "dev": true }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-7.12.0.tgz", - "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", + "node_modules/undici": { + "version": "6.19.8", + "resolved": "https://registry.npmmirror.com/undici/-/undici-6.19.8.tgz", + "integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==", "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0" - }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" + "node": ">=18.17" } }, "node_modules/undici-types": { - "version": "6.19.6", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.19.6.tgz", - "integrity": "sha512-e/vggGopEfTKSvj4ihnOLTsqhrKRN3LeO6qSN/GxohhuRv8qH9bNQ4B8W7e/vFL+0XTnmHPB4/kegunZGA4Org==", - "dev": true, - "license": "MIT" - }, - "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } + "version": "6.19.8", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmmirror.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" } }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", - "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -5000,7 +5002,6 @@ "version": "9.0.1", "resolved": "https://registry.npmmirror.com/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", - "license": "MIT", "dependencies": { "minimatch": "^5.1.0", "semver": "^7.3.7", @@ -5010,20 +5011,10 @@ "vscode": "^1.82.0" } }, - "node_modules/vscode-languageclient/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/vscode-languageclient/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5035,7 +5026,6 @@ "version": "9.0.1", "resolved": "https://registry.npmmirror.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", - "license": "MIT", "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, @@ -5047,173 +5037,137 @@ "version": "3.17.5", "resolved": "https://registry.npmmirror.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", - "license": "MIT", "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", - "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", - "license": "MIT" + "version": "1.0.12", + "resolved": "https://registry.npmmirror.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==" }, "node_modules/vscode-languageserver-types": { "version": "3.17.5", "resolved": "https://registry.npmmirror.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "license": "MIT" + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" }, - "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", - "license": "MIT" + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true }, - "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "node_modules/vscode-textmate": { + "version": "7.0.4", + "resolved": "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-7.0.4.tgz", + "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A==", + "dev": true + }, + "node_modules/vscode-tmgrammar-test": { + "version": "0.1.3", + "resolved": "https://registry.npmmirror.com/vscode-tmgrammar-test/-/vscode-tmgrammar-test-0.1.3.tgz", + "integrity": "sha512-Wg6Pz+ePAT1O+F/A1Fc4wS5vY2X+HNtgN4qMdL+65NLQYd1/zdDWH4fhwsLjX8wTzeXkMy49Cr4ZqWTJ7VnVxg==", "dev": true, - "license": "MIT", "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "bottleneck": "^2.19.5", + "chalk": "^2.4.2", + "commander": "^9.2.0", + "diff": "^4.0.2", + "glob": "^7.1.6", + "vscode-oniguruma": "^1.5.1", + "vscode-textmate": "^7.0.1" }, - "engines": { - "node": ">=10.13.0" + "bin": { + "vscode-tmgrammar-snap": "dist/snapshot.js", + "vscode-tmgrammar-test": "dist/unit.js" } }, - "node_modules/webpack": { - "version": "5.91.0", - "resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.91.0.tgz", - "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", + "node_modules/vscode-tmgrammar-test/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.16.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/vscode-tmgrammar-test/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "node": "^12.20.0 || >=14" } }, - "node_modules/webpack-cli": { - "version": "4.10.0", - "resolved": "https://registry.npmmirror.com/webpack-cli/-/webpack-cli-4.10.0.tgz", - "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "node_modules/vscode-tmgrammar-test/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/vscode-tmgrammar-test/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "cross-spawn": "^7.0.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=10.13.0" + "node": "*" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/vscode-tmgrammar-test/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">= 10" + "node": "*" } }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, - "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" + "iconv-lite": "0.6.3" }, "engines": { - "node": ">=10.0.0" + "node": ">=18" } }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=10.13.0" + "node": ">=18" } }, "node_modules/which": { @@ -5221,7 +5175,6 @@ "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -5232,19 +5185,11 @@ "node": ">= 8" } }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true, - "license": "MIT" - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5253,22 +5198,168 @@ "version": "6.5.1", "resolved": "https://registry.npmmirror.com/workerpool/-/workerpool-6.5.1.tgz", "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "Apache-2.0" + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "dev": true, - "license": "ISC" + "engines": { + "node": ">=4.0" + } }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } @@ -5277,15 +5368,40 @@ "version": "4.0.0", "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "ISC" + "engines": { + "node": ">=12" + } }, "node_modules/yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, - "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -5296,12 +5412,50 @@ "node": ">=10" } }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmmirror.com/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 338be832..e2cd5f78 100644 --- a/package.json +++ b/package.json @@ -1,111 +1,666 @@ { "name": "vscode-autohotkey2-lsp", "displayName": "AutoHotkey v2 Language Support", - "version": "2.5.2", - "description": "AutoHotkey v2 language support, forked from thqby's extension", + "description": "AutoHotkey v2 Language Support, based on vscode-lsp.", + "author": "thqby", + "publisher": "thqby", + "version": "2.5.3", + "license": "LGPLv3.0", "categories": [ - "Debuggers", "Formatters", "Programming Languages", "Snippets" ], "keywords": [ - "vscode", - "autohotkey", "ahk", "ahk2", - "ahk v2" + "autohotkey", + "autohotkey2" ], - "homepage": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp/blob/main/README.md", - "bugs": { - "url": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp/issues" - }, "repository": { "type": "git", - "url": "https://github.com/mark-wiemer-org/vscode-autohotkey2-lsp" + "url": "https://github.com/thqby/vscode-autohotkey2-lsp" }, - "license": "LGPLv3.0", - "author": "thqby and Mark Wiemer", - "publisher": "mark-wiemer", - "main": "./client/dist/extension", - "scripts": { - "prebuild": "npm run clean:dist", - "build": "node build.mjs --mode=production", - "prebuild:dev": "npm run clean", - "build:dev": "node build.mjs", - "build:old": "webpack", - "clean:dist": "del-cli client/dist server/dist/*.js*", - "clean:out": "del-cli client/out server/out", - "compile-cli": "webpack --config webpack.config.cli.js --mode production --devtool hidden-source-map", - "precompile-ts": "npm run clean:out", - "compile-ts": "tsc -b", - "compile-ts//": "Compile TS files", - "compile//": "Compile the extension for packaging and publishing", - "eslint": "npm run eslint:files -- client server && echo No ESLint problems", - "eslint:files": "eslint --max-warnings=0", - "eslint:fix": "npm run eslint:files -- client server --fix", - "format": "prettier --check .", - "format:fix": "prettier --write .", - "lint": "npm run format && npm run eslint && npm run sort-package-json", - "lint:fix": "npm run format:fix && npm run eslint:fix && npm run sort-package-json:fix", - "sort-package-json": "sort-package-json --check", - "sort-package-json:fix": "sort-package-json", - "pretest-unit": "npm run compile-ts", - "test-unit": "mocha", - "validate": "npm run lint && npm run test-unit", - "validate:ci": "npm run lint && npm run test-unit", - "validate:ci:fix": "npm run lint:fix && npm run test-unit", - "validate:fix": "npm run lint:fix && npm run test-unit", - "watch": "tsc -b -w" + "homepage": "https://github.com/thqby/vscode-autohotkey2-lsp/blob/main/README.md", + "icon": "icon.png", + "bugs": { + "url": "https://github.com/thqby/vscode-autohotkey2-lsp/issues" }, - "prettier": { - "singleQuote": true, - "tabWidth": 4, - "trailingComma": "all", - "useTabs": true, - "overrides": [ - { - "files": [ - "*.yml", - "*.yaml" + "engines": { + "vscode": "^1.82.0" + }, + "main": "./client/dist/extension", + "browser": "./client/dist/browserClientMain", + "contributes": { + "breakpoints": [ + { + "language": "ahk2" + } + ], + "languages": [ + { + "id": "ahk2", + "aliases": [ + "AutoHotkey2", + "autohotkey2", + "ahk2" ], - "options": { - "tabWidth": 2 + "extensions": [ + ".ahk", + ".ah2", + ".ahk2" + ], + "configuration": "./ahk2.configuration.json", + "icon": { + "dark": "icon_filetype.png", + "light": "icon_filetype.png" + } + }, + { + "id": "ahk", + "aliases": [ + "AutoHotkey" + ] + }, + { + "id": "~ahk2-output" + } + ], + "grammars": [ + { + "language": "ahk2", + "scopeName": "source.ahk2", + "path": "./syntaxes/ahk2.tmLanguage.json", + "embeddedLanguages": { + "meta.embedded.ahk2": "ahk2" + }, + "unbalancedBracketScopes": [ + "keyword.keys.ahk2" + ] + }, + { + "language": "~ahk2-output", + "scopeName": "ahk2.output", + "path": "./syntaxes/ahk2-output.tmLanguage.json" + } + ], + "configuration": { + "title": "AutoHotkey2", + "properties": { + "AutoHotkey2.AutoLibInclude": { + "scope": "window", + "type": "string", + "enum": [ + "Disabled", + "Local", + "User and Standard", + "All" + ], + "default": "Disabled", + "description": "%ahk2.autolibinclude%" + }, + "AutoHotkey2.CommentTags": { + "scope": "window", + "type": "string", + "default": "^;;\\s*(?.+)", + "description": "%ahk2.commenttags%" + }, + "AutoHotkey2.CompilerCMD": { + "scope": "window", + "type": "string", + "default": "/compress 0 /base ${execPath}", + "markdownDescription": "%ahk2.compilercmd%" + }, + "AutoHotkey2.CompleteFunctionParens": { + "scope": "window", + "type": "boolean", + "default": false, + "markdownDescription": "%ahk2.completefunctionparens%" + }, + "AutoHotkey2.DebugConfiguration": { + "scope": "window", + "type": "object", + "default": { + "port": "9002-9100", + "useAnnounce": "detail", + "useAutoJumpToError": true, + "useDebugDirective": true, + "usePerfTips": true + }, + "description": "%ahk2.debugconfiguration%" + }, + "AutoHotkey2.Diagnostics.ClassNonDynamicMemberCheck": { + "scope": "window", + "type": "boolean", + "default": true, + "description": "%ahk2.diagnostics.class-non-dynamic-member-check%" + }, + "AutoHotkey2.Diagnostics.ParamsCheck": { + "scope": "window", + "type": "boolean", + "default": true, + "description": "%ahk2.diagnostics.paramscheck%" + }, + "AutoHotkey2.Warn.VarUnset": { + "scope": "window", + "type": "boolean", + "default": true, + "description": "%ahk2.warn.varunset%" + }, + "AutoHotkey2.Warn.LocalSameAsGlobal": { + "scope": "window", + "type": "boolean", + "default": false, + "description": "%ahk2.warn.localsameasglobal%" + }, + "AutoHotkey2.Warn.CallWithoutParentheses": { + "scope": "window", + "type": "string", + "enum": [ + "Off", + "Parentheses", + "On" + ], + "default": "Off", + "description": "%ahk2.warn.callwithoutparentheses%" + }, + "AutoHotkey2.ActionWhenV1IsDetected": { + "scope": "window", + "type": "string", + "default": "Warn", + "enum": [ + "Continue", + "Warn", + "StopParsing", + "SwitchToV1", + "SkipLine" + ], + "description": "%ahk2.actionwhenv1isdetected%" + }, + "AutoHotkey2.CompletionCommitCharacters": { + "scope": "window", + "type": "object", + "properties": { + "Class": { + "type": "string" + }, + "Function": { + "type": "string" + } + }, + "additionalProperties": { + "type": "string" + }, + "default": { + "Class": ".(", + "Function": "(" + }, + "markdownDescription": "%ahk2.completioncommitcharacters%" + }, + "AutoHotkey2.Files.Exclude": { + "scope": "window", + "type": "array", + "default": [], + "items": { + "type": "string" + }, + "uniqueItems": true, + "description": "%ahk2.files.exclude%" + }, + "AutoHotkey2.Files.ScanMaxDepth": { + "scope": "window", + "type": "integer", + "default": 2, + "description": "%ahk2.files.scanmaxdepth%" + }, + "AutoHotkey2.FormatOptions": { + "scope": "window", + "type": "object", + "properties": { + "array_style": { + "type": "string", + "enum": [ + "collapse", + "expand", + "none" + ], + "default": "none" + }, + "brace_style": { + "type": "string", + "enum": [ + "One True Brace", + "Allman", + "One True Brace Variant" + ], + "enumDescriptions": [ + "if 1 {\n} else {\n}", + "if 1\n{\n}\nelse\n{\n}", + "if 1 {\n}\nelse {\n}" + ] + }, + "break_chained_methods": { + "type": "boolean", + "default": false + }, + "ignore_comment": { + "type": "boolean", + "default": false + }, + "indent_string": { + "type": "string", + "default": "\t" + }, + "indent_between_hotif_directive": { + "type": "boolean", + "default": false + }, + "keyword_start_with_uppercase": { + "type": "boolean", + "default": false + }, + "max_preserve_newlines": { + "type": "number", + "default": 2 + }, + "object_style": { + "type": "string", + "enum": [ + "collapse", + "expand", + "none" + ], + "default": "none" + }, + "preserve_newlines": { + "type": "boolean", + "default": true + }, + "space_before_conditional": { + "type": "boolean", + "default": true + }, + "space_after_double_colon": { + "type": "boolean", + "default": true + }, + "space_in_empty_paren": { + "type": "boolean", + "default": false + }, + "space_in_other": { + "type": "boolean", + "default": true + }, + "space_in_paren": { + "type": "boolean", + "default": false + }, + "switch_case_alignment": { + "type": "boolean", + "default": false + }, + "symbol_with_same_case": { + "type": "boolean", + "default": false + }, + "white_space_before_inline_comment": { + "type": "string" + }, + "wrap_line_length": { + "type": "number", + "default": 0 + } + }, + "additionalProperties": { + "type": "string" + }, + "default": {} + }, + "AutoHotkey2.InterpreterPath": { + "scope": "window", + "type": "string", + "default": "C:\\Program Files\\Autohotkey\\v2\\AutoHotkey.exe", + "markdownDescription": "%ahk2.interpreterpath%" + }, + "AutoHotkey2.SymbolFoldingFromOpenBrace": { + "scope": "window", + "type": "boolean", + "default": false, + "description": "%ahk2.symbolfoldingfromopenbrace%" + }, + "AutoHotkey2.WorkingDirs": { + "scope": "window", + "type": "array", + "default": [], + "items": { + "type": "string" + }, + "uniqueItems": true, + "description": "%ahk2.workingdirs%" + }, + "AutoHotkey2.Syntaxes": { + "scope": "window", + "type": "string", + "markdownDescription": "%ahk2.syntaxes%" + } + } + }, + "configurationDefaults": { + "[ahk2]": { + "editor.defaultFormatter": "thqby.vscode-autohotkey2-lsp", + "editor.quickSuggestions": { + "other": true, + "comments": false, + "strings": true + } + } + }, + "commands": [ + { + "enablement": "editorLangId == ahk2 && shellExecutionSupported", + "command": "ahk2.debug.file", + "title": "%ahk2.debug.file%", + "icon": "$(debug)", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && shellExecutionSupported", + "command": "ahk2.debug.configs", + "title": "%ahk2.debug.configs%", + "icon": "$(debug-all)", + "category": "ahk2" + }, + { + "enablement": "shellExecutionSupported", + "command": "ahk2.debug.attach", + "title": "%ahk2.debug.attach%", + "icon": "$(debug-alt)", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && shellExecutionSupported", + "command": "ahk2.debug.params", + "title": "%ahk2.debug.params%", + "icon": "$(debug-console)", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2", + "command": "ahk2.diagnose.all", + "title": "%ahk2.diagnose.all%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2", + "command": "ahk2.extract.symbols", + "title": "%ahk2.extract.symbols%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && shellExecutionSupported", + "command": "ahk2.run", + "title": "%ahk2.run%", + "icon": "$(play)", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.run.selection", + "title": "%ahk2.run.selection%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.stop", + "title": "%ahk2.stop%", + "icon": "$(stop)", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && shellExecutionSupported", + "command": "ahk2.compile", + "title": "%ahk2.compile%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.help", + "title": "%ahk2.help%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2", + "command": "ahk2.generate.comment", + "title": "%ahk2.generate.comment%", + "category": "ahk2" + }, + { + "enablement": "!isWeb", + "command": "ahk2.set.interpreter", + "title": "%ahk2.set.interpreter%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2", + "command": "ahk2.update.versioninfo", + "title": "%ahk2.update.versioninfo%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 || editorLangId == ahk", + "command": "ahk2.switch", + "title": "Switch v1/v2", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.select.syntaxes", + "title": "%ahk2.select.syntaxes%", + "category": "ahk2" + }, + { + "enablement": "editorLangId == ahk2 && resourceScheme == file", + "command": "ahk2.set.scriptdir", + "title": "%ahk2.set.scriptdir%", + "category": "ahk2" + } + ], + "menus": { + "editor/context": [ + { + "submenu": "ahk2.context", + "group": "navigation@0" + } + ], + "editor/title/run": [ + { + "command": "ahk2.run", + "group": "navigation@0", + "when": "resourceLangId == ahk2 && shellExecutionSupported" + }, + { + "command": "ahk2.stop", + "group": "navigation@1", + "when": "resourceLangId == ahk2 && ahk2:isRunning && shellExecutionSupported" + }, + { + "command": "ahk2.debug.file", + "group": "navigation@2", + "when": "resourceLangId == ahk2 && shellExecutionSupported" + }, + { + "command": "ahk2.debug.configs", + "group": "navigation@3", + "when": "resourceLangId == ahk2 && shellExecutionSupported" + }, + { + "command": "ahk2.debug.params", + "group": "navigation@4", + "when": "resourceLangId == ahk2 && shellExecutionSupported" + }, + { + "command": "ahk2.debug.attach", + "group": "navigation@5", + "when": "resourceLangId == ahk2 && shellExecutionSupported" + } + ], + "ahk2.context": [ + { + "when": "editorLangId == ahk2 && !isWeb && editorHasSelection", + "command": "ahk2.run.selection", + "group": "navigation@0" + }, + { + "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection", + "command": "ahk2.run", + "group": "navigation@0" + }, + { + "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning", + "command": "ahk2.stop", + "group": "navigation@1" + }, + { + "command": "ahk2.debug.file", + "when": "resourceLangId == ahk2 && shellExecutionSupported", + "group": "navigation@2" + }, + { + "command": "ahk2.debug.configs", + "when": "resourceLangId == ahk2 && shellExecutionSupported", + "group": "navigation@3" + }, + { + "command": "ahk2.debug.params", + "when": "resourceLangId == ahk2 && shellExecutionSupported", + "group": "navigation@4" + }, + { + "command": "ahk2.debug.attach", + "when": "resourceLangId == ahk2 && shellExecutionSupported", + "group": "navigation@5" + }, + { + "when": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.help", + "group": "other@0" + }, + { + "when": "editorLangId == ahk2 && !isWeb", + "command": "ahk2.compile", + "group": "other@1" + }, + { + "when": "editorLangId == ahk2", + "command": "ahk2.generate.comment", + "group": "other@2" + }, + { + "when": "editorLangId == ahk2", + "command": "ahk2.update.versioninfo", + "group": "other@3" + }, + { + "when": "editorLangId == ahk2", + "command": "ahk2.diagnose.all", + "group": "other@4" + }, + { + "when": "editorLangId == ahk2", + "command": "ahk2.extract.symbols", + "group": "other@5" + }, + { + "when": "editorLangId == ahk2 && resourceScheme == file", + "command": "ahk2.set.scriptdir", + "group": "other@6" + } + ] + }, + "submenus": [ + { + "id": "ahk2.context", + "label": "AutoHotkey v2" + } + ], + "keybindings": [ + { + "command": "ahk2.run", + "key": "ctrl+f5", + "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection" + }, + { + "command": "ahk2.run.selection", + "key": "ctrl+f5", + "when": "editorLangId == ahk2 && !isWeb && editorHasSelection" + }, + { + "command": "ahk2.compile", + "key": "ctrl+shift+f5", + "when": "editorLangId == ahk2 && !isWeb" + }, + { + "command": "ahk2.debug.file", + "key": "f5", + "when": "editorLangId == ahk2 && debuggersAvailable && debugState == 'inactive'" + }, + { + "command": "ahk2.debug.params", + "key": "shift+f5", + "when": "editorLangId == ahk2 && debuggersAvailable && debugState == 'inactive'" + }, + { + "command": "ahk2.help", + "key": "ctrl+f1", + "when": "editorLangId == ahk2 && !isWeb" + }, + { + "command": "ahk2.stop", + "key": "ctrl+f6", + "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning" + } + ], + "semanticTokenScopes": [ + { + "language": "ahk2", + "scopes": { + "operator": [ + "keyword.operator.wordlike.ahk2" + ] } } ] }, - "mocha": { - "spec": "./**/out/**/*.test.js" + "scripts": { + "check-types": "tsc", + "build-cli": "node esbuild.mjs --cli", + "eslint": "eslint --fix", + "package": "vsce package", + "publish": "vsce publish", + "test": "vscode-test", + "test-grammar": "vscode-tmgrammar-snap tmgrammar-test/*.ahk", + "vscode:prepublish": "node esbuild.mjs && npm run test && npm run test-grammar", + "watch": "node esbuild.mjs --dev", + "watch-web": "node esbuild.mjs --web" + }, + "devDependencies": { + "@types/node": "^20.14.0", + "@types/vscode": "1.93.0", + "@vscode/test-cli": "^0.0.10", + "@vscode/test-electron": "^2.4.1", + "@vscode/vsce": "^2.32.0", + "esbuild": "^0.24.0", + "eslint": "^9.11.0", + "typescript": "5.5.4", + "typescript-eslint": "^8.7.0", + "vscode-tmgrammar-test": "^0.1.3" }, "dependencies": { + "path-browserify": "^1.0.1", "vscode-languageclient": "^9.0.1", "vscode-languageserver": "^9.0.1", - "vscode-languageserver-textdocument": "^1.0.11", + "vscode-languageserver-textdocument": "^1.0.12", "vscode-uri": "^3.0.8" - }, - "devDependencies": { - "@eslint/js": "^9.4.0", - "@types/mocha": "^10.0.8", - "@types/node": "^20.16.0", - "@types/vscode": "^1.82.0", - "del-cli": "^5.1.0", - "esbuild": "^0.23.1", - "eslint": "^9.4.0", - "globals": "^15.4.0", - "mocha": "^10.7.0", - "prettier": "3.3.3", - "sort-package-json": "^2.10.0", - "ts-loader": "^9.4.0", - "typescript": "^5.3.2", - "typescript-eslint": "^7.12.0", - "webpack": "^5.74.0", - "webpack-cli": "^4.10.0" - }, - "engines": { - "vscode": "^1.82.0" - }, - "overrides": { - "eslint": "^9.4.0" } -} +} \ No newline at end of file diff --git a/package.nls.json b/package.nls.json new file mode 100644 index 00000000..f82ad6af --- /dev/null +++ b/package.nls.json @@ -0,0 +1,37 @@ +{ + "ahk2.actionwhenv1isdetected": "Action when v1 script is detected", + "ahk2.autolibinclude": "Provide completion and automatic include from User and Standard library, Local library", + "ahk2.commenttags": "A regular expression used to extract named tags from comments and generate module symbols", + "ahk2.compile": "Compile Script", + "ahk2.compilercmd": "Compiler command line options. If ahk2exe.exe is not specified, the default path will be used. `${execPath}` is equal to the currently selected AutoHotkey.exe", + "ahk2.completefunctionparens": "Parentheses are added to function completion when there is no `(` or `[` on the right; otherwise move the cursor to the right", + "ahk2.completioncommitcharacters": "Characters which commit auto completion, such as `.(`", + "ahk2.debug.attach": "Attach to ahk process", + "ahk2.debug.configs": "Debug ahk File using launch.json", + "ahk2.debug.file": "Debug ahk File", + "ahk2.debug.params": "Debug ahk File with Params", + "ahk2.debugconfiguration": "Append debugging configuration to the currently started debugger, same as launch.json configuration", + "ahk2.description": "Autohotkey2 Language Support using vscode-lsp", + "ahk2.diagnose.all": "Diagnostic All", + "ahk2.diagnostics.class-non-dynamic-member-check": "Check whether non-dynamic members of class exist", + "ahk2.diagnostics.paramscheck": "Check that the function call has the correct number of arguments", + "ahk2.warn.varunset": "Display warnings for each variable that has never been directly assigned or used with the reference operator", + "ahk2.warn.localsameasglobal": "Display warnings for each undeclared local variable which has the same name as a global variable", + "ahk2.warn.callwithoutparentheses": "Display warnings for each function or method call without parentheses", + "ahk2.extract.symbols": "Extract Symbol Information", + "ahk2.files.exclude": "Configure glob patterns for excluding files and folders when scanning ahk files.", + "ahk2.files.scanmaxdepth": "Controls the depth when scanning ahk files.", + "ahk2.generate.comment": "Generate Comment Template", + "ahk2.help": "Quick Help", + "ahk2.interpreterpath": "The path of the `AutoHotkey.exe` executable file. If `AutoHotkeyUX.exe` is selected, the script will be launched using UX Launcher.", + "ahk2.run": "Run ahk File", + "ahk2.run.selection": "Run Selected Script", + "ahk2.select.syntaxes": "Select Language Definition Folder", + "ahk2.set.interpreter": "Select AutoHotkey2 Interpreter", + "ahk2.set.scriptdir": "Set Here as A_ScriptDir", + "ahk2.stop": "Stop Running Script", + "ahk2.symbolfoldingfromopenbrace": "Forced symbol folding starts at open brace", + "ahk2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", + "ahk2.update.versioninfo": "Update File Version Info", + "ahk2.workingdirs": "Sets the working directory for the script" +} \ No newline at end of file diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json new file mode 100644 index 00000000..ed30b04f --- /dev/null +++ b/package.nls.zh-cn.json @@ -0,0 +1,127 @@ +{ + "ahk2.actionwhenv1isdetected": "检测到v1脚本时的行为", + "ahk2.autolibinclude": "对用户库和标准库, 本地库提供补全和自动include", + "ahk2.browse": "浏览文件系统来选择一个 AutoHotkey2 解释器", + "ahk2.commenttags": "用来从注释中提取命名标记的正则表达式, 并生成模块符号", + "ahk2.compile": "编译脚本", + "ahk2.compiledfailed": "编译失败!", + "ahk2.compiledsuccessfully": "编译成功!", + "ahk2.compilercmd": "编译器命令行选项. 如果未指定ahk2exe.exe, 将使用默认路径. `${execPath}`等价于当前选择的AutoHotkey.exe", + "ahk2.completefunctionparens": "当右侧不存在`(`或`[`时, 给函数补全添加括号; 否则向右移动光标", + "ahk2.completioncommitcharacters": "提交自动完成的字符, 例如`.(`", + "ahk2.current": "当前: {0}", + "ahk2.debug.attach": "附加到ahk进程", + "ahk2.debug.configs": "使用launch.json调试ahk文件", + "ahk2.debug.file": "调试ahk文件", + "ahk2.debug.params": "带参数调试", + "ahk2.debugconfiguration": "追加调试配置到当前启动的调试器, 与launch.json配置相同", + "ahk2.debugextnotexist": "未找到debug扩展, 请先安装debug扩展!", + "ahk2.description": "基于 vscode-lsp 协议的 Autohotkey2 语言支持", + "ahk2.diagnose.all": "诊断全部", + "ahk2.diagnostics.class-non-dynamic-member-check": "检查类非动态成员是否存在", + "ahk2.diagnostics.paramscheck": "检查函数调用参数个数是否正确", + "ahk2.enterahkpath": "请输入 AutoHotkey2 解释器的路径", + "ahk2.entercmd": "输入需要传递的命令行参数", + "ahk2.enterorfind": "输入路径或选择一个现有的解释器", + "ahk2.enterversion": "输入版本号", + "ahk2.filenotexist": "'{0}'文件不存在", + "ahk2.files.exclude": "配置 glob 模式以在扫描ahk文件时排除文件和文件夹.", + "ahk2.files.scanmaxdepth": "控制扫描ahk文件时的深度.", + "ahk2.find": "浏览...", + "ahk2.generate.comment": "生成注释模板", + "ahk2.help": "快捷帮助", + "ahk2.interpreterpath": "`AutoHotkey.exe`可执行文件的路径. 如果选择`AutoHotkeyUX.exe`, 将使用UX Launcher启动脚本.", + "ahk2.extract.symbols": "提取符号信息", + "ahk2.run": "运行ahk文件", + "ahk2.run.selection": "运行选择的脚本", + "ahk2.savebeforecompilation": "编译前请先保存脚本", + "ahk2.select": "选择", + "ahk2.select.syntaxes": "选择语言定义文件夹", + "ahk2.set.interpreter": "选择AutoHotkey2解释器", + "ahk2.set.scriptdir": "设置此处为A_ScriptDir", + "ahk2.stop": "停止运行中的脚本", + "ahk2.symbolfoldingfromopenbrace": "强制符号折叠从大括号处开始", + "ahk2.syntaxes": "指定用于智能感知的`ahk2.json`, `*.snippet.json`和`ahk2.d.ahk`文件的文件夹路径.", + "ahk2.unknownversion": "未知版本", + "ahk2.update.versioninfo": "更新文件版本信息", + "ahk2.warn.callwithoutparentheses": "为每个不带括号的函数或方法调用显示警告", + "ahk2.warn.localsameasglobal": "为每个与全局变量同名的未声明的局部变量显示警告", + "ahk2.warn.varunset": "为每个从未直接赋值或与引用操作符一起使用的变量的显示警告", + "ahk2.workingdirs": "设置脚本的工作目录", + "action.skipline": "跳过行", + "action.stopparsing": "停止解析", + "action.switchtov1": "切换到ahk v1", + "codeaction.include": "导入 '{0}'", + "completionitem.author": "添加作者, 描述, 日期, 版本等文件信息.", + "completionitem.generatecomment": "生成当前作用域函数/方法的注释模板.", + "completionitem.include": "从'{0}'自动导入", + "completionitem.new": "构造类的新实例.", + "completionitem.prototype": "检索或设置类的所有实例所基于的对象.", + "completionitem.super": "在继承类中, super 可以代替 this 来访问在派生类中被重写的方法或属性的超类版本.", + "completionitem.this": "在类中, 通过 this 访问该类的其他实例变量和方法.", + "completionitem.thishotkey": "热键函数的隐藏参数.", + "completionitem.value": "在动态属性 set 中, Value 包含被分配的值.", + "diagnostic.acceptparams": "'{0}' 接受{1}个参数", + "diagnostic.assignerr": "{0} '{1}'不能用作输出变量", + "diagnostic.classinfuncerr": "函数不能包含类", + "diagnostic.classuseerr": "类不能用作输出变量", + "diagnostic.conflictserr": "{0} '{2}'声明和已存在的{1}冲突", + "diagnostic.declarationerr": "意外的声明", + "diagnostic.defaultvalmissing": "'{0}' 需要参数默认值", + "diagnostic.deprecated": "使用'{0}'而不是'{1}'", + "diagnostic.didyoumean": "你是想用'{0}'吗?", + "diagnostic.dupdeclaration": "重复声明", + "diagnostic.duplabel": "重复的标签声明", + "diagnostic.filenotexist": "'{0}'文件不存在", + "diagnostic.funccallerr": "函数调用需要空格或'(', 仅在参数之间使用逗号", + "diagnostic.funccallerr2": "在表达式中, 函数调用需要括号", + "diagnostic.hotdeferr": "热键/热字串不能在函数/类中定义", + "diagnostic.hotmissbrace": "热键或热字符串缺少左括号", + "diagnostic.invaliddefinition": "无效的{0}定义", + "diagnostic.invalidencoding": "'{0}' 无效的文件编码", + "diagnostic.invalidhotdef": "无效的热键定义", + "diagnostic.invalidparam": "无效的参数定义", + "diagnostic.invalidprop": "不是有效的getter/setter属性", + "diagnostic.invalidpropname": "对象字面量中的属性名无效", + "diagnostic.invalidsymbolname": "无效的符号命名 '{0}'", + "diagnostic.invalidscope": "'{0}'不能在函数/类中使用", + "diagnostic.invalidsuper": "'super'仅在类内部有效", + "diagnostic.maybehavenotmember": "类'{0}'可能没有成员'{1}'", + "diagnostic.maybev1": "这可能是一个v1脚本, lexer停止解析.", + "diagnostic.missing": "丢失对应的 '{0}'", + "diagnostic.missingparam": "缺少必需的参数", + "diagnostic.missingoperand": "缺少操作数", + "diagnostic.missingretval": "函数缺少返回值", + "diagnostic.missingspace": "前面缺少空格或运算符", + "diagnostic.objectliteralerr": "对象字面量存在错误", + "diagnostic.outofloop": "Break/Continue必须被循环包围", + "diagnostic.paramcounterr": "应有 {0} 个参数, 但获得 {1} 个", + "diagnostic.pathinvalid": "无效的文件路径", + "diagnostic.propdeclaraerr": "不是有效的方法, 类或属性定义", + "diagnostic.propemptyparams": "动态属性不允许使用空[]", + "diagnostic.propnotinit": "属性声明未初始化", + "diagnostic.requirev1": "此脚本需要AutoHotkey v1, lexer停止解析.", + "diagnostic.requirevariable": "'&'需要一个变量", + "diagnostic.requireversion": "该特性需要AutoHotkey版本 >= v{0}", + "diagnostic.reservedworderr": "保留字'{0}'不得用作变量名", + "diagnostic.resourcenotfound": "未找到或无法解析资源", + "diagnostic.skipline": "该行被跳过且未解析", + "diagnostic.syntaxerror": "语法错误. 具体为: {0}", + "diagnostic.tryswitchtov1": "尝试切换到AutoHotkey v1.", + "diagnostic.typemaybenot": "类型可能不是 '{0}'", + "diagnostic.unexpected": "意外的'{0}'", + "diagnostic.unknown": "未知的{0}", + "diagnostic.unknownoperatoruse": "未知的操作符使用", + "diagnostic.unknowntoken": "未知的Token '{0}'", + "diagnostic.unsupportinclude": "函数、类中的#include无法正确地推导作用域和代码补全", + "diagnostic.unterminated": "未终止的字符串文本", + "warn.varisunset": "变量'{0}'似乎从未被赋值", + "warn.localsameasglobal": "局部变量'{0}'与全局变量具有相同的名称", + "warn.callwithoutparentheses": "函数或方法调用没有使用括号", + "response.cannotrename": "无法重命名此元素。", + "response.cannotrenamestdlib": "不能重命名标准AutoHotkey库中定义的元素。", + "setting.ahkpatherr": "AutoHotkey解释器不存在, 在'设置-AutoHotkey2.InterpreterPath'中重新指定", + "setting.getenverr": "获取环境变量失败", + "setting.uialimit": "由于安全限制, UIA可执行文件不允许重定向stdin/stdout, 因此依赖于此的一些功能将无法工作", + "setting.versionerr": "当前AutoHotkey.exe不是v2版本, 无法获得正确的语法解析、补全等功能" +} \ No newline at end of file diff --git a/server/cli/cli.ts b/server/cli/cli.ts new file mode 100644 index 00000000..05dd3b9a --- /dev/null +++ b/server/cli/cli.ts @@ -0,0 +1,25 @@ +import { openFile } from '../src/common'; +import { Lexer } from '../src/Lexer'; + +function main() { + const options: Record = {}; + process.argv.slice(2).forEach(s => { + const arr = s.split('='); + options[arr[0]] = arr[1]; + }); + let path: string = options.path ?? ''; + path = path.replace(/^(['"])(.*)\1$/, '$2'); + if (!path) + return; + try { + const td = openFile(path, false); + if (!td) + return; + const sc = new Lexer(td).beautify({}); + console.log(sc); + } catch (e) { + console.error(e); + } +} + +main() \ No newline at end of file diff --git a/server/package-lock.json b/server/package-lock.json deleted file mode 100644 index 83b084e0..00000000 --- a/server/package-lock.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "vscode-autohotkey2-server", - "lockfileVersion": 1 -} diff --git a/server/package.json b/server/package.json index 403a1a88..8d224825 100644 --- a/server/package.json +++ b/server/package.json @@ -1,9 +1,7 @@ { - "name": "vscode-autohotkey2-server", - "description": "Autohotkey2 Language Server using vscode-lsp.", - "license": "LGPLv3.0", - "engines": { - "node": "*" - }, - "dependencies": {} -} + "browser": { + "child_process": false, + "fs": false, + "path": "path-browserify" + } +} \ No newline at end of file diff --git a/server/src/Lexer.ts b/server/src/Lexer.ts index c0d1b59a..a510b3f7 100644 --- a/server/src/Lexer.ts +++ b/server/src/Lexer.ts @@ -22,7 +22,7 @@ import { builtin_ahkv1_commands, builtin_variable, builtin_variable_h } from './ import { action, completionitem, diagnostic, warn } from './localize'; import { a_vars, ahk_version, ahkuris, ahkvars, alpha_3, connection, ahkppConfig, - hoverCache, isBrowser, isahk2_h, lexers, libdirs, libfuncs, locale, openAndParse, openFile, + hoverCache, isahk2_h, lexers, libdirs, libfuncs, locale, openAndParse, openFile, restorePath, rootdir, setTextDocumentLanguage, symbolProvider, utils, workspaceFolders } from './common'; import { newFormatterConfig, FormatterConfig, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses, getCfg, CfgKey } from './config'; @@ -268,7 +268,7 @@ const MODE = { BlockStatement: 'BlockStatement', Statement: 'Statement', ObjectL const KEYS_RE = /^(alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab|shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton1|xbutton2|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\d]{1,2}(sc[a-f\d]+)?|sc[a-f\d]+|`[;{]|[\x21-\x7E])$/i; const EMPTY_TOKEN: Token = { type: '', content: '', offset: 0, length: 0, topofline: 0, next_token_offset: -1 }; export const ASSIGN_TYPE = [':=', '??=']; -const STYLE = { collapse: 2, expand: 1, none: 0 }; +const OBJECT_STYLE = { collapse: 2, expand: 1, none: 0 }; const ZERO_RANGE = { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } }; const META_FUNCNAME = ['__NEW', '__INIT', '__ITEM', '__ENUM', '__GET', '__CALL', '__SET', '__DELETE']; export const ANY = create_prototype('Any'); @@ -321,7 +321,7 @@ class ParseStopError { } export class Lexer { - public actionWhenV1Detected: ActionType = getCfg(newAhkppConfig(), CfgKey.ActionWhenV1Detected); + public actionWhenV1Detected?: ActionType = getCfg(newAhkppConfig(), CfgKey.ActionWhenV1Detected); public actived = false; public beautify: (options: FormatterConfig, range?: Range) => string; public checkmember: boolean | undefined; @@ -1136,6 +1136,8 @@ export class Lexer { } } else { const d_path = this.fsPath.replace(/\.\w+$/, '.d.ahk'); + if (!this.fsPath.endsWith('2')) + delete this.actionWhenV1Detected; this.parseScript = function (): void { input = this.document.getText(), input_length = input.length, includedir = this.scriptpath, dlldir = ''; begin_line = true, requirev2 = false, maybev1 = 0, lst = { ...EMPTY_TOKEN }, currsymbol = last_comment_fr = undefined; @@ -1153,7 +1155,7 @@ export class Lexer { } else console.error(e); } - if (!isBrowser) { + if (!process.env.BROWSER) { const m = _this.d_uri && find_d_ahk(resolve_scriptdir(_this.d_uri)) || find_d_ahk(d_path); if (m) includetable[_this.d_uri = m.uri] = m.path; @@ -2543,6 +2545,8 @@ export class Lexer { if (bak.type === 'TK_DOT') { addprop(lk); } else if ((vr = addvariable(lk, mode, sta))) { + if (mode === 2 && local) + lk.semantic!.modifier = SemanticTokenModifiers.static; if ((pc = comments[vr.selectionRange.start.line])) set_detail(vr, pc); } else if (local) @@ -2561,7 +2565,8 @@ export class Lexer { if (mode === 2) { let llk = lk, ttk = tk, err = diagnostic.propnotinit(), dots = 0; const v = addvariable(lk, 2, sta)!; - v.def = false; + if (v.def = false, local) + lk.semantic!.modifier = SemanticTokenModifiers.static; if (tk.type as string === 'TK_DOT') { while (nexttoken() && tk.type === 'TK_WORD') { if (!nexttoken()) @@ -4032,7 +4037,7 @@ export class Lexer { if (!m.endsWith('.ahk')) m += '.d.ahk'; if (m.startsWith('~/')) - u = isBrowser ? URI.parse(rootdir + m.slice(1)) : URI.file(rootdir + m.slice(1)); + u = process.env.BROWSER ? URI.parse(rootdir + m.slice(1)) : URI.file(rootdir + m.slice(1)); else if (/^([a-z]:)?\//.test(m)) u = URI.file(m); else if (!m.includes(':')) { @@ -4075,7 +4080,7 @@ export class Lexer { dlldir = ''; else if (tk) _this.addDiagnostic(diagnostic.pathinvalid(), tk.offset, tk.length); - } else if (!isBrowser) { + } else if (!process.env.BROWSER) { if (isdll) { if (existsSync(m) && statSync(m).isDirectory()) dlldir = m.endsWith('/') || m.endsWith('\\') ? m : m + '\\'; @@ -5397,7 +5402,9 @@ export class Lexer { set_mode(next_mode); flags.last_word = ''; - flags.indentation_level = real_indentation_level(); + previous_flags.indentation_level = Math.min( + previous_flags.indentation_level, + flags.indentation_level = real_indentation_level()) print_token(); // (options\n...\n) @@ -5411,7 +5418,7 @@ export class Lexer { // In all cases, if we newline while inside an expression it should be indented. indent(); - if (token_text === '[' && (flags.arrayStyle ?? opt.arrayStyle) === STYLE.expand) + if (token_text === '[' && (flags.arrayStyle ?? opt.arrayStyle) === OBJECT_STYLE.expand) print_newline(true); } @@ -5421,25 +5428,21 @@ export class Lexer { while (flags.mode === MODE.Statement) restore_mode(); - if (token_text === ']' && flags.mode === MODE.ArrayLiteral) { + const is_array = token_text === ']' && flags.mode === MODE.ArrayLiteral; + restore_mode(); + if (is_array) { const style = flags.arrayStyle ?? opt.arrayStyle; - if (style === STYLE.collapse || last_text === '[') + if (style === OBJECT_STYLE.collapse || last_text === '[' || flags.indentation_level >= previous_flags.indentation_level) trim_newlines(); else if (style || input_wanted_newline && opt.preserveNewlines) print_newline(true); - } else if ((last_type === 'TK_END_EXPR' || last_type === 'TK_END_BLOCK') && flags.indentation_level < flags.parent.indentation_level) + } else if ((last_type === 'TK_END_EXPR' || last_type === 'TK_END_BLOCK') && flags.indentation_level >= previous_flags.indentation_level) trim_newlines(); else if (last_type !== 'TK_START_EXPR') allow_wrap_or_preserved_newline(); output_space_before_token = Boolean(opt.spaceInParen && !(last_type === 'TK_START_EXPR' && !opt.spaceInEmptyParen)); - restore_mode(); - if (just_added_newline() && output_lines.length > 1) { - const level = flags.indentation_level; - flags.indentation_level = real_indentation_level(previous_flags.start_line_index); - print_token(); - flags.indentation_level = level; - } else print_token(); + print_token(); continuation_sections_mode ??= false; } @@ -5452,7 +5455,7 @@ export class Lexer { output_space_before_token ||= space_in_other && last_type !== 'TK_START_EXPR'; print_token(), indent(); - if ((flags.objectStyle ?? opt.objectStyle) === STYLE.expand) + if ((flags.objectStyle ?? opt.objectStyle) === OBJECT_STYLE.expand) print_newline(true); else output_space_before_token = space_in_other; } else { @@ -5496,7 +5499,7 @@ export class Lexer { const is_obj = flags.mode === MODE.ObjectLiteral, is_exp = is_obj || (ck.in_expr !== undefined); if (is_obj) { const style = flags.objectStyle ?? opt.objectStyle; - if (style === STYLE.collapse || last_text === '{') + if (style === OBJECT_STYLE.collapse || last_text === '{') trim_newlines(); else if (style || input_wanted_newline && opt.preserveNewlines) print_newline(true); @@ -5512,8 +5515,7 @@ export class Lexer { if (opt.braceStyle !== undefined) print_newline(true); output_space_before_token = space_in_other; - } else if (flags.mode !== MODE.BlockStatement) - flags.indentation_level = (flags.parent ?? flags).indentation_level + 1; + } } function handle_word() { @@ -5655,7 +5657,7 @@ export class Lexer { !is_line_continue(ck.previous_token ?? EMPTY_TOKEN, ck)) print_newline(preserve_statement_flags); else if (input_wanted_newline && (opt.preserveNewlines || ck.symbol)) { - if (ck.symbol || get_style() !== STYLE.collapse) + if (ck.symbol || get_style() !== OBJECT_STYLE.collapse) print_newline(!ck.symbol); } else if (['TK_COMMA', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR'].includes(last_type)) if (!start_of_object_property()) @@ -5747,7 +5749,7 @@ export class Lexer { if (style) trim_newlines(); print_token(); - if (style === STYLE.expand) + if (style === OBJECT_STYLE.expand) print_newline(true); else output_space_before_token = space_in_other; } @@ -5894,24 +5896,7 @@ export class Lexer { flags.had_comment = 3; } - function format_directives(str: string) { - const m = str.match(/^;\s*@format\b/i); - if (!m) return; - str = str.substring(m[0].length); - for (const s of str.split(',')) { - const p = s.indexOf(':'); - let k; - switch (k = s.substring(0, p).trim()) { - case 'arrayStyle': - case 'objectStyle': - flags[k] = STYLE[s.substring(p + 1).trim() as keyof typeof STYLE]; - break; - } - } - } - function handle_inline_comment() { - format_directives(token_text); if (opt.ignoreComment) return; if (just_added_newline() && output_lines.length > 1) @@ -5933,7 +5918,6 @@ export class Lexer { else if (flags.had_comment < 2) trim_newlines(); } - format_directives(token_text); if (opt.ignoreComment) return; token_text.split('\n').forEach(s => { @@ -6086,11 +6070,7 @@ export class Lexer { return null; if (name === 'THIS') return { node, uri, scope, is_this: true }; - get_class_base(node, this) - let cls = node as ClassNode; - const isinst = !cls.prototype; - cls = node = find_class(this, cls.extends || (isinst ? 'object' : 'class'), cls.extendsuri)!; - if (node && (!isinst || (node = cls.prototype!))) + if ((node = get_class_base(node, this))) return { node, uri, scope, is_this: false }; return null; } @@ -6304,7 +6284,7 @@ export class Lexer { } public initLibDirs(dir?: string) { - if (isBrowser) + if (process.env.BROWSER) return; let workDir: string; if (!dir) { @@ -6379,6 +6359,7 @@ export class Lexer { public update() { const uri = this.uri, initial = this.include; this.parseScript(); + this.foldingranges.reverse(); if (libfuncs[uri]) { libfuncs[uri].length = 0; libfuncs[uri].push(...Object.values(this.declaration).filter(it => it.kind === SymbolKind.Class || it.kind === SymbolKind.Function)); @@ -6391,7 +6372,8 @@ export class Lexer { change = 1; if (!change) return this.sendDiagnostics(true); - parse_include(this, this.scriptdir); + if (!process.env.BROWSER) + parse_include(this, this.scriptdir); if (change === 1) { const c = traverse_include(this); for (const u in this.included) @@ -6852,7 +6834,7 @@ export function decltype_expr(lex: Lexer, tk: Token, end_pos: number | Position, while ((tk = op_stack.pop()!)) calculate(tk); const result = new Set; - let syms: Set | AhkSymbol[] = []; + let syms: Set | AhkSymbol[] = [], that; for (tk of stack) { if (tk.symbol) { if (tk.symbol.kind === SymbolKind.Property) { @@ -6865,19 +6847,22 @@ export function decltype_expr(lex: Lexer, tk: Token, end_pos: number | Position, } else switch (tk.type) { case 'TK_FUNC': { const call = !!tk.data, name = tk.content.toLowerCase() || (call ? 'call' : '__item'); - syms = decltype_invoke(lex, syms, name, call, tk.paraminfo); + syms = decltype_invoke(lex, syms, name, call, tk.paraminfo, that); break; } case 'TK_WORD': { const pos = lex.document.positionAt(tk.offset); const r = find_symbol(lex, tk.content, SymbolKind.Variable, pos); - if (!r) continue; + if (!r) break; syms = new Set; const node = r.node; if (node.kind === SymbolKind.Variable) { for (const n of decltype_var(node, lex, pos, r.scope, _this)) syms.add(n); - } else syms.add(node); + } else if (syms.add(node), r.is_this !== undefined) { + that = _this ?? node as ClassNode; + continue; + } break; } case 'TK_NUMBER': @@ -6914,6 +6899,7 @@ export function decltype_expr(lex: Lexer, tk: Token, end_pos: number | Position, syms = []; break; } + that = undefined; } for (const n of syms) result.add(n); @@ -7054,22 +7040,22 @@ export function decltype_expr(lex: Lexer, tk: Token, end_pos: number | Position, } } -export function decltype_invoke(lex: Lexer, syms: Set | AhkSymbol[], name: string, call: boolean, paraminfo?: ParamInfo) { +export function decltype_invoke(lex: Lexer, syms: Set | AhkSymbol[], name: string, call: boolean, paraminfo?: ParamInfo, _this?: ClassNode) { const tps = new Set; + let that = _this; for (let n of syms) { - const _this = n as ClassNode; + const cls = n as ClassNode; + that = _this ?? cls; switch (n.kind) { case 0 as SymbolKind: return [ANY]; case SymbolKind.Class: if (call && name === 'call') { - if (!(n = get_class_member(lex, _this, name, call)!)) - if (invoke_meta_func(_this)) + if (!(n = get_class_member(lex, cls, name, call)!)) + if (invoke_meta_func(cls)) break; else continue; const full = (n as Variable).full ?? ''; - if (full.startsWith('(Object)')) - n = _this; - else if (full.startsWith('(ComObject)')) { + if (full.startsWith('(ComObject)')) { const tks = lex.tokens, s = []; let tk = tks[tks[paraminfo?.offset!]?.next_token_offset]; if (tk?.type === 'TK_STRING') { @@ -7097,37 +7083,37 @@ export function decltype_invoke(lex: Lexer, syms: Set | AhkSymbol[], break; // fall through default: - if (!(n = get_class_member(lex, _this, name, call)!)) - if ((n = invoke_meta_func(_this)!)) + if (!(n = get_class_member(lex, cls, name, call)!)) + if ((n = invoke_meta_func(cls)!)) break; else continue; if (n.kind !== SymbolKind.Property) { if ((n as FuncNode).alias) { // if (paraminfo) continue; - const tt = decltype_returns(n, lexers[n.uri!] ?? lex, _this); + const tt = decltype_returns(n, lexers[n.uri!] ?? lex, that); for (const t of call ? decltype_invoke(lex, tt, 'call', true) : tt) tps.add(t); continue; } else if (call) break; if (!paraminfo) tps.add(n); - else for (const t of decltype_invoke(lex, [n], '__item', false, paraminfo)) + else for (const t of decltype_invoke(lex, [n], '__item', false, paraminfo, that)) tps.add(t); continue; } else if ((n as FuncNode).alias) { - const tt = decltype_invoke(lex, decltype_returns(n, lexers[n.uri!] ?? lex, _this), 'call', true); + const tt = decltype_invoke(lex, decltype_returns(n, lexers[n.uri!] ?? lex, that), 'call', true); for (const t of call ? decltype_invoke(lex, tt, 'call', true) : tt) tps.add(t); continue; } else if (call || paraminfo && !(n as Property).get?.params.length) { - for (const t of decltype_invoke(lex, decltype_returns(n, lexers[n.uri!] ?? lex, _this), + for (const t of decltype_invoke(lex, decltype_returns(n, lexers[n.uri!] ?? lex, that), call ? 'call' : '__item', call, paraminfo)) tps.add(t); continue; } break; } - for (const t of decltype_returns(n, lexers[n.uri!] ?? lex, _this)) + for (const t of decltype_returns(n, lexers[n.uri!] ?? lex, that)) tps.add(t); } return tps; @@ -7137,7 +7123,7 @@ export function decltype_invoke(lex: Lexer, syms: Set | AhkSymbol[], if (n.kind === SymbolKind.Method && !(n as FuncNode).alias) return n; const syms = n.kind === SymbolKind.Class ? [n] : !n.children ? - decltype_returns(n, lexers[n.uri!] ?? lex, _this) : undefined; + decltype_returns(n, lexers[n.uri!] ?? lex, that) : undefined; if (!syms?.length) return; for (const t of decltype_invoke(lex, syms, 'call', true, paraminfo)) @@ -7151,7 +7137,7 @@ function decltype_byref(sym: Variable, lex: Lexer, types: AhkSymbol[], _this?: C return []; const { pos, index, kind } = res; const context = lex.getContext(pos); - const tps = decltype_expr(lex, context.token, context.range.end); + const tps = decltype_expr(lex, context.token, context.range.end, _this); let iscall = true; if (tps.includes(ANY)) return [ANY]; diff --git a/server/src/ahkProvider.ts b/server/src/ahkProvider.ts index 6531fbaa..91d158f6 100644 --- a/server/src/ahkProvider.ts +++ b/server/src/ahkProvider.ts @@ -1,7 +1,7 @@ import { createClientSocketTransport, createMessageConnection, createServerSocketTransport, MessageConnection } from 'vscode-languageserver/node'; import { spawn } from 'child_process'; import { resolvePath } from './scriptrunner'; -import { interpreterPathV2, isWindows, rootdir } from './common'; +import { interpreterPathV2, rootdir } from './common'; let ahk_server: MessageConnection | undefined | null; async function get_ahkProvider_port(): Promise { @@ -40,7 +40,7 @@ export async function get_ahkProvider(): Promise { if (ahk_server !== undefined) return ahk_server; let port = 0; - if (isWindows) + if (!process.env.BROWSER && process.platform === 'win32') port = await get_ahkProvider_port(); if (!port) return ahk_server = null; diff --git a/server/src/browserServerMain.ts b/server/src/browserServerMain.ts new file mode 100644 index 00000000..17c8bef7 --- /dev/null +++ b/server/src/browserServerMain.ts @@ -0,0 +1,161 @@ +import { TextDocument } from 'vscode-languageserver-textdocument'; +import { + createConnection, BrowserMessageReader, BrowserMessageWriter, DidChangeConfigurationNotification, + InitializeResult, TextDocuments, TextDocumentSyncKind +} from 'vscode-languageserver/browser'; +import { + chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, + defintionProvider, documentFormatting, enumNames, executeCommandProvider, exportSymbols, getVersionInfo, + hoverProvider, initahk2cache, Lexer, lexers, loadahk2, loadlocalize, prepareRename, rangeFormatting, + referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, + SemanticTokenTypes, set_ahk_h, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, + signatureProvider, symbolProvider, typeFormatting, updateAhkppConfig, workspaceSymbolProvider +} from './common'; +import { AhkppConfig } from './config'; + +const languageServer = 'ahk2-language-server'; +const messageReader = new BrowserMessageReader(self); +const messageWriter = new BrowserMessageWriter(self); +const documents = new TextDocuments(TextDocument); +const workspaceFolders = new Set(); +const connection = set_Connection(createConnection(messageReader, messageWriter)); + +let hasConfigurationCapability = false, hasWorkspaceFolderCapability = false; +let uri_switch_to_ahk2 = ''; + +connection.onInitialize(params => { + const capabilities = params.capabilities; + hasConfigurationCapability = !!( + capabilities.workspace && !!capabilities.workspace.configuration + ); + hasWorkspaceFolderCapability = !!( + capabilities.workspace && !!capabilities.workspace.workspaceFolders + ); + + const result: InitializeResult = { + serverInfo: { + name: languageServer, + }, + capabilities: { + textDocumentSync: { + change: TextDocumentSyncKind.Incremental, + openClose: true + }, + completionProvider: { + resolveProvider: false, + triggerCharacters: ['.', '#', '*', '@'] + }, + signatureHelpProvider: { + triggerCharacters: ['(', ',', ' '] + }, + documentSymbolProvider: true, + definitionProvider: true, + documentFormattingProvider: true, + documentRangeFormattingProvider: true, + documentOnTypeFormattingProvider: { firstTriggerCharacter: '}', moreTriggerCharacter: ['\n', ...Object.keys(chinese_punctuations)] }, + executeCommandProvider: { commands: Object.keys(commands) }, + hoverProvider: true, + foldingRangeProvider: true, + colorProvider: true, + renameProvider: { prepareProvider: true }, + referencesProvider: { workDoneProgress: true }, + semanticTokensProvider: { + legend: { + tokenTypes: enumNames(SemanticTokenTypes), + tokenModifiers: enumNames(SemanticTokenModifiers) + }, + full: true, + range: true + }, + workspaceSymbolProvider: true + } + }; + if (hasWorkspaceFolderCapability) { + params.workspaceFolders?.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); + result.capabilities.workspace = { workspaceFolders: { supported: true } }; + } + + const configs: AhkppConfig = params.initializationOptions; + set_ahk_h(true); + set_locale(params.locale); + set_dirname(configs.extensionUri!); + loadlocalize(); + updateAhkppConfig(configs); + set_WorkspaceFolders(workspaceFolders); + set_version('3.0.0'); + initahk2cache(); + loadahk2(); + loadahk2('ahk2_h'); + loadahk2('winapi', 4); + return result; +}); + +connection.onInitialized(() => { + if (hasConfigurationCapability) { + // Register for all configuration changes. + connection.client.register(DidChangeConfigurationNotification.type); + } + if (hasWorkspaceFolderCapability) { + connection.workspace.onDidChangeWorkspaceFolders(event => { + event.removed.forEach(it => workspaceFolders.delete(it.uri.toLowerCase() + '/')); + event.added.forEach(it => workspaceFolders.add(it.uri.toLowerCase() + '/')); + set_WorkspaceFolders(workspaceFolders); + }); + } +}); + +connection.onDidChangeConfiguration(async change => { + let newset: AhkppConfig | undefined = change?.settings; + if (hasConfigurationCapability && !newset) + newset = await connection.workspace.getConfiguration('AutoHotkey2'); + if (!newset) { + connection.window.showWarningMessage('Failed to obtain the configuration'); + return; + } + updateAhkppConfig(newset); + set_WorkspaceFolders(workspaceFolders); +}); + +documents.onDidOpen(e => { + const to_ahk2 = uri_switch_to_ahk2 === e.document.uri; + const uri = e.document.uri.toLowerCase(); + let doc = lexers[uri]; + if (doc) doc.document = e.document; + else lexers[uri] = doc = new Lexer(e.document); + doc.actived = true; + if (to_ahk2) + doc.actionWhenV1Detected = 'Continue'; +}); + +documents.onDidClose(e => lexers[e.document.uri.toLowerCase()]?.close()); +documents.onDidChangeContent(e => lexers[e.document.uri.toLowerCase()].update()); + +connection.onCompletion(completionProvider); +connection.onColorPresentation(colorPresentation); +connection.onDocumentColor(colorProvider); +connection.onDefinition(defintionProvider); +connection.onDocumentFormatting(documentFormatting); +connection.onDocumentRangeFormatting(rangeFormatting); +connection.onDocumentOnTypeFormatting(typeFormatting); +connection.onDocumentSymbol(symbolProvider); +connection.onFoldingRanges(params => lexers[params.textDocument.uri.toLowerCase()].foldingranges); +connection.onHover(hoverProvider); +connection.onPrepareRename(prepareRename); +connection.onReferences(referenceProvider); +connection.onRenameRequest(renameProvider); +connection.onSignatureHelp(signatureProvider); +connection.onExecuteCommand(executeCommandProvider); +connection.onWorkspaceSymbol(workspaceSymbolProvider); +connection.languages.semanticTokens.on(semanticTokensOnFull); +connection.languages.semanticTokens.onRange(semanticTokensOnRange); +connection.onRequest('ahk2.exportSymbols', exportSymbols); +connection.onRequest('ahk++.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); +connection.onRequest('ahk2.getVersionInfo', getVersionInfo); +connection.onNotification('onDidCloseTextDocument', + (params: { uri: string, id: string }) => { + if (params.id === 'ahk2') + lexers[params.uri.toLowerCase()]?.close(true); + else uri_switch_to_ahk2 = params.uri; + }); +documents.listen(connection); +connection.listen(); diff --git a/server/src/common.ts b/server/src/common.ts index b9274c62..fe49975d 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -6,8 +6,9 @@ import { TextDocument } from 'vscode-languageserver-textdocument'; import { CompletionItem, CompletionItemKind, Hover, InsertTextFormat, Range, SymbolKind } from 'vscode-languageserver-types'; import { AhkSymbol, Lexer, setCommentTagRegex } from './Lexer'; import { diagnostic } from './localize'; -import { isBrowser, jsDocTagNames } from './constants'; +import { jsDocTagNames } from './constants'; import { AhkppConfig, CfgKey, getCfg, newAhkppConfig } from './config'; + export * from './codeActionProvider'; export * from './colorProvider'; export * from './commandProvider'; @@ -30,7 +31,7 @@ export const alpha_3 = encode_version('2.1-alpha.3'); export const ahkppConfig: AhkppConfig = newAhkppConfig(); export const utils = { get_DllExport: (_paths: string[] | Set, _onlyone = false) => Promise.resolve([] as string[]), - get_RCDATA: (_path?: string) => ({ uri: '', path: '' } as { uri: string, path: string, paths?: string[] } | undefined), + get_RCDATA: (_path?: string) => undefined as { uri: string, path: string, paths?: string[] } | undefined, get_ahkProvider: async () => null as unknown as Promise }; @@ -85,7 +86,7 @@ export function read_ahk_file(path: string, showError = true) { } export function openFile(path: string, showError = true): TextDocument | undefined { - if (isBrowser) { + if (process.env.BROWSER) { const data = getwebfile(path); if (data) return TextDocument.create(data.url, 'ahk2', -10, data.text); @@ -107,7 +108,7 @@ export function openAndParse(path: string, showError = true, cache = true) { } export function restorePath(path: string): string { - if (isBrowser || !existsSync(path)) + if (process.env.BROWSER || !existsSync(path)) return path; if (path.includes('..')) path = resolve(path); @@ -194,7 +195,7 @@ export function loadahk2(filename = 'ahk2', d = 3) { let path: string | undefined; const syntaxesPath = process.env.SYNTAXES_PATH || 'syntaxes'; const file = `${rootdir}/${syntaxesPath}/<>/${filename}`; - if (isBrowser) { + if (process.env.BROWSER) { const td = openFile(file + '.d.ahk'); if (td) { const doc = new Lexer(td, undefined, d); @@ -367,7 +368,10 @@ export function enum_ahkfiles(dirpath: string) { } } -/** Updates `extsettings` with the provided config values */ +/** + * Updates `extsettings` with the provided config values + * Formerly `update_settings` + */ export function updateAhkppConfig(newConfig: AhkppConfig) { try { setCommentTagRegex(getCfg(newConfig, CfgKey.CommentTagRegex)); @@ -377,7 +381,7 @@ export function updateAhkppConfig(newConfig: AhkppConfig) { setCommentTagRegex(getCfg(newAhkppConfig(), CfgKey.CommentTagRegex)) connection.console.error(e as string); } - newConfig.v2.workingDirectories = newConfig.v2.workingDirectories.map(dir => + (newConfig as any)[CfgKey.WorkingDirectories] = getCfg(newConfig, CfgKey.WorkingDirectories).map(dir => (dir = URI.file(dir.includes(':') ? dir : resolve(dir)).toString().toLowerCase()) .endsWith('/') ? dir : dir + '/'); scanExclude = {}; @@ -392,10 +396,10 @@ export function updateAhkppConfig(newConfig: AhkppConfig) { scanExclude.file = file; if (folder.length) scanExclude.folder = folder; - if (newConfig.v2.file.maxScanDepth < 0) - newConfig.v2.file.maxScanDepth = Infinity; - if (newConfig.v2.general.syntaxes) - newConfig.v2.general.syntaxes = resolve(newConfig.v2.general.syntaxes).toLowerCase(); + if (getCfg(newConfig, CfgKey.MaxScanDepth) < 0) + (newConfig as any)[CfgKey.MaxScanDepth] = Infinity; + if (getCfg(newConfig, CfgKey.Syntaxes)) + (newConfig as any)[CfgKey.Syntaxes] = resolve(getCfg(newConfig, CfgKey.Syntaxes)).toLowerCase(); Object.assign(ahkppConfig, newConfig); } @@ -409,7 +413,7 @@ function encode_version(version: string) { } export async function sendAhkRequest(method: string, params: unknown[]) { - if (isBrowser) + if (process.env.BROWSER) return undefined; return utils.get_ahkProvider().then((server) => server?.sendRequest(method, ...params)); } @@ -442,7 +446,7 @@ export function set_version(version: string) { ahk_version = encode_version(vers export function set_WorkspaceFolders(folders: Set) { const old = workspaceFolders; workspaceFolders = [...folders]; - ahkppConfig.v2.workingDirectories.forEach(dir => { if (!folders.has(dir)) workspaceFolders.push(dir) }); + getCfg(ahkppConfig, CfgKey.WorkingDirectories).forEach(dir => { if (!folders.has(dir)) workspaceFolders.push(dir) }); workspaceFolders.sort().reverse(); if (old.length === workspaceFolders.length && !old.some((v, i) => workspaceFolders[i] !== v)) diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index 3ba3144f..34a43f80 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -10,10 +10,10 @@ import { a_vars, ahkuris, ahkvars, allIdentifierChar, completionItemCache, completionitem, decltype_expr, dllcalltpe, ahkppConfig, find_class, find_symbol, find_symbols, get_detail, generate_fn_comment, get_callinfo, get_class_constructor, get_class_member, get_class_members, - isBrowser, lexers, libfuncs, make_search_re, sendAhkRequest, utils, winapis, + lexers, libfuncs, make_search_re, sendAhkRequest, utils, winapis } from './common'; import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; -import { BraceStyle, CompletionCommitCharacters, CfgKey, FormatterConfig, getCfg } from './config'; +import { BraceStyle, CompletionCommitCharacters, CfgKey, FormatterConfig, getCfg, LibrarySuggestions } from './config'; export async function completionProvider(params: CompletionParams, _token: CancellationToken): Promise> { let { position, textDocument: { uri } } = params; @@ -29,7 +29,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance if (triggerCharacter === '*') { const tk = doc.tokens[doc.document.offsetAt(position) - 3]; if (tk?.type === 'TK_BLOCK_COMMENT') { - if (!tk.previous_token?.type) { + if (!tk.previous_token?.type && tk === doc.get_token(0, false)) { items.push({ label: '/** */', detail: 'File Doc', kind: CompletionItemKind.Text, @@ -127,7 +127,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance // fall through case '#include': case '#includeagain': { - if (isBrowser) + if (process.env.BROWSER) return; const l = doc.document.offsetAt(position) - token.offset; const text = token!.content; @@ -696,8 +696,8 @@ export async function completionProvider(params: CompletionParams, _token: Cance } // library suggestions - if (ahkppConfig.v2.general.librarySuggestions) { - const librarySuggestions = ahkppConfig.v2.general.librarySuggestions; + if (getCfg(ahkppConfig, CfgKey.LibrarySuggestions)) { + const librarySuggestions = getCfg(ahkppConfig, CfgKey.LibrarySuggestions); const libdirs = doc.libdirs, caches: Record = {}; let exportnum = 0, line = -1, first_is_comment: boolean | undefined, cm: Token; let dir = doc.workspaceFolder; @@ -794,7 +794,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance vars[cl] ??= items.push(convertNodeCompletion(t)); } function add_paths(only_folder = false, ext_re?: RegExp) { - if (isBrowser) + if (process.env.BROWSER) return; offset ??= doc.document.offsetAt(position); let path = token.content.substring(1, offset - token.offset), suf = ''; @@ -841,7 +841,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance } catch { } } async function add_dllexports() { - if (isBrowser) + if (process.env.BROWSER) return; offset ??= doc.document.offsetAt(position); let pre = token.content.substring(1, offset - token.offset), suf = '', t; diff --git a/server/src/config.ts b/server/src/config.ts index 88b91753..b7e2b96d 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -24,6 +24,7 @@ export enum BraceStyle { } export interface FormatterConfig { + // AHK++ values arrayStyle: ObjectOrArrayStyle; braceStyle: BraceStyle; breakChainedMethods: boolean; @@ -43,6 +44,27 @@ export interface FormatterConfig { symbolWithSameCase: boolean; whitespaceBeforeInlineComment: string; wrapLineLength: number; + + // thqby values + array_style?: 'collapse' | 'expand' | 'none'; + brace_style?: 'One True Brace' | 'Allman' | 'One True Brace Variant'; + break_chained_methods?: boolean; + ignore_comment?: boolean; + indent_string?: string; + indent_between_hot_if_directives?: boolean; + keyword_start_with_uppercase?: boolean; + max_preserve_newlines?: number; + object_style?: 'collapse' | 'expand' | 'none'; + preserve_newlines?: boolean; + space_before_conditional?: boolean; + space_after_double_colon?: boolean; + space_in_empty_paren?: boolean; + space_in_other?: boolean; + space_in_paren?: boolean; + switch_case_alignment?: boolean; + symbol_with_same_case?: boolean; + whitespace_before_inline_comment?: string; + wrap_line_length?: number; } /** Defined in package.json */ @@ -61,23 +83,43 @@ export enum CallWithoutParentheses { } export enum CfgKey { - ActionWhenV1Detected = 'v2.general.actionWhenV1Detected', - CallWithoutParentheses = 'v2.warn.callWithoutParentheses', - ClassNonDynamicMemberCheck = 'v2.diagnostics.classNonDynamicMemberCheck', - CommentTagRegex = 'v2.general.commentTagRegex', // still used directly in some places - CompleteFunctionCalls = 'v2.general.completeFunctionCalls', - CompletionCommitCharacters = 'v2.completionCommitCharacters', - Exclude = 'v2.exclude', // still used directly in some places - Formatter = 'v2.formatter', - InterpreterPath = 'v2.file.interpreterPath', // still used directly in some places - LibrarySuggestions = 'v2.general.librarySuggestions', - LocalSameAsGlobal = 'v2.warn.localSameAsGlobal', - MaxScanDepth = 'v2.file.maxScanDepth', - ParamsCheck = 'v2.diagnostics.paramsCheck', - SymbolFoldingFromOpenBrace = 'v2.general.symbolFoldingFromOpenBrace', - Syntaxes = 'v2.general.syntaxes', - VarUnset = 'v2.warn.varUnset', - WorkingDirectories = 'v2.workingDirectories', // still used directly in some places + //* ahkpp values + // ActionWhenV1Detected = 'v2.general.actionWhenV1Detected', + // CallWithoutParentheses = 'v2.warn.callWithoutParentheses', + // ClassNonDynamicMemberCheck = 'v2.diagnostics.classNonDynamicMemberCheck', + // CommentTagRegex = 'v2.general.commentTagRegex', + // CompleteFunctionCalls = 'v2.general.completeFunctionCalls', + // CompletionCommitCharacters = 'v2.completionCommitCharacters', + // Exclude = 'v2.exclude', + // Formatter = 'v2.formatter', + // InterpreterPath = 'v2.file.interpreterPath', + // LibrarySuggestions = 'v2.general.librarySuggestions', + // LocalSameAsGlobal = 'v2.warn.localSameAsGlobal', + // MaxScanDepth = 'v2.file.maxScanDepth', + // ParamsCheck = 'v2.diagnostics.paramsCheck', + // SymbolFoldingFromOpenBrace = 'v2.general.symbolFoldingFromOpenBrace', + // Syntaxes = 'v2.general.syntaxes', + // VarUnset = 'v2.warn.varUnset', + // WorkingDirectories = 'v2.workingDirectories', + + //* thqby values + ActionWhenV1Detected = 'ActionWhenV1IsDetected', + CallWithoutParentheses = 'Warn.CallWithoutParentheses', + ClassNonDynamicMemberCheck = 'Diagnostics.ClassNonDynamicMemberCheck', + CommentTagRegex = 'CommentTags', + CompleteFunctionCalls = 'CompleteFunctionParens', + CompletionCommitCharacters = 'CompletionCommitCharacters', + Exclude = 'Files.Exclude', + Formatter = 'FormatOptions', + InterpreterPath = 'InterpreterPath', + LibrarySuggestions = 'AutoLibInclude', + LocalSameAsGlobal = 'Warn.LocalSameAsGlobal', + MaxScanDepth = 'Files.ScanMaxDepth', + ParamsCheck = 'Diagnostics.ParamsCheck', + SymbolFoldingFromOpenBrace = 'SymbolFoldingFromOpenBrace', + Syntaxes = 'Syntaxes', + VarUnset = 'Warn.varUnset', + WorkingDirectories = 'WorkingDirs', } export interface CompletionCommitCharacters { diff --git a/server/src/constants.ts b/server/src/constants.ts index 28c6de83..b6cf456b 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -24,9 +24,6 @@ export const chinese_punctuations: Record = { '!': '!' }; -export const isBrowser = typeof process === 'undefined'; -export const isWindows = !isBrowser && process.platform === 'win32'; - export const jsDocTagNames = [ "abstract", "access", diff --git a/server/src/formattingProvider.ts b/server/src/formattingProvider.ts index 1c7fa8ad..43c906c3 100644 --- a/server/src/formattingProvider.ts +++ b/server/src/formattingProvider.ts @@ -1,10 +1,10 @@ import { DocumentFormattingParams, DocumentOnTypeFormattingParams, DocumentRangeFormattingParams, Position, Range, TextEdit } from 'vscode-languageserver'; import { chinese_punctuations, ahkppConfig, lexers, Token } from './common'; -import { FormatterConfig } from './config'; +import { CfgKey, FormatterConfig, getCfg } from './config'; export async function documentFormatting(params: DocumentFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], range = Range.create(0, 0, doc.document.lineCount, 0); - const opts = { ...ahkppConfig.v2.formatter }; + const opts = getCfg(ahkppConfig, CfgKey.Formatter); opts.indentString ??= params.options.insertSpaces ? ' '.repeat(params.options.tabSize) : '\t'; const newText = doc.beautify(opts); return [{ range, newText }]; @@ -12,7 +12,7 @@ export async function documentFormatting(params: DocumentFormattingParams): Prom export async function rangeFormatting(params: DocumentRangeFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], range = params.range; - const opts = { ...ahkppConfig.v2.formatter }; + const opts = getCfg(ahkppConfig, CfgKey.Formatter); opts.indentString = params.options.insertSpaces ? ' '.repeat(params.options.tabSize) : '\t'; const newText = doc.beautify(opts, range).trim(); return [{ range, newText }]; @@ -20,7 +20,7 @@ export async function rangeFormatting(params: DocumentRangeFormattingParams): Pr export async function typeFormatting(params: DocumentOnTypeFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], { ch, position } = params; - const options: FormatterConfig = { ...ahkppConfig.v2.formatter }; + const options = getCfg(ahkppConfig, CfgKey.Formatter); let tk: Token, s: string, pp: number | undefined, result: TextEdit[] | undefined; options.indentString = ' '.repeat(params.options.tabSize); s = doc.document.getText({ start: { line: 0, character: 0 }, end: { line: 0, character: 1 } }); diff --git a/server/src/localize.ts b/server/src/localize.ts index b3e95a44..1fe2fdc1 100644 --- a/server/src/localize.ts +++ b/server/src/localize.ts @@ -1,4 +1,4 @@ -import { rootdir, getlocalefile, getwebfile, isBrowser } from './common'; +import { rootdir, getlocalefile, getwebfile } from './common'; import { CfgKey } from './config'; let loadedCollection: Record = {}; @@ -102,7 +102,7 @@ export const response = { } export function loadlocalize() { - if (isBrowser) { + if (process.env.BROWSER) { const data = getwebfile(`${rootdir}/package.nls.<>.json`); if (data) loadedCollection = JSON.parse(data.text); diff --git a/server/src/scriptrunner.ts b/server/src/scriptrunner.ts index 68900eef..890ded05 100644 --- a/server/src/scriptrunner.ts +++ b/server/src/scriptrunner.ts @@ -1,5 +1,5 @@ import { execSync, spawnSync } from 'child_process'; -import { interpreterPathV2, isWindows } from './common'; +import { interpreterPathV2 } from './common'; import { lstatSync, readlinkSync } from 'fs'; import { resolve } from 'path'; @@ -33,7 +33,7 @@ export function resolvePath(path: string, resolveSymbolicLink = false): string { const paths: string[] = []; if (!path.includes(':')) paths.push(resolve(path)); - if (isWindows && !/[\\/]/.test(path)) + if (!process.env.BROWSER && process.platform === 'win32' && !/[\\/]/.test(path)) paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); paths.push(path); for (let path of paths) { diff --git a/server/src/semanticTokensProvider.ts b/server/src/semanticTokensProvider.ts index 459127a7..08187d19 100644 --- a/server/src/semanticTokensProvider.ts +++ b/server/src/semanticTokensProvider.ts @@ -1,6 +1,6 @@ import { CancellationToken, DocumentSymbol, Range, SemanticTokens, SemanticTokensParams, SemanticTokensRangeParams, SymbolKind } from 'vscode-languageserver'; import { - ASSIGN_TYPE, AhkSymbol, ClassNode, FuncNode, Lexer, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, Token, Variable, + ASSIGN_TYPE, AhkSymbol, ClassNode, FuncNode, Lexer, Property, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, Token, Variable, checkParams, diagnostic, ahkppConfig, get_class_member, get_class_members, globalsymbolcache, lexers, symbolProvider } from './common'; import { CfgKey, getCfg } from './config'; @@ -118,9 +118,8 @@ function resolveSemanticType(name: string, tk: Token, doc: Lexer) { if (tk.callsite) checkParams(doc, curclass as unknown as FuncNode, tk.callsite); return sem.type = SemanticTokenTypes.class; case SymbolKind.Property: { - const t = n.children; - if (t?.length === 1 && t[0].name.toLowerCase() === 'get') - sem.modifier = (sem.modifier ?? 0) | SemanticTokenModifiers.readonly | SemanticTokenModifiers.static; + const t = n as Property; + sem.modifier = (sem.modifier ?? 0) | (n.static ? SemanticTokenModifiers.static : 0) | (!t.set && t.children ? SemanticTokenModifiers.readonly : 0); curclass = curclass.range === n.range ? curclass.prototype : undefined; return sem.type = SemanticTokenTypes.property; } diff --git a/server/src/server.ts b/server/src/server.ts index c7be99ea..83b3e77a 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -172,7 +172,7 @@ connection.onInitialize(async (params) => { if (envAhkppConfig) updateAhkppConfig(envAhkppConfig); if ( !(await setInterpreter( - resolvePath((ahkppConfig.v2.file.interpreterPath ??= '')), + resolvePath(getCfg(ahkppConfig, CfgKey.InterpreterPath) ?? ''), )) ) patherr(setting.ahkpatherr()); @@ -261,16 +261,11 @@ documents.onDidOpen(e => { const uri = e.document.uri.toLowerCase(); let doc = lexers[uri]; if (doc) doc.document = e.document; - else { - lexers[uri] = doc = new Lexer(e.document); - } - Object.defineProperty((doc.include = {}), '', { - value: '', - enumerable: false, - }); + else lexers[uri] = doc = new Lexer(e.document); + Object.defineProperty(doc.include, '', { value: '', enumerable: false }); doc.actived = true; if (to_ahk2) doc.actionWhenV1Detected = 'Continue'; - if (includeLocalLibrary(ahkppConfig.v2.general.librarySuggestions)) + if (includeLocalLibrary(getCfg(ahkppConfig, CfgKey.LibrarySuggestions))) parseproject(uri).then( () => doc.last_diags && @@ -400,7 +395,7 @@ async function initpathenv(samefolder = false, retry = true): Promise { } } clearLibfuns(); - if (includeUserAndStandardLibrary(ahkppConfig.v2.general.librarySuggestions)) parseuserlibs(); + if (includeUserAndStandardLibrary(getCfg(ahkppConfig, CfgKey.LibrarySuggestions))) parseuserlibs(); return true; async function update_rcdata() { const pe = new PEFile(interpreterPathV2); @@ -466,7 +461,7 @@ async function changeInterpreter(oldpath: string, newpath: string) { const doc = lexers[td.uri.toLowerCase()]; if (!doc) return; doc.initLibDirs(doc.scriptdir); - if (includeLocalLibrary(ahkppConfig.v2.general.librarySuggestions)) parseproject(doc.uri); + if (includeLocalLibrary(getCfg(ahkppConfig, CfgKey.LibrarySuggestions))) parseproject(doc.uri); }); return true; } diff --git a/server/src/symbolProvider.ts b/server/src/symbolProvider.ts index 4cbb8c8a..6136385b 100644 --- a/server/src/symbolProvider.ts +++ b/server/src/symbolProvider.ts @@ -8,7 +8,7 @@ import { ANY, AhkSymbol, CallSite, ClassNode, FuncNode, FuncScope, Lexer, Property, SUPER, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, THIS, Token, VARREF, Variable, ahkuris, ahkvars, check_same_name_error, connection, decltype_expr, - diagnostic, enum_ahkfiles, ahkppConfig, find_class, get_class_constructor, isBrowser, + diagnostic, enum_ahkfiles, ahkppConfig, find_class, get_class_constructor, is_line_continue, lexers, make_same_name_error, openFile, warn, workspaceFolders } from './common'; import { CfgKey, getCfg } from './config'; @@ -374,7 +374,7 @@ export async function workspaceSymbolProvider(params: WorkspaceSymbolParams, tok const reg = new RegExp(query.match(/[^\w]/) ? query.replace(/(.)/g, '$1.*') : '(' + query.replace(/(.)/g, '$1.*') + '|[^\\w])', 'i'); for (const uri in lexers) if (filterSymbols(uri)) return symbols; - if (!isBrowser) { + if (!process.env.BROWSER) { let uri: string, d: Lexer, t: TextDocument | undefined; for (let dir of workspaceFolders) { dir = URI.parse(dir).fsPath; diff --git a/server/tsconfig.json b/server/tsconfig.json deleted file mode 100644 index e156e410..00000000 --- a/server/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2022", "WebWorker"], - "module": "commonjs", - "moduleResolution": "node", - "sourceMap": true, - "strict": true, - "outDir": "out" - }, - "include": ["src"], - "exclude": ["node_modules", ".vscode-test", ".vscode-test-web"] -} diff --git a/syntaxes/ahk2.tmLanguage.json b/syntaxes/ahk2.tmLanguage.json index 8824da5f..e828e16f 100644 --- a/syntaxes/ahk2.tmLanguage.json +++ b/syntaxes/ahk2.tmLanguage.json @@ -1,2361 +1,2361 @@ { - "name": "autohotkey2", - "scopeName": "source.ahk2", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "include": "#hotkey_hotstring" - }, - { - "include": "#switch_statement" - }, - { - "include": "#object_property" - }, - { - "include": "#reserved" - }, - { - "include": "#numbers" - }, - { - "include": "#operators" - }, - { - "include": "#strings" - }, - { - "include": "#pre_definition" - }, - { - "include": "#class_block" - }, - { - "include": "#block" - }, - { - "include": "#continuation_section" - }, - { - "include": "#parens" - }, - { - "include": "#function_call" - }, - { - "include": "#property" - }, - { - "include": "#variables" - } - ], - "repository": { - "block": { - "patterns": [ - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.ahk2" - } - }, - "patterns": [ - { - "include": "#block_innards" - } - ] - } - ] - }, - "block_innards": { - "patterns": [ - { - "include": "#object_property" - }, - { - "name": "meta.initialization.ahk2", - "begin": "(?x)\n(?:\n (?:\n\t(?=[ \t])(?=+!]+ | \\(\\) | \\[\\]))\n)\n[ \t]*(\\() # opening bracket", - "beginCaptures": { - "1": { - "name": "variable.other.ahk2" - }, - "2": { - "name": "punctuation.section.parens.begin.bracket.round.initialization.ahk2" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.section.parens.end.bracket.round.initialization.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.ahk2" - } - }, - "patterns": [ - { - "include": "#block_innards" - } - ] - }, - { - "include": "$base" - } - ] - }, - "case_statement": { - "name": "meta.conditional.case.ahk2", - "begin": "(?<=^[ \t]*\\{?[ \t]*)((?i:case))(?!\\w)", - "beginCaptures": { - "1": { - "name": "keyword.control.case.ahk2" - } - }, - "end": "(:)", - "endCaptures": { - "1": { - "name": "punctuation.separator.colon.case.ahk2" - } - }, - "patterns": [ - { - "include": "#strings" - }, - { - "include": "#numbers" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "\\.(?=\\w)", - "name": "punctuation.accessor.ahk2" - }, - { - "include": "#function_call" - }, - { - "match": "{", - "name": "punctuation.section.block.begin.ahk2" - }, - { - "match": "}", - "name": "punctuation.section.block.end.ahk2" - }, - { - "match": "\\[|\\(", - "name": "punctuation.section.parens.begin.ahk2" - }, - { - "match": "\\]|\\)", - "name": "punctuation.section.parens.end.ahk2" - }, - { - "include": "#operators" - }, - { - "include": "#variables" - }, - { - "include": "#comments" - } - ] - }, - "class_block": { - "name": "meta.block.class.ahk2", - "begin": "(^|(?<=^[ \t]*\\*/))[ \t]*((?i:class))[ \t]+(\\$?\\w+(\\.\\w+)*)", - "beginCaptures": { - "2": { - "name": "storage.type.class.ahk2" - }, - "3": { - "name": "entity.name.type.class.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.class.end.ahk2" - } - }, - "patterns": [ - { - "begin": "\\G(?!\\{)", - "end": "(?=\\{)", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "\\G[ \t]*(<)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.begin.ahk2" - } - }, - "end": ">", - "endCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.end.ahk2" - } - }, - "patterns": [ - { - "match": "\\w+", - "name": "entity.name.type.parameter" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "=", - "name": "keyword.operator.assignment.ahk2" - }, - { - "match": "\\.", - "name": "punctuation.accessor.ahk2" - }, - { - "match": "\\|", - "name": "keyword.operator.ahk2" - } - ] - }, - { - "match": "\\b((?i:extends))([ \t]+([\\w.]+))?", - "captures": { - "1": { - "name": "storage.modifier.ahk2" - }, - "3": { - "patterns": [ - { - "match": "\\.(?=\\w)", - "name": "punctuation.accessor.ahk2" - }, - { - "include": "#default_classes" - }, - { - "match": "\\b[^.]+\\b", - "name": "entity.name.type.class.ahk2" - } - ] - } - } - } - ] - }, - { - "begin": "\\{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.class.begin.ahk2" - } - }, - "end": "(?=})", - "name": "meta.block.class.body.ahk2", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "match": "(?<=^[ \t]*)(?i:static)(?=[ \t]+\\w)", - "name": "storage.modifier.ahk2" - }, - { - "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)[ \t]*(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "patterns": [ - { - "match": "\\b(?i:__item)\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "variable.other.property.ahk2" - }, - "2": { - "name": "storage.type.function.arrow.ahk2" - }, - "4": { - "name": "comment.line.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.block.prototype.body.ahk2", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - { - "match": "(?<=(^[ \t]*(?i:static[ \t]+)?|,[ \t]*))\\w+(?=[ \t]*:=)", - "captures": { - "0": { - "patterns": [ - { - "match": "\\b(?i:__item)\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "variable.other.property.ahk2" - } - } - }, - { - "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)(?=\\()", - "beginCaptures": { - "1": { - "patterns": [ - { - "match": "\\b(__(?i:new|init|enum|get|call|set|delete))\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "entity.name.function.method.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.block.method.ahk2", - "patterns": [ - { - "begin": "\\G\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.ahk2" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.method.begin.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.method.end.ahk2" - } - }, - "name": "meta.block.method.body.ahk2", - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.block.method.body.ahk2", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - } - ] - }, - { - "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)\\b\\w+\\b(?=(\\[|[ \t]*\\{?([ \t];.*)?\\n))", - "beginCaptures": { - "0": { - "patterns": [ - { - "match": "\\b(?i:__item)\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "variable.other.property.ahk2" - } - }, - "name": "meta.block.property.ahk2", - "end": "(?=\\n)", - "endCaptures": { - "1": { - "name": "punctuation.definition.block.property.end.ahk2" - } - }, - "patterns": [ - { - "begin": "\\G\\[", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.ahk2" - } - }, - "end": "\\]", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.property.begin.ahk2" - } - }, - "end": "(?=})", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.property.end.ahk2" - } - }, - "name": "meta.block.property.body.ahk2", - "patterns": [ - { - "begin": "(?<=^[ \t]*)(?i:set)\\b", - "beginCaptures": { - "0": { - "name": "storage.type.setter.ahk2" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.property.setter.begin.ahk2" - } - }, - "name": "meta.block.property.setter.body.ahk2", - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.property.setter.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "name": "meta.block.property.setter.body.ahk2", - "end": "(?=\\n)", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - } - ] - }, - { - "begin": "(?<=^[ \t]*)(?i:get)\\b", - "beginCaptures": { - "0": { - "name": "storage.type.getter.ahk2" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.property.getter.begin.ahk2" - } - }, - "name": "meta.block.property.getter.body.ahk2", - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.property.getter.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "name": "meta.block.property.getter.body.ahk2", - "end": "(?=\\n)", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - } - ] - }, - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "name": "meta.block.property.getter.body.ahk2", - "end": "(?=\\n)", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - { - "include": "#variables" - } - ] - }, - { - "include": "#class_block" - }, - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - } - ] - }, - "comments": { - "patterns": [ - { - "name": "comment.block.jsdoc.ahk2", - "begin": "^[ \t]*(\\/\\*\\*)(?!\\/)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.begin.ahk2" - } - }, - "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.comment.end.ahk2" - } - }, - "patterns": [ - { - "include": "#docblock" - } - ] - }, - { - "name": "comment.block.ahk2", - "begin": "(?<=^[ \t]*)(\\/\\*)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.begin.ahk2" - } - }, - "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.comment.end.ahk2" - } - } - }, - { - "name": "comment.line.ahk2", - "match": "(?<=(^[ \t]*|[ \t]))(;.*)" - } - ] - }, - "compiler_directive": { - "patterns": [ - { - "name": "comment.block.ahk2", - "begin": "^[ \t]*(\\/\\*)((?i:@ahk2exe-keep))", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.begin.ahk2" - }, - "2": { - "name": "keyword.control.directive.conditional.ahk2" - } - }, - "end": "^[ \t]*(\\*\\/)", - "endCaptures": { - "1": { - "name": "punctuation.definition.comment.end.ahk2" - } - } - }, - { - "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-ignore(begin|end))", - "name": "keyword.control.directive.ahk2" - }, - { - "begin": "^[ \t]*(;[ \t]*@(?i:ahk2exe-let))\\b", - "beginCaptures": { - "0": { - "name": "keyword.control.directive.ahk2" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "include": "#strings" - }, - { - "include": "#numbers" - }, - { - "match": "\\b([_[:alpha:]][_[:alnum:]]*)(?=[ \t]*=)", - "name": "constant.language.ahk2" - }, - { - "match": "=", - "name": "keyword.operator.assignment.ahk2" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - } - ] - }, - { - "begin": "^[ \t]*((;[ \t]*@)(?i:include))\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.preprocessor.include.ahk2", - "patterns": [ - { - "begin": "[^ \t;]", - "end": "(?=(?:[ \t]+;))|(?=\\n)", - "name": "string.literal.include.ahk2" - }, - { - "match": "(?:[ \t]+);.*", - "name": "comment.line.ahk2" - } - ] - }, - { - "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-\\w+)\\b([ \t].*)?", - "name": "keyword.control.directive.ahk2", - "captures": { - "1": { - "name": "string.literal.ahk2" - } - } - }, - { - "match": "(?<=^|[ \t]);[ \t]*@(?:[\\w\\-]+)\\b([ \t]+(.*))?", - "name": "keyword.control.directive.ahk2", - "captures": { - "2": { - "name": "comment.line.ahk2" - } - } - } - ] - }, - "conditional_context": { - "patterns": [ - { - "include": "$self" - }, - { - "include": "#block_innards" - } - ] - }, - "continuation_section": { - "name": "meta.parens.continuation_section.ahk2", - "begin": "(?<=^[ \t]*)(\\()((((?i:join)[^ \t]*|[^ \t();]+)(?=[ \t]|$)|[ \t]+)*)((?<=[ \t]);.*)?$", - "beginCaptures": { - "1": { - "name": "punctuation.section.parens.begin.ahk2" - }, - "2": { - "patterns": [ - { - "match": "(?<=[ \t]|^[ \t]*\\()(?i:c(om(ments?)?)?|[lr]trim0?|`|join(`s|[^ \t]){0,15})(?=[ \t]|$)", - "name": "string.options.ahk2 markup.italic" - }, - { - "match": "[^ \t]+", - "name": "invalid.options.ahk2 markup.strikethrough" - } - ] - }, - "5": { - "name": "comment.line.ahk2" - } - }, - "end": "^[ \t]*(\\))", - "endCaptures": { - "1": { - "name": "punctuation.section.parens.end.ahk2" - } - }, - "patterns": [ - { - "include": "#continuation_section_innards" - } - ] - }, - "continuation_section_innards": { - "patterns": [ - { - "begin": "('|\")", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin.ahk2" - } - }, - "end": "(\\1)|(?=^[ \t]*\\))", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.ahk2" - } - }, - "name": "string.continuation_section_innards.ahk2", - "patterns": [ - { - "include": "#string_escaped_char" - } - ] - }, - { - "include": "#variables" - }, - { - "match": "{", - "name": "punctuation.section.block.begin.ahk2" - }, - { - "match": "}", - "name": "punctuation.section.block.end.ahk2" - }, - { - "match": "\\[", - "name": "punctuation.section.parens.begin.ahk2" - }, - { - "match": "\\]", - "name": "punctuation.section.parens.end.ahk2" - }, - { - "include": "#parens" - }, - { - "include": "$base" - } - ] - }, - "default_classes": { - "patterns": [ - { - "begin": "(?*/]\n (?:[^@<>*/]|\\*[^/])*\n)\n(?:\n \\s*\n (<)\n ([^>\\s]+)\n (>)\n)?", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - }, - "4": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "5": { - "name": "constant.other.email.link.underline.jsdoc" - }, - "6": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)borrows) \\s+\n((?:[^@\\s*/]|\\*[^/])+) # \n\\s+ (as) \\s+ # as\n((?:[^@\\s*/]|\\*[^/])+) # ", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - }, - "4": { - "name": "keyword.operator.control.jsdoc" - }, - "5": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "name": "meta.embedded.ahk2 meta.example.jsdoc", - "begin": "((@)example)\\s+", - "end": "(?=@|\\*+/)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "patterns": [ - { - "match": "^\\s*\\*\\s+", - "name": "comment.block.ahk2" - }, - { - "contentName": "constant.other.description.jsdoc", - "begin": "\\G(<)caption(>)", - "beginCaptures": { - "0": { - "name": "entity.name.tag.inline.jsdoc" - }, - "1": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - }, - "end": "()|(?=\\*/)", - "endCaptures": { - "0": { - "name": "entity.name.tag.inline.jsdoc" - }, - "1": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - }, - "patterns": [ - { - "match": "^\\s*\\*\\s", - "name": "comment.block.ahk2" - } - ] - }, - { - "include": "$base" - } - ] - }, - { - "name": "meta.overload.ahk2", - "begin": "((@)overload)\\s+", - "end": "(?=\\n|^\\s*\\*)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "match": "(?x) ((@)kind) \\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\b", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "constant.language.symbol-type.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)see)\n\\s+\n(?:\n # URL\n (\n (?=https?://)\n (?:[^\\s*]|\\*[^/])+\n )\n |\n # JSDoc namepath\n (\n (?!\n # Avoid matching bare URIs (also acceptable as links)\n https?://\n |\n # Avoid matching {@inline tags}; we match those below\n (?:\\[[^\\[\\]]*\\])? # Possible description [preceding]{@tag}\n {@(?:link|linkcode|linkplain|tutorial)\\b\n )\n # Matched namepath\n (?:[^@\\s*/]|\\*[^/])+\n )\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.link.underline.jsdoc" - }, - "4": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)template)\n\\s+\n# One or more valid identifiers\n(\n [A-Za-z_$] # First character: non-numeric word character\n [\\w$.\\[\\]]* # Rest of identifier\n (?: # Possible list of additional identifiers\n \\s* , \\s*\n [A-Za-z_$]\n [\\w$.\\[\\]]*\n )*\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - } - } - }, - { - "begin": "((@)typedef)\\s+(?={)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", - "patterns": [ - { - "include": "#jsdoctype" - }, - { - "name": "entity.name.type.instance.jsdoc", - "match": "(?:[^@\\s*/]|\\*[^/])+" - } - ] - }, - { - "begin": "((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\s+(?=[\\[{]|(?!\\d)\\w)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]\\w])", - "patterns": [ - { - "include": "#jsdoctype" - }, - { - "name": "variable.other.jsdoc", - "match": "((?!\\d)\\w[\\w.\\[\\]]*)" - }, - { - "name": "variable.other.jsdoc", - "match": "(?x)\n(\\[)\\s*\n\\w+\n(?:\n (?:\\[\\])? # Foo[ ].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [\\w$]+\n)*\n(?:\n \\s*\n (=) # [foo=bar] Default parameter value\n \\s*\n (\n # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\n (?>\n \"(?:(?:\\*(?!/))|(?:\\\\(?!\"))|[^*\\\\])*?\" | # [foo=\"bar\"] Double-quoted\n '(?:(?:\\*(?!/))|(?:\\\\(?!'))|[^*\\\\])*?' | # [foo='bar'] Single-quoted\n \\[ (?:(?:\\*(?!/))|[^*])*? \\] | # [foo=[1,2]] Array literal\n (?:(?:\\*(?!/))|\\s(?!\\s*\\])|\\[.*?(?:\\]|(?=\\*/))|[^*\\s\\[\\]])* # Everything else\n )*\n )\n)?\n\\s*(?:(\\])((?:[^*\\s]|\\*[^\\s/])+)?|(?=\\*/))", - "captures": { - "1": { - "name": "punctuation.definition.optional-value.begin.bracket.square.jsdoc" - }, - "2": { - "name": "keyword.operator.assignment.jsdoc" - }, - "3": { - "name": "meta.embedded.ahk2" - }, - "4": { - "name": "punctuation.definition.optional-value.end.bracket.square.jsdoc" - }, - "5": { - "name": "invalid.illegal.syntax.jsdoc" - } - } - } - ] - }, - { - "begin": "(?x)\n(\n (@)\n (?:define|enum|exception|export|extends|lends|implements|modifies\n |namespace|private|protected|returns?|suppress|this|throws|type\n |yields?)\n)\n\\s+(?={)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", - "patterns": [ - { - "include": "#jsdoctype" - } - ] - }, - { - "match": "((@)method)\\b\\s*((\\w|[^\\x00-\\x7f])+)?", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.function.method.ahk2" - } - } - }, - { - "match": "(?x)\n(\n (@)\n (?:alias|augments|callback|constructs|emits|event|fires|exports?\n |extends|external|function|func|host|lends|listens|interface|memberof!?\n |module|mixes|mixin|name|requires|see|this|typedef|uses)\n)\n\\s+\n(\n (?:\n [^{}@\\s*] | \\*[^/]\n )+\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "contentName": "variable.other.jsdoc", - "begin": "((@)(?:default(?:value)?|license|version))\\s+(([''\"]))", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - }, - "4": { - "name": "punctuation.definition.string.begin.jsdoc" - } - }, - "end": "(\\3)|(?=$|\\*/)", - "endCaptures": { - "0": { - "name": "variable.other.jsdoc" - }, - "1": { - "name": "punctuation.definition.string.end.jsdoc" - } - } - }, - { - "match": "((@)(?:default(?:value)?|license|tutorial|variation|version))\\s+([^\\s*]+)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - } - } - }, - { - "name": "storage.type.class.jsdoc", - "match": "(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\b", - "captures": { - "1": { - "name": "punctuation.definition.block.tag.jsdoc" - } - } - }, - { - "include": "#inline-tags" - }, - { - "match": "((@)(?:[_$[:alpha:]][_$[:alnum:]]*))(?=\\s+)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - } - } - ] - }, - "function_call": { - "match": "([_[:alpha:]][[:alnum:]_]*+)(?=\\()", - "captures": { - "1": { - "name": "entity.name.function.ahk2", - "patterns": [ - { - "match": "(?<=\\.).+", - "name": "entity.name.function.method.ahk2" - }, - { - "include": "#variables_language" - } - ] - } - } - }, - "function_call_notparens": { - "patterns": [ - { - "match": "(?<=^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\b(?>=|\\?|\\{))|$))", - "name": "entity.name.function.ahk2", - "captures": { - "0": { - "patterns": [ - { - "include": "#function_defaultLibrary" - } - ] - } - } - }, - { - "match": "(?<=(^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\.)+)([[:alpha:]_][[:alnum:]_]*\\b)(?=$|[ \t]((?!([ \t]*[+\\-*/^&:.|]?=|<<=|>>=|\\?|\\{))|$))", - "name": "entity.name.function.method.ahk2" - } - ] - }, - "function_defaultLibrary": { - "patterns": [ - { - "match": "(?$~*!+#^]*?)(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))|~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+)[ \t]+&[ \t]+~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))([ \t]+up)?)(::)", - "beginCaptures": { - "1": { - "name": "hotkey.ahk2", - "patterns": [ - { - "match": "(?<=[ \t])&(?=[ \t]+[^ \t]+(?i:[ \t]+up)?$)", - "name": "keyword.operator.ahk2" - }, - { - "match": "(?<=(&[ \t]+|^[ \t]*))([<>$~*!+#^]*?)(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+|`[;{]|[\\x21-\\x3A\\x3C-\\x7E]|(?<=[^ \t]);)(?=([ \t]|$))", - "name": "keyword.keys.ahk2" - } - ] - }, - "7": { - "name": "keyword.keys.up.ahk2" - }, - "8": { - "name": "punctuation.definition.colon" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "match": "(?<=\\G[ \t]*)((?i:alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab)\\b|([<>]?[!+#^]){0,4}(`[{;]|(?<=\\G);|[^{;]|(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))(?=([ \t]+;.*|[ \t]*)\\n))", - "name": "keyword.keys.ahk2" - }, - { - "include": "$base" - } - ] - }, - { - "match": "(?<=^[ \t]*\\{?[ \t]*)(\\w+)(:)(?=[ \t]*([ \t];.*)?$)", - "captures": { - "1": { - "name": "entity.name.label.ahk2" - }, - "2": { - "name": "punctuation.definition.colon" - } - } - } - ] - }, - "hotstring_execute": { - "match": "^[ \t]*(:)([^:]*)(:)((`.|[^`])*?)(::)", - "captures": { - "1": { - "name": "punctuation.definition.colon" - }, - "2": { - "patterns": [ - { - "match": "(?i:(s[ipe]|[*?borstz]0?|c[01]?|k-1|[kp]\\d+|x1?))", - "name": "string.options.ahk2 markup.italic" - }, - { - "match": "[^ \t]", - "name": "invalid.options.ahk2 markup.strikethrough" - } - ] - }, - "3": { - "name": "punctuation.definition.colon" - }, - "4": { - "name": "keyword.keys.ahk2 markup.underline" - }, - "6": { - "name": "punctuation.definition.colon" - } - }, - "name": "hotstring.ahk2" - }, - "inline-tags": { - "patterns": [ - { - "name": "constant.other.description.jsdoc", - "match": "(\\[)[^\\]]+(\\])(?={@(?:link|linkcode|linkplain|tutorial))", - "captures": { - "1": { - "name": "punctuation.definition.bracket.square.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.square.end.jsdoc" - } - } - }, - { - "name": "entity.name.type.instance.jsdoc", - "begin": "({)((@)(?:link(?:code|plain)?|tutorial))\\s*", - "beginCaptures": { - "1": { - "name": "punctuation.definition.bracket.curly.begin.jsdoc" - }, - "2": { - "name": "storage.type.class.jsdoc" - }, - "3": { - "name": "punctuation.definition.inline.tag.jsdoc" - } - }, - "end": "}|(?=\\*/)", - "endCaptures": { - "0": { - "name": "punctuation.definition.bracket.curly.end.jsdoc" - } - }, - "patterns": [ - { - "match": "\\G((?=https?://)(?:[^|}\\s*]|\\*[/])+)(\\|)?", - "captures": { - "1": { - "name": "variable.other.link.underline.jsdoc" - }, - "2": { - "name": "punctuation.separator.pipe.jsdoc" - } - } - }, - { - "match": "\\G((?:[^{}@\\s|*]|\\*[^/])+)(\\|)?", - "captures": { - "1": { - "name": "variable.other.description.jsdoc" - }, - "2": { - "name": "punctuation.separator.pipe.jsdoc" - } - } - } - ] - } - ] - }, - "brackets": { - "patterns": [ - { - "match": "^\\s*\\*\\s+", - "name": "comment.block.ahk2" - }, - { - "match": "(['\"])(`\\1|.(??:=.&|^]+|[~+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or)))[ \t]*([ \t];.*)?\\n", - "beginCaptures": { - "1": { - "patterns": [ - { - "include": "#operators" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "=>", - "name": "storage.type.function.arrow.ahk2" - } - ] - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "end": "(?!([*/<>?:=.]+|[+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or))))[ \t]*([ \t];.*)?(?=\\n)|(?<=^[ \t]*(?i:class|static|if|try|loop|while)[ \t]+\\w+)", - "endCaptures": { - "3": { - "name": "comment.line.ahk2" - } - }, - "patterns": [ - { - "match": "(?<=^[ \t]*)\\w+(?=(\\n|[ \t]))", - "captures": { - "0": { - "patterns": [ - { - "include": "#variables" - } - ] - } - } - }, - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - "numbers": { - "match": "(?", - "name": "storage.type.function.arrow.ahk2" - }, - { - "match": "\\.=|\\+=|-=|\\*=|/?/=", - "name": "keyword.operator.assignment.compound.ahk2" - }, - { - "match": "&=|\\^=|<<=|>>>=|>>=|\\|=", - "name": "keyword.operator.assignment.compound.bitwise.ahk2" - }, - { - "match": "<<|>>>|>>", - "name": "keyword.operator.bitwise.shift.ahk2" - }, - { - "match": "!=|<=|>=|=?=|<|>", - "name": "keyword.operator.comparison.ahk2" - }, - { - "match": "~=", - "name": "keyword.operator.regexp.ahk2" - }, - { - "match": "\\?\\?|&&|!|\\|\\|", - "name": "keyword.operator.logical.ahk2" - }, - { - "match": "&|\\||\\^|~", - "name": "keyword.operator.ahk2" - }, - { - "match": ":=", - "name": "keyword.operator.assignment.ahk2" - }, - { - "match": "\\.(?=\\w)", - "name": "punctuation.accessor.ahk2" - }, - { - "match": "\\*|/|-|\\+|\\.", - "name": "keyword.operator.ahk2" - }, - { - "match": "%", - "name": "punctuation.parens.percent.ahk2" - }, - { - "match": "\\[", - "name": "punctuation.square.begin.ahk2" - }, - { - "match": "\\]", - "name": "punctuation.square.end.ahk2" - }, - { - "match": "\\?(?=[ \t]*[,)\\]}])", - "name": "keyword.operator.optional.ahk2" - }, - { - "match": "\\?|:(?!\\:)", - "name": "keyword.operator.ternary.ahk2" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - } - ] - }, - "parens": { - "name": "meta.parens.ahk2", - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "punctuation.section.parens.begin.bracket.round.ahk2" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.section.parens.end.bracket.round.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - "property": { - "patterns": [ - { - "name": "variable.other.property.ahk2", - "match": "\\b(?<=\\.)[_[:alnum:]]+\\b" - } - ] - }, - "pre_definition": { - "patterns": [ - { - "begin": "^[ \t]*((#)(?i:dllload|hotstring|include(again)?|mapcasesense|requires|errorstdout|definedefault(array|map|object)value|windowclass(gui|main)|singleinstance|targetcontrolerror|targetwindowerror))\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - }, - "end": "\\n", - "name": "meta.preprocessor.ahk2", - "patterns": [ - { - "match": "[^ \t;].*?(?=([ \t]+;|[ \t]*\\n))", - "name": "string.literal.ahk2" - }, - { - "match": "(?<=[ \t]);.*", - "name": "comment.line.ahk2" - } - ] - }, - { - "begin": "^[ \t]*((#)(?i:warn))\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - }, - "end": "\\n", - "name": "meta.preprocessor.ahk2", - "patterns": [ - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "\\w+", - "name": "string.literal.ahk2" - }, - { - "match": "(?<=[ \t]);.*", - "name": "comment.line.ahk2" - } - ] - }, - { - "match": "^[ \t]*((#)(?i:clipboardtimeout|criticalobject(sleeptime|timeout)|hotif|hotiftimeout|inputlevel|initexec|maxthreads|maxthreadsbuffer|maxthreadsperhotkey|notrayicon|suspendexempt|usehook|usestdlib|warn|warncontinuableexception|winactivateforce))\\b", - "captures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - } - }, - { - "begin": "^[ \t]*((#)(?i:dllimport))([ \t]+(\\w+)[ \t]*(,?))?", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - }, - "4": { - "name": "entity.name.function.ahk2" - }, - "5": { - "name": "punctuation.separator.comma.ahk2" - } - }, - "end": "\\n", - "name": "meta.preprocessor.ahk2", - "patterns": [ - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "[^,\\n\\r]+", - "name": "string.literal.ahk2" - } - ] - } - ] - }, - "reserved": { - "patterns": [ - { - "match": "(?(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))(\\()", - "beginCaptures": { - "1": { - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - } - ] - }, - "2": { - "name": "comment.block.ahk2 punctuation.definition.comment.begin.ahk2" - }, - "3": { - "name": "comment.block.ahk2" - }, - "4": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.ahk2 punctuation.definition.comment.end.ahk2" - }, - { - "match": "\\*", - "name": "comment.block.ahk2" - } - ] - }, - "5": { - "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.ahk2" - } - }, - "end": "(\\))", - "endCaptures": { - "1": { - "name": "punctuation.section.parens.end.bracket.round.conditional.switch.ahk2" - } - }, - "patterns": [ - { - "include": "#conditional_context" - } - ] - }, - "switch_statement": { - "name": "meta.block.switch.ahk2", - "begin": "(((?>(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))((?\\[\\]=]))", - "patterns": [ - { - "name": "meta.head.switch.ahk2", - "begin": "\\G ?", - "end": "(?=+!]+ | \\(\\) | \\[\\]))\n)\n[ \t]*(\\() # opening bracket", + "beginCaptures": { + "1": { + "name": "variable.other.ahk2" + }, + "2": { + "name": "punctuation.section.parens.begin.bracket.round.initialization.ahk2" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.initialization.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.ahk2" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.ahk2" + } + }, + "patterns": [ + { + "include": "#block_innards" + } + ] + }, + { + "include": "$base" + } + ] + }, + "case_statement": { + "name": "meta.conditional.case.ahk2", + "begin": "(?<=^[ \t]*\\{?[ \t]*)((?i:case))(?!\\w)", + "beginCaptures": { + "1": { + "name": "keyword.control.case.ahk2" + } + }, + "end": "(:)", + "endCaptures": { + "1": { + "name": "punctuation.separator.colon.case.ahk2" + } + }, + "patterns": [ + { + "include": "#strings" + }, + { + "include": "#numbers" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "\\.(?=\\w)", + "name": "punctuation.accessor.ahk2" + }, + { + "include": "#function_call" + }, + { + "match": "{", + "name": "punctuation.section.block.begin.ahk2" + }, + { + "match": "}", + "name": "punctuation.section.block.end.ahk2" + }, + { + "match": "\\[|\\(", + "name": "punctuation.section.parens.begin.ahk2" + }, + { + "match": "\\]|\\)", + "name": "punctuation.section.parens.end.ahk2" + }, + { + "include": "#operators" + }, + { + "include": "#variables" + }, + { + "include": "#comments" + } + ] + }, + "class_block": { + "name": "meta.block.class.ahk2", + "begin": "(^|(?<=^[ \t]*\\*/))[ \t]*((?i:class))[ \t]+(\\$?\\w+(\\.\\w+)*)", + "beginCaptures": { + "2": { + "name": "storage.type.class.ahk2" + }, + "3": { + "name": "entity.name.type.class.ahk2" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.class.end.ahk2" + } + }, + "patterns": [ + { + "begin": "\\G(?!\\{)", + "end": "(?=\\{)", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "\\G[ \t]*(<)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.typeparameters.begin.ahk2" + } + }, + "end": ">", + "endCaptures": { + "0": { + "name": "punctuation.definition.typeparameters.end.ahk2" + } + }, + "patterns": [ + { + "match": "\\w+", + "name": "entity.name.type.parameter" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "=", + "name": "keyword.operator.assignment.ahk2" + }, + { + "match": "\\.", + "name": "punctuation.accessor.ahk2" + }, + { + "match": "\\|", + "name": "keyword.operator.ahk2" + } + ] + }, + { + "match": "\\b((?i:extends))([ \t]+([\\w.]+))?", + "captures": { + "1": { + "name": "storage.modifier.ahk2" + }, + "3": { + "patterns": [ + { + "match": "\\.(?=\\w)", + "name": "punctuation.accessor.ahk2" + }, + { + "include": "#default_classes" + }, + { + "match": "\\b[^.]+\\b", + "name": "entity.name.type.class.ahk2" + } + ] + } + } + } + ] + }, + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.class.begin.ahk2" + } + }, + "end": "(?=})", + "name": "meta.block.class.body.ahk2", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "match": "(?<=^[ \t]*)(?i:static)(?=[ \t]+\\w)", + "name": "storage.modifier.ahk2" + }, + { + "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)[ \t]*(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "patterns": [ + { + "match": "\\b(?i:__item)\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "variable.other.property.ahk2" + }, + "2": { + "name": "storage.type.function.arrow.ahk2" + }, + "4": { + "name": "comment.line.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.block.prototype.body.ahk2", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + { + "match": "(?<=(^[ \t]*(?i:static[ \t]+)?|,[ \t]*))\\w+(?=[ \t]*:=)", + "captures": { + "0": { + "patterns": [ + { + "match": "\\b(?i:__item)\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "variable.other.property.ahk2" + } + } + }, + { + "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)(?=\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "match": "\\b(__(?i:new|init|enum|get|call|set|delete))\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "entity.name.function.method.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.block.method.ahk2", + "patterns": [ + { + "begin": "\\G\\(", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.ahk2" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.method.begin.ahk2" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.method.end.ahk2" + } + }, + "name": "meta.block.method.body.ahk2", + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.block.method.body.ahk2", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + } + ] + }, + { + "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)\\b\\w+\\b(?=(\\[|[ \t]*\\{?([ \t];.*)?\\n))", + "beginCaptures": { + "0": { + "patterns": [ + { + "match": "\\b(?i:__item)\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "variable.other.property.ahk2" + } + }, + "name": "meta.block.property.ahk2", + "end": "(?=\\n)", + "endCaptures": { + "1": { + "name": "punctuation.definition.block.property.end.ahk2" + } + }, + "patterns": [ + { + "begin": "\\G\\[", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.ahk2" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.property.begin.ahk2" + } + }, + "end": "(?=})", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.property.end.ahk2" + } + }, + "name": "meta.block.property.body.ahk2", + "patterns": [ + { + "begin": "(?<=^[ \t]*)(?i:set)\\b", + "beginCaptures": { + "0": { + "name": "storage.type.setter.ahk2" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.property.setter.begin.ahk2" + } + }, + "name": "meta.block.property.setter.body.ahk2", + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.property.setter.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "name": "meta.block.property.setter.body.ahk2", + "end": "(?=\\n)", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + } + ] + }, + { + "begin": "(?<=^[ \t]*)(?i:get)\\b", + "beginCaptures": { + "0": { + "name": "storage.type.getter.ahk2" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.property.getter.begin.ahk2" + } + }, + "name": "meta.block.property.getter.body.ahk2", + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.property.getter.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "name": "meta.block.property.getter.body.ahk2", + "end": "(?=\\n)", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "name": "meta.block.property.getter.body.ahk2", + "end": "(?=\\n)", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + { + "include": "#variables" + } + ] + }, + { + "include": "#class_block" + }, + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + } + ] + }, + "comments": { + "patterns": [ + { + "name": "comment.block.jsdoc.ahk2", + "begin": "^[ \t]*(\\/\\*\\*)(?!\\/)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.ahk2" + } + }, + "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.ahk2" + } + }, + "patterns": [ + { + "include": "#docblock" + } + ] + }, + { + "name": "comment.block.ahk2", + "begin": "(?<=^[ \t]*)(\\/\\*)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.ahk2" + } + }, + "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.ahk2" + } + } + }, + { + "name": "comment.line.ahk2", + "match": "(?<=(^[ \t]*|[ \t]))(;.*)" + } + ] + }, + "compiler_directive": { + "patterns": [ + { + "name": "comment.block.ahk2", + "begin": "^[ \t]*(\\/\\*)((?i:@ahk2exe-keep))", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.ahk2" + }, + "2": { + "name": "keyword.control.directive.conditional.ahk2" + } + }, + "end": "^[ \t]*(\\*\\/)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.ahk2" + } + } + }, + { + "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-ignore(begin|end))", + "name": "keyword.control.directive.ahk2" + }, + { + "begin": "^[ \t]*(;[ \t]*@(?i:ahk2exe-let))\\b", + "beginCaptures": { + "0": { + "name": "keyword.control.directive.ahk2" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "include": "#strings" + }, + { + "include": "#numbers" + }, + { + "match": "\\b([_[:alpha:]][_[:alnum:]]*)(?=[ \t]*=)", + "name": "constant.language.ahk2" + }, + { + "match": "=", + "name": "keyword.operator.assignment.ahk2" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + } + ] + }, + { + "begin": "^[ \t]*((;[ \t]*@)(?i:include))\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.preprocessor.include.ahk2", + "patterns": [ + { + "begin": "[^ \t;]", + "end": "(?=(?:[ \t]+;))|(?=\\n)", + "name": "string.literal.include.ahk2" + }, + { + "match": "(?:[ \t]+);.*", + "name": "comment.line.ahk2" + } + ] + }, + { + "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-\\w+)\\b([ \t].*)?", + "name": "keyword.control.directive.ahk2", + "captures": { + "1": { + "name": "string.literal.ahk2" + } + } + }, + { + "match": "(?<=^|[ \t]);[ \t]*@(?:[\\w\\-]+)\\b([ \t]+(.*))?", + "name": "keyword.control.directive.ahk2", + "captures": { + "2": { + "name": "comment.line.ahk2" + } + } + } + ] + }, + "conditional_context": { + "patterns": [ + { + "include": "$self" + }, + { + "include": "#block_innards" + } + ] + }, + "continuation_section": { + "name": "meta.parens.continuation_section.ahk2", + "begin": "(?<=^[ \t]*)(\\()((((?i:join)[^ \t]*|[^ \t();]+)(?=[ \t]|$)|[ \t]+)*)((?<=[ \t]);.*)?$", + "beginCaptures": { + "1": { + "name": "punctuation.section.parens.begin.ahk2" + }, + "2": { + "patterns": [ + { + "match": "(?<=[ \t]|^[ \t]*\\()(?i:c(om(ments?)?)?|[lr]trim0?|`|join(`s|[^ \t]){0,15})(?=[ \t]|$)", + "name": "string.options.ahk2 markup.italic" + }, + { + "match": "[^ \t]+", + "name": "invalid.options.ahk2 markup.strikethrough" + } + ] + }, + "5": { + "name": "comment.line.ahk2" + } + }, + "end": "^[ \t]*(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.ahk2" + } + }, + "patterns": [ + { + "include": "#continuation_section_innards" + } + ] + }, + "continuation_section_innards": { + "patterns": [ + { + "begin": "('|\")", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.begin.ahk2" + } + }, + "end": "(\\1)|(?=^[ \t]*\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.ahk2" + } + }, + "name": "string.continuation_section_innards.ahk2", + "patterns": [ + { + "include": "#string_escaped_char" + } + ] + }, + { + "include": "#variables" + }, + { + "match": "{", + "name": "punctuation.section.block.begin.ahk2" + }, + { + "match": "}", + "name": "punctuation.section.block.end.ahk2" + }, + { + "match": "\\[", + "name": "punctuation.section.parens.begin.ahk2" + }, + { + "match": "\\]", + "name": "punctuation.section.parens.end.ahk2" + }, + { + "include": "#parens" + }, + { + "include": "$base" + } + ] + }, + "default_classes": { + "patterns": [ + { + "begin": "(?*/]\n (?:[^@<>*/]|\\*[^/])*\n)\n(?:\n \\s*\n (<)\n ([^>\\s]+)\n (>)\n)?", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.type.instance.jsdoc" + }, + "4": { + "name": "punctuation.definition.bracket.angle.begin.jsdoc" + }, + "5": { + "name": "constant.other.email.link.underline.jsdoc" + }, + "6": { + "name": "punctuation.definition.bracket.angle.end.jsdoc" + } + } + }, + { + "match": "(?x)\n((@)borrows) \\s+\n((?:[^@\\s*/]|\\*[^/])+) # \n\\s+ (as) \\s+ # as\n((?:[^@\\s*/]|\\*[^/])+) # ", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.type.instance.jsdoc" + }, + "4": { + "name": "keyword.operator.control.jsdoc" + }, + "5": { + "name": "entity.name.type.instance.jsdoc" + } + } + }, + { + "name": "meta.embedded.ahk2 meta.example.jsdoc", + "begin": "((@)example)\\s+", + "end": "(?=@|\\*+/)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "patterns": [ + { + "match": "^\\s*\\*\\s+", + "name": "comment.block.ahk2" + }, + { + "contentName": "constant.other.description.jsdoc", + "begin": "\\G(<)caption(>)", + "beginCaptures": { + "0": { + "name": "entity.name.tag.inline.jsdoc" + }, + "1": { + "name": "punctuation.definition.bracket.angle.begin.jsdoc" + }, + "2": { + "name": "punctuation.definition.bracket.angle.end.jsdoc" + } + }, + "end": "()|(?=\\*/)", + "endCaptures": { + "0": { + "name": "entity.name.tag.inline.jsdoc" + }, + "1": { + "name": "punctuation.definition.bracket.angle.begin.jsdoc" + }, + "2": { + "name": "punctuation.definition.bracket.angle.end.jsdoc" + } + }, + "patterns": [ + { + "match": "^\\s*\\*\\s", + "name": "comment.block.ahk2" + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "name": "meta.overload.ahk2", + "begin": "((@)overload)\\s+", + "end": "(?=\\n|^\\s*\\*)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "match": "(?x) ((@)kind) \\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\b", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "constant.language.symbol-type.jsdoc" + } + } + }, + { + "match": "(?x)\n((@)see)\n\\s+\n(?:\n # URL\n (\n (?=https?://)\n (?:[^\\s*]|\\*[^/])+\n )\n |\n # JSDoc namepath\n (\n (?!\n # Avoid matching bare URIs (also acceptable as links)\n https?://\n |\n # Avoid matching {@inline tags}; we match those below\n (?:\\[[^\\[\\]]*\\])? # Possible description [preceding]{@tag}\n {@(?:link|linkcode|linkplain|tutorial)\\b\n )\n # Matched namepath\n (?:[^@\\s*/]|\\*[^/])+\n )\n)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.link.underline.jsdoc" + }, + "4": { + "name": "entity.name.type.instance.jsdoc" + } + } + }, + { + "match": "(?x)\n((@)template)\n\\s+\n# One or more valid identifiers\n(\n [A-Za-z_$] # First character: non-numeric word character\n [\\w$.\\[\\]]* # Rest of identifier\n (?: # Possible list of additional identifiers\n \\s* , \\s*\n [A-Za-z_$]\n [\\w$.\\[\\]]*\n )*\n)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.jsdoc" + } + } + }, + { + "begin": "((@)typedef)\\s+(?={)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", + "patterns": [ + { + "include": "#jsdoctype" + }, + { + "name": "entity.name.type.instance.jsdoc", + "match": "(?:[^@\\s*/]|\\*[^/])+" + } + ] + }, + { + "begin": "((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\s+(?=[\\[{]|(?!\\d)\\w)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "end": "(?=\\s|\\*/|[^{}\\[\\]\\w])", + "patterns": [ + { + "include": "#jsdoctype" + }, + { + "name": "variable.other.jsdoc", + "match": "((?!\\d)\\w[\\w.\\[\\]]*)" + }, + { + "name": "variable.other.jsdoc", + "match": "(?x)\n(\\[)\\s*\n\\w+\n(?:\n (?:\\[\\])? # Foo[ ].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [\\w$]+\n)*\n(?:\n \\s*\n (=) # [foo=bar] Default parameter value\n \\s*\n (\n # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\n (?>\n \"(?:(?:\\*(?!/))|(?:\\\\(?!\"))|[^*\\\\])*?\" | # [foo=\"bar\"] Double-quoted\n '(?:(?:\\*(?!/))|(?:\\\\(?!'))|[^*\\\\])*?' | # [foo='bar'] Single-quoted\n \\[ (?:(?:\\*(?!/))|[^*])*? \\] | # [foo=[1,2]] Array literal\n (?:(?:\\*(?!/))|\\s(?!\\s*\\])|\\[.*?(?:\\]|(?=\\*/))|[^*\\s\\[\\]])* # Everything else\n )*\n )\n)?\n\\s*(?:(\\])((?:[^*\\s]|\\*[^\\s/])+)?|(?=\\*/))", + "captures": { + "1": { + "name": "punctuation.definition.optional-value.begin.bracket.square.jsdoc" + }, + "2": { + "name": "keyword.operator.assignment.jsdoc" + }, + "3": { + "name": "meta.embedded.ahk2" + }, + "4": { + "name": "punctuation.definition.optional-value.end.bracket.square.jsdoc" + }, + "5": { + "name": "invalid.illegal.syntax.jsdoc" + } + } + } + ] + }, + { + "begin": "(?x)\n(\n (@)\n (?:define|enum|exception|export|extends|lends|implements|modifies\n |namespace|private|protected|returns?|suppress|this|throws|type\n |yields?)\n)\n\\s+(?={)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", + "patterns": [ + { + "include": "#jsdoctype" + } + ] + }, + { + "match": "((@)method)\\b\\s*((\\w|[^\\x00-\\x7f])+)?", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.function.method.ahk2" + } + } + }, + { + "match": "(?x)\n(\n (@)\n (?:alias|augments|callback|constructs|emits|event|fires|exports?\n |extends|external|function|func|host|lends|listens|interface|memberof!?\n |module|mixes|mixin|name|requires|see|this|typedef|uses)\n)\n\\s+\n(\n (?:\n [^{}@\\s*] | \\*[^/]\n )+\n)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.type.instance.jsdoc" + } + } + }, + { + "contentName": "variable.other.jsdoc", + "begin": "((@)(?:default(?:value)?|license|version))\\s+(([''\"]))", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.jsdoc" + }, + "4": { + "name": "punctuation.definition.string.begin.jsdoc" + } + }, + "end": "(\\3)|(?=$|\\*/)", + "endCaptures": { + "0": { + "name": "variable.other.jsdoc" + }, + "1": { + "name": "punctuation.definition.string.end.jsdoc" + } + } + }, + { + "match": "((@)(?:default(?:value)?|license|tutorial|variation|version))\\s+([^\\s*]+)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.jsdoc" + } + } + }, + { + "name": "storage.type.class.jsdoc", + "match": "(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\b", + "captures": { + "1": { + "name": "punctuation.definition.block.tag.jsdoc" + } + } + }, + { + "include": "#inline-tags" + }, + { + "match": "((@)(?:[_$[:alpha:]][_$[:alnum:]]*))(?=\\s+)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + } + } + ] + }, + "function_call": { + "match": "([_[:alpha:]][[:alnum:]_]*+)(?=\\()", + "captures": { + "1": { + "name": "entity.name.function.ahk2", + "patterns": [ + { + "match": "(?<=\\.).+", + "name": "entity.name.function.method.ahk2" + }, + { + "include": "#variables_language" + } + ] + } + } + }, + "function_call_notparens": { + "patterns": [ + { + "match": "(?<=^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\b(?>=|\\?|\\{))|$))", + "name": "entity.name.function.ahk2", + "captures": { + "0": { + "patterns": [ + { + "include": "#function_defaultLibrary" + } + ] + } + } + }, + { + "match": "(?<=(^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\.)+)([[:alpha:]_][[:alnum:]_]*\\b)(?=$|[ \t]((?!([ \t]*[+\\-*/^&:.|]?=|<<=|>>=|\\?|\\{))|$))", + "name": "entity.name.function.method.ahk2" + } + ] + }, + "function_defaultLibrary": { + "patterns": [ + { + "match": "(?$~*!+#^]*?)(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))|~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+)[ \t]+&[ \t]+~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))([ \t]+up)?)(::)", + "beginCaptures": { + "1": { + "name": "hotkey.ahk2", + "patterns": [ + { + "match": "(?<=[ \t])&(?=[ \t]+[^ \t]+(?i:[ \t]+up)?$)", + "name": "keyword.operator.ahk2" + }, + { + "match": "(?<=(&[ \t]+|^[ \t]*))([<>$~*!+#^]*?)(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+|`[;{]|[\\x21-\\x3A\\x3C-\\x7E]|(?<=[^ \t]);)(?=([ \t]|$))", + "name": "keyword.keys.ahk2" + } + ] + }, + "7": { + "name": "keyword.keys.up.ahk2" + }, + "8": { + "name": "punctuation.definition.colon" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "match": "(?<=\\G[ \t]*)((?i:alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab)\\b|([<>]?[!+#^]){0,4}(`[{;]|(?<=\\G);|[^{;]|(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))(?=([ \t]+;.*|[ \t]*)\\n))", + "name": "keyword.keys.ahk2" + }, + { + "include": "$base" + } + ] + }, + { + "match": "(?<=^[ \t]*\\{?[ \t]*)(\\w+)(:)(?=[ \t]*([ \t];.*)?$)", + "captures": { + "1": { + "name": "entity.name.label.ahk2" + }, + "2": { + "name": "punctuation.definition.colon" + } + } + } + ] + }, + "hotstring_execute": { + "match": "^[ \t]*(:)([^:]*)(:)((`.|[^`])*?)(::)", + "captures": { + "1": { + "name": "punctuation.definition.colon" + }, + "2": { + "patterns": [ + { + "match": "(?i:(s[ipe]|[*?borstz]0?|c[01]?|k-1|[kp]\\d+|x1?))", + "name": "string.options.ahk2 markup.italic" + }, + { + "match": "[^ \t]", + "name": "invalid.options.ahk2 markup.strikethrough" + } + ] + }, + "3": { + "name": "punctuation.definition.colon" + }, + "4": { + "name": "keyword.keys.ahk2 markup.underline" + }, + "6": { + "name": "punctuation.definition.colon" + } + }, + "name": "hotstring.ahk2" + }, + "inline-tags": { + "patterns": [ + { + "name": "constant.other.description.jsdoc", + "match": "(\\[)[^\\]]+(\\])(?={@(?:link|linkcode|linkplain|tutorial))", + "captures": { + "1": { + "name": "punctuation.definition.bracket.square.begin.jsdoc" + }, + "2": { + "name": "punctuation.definition.bracket.square.end.jsdoc" + } + } + }, + { + "name": "entity.name.type.instance.jsdoc", + "begin": "({)((@)(?:link(?:code|plain)?|tutorial))\\s*", + "beginCaptures": { + "1": { + "name": "punctuation.definition.bracket.curly.begin.jsdoc" + }, + "2": { + "name": "storage.type.class.jsdoc" + }, + "3": { + "name": "punctuation.definition.inline.tag.jsdoc" + } + }, + "end": "}|(?=\\*/)", + "endCaptures": { + "0": { + "name": "punctuation.definition.bracket.curly.end.jsdoc" + } + }, + "patterns": [ + { + "match": "\\G((?=https?://)(?:[^|}\\s*]|\\*[/])+)(\\|)?", + "captures": { + "1": { + "name": "variable.other.link.underline.jsdoc" + }, + "2": { + "name": "punctuation.separator.pipe.jsdoc" + } + } + }, + { + "match": "\\G((?:[^{}@\\s|*]|\\*[^/])+)(\\|)?", + "captures": { + "1": { + "name": "variable.other.description.jsdoc" + }, + "2": { + "name": "punctuation.separator.pipe.jsdoc" + } + } + } + ] + } + ] + }, + "brackets": { + "patterns": [ + { + "match": "^\\s*\\*\\s+", + "name": "comment.block.ahk2" + }, + { + "match": "(['\"])(`\\1|.(??:=.&|^]+|[~+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or)))[ \t]*([ \t];.*)?\\n", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#operators" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "=>", + "name": "storage.type.function.arrow.ahk2" + } + ] + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "end": "(?!([*/<>?:=.]+|[+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or))))[ \t]*([ \t];.*)?(?=\\n)|(?<=^[ \t]*(?i:class|static|if|try|loop|while)[ \t]+\\w+)", + "endCaptures": { + "3": { + "name": "comment.line.ahk2" + } + }, + "patterns": [ + { + "match": "(?<=^[ \t]*)\\w+(?=(\\n|[ \t]))", + "captures": { + "0": { + "patterns": [ + { + "include": "#variables" + } + ] + } + } + }, + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + "numbers": { + "match": "(?", + "name": "storage.type.function.arrow.ahk2" + }, + { + "match": "\\.=|\\+=|-=|\\*=|/?/=", + "name": "keyword.operator.assignment.compound.ahk2" + }, + { + "match": "&=|\\^=|<<=|>>>=|>>=|\\|=", + "name": "keyword.operator.assignment.compound.bitwise.ahk2" + }, + { + "match": "<<|>>>|>>", + "name": "keyword.operator.bitwise.shift.ahk2" + }, + { + "match": "!=|<=|>=|=?=|<|>", + "name": "keyword.operator.comparison.ahk2" + }, + { + "match": "~=", + "name": "keyword.operator.regexp.ahk2" + }, + { + "match": "\\?\\?|&&|!|\\|\\|", + "name": "keyword.operator.logical.ahk2" + }, + { + "match": "&|\\||\\^|~", + "name": "keyword.operator.ahk2" + }, + { + "match": ":=", + "name": "keyword.operator.assignment.ahk2" + }, + { + "match": "\\.(?=\\w)", + "name": "punctuation.accessor.ahk2" + }, + { + "match": "\\*|/|-|\\+|\\.", + "name": "keyword.operator.ahk2" + }, + { + "match": "%", + "name": "punctuation.parens.percent.ahk2" + }, + { + "match": "\\[", + "name": "punctuation.square.begin.ahk2" + }, + { + "match": "\\]", + "name": "punctuation.square.end.ahk2" + }, + { + "match": "\\?(?=[ \t]*[,)\\]}])", + "name": "keyword.operator.optional.ahk2" + }, + { + "match": "\\?|:(?!\\:)", + "name": "keyword.operator.ternary.ahk2" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + } + ] + }, + "parens": { + "name": "meta.parens.ahk2", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.ahk2" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + "property": { + "patterns": [ + { + "name": "variable.other.property.ahk2", + "match": "\\b(?<=\\.)[_[:alnum:]]+\\b" + } + ] + }, + "pre_definition": { + "patterns": [ + { + "begin": "^[ \t]*((#)(?i:dllload|hotstring|include(again)?|mapcasesense|requires|errorstdout|definedefault(array|map|object)value|windowclass(gui|main)|singleinstance|targetcontrolerror|targetwindowerror))\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + }, + "end": "\\n", + "name": "meta.preprocessor.ahk2", + "patterns": [ + { + "match": "[^ \t;].*?(?=([ \t]+;|[ \t]*\\n))", + "name": "string.literal.ahk2" + }, + { + "match": "(?<=[ \t]);.*", + "name": "comment.line.ahk2" + } + ] + }, + { + "begin": "^[ \t]*((#)(?i:warn))\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + }, + "end": "\\n", + "name": "meta.preprocessor.ahk2", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "\\w+", + "name": "string.literal.ahk2" + }, + { + "match": "(?<=[ \t]);.*", + "name": "comment.line.ahk2" + } + ] + }, + { + "match": "^[ \t]*((#)(?i:clipboardtimeout|criticalobject(sleeptime|timeout)|hotif|hotiftimeout|inputlevel|initexec|maxthreads|maxthreadsbuffer|maxthreadsperhotkey|notrayicon|suspendexempt|usehook|usestdlib|warn|warncontinuableexception|winactivateforce))\\b", + "captures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + } + }, + { + "begin": "^[ \t]*((#)(?i:dllimport))([ \t]+(\\w+)[ \t]*(,?))?", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + }, + "4": { + "name": "entity.name.function.ahk2" + }, + "5": { + "name": "punctuation.separator.comma.ahk2" + } + }, + "end": "\\n", + "name": "meta.preprocessor.ahk2", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "[^,\\n\\r]+", + "name": "string.literal.ahk2" + } + ] + } + ] + }, + "reserved": { + "patterns": [ + { + "match": "(?(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + } + ] + }, + "2": { + "name": "comment.block.ahk2 punctuation.definition.comment.begin.ahk2" + }, + "3": { + "name": "comment.block.ahk2" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.ahk2 punctuation.definition.comment.end.ahk2" + }, + { + "match": "\\*", + "name": "comment.block.ahk2" + } + ] + }, + "5": { + "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.ahk2" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.conditional.switch.ahk2" + } + }, + "patterns": [ + { + "include": "#conditional_context" + } + ] + }, + "switch_statement": { + "name": "meta.block.switch.ahk2", + "begin": "(((?>(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))((?\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.switch.ahk2", + "begin": "\\G ?", + "end": "(?#HotIf WinActive("ahk_class Notepad") or WinActive(MyWindowTitle) +#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 +# ^^^^^ source.ahk2 keyword.control.directive.ahk2 +# ^ source.ahk2 +# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 +# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 +# ^^^^^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 +# ^ source.ahk2 meta.parens.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 +# ^ source.ahk2 +# ^^ source.ahk2 keyword.operator.expression.ahk2 +# ^ source.ahk2 +# ^^^^^^^^^ source.ahk2 entity.name.function.ahk2 support.function.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.begin.bracket.round.ahk2 +# ^^^^^^^^^^^^^ source.ahk2 meta.parens.ahk2 variable.other.ahk2 +# ^ source.ahk2 meta.parens.ahk2 punctuation.section.parens.end.bracket.round.ahk2 +>#Space::MsgBox "You pressed Win+Spacebar in Notepad or " MyWindowTitle +#^^^^^^ source.ahk2 hotkey.ahk2 keyword.keys.ahk2 +# ^^ source.ahk2 punctuation.definition.colon +# ^^^^^^ source.ahk2 variable.other.ahk2 support.function.ahk2 +# ^ source.ahk2 +# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.begin.ahk2 +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.ahk2 string.quoted.ahk2 +# ^ source.ahk2 string.quoted.ahk2 punctuation.definition.string.end.ahk2 +# ^ source.ahk2 +# ^^^^^^^^^^^^^ source.ahk2 variable.other.ahk2 +>#HotIf +#^ source.ahk2 keyword.control.directive.ahk2 punctuation.definition.directive.ahk2 +# ^^^^^ source.ahk2 keyword.control.directive.ahk2 +> \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index f1057913..cdf1a711 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,11 @@ { "compilerOptions": { - "module": "commonjs", - "target": "ES2021", - "lib": ["ES2021"], - "outDir": "out", - "rootDir": "src", - "sourceMap": true, - "composite": true + "esModuleInterop": true, + "lib": ["ESNext", "WebWorker"], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "noEmit": true, + "strict": true }, - "include": ["src"], - "exclude": ["node_modules", ".vscode-test"], - "references": [{ "path": "./client" }, { "path": "./server" }] + "include": ["client/src", "server/src"] } diff --git a/webpack.config.cli.js b/webpack.config.cli.js deleted file mode 100644 index 5b13444a..00000000 --- a/webpack.config.cli.js +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -//@ts-check - -'use strict'; - -const path = require('path'); - -/**@type {import('webpack').Configuration}*/ - -// Compile to cli -const nodeCLIConfig = /** @type WebpackConfig */ { - context: path.join(__dirname, 'server'), - mode: 'none', - target: 'node', - entry: { - cli: './cli/cli.ts', - }, - output: { - filename: '[name].js', - path: path.join(__dirname, 'server', 'cli', 'dist'), - libraryTarget: 'commonjs', - }, - resolve: { - mainFields: ['module', 'main'], - extensions: ['.ts', '.js'], // support ts-files and js-files - alias: {}, - }, - module: { - rules: [ - { - test: /\.ts$/, - exclude: /node_modules/, - use: [ - { - loader: 'ts-loader', - }, - ], - }, - ], - }, - externals: { - vscode: 'commonjs vscode', // ignored because it doesn't exist - }, - performance: { - hints: false, - }, - devtool: 'source-map', -}; -module.exports = [nodeCLIConfig]; diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 1936730b..00000000 --- a/webpack.config.js +++ /dev/null @@ -1,92 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -//@ts-check - -'use strict'; - -const path = require('path'); - -/**@type {import('webpack').Configuration}*/ - -const nodeClientConfig = /** @type WebpackConfig */ { - context: path.join(__dirname, 'client'), - mode: 'none', - target: 'node', - entry: { - extension: './src/extension.ts', - }, - output: { - filename: '[name].js', - path: path.join(__dirname, 'client', 'dist'), - libraryTarget: 'commonjs', - }, - resolve: { - mainFields: ['module', 'main'], - extensions: ['.ts', '.js'], // support ts-files and js-files - alias: {}, - }, - module: { - rules: [ - { - test: /\.ts$/, - exclude: /node_modules/, - use: [ - { - loader: 'ts-loader', - }, - ], - }, - ], - }, - externals: { - vscode: 'commonjs vscode', // ignored because it doesn't exist - }, - performance: { - hints: false, - }, - devtool: 'source-map', -}; - -const nodeServerConfig = /** @type WebpackConfig */ { - context: path.join(__dirname, 'server'), - mode: 'none', - target: 'node', - entry: { - server: './src/server.ts', - }, - output: { - filename: '[name].js', - path: path.join(__dirname, 'server', 'dist'), - libraryTarget: 'commonjs', - }, - resolve: { - mainFields: ['module', 'main'], - extensions: ['.ts', '.js'], // support ts-files and js-files - alias: {}, - }, - module: { - rules: [ - { - test: /\.ts$/, - exclude: /node_modules/, - use: [ - { - loader: 'ts-loader', - }, - ], - }, - ], - }, - externals: { - vscode: 'commonjs vscode', // ignored because it doesn't exist - }, - performance: { - hints: false, - }, - devtool: 'source-map', -}; - -module.exports = [nodeClientConfig, nodeServerConfig]; From 090fdb316b695a6ef6d19af499be6c80bd07c234 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:30:11 -0700 Subject: [PATCH 44/60] Merge upstream-main with updated env.ts (#57) Co-authored-by: thqby <294633707@qq.com> --- .gitattributes | 1 + .github/FUNDING.yml | 5 + .github/workflows/node.js.yml | 8 +- .prettierignore | 4 +- .vscode-test.mjs | 19 +- .vscode/extensions.json | 2 +- .vscode/launch.json | 38 +- .vscode/settings.json | 4 +- .vscode/tasks.json | 4 +- CHANGELOG.md | 1098 ++-- README.zh-CN.md | 363 ++ client/src/browserClientMain.ts | 29 +- client/src/config.ts | 45 +- client/src/extension.ts | 267 +- client/src/test/extension.test.ts | 366 +- .../test/formatting/array_object_style.in.ahk | 10 + ...t_style.ahk => array_object_style.out.ahk} | 32 +- client/src/test/formatting/autoclicker.in.ahk | 17 + .../src/test/formatting/autoclicker.out.ahk | 16 + client/src/test/formatting/braceStyle.in.ahk | 26 + client/src/test/formatting/braceStyle.out.ahk | 26 + docs/development.md | 11 + esbuild.mjs | 123 +- eslint.config.mjs | 50 +- package-lock.json | 1057 +++- package.json | 977 ++-- package.nls.json | 2 +- package.nls.zh-cn.json | 2 +- readme.md | 365 +- server/cli/cli.ts | 12 +- server/package.json | 2 +- server/src/ahkProvider.ts | 4 +- server/src/browserServerMain.ts | 31 +- server/src/commandProvider.ts | 45 +- server/src/common.spec.ts | 202 + server/src/common.ts | 93 +- server/src/completionProvider.ts | 43 +- server/src/config.ts | 253 - server/src/formattingProvider.ts | 10 +- server/src/lexer.spec.ts | 113 + server/src/{Lexer.ts => lexer.ts} | 355 +- server/src/localize.ts | 4 +- server/src/scriptrunner.ts | 10 +- server/src/semanticTokensProvider.ts | 6 +- server/src/server.ts | 230 +- server/src/symbolProvider.ts | 15 +- server/src/utils.ts | 19 - syntaxes/ahk2-output.tmLanguage.json | 2 +- syntaxes/ahk2.tmLanguage.json | 4718 ++++++++--------- tsconfig.json | 2 +- util/src/.gitignore | 2 + util/src/config.spec.ts | 78 + util/src/config.ts | 311 ++ util/src/env.ts | 106 + 54 files changed, 7293 insertions(+), 4340 deletions(-) create mode 100644 .github/FUNDING.yml create mode 100644 README.zh-CN.md create mode 100644 client/src/test/formatting/array_object_style.in.ahk rename client/src/test/formatting/{array_object_style.ahk => array_object_style.out.ahk} (54%) create mode 100644 client/src/test/formatting/autoclicker.in.ahk create mode 100644 client/src/test/formatting/autoclicker.out.ahk create mode 100644 client/src/test/formatting/braceStyle.in.ahk create mode 100644 client/src/test/formatting/braceStyle.out.ahk create mode 100644 docs/development.md create mode 100644 server/src/common.spec.ts delete mode 100644 server/src/config.ts create mode 100644 server/src/lexer.spec.ts rename server/src/{Lexer.ts => lexer.ts} (96%) delete mode 100644 server/src/utils.ts create mode 100644 util/src/.gitignore create mode 100644 util/src/config.spec.ts create mode 100644 util/src/config.ts create mode 100644 util/src/env.ts diff --git a/.gitattributes b/.gitattributes index 94f480de..ccfad98a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ +# Prettier defaults to LF and most files are already saved that way * text=auto eol=lf \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..508324cc --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,5 @@ +# These are supported funding model platforms + +github: thqby +custom: + - https://www.paypal.me/thqby diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index cabc9139..14607a3c 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -5,9 +5,9 @@ name: Build on: push: - branches: ["main"] + branches: ['main'] pull_request: - branches: ["main"] + branches: ['main', 'upstream-main'] workflow_dispatch: merge_group: @@ -27,6 +27,6 @@ jobs: uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - cache: "npm" + cache: 'npm' - run: npm install - - run: npm run vscode:prepublish + - run: npm run validate diff --git a/.prettierignore b/.prettierignore index 2e589f88..44b182a9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -22,7 +22,7 @@ server/src/constants.ts server/src/definitionProvider.ts server/src/formattingProvider.ts server/src/hoverProvider.ts -server/src/Lexer.ts +server/src/lexer.ts server/src/localize.ts server/src/PEFile.ts server/src/referencesProvider.ts @@ -31,4 +31,4 @@ server/src/scriptrunner.ts server/src/semanticTokensProvider.ts server/src/server.ts server/src/signatureProvider.ts -server/src/symbolProvider.ts \ No newline at end of file +server/src/symbolProvider.ts diff --git a/.vscode-test.mjs b/.vscode-test.mjs index 15777653..1fcfb459 100644 --- a/.vscode-test.mjs +++ b/.vscode-test.mjs @@ -3,23 +3,24 @@ import { defineConfig } from '@vscode/test-cli'; import { execSync } from 'child_process'; let timeout, vscode_path; -if (process.execPath.toLowerCase().endsWith('code.exe')) - timeout = 0; +if (process.execPath.toLowerCase().endsWith('code.exe')) timeout = 0; else { try { - const m = execSync('chcp 65001 && reg query HKCR\\vscode\\shell\\open\\command', { encoding: 'utf8' }) - .match(/REG_SZ\s+("([^"]+)"|\S+)/); + const m = execSync( + 'chcp 65001 && reg query HKCR\\vscode\\shell\\open\\command', + { encoding: 'utf8' }, + ).match(/REG_SZ\s+("([^"]+)"|\S+)/); vscode_path = m[2] || m[1]; - } catch { } + } catch {} } export default defineConfig({ files: 'client/dist/test/**/*.test.js', mocha: { failZero: true, - timeout + timeout, }, useInstallation: vscode_path && { - fromPath: vscode_path - } -}); \ No newline at end of file + fromPath: vscode_path, + }, +}); diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 6a3c7b3e..05eb2cd0 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,4 +3,4 @@ "connor4312.esbuild-problem-matchers", "dbaeumer.vscode-eslint" ] -} \ No newline at end of file +} diff --git a/.vscode/launch.json b/.vscode/launch.json index 38a800c4..02b02aee 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,12 +8,26 @@ "name": "Launch Client", "runtimeExecutable": "${execPath}", "preLaunchTask": "npm: watch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/client/dist/**/*.js" - ] + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/client/dist/**/*.js"] + }, + { + "type": "extensionHost", + "request": "launch", + "name": "Launch Client (e2e)", + "runtimeExecutable": "${execPath}", + "preLaunchTask": "npm: build:e2e", + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/client/dist/**/*.js"] + }, + { + "type": "extensionHost", + "request": "launch", + "name": "Launch Client (prod)", + "runtimeExecutable": "${execPath}", + "preLaunchTask": "npm: build", + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/client/dist/**/*.js"] }, { "type": "node", @@ -27,6 +41,7 @@ ] }, { + // Results go to Debug Console (Ctrl+Shift+Y) "name": "Extension Tests", "type": "extensionHost", "request": "launch", @@ -36,9 +51,7 @@ "--disable-extensions", "--extensionDevelopmentPath=${workspaceFolder}" ], - "outFiles": [ - "${workspaceFolder}/client/dist/test/**/*.js" - ], + "outFiles": ["${workspaceFolder}/client/dist/test/**/*.js"], "testConfiguration": "${workspaceFolder}/.vscode-test.mjs" }, { @@ -61,10 +74,7 @@ "compounds": [ { "name": "Client + Server", - "configurations": [ - "Launch Client", - "Attach to Server" - ] + "configurations": ["Launch Client", "Attach to Server"] } ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index f494c7af..59ccad0b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,7 @@ "typescript.tsc.autoDetect": "off", "typescript.preferences.quoteStyle": "single", "git.ignoreLimitWarning": true, - "editor.formatOnSave": false + "AutoHotkey2.InterpreterPath": "c:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe", + "typescript.tsdk": "node_modules\\typescript\\lib", + "editor.formatOnSave": true } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6670d29e..e72e1a3c 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -6,6 +6,7 @@ "script": "watch", "group": "build", "isBackground": true, + // Requires connor4312.esbuild-problem-matchers extension "problemMatcher": "$esbuild-watch" }, { @@ -13,7 +14,8 @@ "script": "watch-web", "group": "build", "isBackground": true, + // Requires connor4312.esbuild-problem-matchers extension "problemMatcher": "$esbuild-watch" } ] -} \ No newline at end of file +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 765d366c..0631e95d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,17 @@ ## 2.5.3 + - 修复[#603](https://github.com/thqby/vscode-autohotkey2-lsp/issues/603) - 修复[#605](https://github.com/thqby/vscode-autohotkey2-lsp/issues/605) ## 2.5.2 -- 修复[#591](https://github.com/thqby/vscode-autohotkey2-lsp/issues/591) -- 修复[#594](https://github.com/thqby/vscode-autohotkey2-lsp/issues/594) -- 修复[#595](https://github.com/thqby/vscode-autohotkey2-lsp/issues/595) -- 修复[#596](https://github.com/thqby/vscode-autohotkey2-lsp/issues/596) +- 修复[#591](https://github.com/thqby/vscode-autohotkey2-lsp/issues/591) +- 修复[#594](https://github.com/thqby/vscode-autohotkey2-lsp/issues/594) +- 修复[#595](https://github.com/thqby/vscode-autohotkey2-lsp/issues/595) +- 修复[#596](https://github.com/thqby/vscode-autohotkey2-lsp/issues/596) ## 2.5.1 + - 修复[#584](https://github.com/thqby/vscode-autohotkey2-lsp/issues/584) - 修复[#587](https://github.com/thqby/vscode-autohotkey2-lsp/issues/587) - [FR #565](https://github.com/thqby/vscode-autohotkey2-lsp/issues/565) @@ -17,1087 +19,1087 @@ ## 2.5.0 -- 修复[#533](https://github.com/thqby/vscode-autohotkey2-lsp/issues/533) -- 修复[#562](https://github.com/thqby/vscode-autohotkey2-lsp/issues/562) -- 修复[#563](https://github.com/thqby/vscode-autohotkey2-lsp/issues/563) -- 修复[#571](https://github.com/thqby/vscode-autohotkey2-lsp/issues/571) -- 修复[#574](https://github.com/thqby/vscode-autohotkey2-lsp/issues/574) -- 修复[#576](https://github.com/thqby/vscode-autohotkey2-lsp/issues/576) -- [FR #564](https://github.com/thqby/vscode-autohotkey2-lsp/issues/564) -- [FR #570](https://github.com/thqby/vscode-autohotkey2-lsp/issues/570) +- 修复[#533](https://github.com/thqby/vscode-autohotkey2-lsp/issues/533) +- 修复[#562](https://github.com/thqby/vscode-autohotkey2-lsp/issues/562) +- 修复[#563](https://github.com/thqby/vscode-autohotkey2-lsp/issues/563) +- 修复[#571](https://github.com/thqby/vscode-autohotkey2-lsp/issues/571) +- 修复[#574](https://github.com/thqby/vscode-autohotkey2-lsp/issues/574) +- 修复[#576](https://github.com/thqby/vscode-autohotkey2-lsp/issues/576) +- [FR #564](https://github.com/thqby/vscode-autohotkey2-lsp/issues/564) +- [FR #570](https://github.com/thqby/vscode-autohotkey2-lsp/issues/570) ## 2.4.9 -- 修复[#548](https://github.com/thqby/vscode-autohotkey2-lsp/issues/548) -- 修复[#551](https://github.com/thqby/vscode-autohotkey2-lsp/issues/551) -- 修复[#552](https://github.com/thqby/vscode-autohotkey2-lsp/issues/552) -- 修复[#554](https://github.com/thqby/vscode-autohotkey2-lsp/issues/554) -- 修复[#556](https://github.com/thqby/vscode-autohotkey2-lsp/issues/556) -- [FR #550](https://github.com/thqby/vscode-autohotkey2-lsp/issues/550) +- 修复[#548](https://github.com/thqby/vscode-autohotkey2-lsp/issues/548) +- 修复[#551](https://github.com/thqby/vscode-autohotkey2-lsp/issues/551) +- 修复[#552](https://github.com/thqby/vscode-autohotkey2-lsp/issues/552) +- 修复[#554](https://github.com/thqby/vscode-autohotkey2-lsp/issues/554) +- 修复[#556](https://github.com/thqby/vscode-autohotkey2-lsp/issues/556) +- [FR #550](https://github.com/thqby/vscode-autohotkey2-lsp/issues/550) ## 2.4.8 -- 修复[#540](https://github.com/thqby/vscode-autohotkey2-lsp/issues/540) -- 修复[#544](https://github.com/thqby/vscode-autohotkey2-lsp/issues/544) -- [FR #543](https://github.com/thqby/vscode-autohotkey2-lsp/issues/543) +- 修复[#540](https://github.com/thqby/vscode-autohotkey2-lsp/issues/540) +- 修复[#544](https://github.com/thqby/vscode-autohotkey2-lsp/issues/544) +- [FR #543](https://github.com/thqby/vscode-autohotkey2-lsp/issues/543) ## 2.4.7 -- 修复[#523](https://github.com/thqby/vscode-autohotkey2-lsp/issues/523) -- 修复[#529](https://github.com/thqby/vscode-autohotkey2-lsp/issues/529) -- [FR #518](https://github.com/thqby/vscode-autohotkey2-lsp/issues/518) +- 修复[#523](https://github.com/thqby/vscode-autohotkey2-lsp/issues/523) +- 修复[#529](https://github.com/thqby/vscode-autohotkey2-lsp/issues/529) +- [FR #518](https://github.com/thqby/vscode-autohotkey2-lsp/issues/518) ## 2.4.6 -- 修复[#511](https://github.com/thqby/vscode-autohotkey2-lsp/issues/511) -- 修复[#511](https://github.com/thqby/vscode-autohotkey2-lsp/issues/517) -- 修复[#521](https://github.com/thqby/vscode-autohotkey2-lsp/issues/521) -- 修复[#524](https://github.com/thqby/vscode-autohotkey2-lsp/issues/524) -- 修复[#525](https://github.com/thqby/vscode-autohotkey2-lsp/issues/525) -- 修复[#526](https://github.com/thqby/vscode-autohotkey2-lsp/issues/526) -- 修复[#527](https://github.com/thqby/vscode-autohotkey2-lsp/issues/527) -- 修复[#528](https://github.com/thqby/vscode-autohotkey2-lsp/issues/528) +- 修复[#511](https://github.com/thqby/vscode-autohotkey2-lsp/issues/511) +- 修复[#511](https://github.com/thqby/vscode-autohotkey2-lsp/issues/517) +- 修复[#521](https://github.com/thqby/vscode-autohotkey2-lsp/issues/521) +- 修复[#524](https://github.com/thqby/vscode-autohotkey2-lsp/issues/524) +- 修复[#525](https://github.com/thqby/vscode-autohotkey2-lsp/issues/525) +- 修复[#526](https://github.com/thqby/vscode-autohotkey2-lsp/issues/526) +- 修复[#527](https://github.com/thqby/vscode-autohotkey2-lsp/issues/527) +- 修复[#528](https://github.com/thqby/vscode-autohotkey2-lsp/issues/528) ## 2.4.4 -- 修复[#509](https://github.com/thqby/vscode-autohotkey2-lsp/issues/509) -- 修复[#510](https://github.com/thqby/vscode-autohotkey2-lsp/issues/510) +- 修复[#509](https://github.com/thqby/vscode-autohotkey2-lsp/issues/509) +- 修复[#510](https://github.com/thqby/vscode-autohotkey2-lsp/issues/510) ## 2.4.3 -- 修复[#506](https://github.com/thqby/vscode-autohotkey2-lsp/issues/506) -- 修复[#507](https://github.com/thqby/vscode-autohotkey2-lsp/issues/507) -- 修复[#508](https://github.com/thqby/vscode-autohotkey2-lsp/issues/508) +- 修复[#506](https://github.com/thqby/vscode-autohotkey2-lsp/issues/506) +- 修复[#507](https://github.com/thqby/vscode-autohotkey2-lsp/issues/507) +- 修复[#508](https://github.com/thqby/vscode-autohotkey2-lsp/issues/508) ## 2.4.2 -- 修复[#499](https://github.com/thqby/vscode-autohotkey2-lsp/issues/499) -- 修复[#503](https://github.com/thqby/vscode-autohotkey2-lsp/issues/503) -- 修复[#505](https://github.com/thqby/vscode-autohotkey2-lsp/issues/505) -- 设置`DefaultDebugger`更改为`DebugConfiguration`, 该设置用于将调试配置追加到当前启动的调试器 [#504](https://github.com/thqby/vscode-autohotkey2-lsp/issues/504) +- 修复[#499](https://github.com/thqby/vscode-autohotkey2-lsp/issues/499) +- 修复[#503](https://github.com/thqby/vscode-autohotkey2-lsp/issues/503) +- 修复[#505](https://github.com/thqby/vscode-autohotkey2-lsp/issues/505) +- 设置`DefaultDebugger`更改为`DebugConfiguration`, 该设置用于将调试配置追加到当前启动的调试器 [#504](https://github.com/thqby/vscode-autohotkey2-lsp/issues/504) ## 2.4.1 -- 修复[#496](https://github.com/thqby/vscode-autohotkey2-lsp/issues/496) -- 修复[#497](https://github.com/thqby/vscode-autohotkey2-lsp/issues/497) +- 修复[#496](https://github.com/thqby/vscode-autohotkey2-lsp/issues/496) +- 修复[#497](https://github.com/thqby/vscode-autohotkey2-lsp/issues/497) ## 2.4.0 -- 修复[#495](https://github.com/thqby/vscode-autohotkey2-lsp/issues/495) +- 修复[#495](https://github.com/thqby/vscode-autohotkey2-lsp/issues/495) ## 2.3.9 -- 修复[#491](https://github.com/thqby/vscode-autohotkey2-lsp/issues/491) -- 增加路径补全和dll导出函数补全通过标注类型`$DirPath`、`$FilePath<'jpg|png'>`、`$DllFunc` +- 修复[#491](https://github.com/thqby/vscode-autohotkey2-lsp/issues/491) +- 增加路径补全和dll导出函数补全通过标注类型`$DirPath`、`$FilePath<'jpg|png'>`、`$DllFunc` ## 2.3.8 -- 修复[#488](https://github.com/thqby/vscode-autohotkey2-lsp/issues/488) +- 修复[#488](https://github.com/thqby/vscode-autohotkey2-lsp/issues/488) ## 2.3.6 -- 修复[#484](https://github.com/thqby/vscode-autohotkey2-lsp/issues/484) -- 修复[#485](https://github.com/thqby/vscode-autohotkey2-lsp/issues/485) -- 修复[#487](https://github.com/thqby/vscode-autohotkey2-lsp/issues/487) -- [FR #486](https://github.com/thqby/vscode-autohotkey2-lsp/issues/486) +- 修复[#484](https://github.com/thqby/vscode-autohotkey2-lsp/issues/484) +- 修复[#485](https://github.com/thqby/vscode-autohotkey2-lsp/issues/485) +- 修复[#487](https://github.com/thqby/vscode-autohotkey2-lsp/issues/487) +- [FR #486](https://github.com/thqby/vscode-autohotkey2-lsp/issues/486) ## 2.3.5 -- 修复[#483](https://github.com/thqby/vscode-autohotkey2-lsp/issues/483) +- 修复[#483](https://github.com/thqby/vscode-autohotkey2-lsp/issues/483) ## 2.3.4 -- 修复[#479](https://github.com/thqby/vscode-autohotkey2-lsp/issues/479) -- 修复[#480](https://github.com/thqby/vscode-autohotkey2-lsp/issues/480) -- 修复[#481](https://github.com/thqby/vscode-autohotkey2-lsp/issues/481) +- 修复[#479](https://github.com/thqby/vscode-autohotkey2-lsp/issues/479) +- 修复[#480](https://github.com/thqby/vscode-autohotkey2-lsp/issues/480) +- 修复[#481](https://github.com/thqby/vscode-autohotkey2-lsp/issues/481) ## 2.3.3 -- 修复[#474](https://github.com/thqby/vscode-autohotkey2-lsp/issues/474) -- 修复[#475](https://github.com/thqby/vscode-autohotkey2-lsp/issues/475) -- 修复[#476](https://github.com/thqby/vscode-autohotkey2-lsp/issues/476) -- 修复[#477](https://github.com/thqby/vscode-autohotkey2-lsp/issues/477) +- 修复[#474](https://github.com/thqby/vscode-autohotkey2-lsp/issues/474) +- 修复[#475](https://github.com/thqby/vscode-autohotkey2-lsp/issues/475) +- 修复[#476](https://github.com/thqby/vscode-autohotkey2-lsp/issues/476) +- 修复[#477](https://github.com/thqby/vscode-autohotkey2-lsp/issues/477) ## 2.3.2 -- 修复[#469](https://github.com/thqby/vscode-autohotkey2-lsp/issues/469) -- 修复[#470](https://github.com/thqby/vscode-autohotkey2-lsp/issues/470) -- 修复[#472](https://github.com/thqby/vscode-autohotkey2-lsp/issues/472) -- 修复[#473](https://github.com/thqby/vscode-autohotkey2-lsp/issues/473) +- 修复[#469](https://github.com/thqby/vscode-autohotkey2-lsp/issues/469) +- 修复[#470](https://github.com/thqby/vscode-autohotkey2-lsp/issues/470) +- 修复[#472](https://github.com/thqby/vscode-autohotkey2-lsp/issues/472) +- 修复[#473](https://github.com/thqby/vscode-autohotkey2-lsp/issues/473) ## 2.3.1 -- 修复[#462](https://github.com/thqby/vscode-autohotkey2-lsp/issues/462) -- [FR #466](https://github.com/thqby/vscode-autohotkey2-lsp/issues/466) +- 修复[#462](https://github.com/thqby/vscode-autohotkey2-lsp/issues/462) +- [FR #466](https://github.com/thqby/vscode-autohotkey2-lsp/issues/466) ## 2.2.9 -- 修复[#450](https://github.com/thqby/vscode-autohotkey2-lsp/issues/450) -- 修复[#453](https://github.com/thqby/vscode-autohotkey2-lsp/issues/453) -- 修复[#456](https://github.com/thqby/vscode-autohotkey2-lsp/issues/456) -- [FR #449](https://github.com/thqby/vscode-autohotkey2-lsp/issues/449) -- [FR #452](https://github.com/thqby/vscode-autohotkey2-lsp/issues/452) +- 修复[#450](https://github.com/thqby/vscode-autohotkey2-lsp/issues/450) +- 修复[#453](https://github.com/thqby/vscode-autohotkey2-lsp/issues/453) +- 修复[#456](https://github.com/thqby/vscode-autohotkey2-lsp/issues/456) +- [FR #449](https://github.com/thqby/vscode-autohotkey2-lsp/issues/449) +- [FR #452](https://github.com/thqby/vscode-autohotkey2-lsp/issues/452) ## 2.2.8 -- 修复[#443](https://github.com/thqby/vscode-autohotkey2-lsp/issues/443) -- 修复[#445](https://github.com/thqby/vscode-autohotkey2-lsp/issues/445) -- 修复[#446](https://github.com/thqby/vscode-autohotkey2-lsp/issues/446) -- [FR #444](https://github.com/thqby/vscode-autohotkey2-lsp/issues/444) +- 修复[#443](https://github.com/thqby/vscode-autohotkey2-lsp/issues/443) +- 修复[#445](https://github.com/thqby/vscode-autohotkey2-lsp/issues/445) +- 修复[#446](https://github.com/thqby/vscode-autohotkey2-lsp/issues/446) +- [FR #444](https://github.com/thqby/vscode-autohotkey2-lsp/issues/444) ## 2.2.7 -- 修复[#432](https://github.com/thqby/vscode-autohotkey2-lsp/issues/432) -- 修复[#435](https://github.com/thqby/vscode-autohotkey2-lsp/issues/435) -- 修复[#438](https://github.com/thqby/vscode-autohotkey2-lsp/issues/438) -- 修复[#439](https://github.com/thqby/vscode-autohotkey2-lsp/issues/439) +- 修复[#432](https://github.com/thqby/vscode-autohotkey2-lsp/issues/432) +- 修复[#435](https://github.com/thqby/vscode-autohotkey2-lsp/issues/435) +- 修复[#438](https://github.com/thqby/vscode-autohotkey2-lsp/issues/438) +- 修复[#439](https://github.com/thqby/vscode-autohotkey2-lsp/issues/439) ## 2.2.6 -- 修复[#428](https://github.com/thqby/vscode-autohotkey2-lsp/issues/428) -- 修复[#429](https://github.com/thqby/vscode-autohotkey2-lsp/issues/429) -- 修复[#431](https://github.com/thqby/vscode-autohotkey2-lsp/issues/431) +- 修复[#428](https://github.com/thqby/vscode-autohotkey2-lsp/issues/428) +- 修复[#429](https://github.com/thqby/vscode-autohotkey2-lsp/issues/429) +- 修复[#431](https://github.com/thqby/vscode-autohotkey2-lsp/issues/431) ## 2.2.5 -- 修复[#422](https://github.com/thqby/vscode-autohotkey2-lsp/issues/422) -- 修复[#426](https://github.com/thqby/vscode-autohotkey2-lsp/issues/426) -- 修复[#427](https://github.com/thqby/vscode-autohotkey2-lsp/issues/427) +- 修复[#422](https://github.com/thqby/vscode-autohotkey2-lsp/issues/422) +- 修复[#426](https://github.com/thqby/vscode-autohotkey2-lsp/issues/426) +- 修复[#427](https://github.com/thqby/vscode-autohotkey2-lsp/issues/427) ## 2.2.4 -- 修复[#416](https://github.com/thqby/vscode-autohotkey2-lsp/issues/416) -- 修复[#418](https://github.com/thqby/vscode-autohotkey2-lsp/issues/418) -- 增加@补全 +- 修复[#416](https://github.com/thqby/vscode-autohotkey2-lsp/issues/416) +- 修复[#418](https://github.com/thqby/vscode-autohotkey2-lsp/issues/418) +- 增加@补全 ## 2.2.2 -- 修复[#412](https://github.com/thqby/vscode-autohotkey2-lsp/issues/412) -- 修复[#413](https://github.com/thqby/vscode-autohotkey2-lsp/issues/413) +- 修复[#412](https://github.com/thqby/vscode-autohotkey2-lsp/issues/412) +- 修复[#413](https://github.com/thqby/vscode-autohotkey2-lsp/issues/413) ## 2.2.1 -- 修复[#408](https://github.com/thqby/vscode-autohotkey2-lsp/issues/408) -- 修复[#409](https://github.com/thqby/vscode-autohotkey2-lsp/issues/409) -- 修复[#411](https://github.com/thqby/vscode-autohotkey2-lsp/issues/411) +- 修复[#408](https://github.com/thqby/vscode-autohotkey2-lsp/issues/408) +- 修复[#409](https://github.com/thqby/vscode-autohotkey2-lsp/issues/409) +- 修复[#411](https://github.com/thqby/vscode-autohotkey2-lsp/issues/411) ## 2.2.0 -- 修复[#402](https://github.com/thqby/vscode-autohotkey2-lsp/issues/402) -- 修复[#403](https://github.com/thqby/vscode-autohotkey2-lsp/issues/403) -- 修复[#405](https://github.com/thqby/vscode-autohotkey2-lsp/issues/405) -- 修复[#407](https://github.com/thqby/vscode-autohotkey2-lsp/issues/407) +- 修复[#402](https://github.com/thqby/vscode-autohotkey2-lsp/issues/402) +- 修复[#403](https://github.com/thqby/vscode-autohotkey2-lsp/issues/403) +- 修复[#405](https://github.com/thqby/vscode-autohotkey2-lsp/issues/405) +- 修复[#407](https://github.com/thqby/vscode-autohotkey2-lsp/issues/407) ## 2.1.8 -- 修复[#399](https://github.com/thqby/vscode-autohotkey2-lsp/issues/399) -- 修复[#400](https://github.com/thqby/vscode-autohotkey2-lsp/issues/400) +- 修复[#399](https://github.com/thqby/vscode-autohotkey2-lsp/issues/399) +- 修复[#400](https://github.com/thqby/vscode-autohotkey2-lsp/issues/400) ## 2.1.7 -- 修复[#392](https://github.com/thqby/vscode-autohotkey2-lsp/issues/392) -- 修复[#394](https://github.com/thqby/vscode-autohotkey2-lsp/issues/394) -- 修复[#396](https://github.com/thqby/vscode-autohotkey2-lsp/issues/396) -- 修复[#397](https://github.com/thqby/vscode-autohotkey2-lsp/issues/397) -- [FR #393](https://github.com/thqby/vscode-autohotkey2-lsp/issues/393) +- 修复[#392](https://github.com/thqby/vscode-autohotkey2-lsp/issues/392) +- 修复[#394](https://github.com/thqby/vscode-autohotkey2-lsp/issues/394) +- 修复[#396](https://github.com/thqby/vscode-autohotkey2-lsp/issues/396) +- 修复[#397](https://github.com/thqby/vscode-autohotkey2-lsp/issues/397) +- [FR #393](https://github.com/thqby/vscode-autohotkey2-lsp/issues/393) ## 2.1.6 -- 修复[#387](https://github.com/thqby/vscode-autohotkey2-lsp/issues/387) -- 修复[#390](https://github.com/thqby/vscode-autohotkey2-lsp/issues/390) +- 修复[#387](https://github.com/thqby/vscode-autohotkey2-lsp/issues/387) +- 修复[#390](https://github.com/thqby/vscode-autohotkey2-lsp/issues/390) ## 2.1.5 -- 修复[#368](https://github.com/thqby/vscode-autohotkey2-lsp/issues/368) -- 修复[#381](https://github.com/thqby/vscode-autohotkey2-lsp/issues/381) -- 修复[#383](https://github.com/thqby/vscode-autohotkey2-lsp/issues/383) -- 修复[#384](https://github.com/thqby/vscode-autohotkey2-lsp/issues/384) -- [FR #380](https://github.com/thqby/vscode-autohotkey2-lsp/issues/380) -- [FR #382](https://github.com/thqby/vscode-autohotkey2-lsp/issues/382) +- 修复[#368](https://github.com/thqby/vscode-autohotkey2-lsp/issues/368) +- 修复[#381](https://github.com/thqby/vscode-autohotkey2-lsp/issues/381) +- 修复[#383](https://github.com/thqby/vscode-autohotkey2-lsp/issues/383) +- 修复[#384](https://github.com/thqby/vscode-autohotkey2-lsp/issues/384) +- [FR #380](https://github.com/thqby/vscode-autohotkey2-lsp/issues/380) +- [FR #382](https://github.com/thqby/vscode-autohotkey2-lsp/issues/382) ## 2.1.4 -- 修复[#378](https://github.com/thqby/vscode-autohotkey2-lsp/issues/378) -- 修复[#379](https://github.com/thqby/vscode-autohotkey2-lsp/issues/379) +- 修复[#378](https://github.com/thqby/vscode-autohotkey2-lsp/issues/378) +- 修复[#379](https://github.com/thqby/vscode-autohotkey2-lsp/issues/379) ## 2.1.3 -- 修复[#371](https://github.com/thqby/vscode-autohotkey2-lsp/issues/371) -- 修复[#373](https://github.com/thqby/vscode-autohotkey2-lsp/issues/373) -- 修复[#375](https://github.com/thqby/vscode-autohotkey2-lsp/issues/375) -- 修复[#377](https://github.com/thqby/vscode-autohotkey2-lsp/issues/377) +- 修复[#371](https://github.com/thqby/vscode-autohotkey2-lsp/issues/371) +- 修复[#373](https://github.com/thqby/vscode-autohotkey2-lsp/issues/373) +- 修复[#375](https://github.com/thqby/vscode-autohotkey2-lsp/issues/375) +- 修复[#377](https://github.com/thqby/vscode-autohotkey2-lsp/issues/377) ## 2.1.2 -- 修复[#364](https://github.com/thqby/vscode-autohotkey2-lsp/issues/364) -- 修复[#366](https://github.com/thqby/vscode-autohotkey2-lsp/issues/366) -- 修复[#370](https://github.com/thqby/vscode-autohotkey2-lsp/issues/370) -- 修复[#371](https://github.com/thqby/vscode-autohotkey2-lsp/issues/371) -- 修复[#372](https://github.com/thqby/vscode-autohotkey2-lsp/issues/372) -- 支持v2.1-alpha.3语法 +- 修复[#364](https://github.com/thqby/vscode-autohotkey2-lsp/issues/364) +- 修复[#366](https://github.com/thqby/vscode-autohotkey2-lsp/issues/366) +- 修复[#370](https://github.com/thqby/vscode-autohotkey2-lsp/issues/370) +- 修复[#371](https://github.com/thqby/vscode-autohotkey2-lsp/issues/371) +- 修复[#372](https://github.com/thqby/vscode-autohotkey2-lsp/issues/372) +- 支持v2.1-alpha.3语法 ## 2.1.1 -- 支持v2.1新语法, 可选链操作符`?.`、空值合并`??=` -- 支持v2.1新语法, 类型化属性`prop: type := val` +- 支持v2.1新语法, 可选链操作符`?.`、空值合并`??=` +- 支持v2.1新语法, 类型化属性`prop: type := val` ## 2.1.0 -- 修复[#354](https://github.com/thqby/vscode-autohotkey2-lsp/issues/354) -- 修复[#356](https://github.com/thqby/vscode-autohotkey2-lsp/issues/356) -- 修复[#358](https://github.com/thqby/vscode-autohotkey2-lsp/issues/358) +- 修复[#354](https://github.com/thqby/vscode-autohotkey2-lsp/issues/354) +- 修复[#356](https://github.com/thqby/vscode-autohotkey2-lsp/issues/356) +- 修复[#358](https://github.com/thqby/vscode-autohotkey2-lsp/issues/358) ## 2.0.9 -- 修复[#351](https://github.com/thqby/vscode-autohotkey2-lsp/issues/351) -- 修复[#352](https://github.com/thqby/vscode-autohotkey2-lsp/issues/352) +- 修复[#351](https://github.com/thqby/vscode-autohotkey2-lsp/issues/351) +- 修复[#352](https://github.com/thqby/vscode-autohotkey2-lsp/issues/352) ## 2.0.8 -- 修复[#345](https://github.com/thqby/vscode-autohotkey2-lsp/issues/345) -- 修复[#348](https://github.com/thqby/vscode-autohotkey2-lsp/issues/348) +- 修复[#345](https://github.com/thqby/vscode-autohotkey2-lsp/issues/345) +- 修复[#348](https://github.com/thqby/vscode-autohotkey2-lsp/issues/348) ## 2.0.7 -- 修复[#339](https://github.com/thqby/vscode-autohotkey2-lsp/issues/339) -- 修复[#340](https://github.com/thqby/vscode-autohotkey2-lsp/issues/340) -- 修复[#341](https://github.com/thqby/vscode-autohotkey2-lsp/issues/341) -- 修复[#342](https://github.com/thqby/vscode-autohotkey2-lsp/issues/342) +- 修复[#339](https://github.com/thqby/vscode-autohotkey2-lsp/issues/339) +- 修复[#340](https://github.com/thqby/vscode-autohotkey2-lsp/issues/340) +- 修复[#341](https://github.com/thqby/vscode-autohotkey2-lsp/issues/341) +- 修复[#342](https://github.com/thqby/vscode-autohotkey2-lsp/issues/342) ## 2.0.6 -- 修复[#337](https://github.com/thqby/vscode-autohotkey2-lsp/issues/337) -- 修复[#338](https://github.com/thqby/vscode-autohotkey2-lsp/issues/338) +- 修复[#337](https://github.com/thqby/vscode-autohotkey2-lsp/issues/337) +- 修复[#338](https://github.com/thqby/vscode-autohotkey2-lsp/issues/338) ## 2.0.5 -- 修复[#333](https://github.com/thqby/vscode-autohotkey2-lsp/issues/333) -- 修复[#334](https://github.com/thqby/vscode-autohotkey2-lsp/issues/334) -- 修复[#336](https://github.com/thqby/vscode-autohotkey2-lsp/issues/336) +- 修复[#333](https://github.com/thqby/vscode-autohotkey2-lsp/issues/333) +- 修复[#334](https://github.com/thqby/vscode-autohotkey2-lsp/issues/334) +- 修复[#336](https://github.com/thqby/vscode-autohotkey2-lsp/issues/336) ## 2.0.4 -- 修复[#331](https://github.com/thqby/vscode-autohotkey2-lsp/issues/331) -- 修复[#332](https://github.com/thqby/vscode-autohotkey2-lsp/issues/332) +- 修复[#331](https://github.com/thqby/vscode-autohotkey2-lsp/issues/331) +- 修复[#332](https://github.com/thqby/vscode-autohotkey2-lsp/issues/332) ## 2.0.2 -- 修复[#324](https://github.com/thqby/vscode-autohotkey2-lsp/issues/324) -- 修复[#327](https://github.com/thqby/vscode-autohotkey2-lsp/issues/327) -- 修复[#328](https://github.com/thqby/vscode-autohotkey2-lsp/issues/328) -- 修复[#329](https://github.com/thqby/vscode-autohotkey2-lsp/issues/329) -- 修复[#330](https://github.com/thqby/vscode-autohotkey2-lsp/issues/330) -- 增加设置项`AutoHotkey2.Files.Exclude`支持扫描时跳过指定文件或文件夹 [FR #326](https://github.com/thqby/vscode-autohotkey2-lsp/issues/326) +- 修复[#324](https://github.com/thqby/vscode-autohotkey2-lsp/issues/324) +- 修复[#327](https://github.com/thqby/vscode-autohotkey2-lsp/issues/327) +- 修复[#328](https://github.com/thqby/vscode-autohotkey2-lsp/issues/328) +- 修复[#329](https://github.com/thqby/vscode-autohotkey2-lsp/issues/329) +- 修复[#330](https://github.com/thqby/vscode-autohotkey2-lsp/issues/330) +- 增加设置项`AutoHotkey2.Files.Exclude`支持扫描时跳过指定文件或文件夹 [FR #326](https://github.com/thqby/vscode-autohotkey2-lsp/issues/326) ## 2.0.1 -- 修复[#321](https://github.com/thqby/vscode-autohotkey2-lsp/issues/321) -- 修复[#244](https://github.com/thqby/vscode-autohotkey2-lsp/issues/244#issuecomment-1547153582) +- 修复[#321](https://github.com/thqby/vscode-autohotkey2-lsp/issues/321) +- 修复[#244](https://github.com/thqby/vscode-autohotkey2-lsp/issues/244#issuecomment-1547153582) ## 2.0.0 -- 修复[#319](https://github.com/thqby/vscode-autohotkey2-lsp/issues/319) -- 修复[#320](https://github.com/thqby/vscode-autohotkey2-lsp/issues/320) +- 修复[#319](https://github.com/thqby/vscode-autohotkey2-lsp/issues/319) +- 修复[#320](https://github.com/thqby/vscode-autohotkey2-lsp/issues/320) ## 1.9.9 -- 修复[#311](https://github.com/thqby/vscode-autohotkey2-lsp/issues/311) -- 修复[#313](https://github.com/thqby/vscode-autohotkey2-lsp/issues/313) -- 修复[#317](https://github.com/thqby/vscode-autohotkey2-lsp/issues/317) -- 修复[#318](https://github.com/thqby/vscode-autohotkey2-lsp/issues/318) +- 修复[#311](https://github.com/thqby/vscode-autohotkey2-lsp/issues/311) +- 修复[#313](https://github.com/thqby/vscode-autohotkey2-lsp/issues/313) +- 修复[#317](https://github.com/thqby/vscode-autohotkey2-lsp/issues/317) +- 修复[#318](https://github.com/thqby/vscode-autohotkey2-lsp/issues/318) ## 1.9.8 -- ahk_h增加winapi函数补全项(`;@include-winapi`启用) -- 诊断未赋值的变量[FR #308](https://github.com/thqby/vscode-autohotkey2-lsp/issues/308) +- ahk_h增加winapi函数补全项(`;@include-winapi`启用) +- 诊断未赋值的变量[FR #308](https://github.com/thqby/vscode-autohotkey2-lsp/issues/308) ## 1.9.7 -- 修复[#306](https://github.com/thqby/vscode-autohotkey2-lsp/issues/306) -- 支持同时运行多个脚本[#307] -- 增加命令`ahk2.extract.symbols`, 提取类、函数等信息 +- 修复[#306](https://github.com/thqby/vscode-autohotkey2-lsp/issues/306) +- 支持同时运行多个脚本[#307] +- 增加命令`ahk2.extract.symbols`, 提取类、函数等信息 ## 1.9.5 -- 修复[#300](https://github.com/thqby/vscode-autohotkey2-lsp/issues/300) -- 修复[#302](https://github.com/thqby/vscode-autohotkey2-lsp/issues/302) -- 修复[#303](https://github.com/thqby/vscode-autohotkey2-lsp/issues/303) +- 修复[#300](https://github.com/thqby/vscode-autohotkey2-lsp/issues/300) +- 修复[#302](https://github.com/thqby/vscode-autohotkey2-lsp/issues/302) +- 修复[#303](https://github.com/thqby/vscode-autohotkey2-lsp/issues/303) ## 1.9.3 -- 修复[#294](https://github.com/thqby/vscode-autohotkey2-lsp/issues/294) +- 修复[#294](https://github.com/thqby/vscode-autohotkey2-lsp/issues/294) ## 1.9.2 -- 修复[#295](https://github.com/thqby/vscode-autohotkey2-lsp/issues/295) -- 修复[#296](https://github.com/thqby/vscode-autohotkey2-lsp/issues/296) -- 修复符号重命名失效 -- 行末注释默认保留前缀留白 +- 修复[#295](https://github.com/thqby/vscode-autohotkey2-lsp/issues/295) +- 修复[#296](https://github.com/thqby/vscode-autohotkey2-lsp/issues/296) +- 修复符号重命名失效 +- 行末注释默认保留前缀留白 ## 1.9.1 -- 修复[#286](https://github.com/thqby/vscode-autohotkey2-lsp/issues/286) -- 修复[#287](https://github.com/thqby/vscode-autohotkey2-lsp/issues/287) -- 修复[#290](https://github.com/thqby/vscode-autohotkey2-lsp/issues/290) -- 修复[#292](https://github.com/thqby/vscode-autohotkey2-lsp/issues/292) +- 修复[#286](https://github.com/thqby/vscode-autohotkey2-lsp/issues/286) +- 修复[#287](https://github.com/thqby/vscode-autohotkey2-lsp/issues/287) +- 修复[#290](https://github.com/thqby/vscode-autohotkey2-lsp/issues/290) +- 修复[#292](https://github.com/thqby/vscode-autohotkey2-lsp/issues/292) ## 1.9.0 -- 修复[#282](https://github.com/thqby/vscode-autohotkey2-lsp/issues/282) -- 增加编辑器标题菜单`运行`和`调试`子菜单 +- 修复[#282](https://github.com/thqby/vscode-autohotkey2-lsp/issues/282) +- 增加编辑器标题菜单`运行`和`调试`子菜单 ## 1.8.9 -- 修复[#273](https://github.com/thqby/vscode-autohotkey2-lsp/issues/273) -- 修复[#279](https://github.com/thqby/vscode-autohotkey2-lsp/issues/279) -- 修复[#280](https://github.com/thqby/vscode-autohotkey2-lsp/issues/280) +- 修复[#273](https://github.com/thqby/vscode-autohotkey2-lsp/issues/273) +- 修复[#279](https://github.com/thqby/vscode-autohotkey2-lsp/issues/279) +- 修复[#280](https://github.com/thqby/vscode-autohotkey2-lsp/issues/280) ## 1.8.8 -- 增加Com对象成员补全 -- 修复[#272](https://github.com/thqby/vscode-autohotkey2-lsp/issues/272) -- 修复[#278](https://github.com/thqby/vscode-autohotkey2-lsp/issues/278) -- 增加格式化选项`keyword_start_with_uppercase`,`symbol_with_same_case` -- 增加支持Com对象成员补全, ProgID补全 +- 增加Com对象成员补全 +- 修复[#272](https://github.com/thqby/vscode-autohotkey2-lsp/issues/272) +- 修复[#278](https://github.com/thqby/vscode-autohotkey2-lsp/issues/278) +- 增加格式化选项`keyword_start_with_uppercase`,`symbol_with_same_case` +- 增加支持Com对象成员补全, ProgID补全 ## 1.8.7 -- 修复[#265](https://github.com/thqby/vscode-autohotkey2-lsp/issues/265) -- 修复[#266](https://github.com/thqby/vscode-autohotkey2-lsp/issues/266) -- 修复[#268](https://github.com/thqby/vscode-autohotkey2-lsp/issues/268) -- 修复[#269](https://github.com/thqby/vscode-autohotkey2-lsp/issues/269) -- 修复[#270](https://github.com/thqby/vscode-autohotkey2-lsp/issues/270) -- 增加`CompletionCommitCharacters`设置项 +- 修复[#265](https://github.com/thqby/vscode-autohotkey2-lsp/issues/265) +- 修复[#266](https://github.com/thqby/vscode-autohotkey2-lsp/issues/266) +- 修复[#268](https://github.com/thqby/vscode-autohotkey2-lsp/issues/268) +- 修复[#269](https://github.com/thqby/vscode-autohotkey2-lsp/issues/269) +- 修复[#270](https://github.com/thqby/vscode-autohotkey2-lsp/issues/270) +- 增加`CompletionCommitCharacters`设置项 ## 1.8.6 -- 修复[#260](https://github.com/thqby/vscode-autohotkey2-lsp/issues/260) -- 修复[#262](https://github.com/thqby/vscode-autohotkey2-lsp/issues/262) -- 修复[#263](https://github.com/thqby/vscode-autohotkey2-lsp/issues/263) +- 修复[#260](https://github.com/thqby/vscode-autohotkey2-lsp/issues/260) +- 修复[#262](https://github.com/thqby/vscode-autohotkey2-lsp/issues/262) +- 修复[#263](https://github.com/thqby/vscode-autohotkey2-lsp/issues/263) ## 1.8.5 -- 修复[#246](https://github.com/thqby/vscode-autohotkey2-lsp/issues/246) -- 修复[#254](https://github.com/thqby/vscode-autohotkey2-lsp/issues/254) -- 修复[#255](https://github.com/thqby/vscode-autohotkey2-lsp/issues/255) -- 修复[#256](https://github.com/thqby/vscode-autohotkey2-lsp/issues/256) +- 修复[#246](https://github.com/thqby/vscode-autohotkey2-lsp/issues/246) +- 修复[#254](https://github.com/thqby/vscode-autohotkey2-lsp/issues/254) +- 修复[#255](https://github.com/thqby/vscode-autohotkey2-lsp/issues/255) +- 修复[#256](https://github.com/thqby/vscode-autohotkey2-lsp/issues/256) ## 1.8.4 -- 增加`FormatOptions.space_after_double_colon`选项[#252](https://github.com/thqby/vscode-autohotkey2-lsp/issues/252) -- 修复[#253](https://github.com/thqby/vscode-autohotkey2-lsp/issues/253) -- 修复一些bug +- 增加`FormatOptions.space_after_double_colon`选项[#252](https://github.com/thqby/vscode-autohotkey2-lsp/issues/252) +- 修复[#253](https://github.com/thqby/vscode-autohotkey2-lsp/issues/253) +- 修复一些bug ## 1.8.3 -- 修复[#242](https://github.com/thqby/vscode-autohotkey2-lsp/issues/242) -- 修复[#245](https://github.com/thqby/vscode-autohotkey2-lsp/issues/245) -- 修复[#247](https://github.com/thqby/vscode-autohotkey2-lsp/issues/247) +- 修复[#242](https://github.com/thqby/vscode-autohotkey2-lsp/issues/242) +- 修复[#245](https://github.com/thqby/vscode-autohotkey2-lsp/issues/245) +- 修复[#247](https://github.com/thqby/vscode-autohotkey2-lsp/issues/247) ## 1.8.2 -- 修复[#236](https://github.com/thqby/vscode-autohotkey2-lsp/issues/236) -- 修复[#238](https://github.com/thqby/vscode-autohotkey2-lsp/issues/238) -- 修复[#239](https://github.com/thqby/vscode-autohotkey2-lsp/issues/239) -- 修复[#240](https://github.com/thqby/vscode-autohotkey2-lsp/issues/240) -- 增加注释开关`;@lint-disable class-static-member-check` +- 修复[#236](https://github.com/thqby/vscode-autohotkey2-lsp/issues/236) +- 修复[#238](https://github.com/thqby/vscode-autohotkey2-lsp/issues/238) +- 修复[#239](https://github.com/thqby/vscode-autohotkey2-lsp/issues/239) +- 修复[#240](https://github.com/thqby/vscode-autohotkey2-lsp/issues/240) +- 增加注释开关`;@lint-disable class-static-member-check` ## 1.8.1 -- 修复[#234](https://github.com/thqby/vscode-autohotkey2-lsp/issues/234) -- 修复[#235](https://github.com/thqby/vscode-autohotkey2-lsp/issues/235) -- 增强[#233](https://github.com/thqby/vscode-autohotkey2-lsp/issues/233) +- 修复[#234](https://github.com/thqby/vscode-autohotkey2-lsp/issues/234) +- 修复[#235](https://github.com/thqby/vscode-autohotkey2-lsp/issues/235) +- 增强[#233](https://github.com/thqby/vscode-autohotkey2-lsp/issues/233) ## 1.8.0 -- 修复[#231](https://github.com/thqby/vscode-autohotkey2-lsp/issues/231) -- 增强[#230](https://github.com/thqby/vscode-autohotkey2-lsp/issues/230) 在工作区中, 解释器路径可以设置为相对路径 -- 修复一些bug +- 修复[#231](https://github.com/thqby/vscode-autohotkey2-lsp/issues/231) +- 增强[#230](https://github.com/thqby/vscode-autohotkey2-lsp/issues/230) 在工作区中, 解释器路径可以设置为相对路径 +- 修复一些bug ## 1.7.9 -- 修复[#227](https://github.com/thqby/vscode-autohotkey2-lsp/issues/227) -- 修复[#228](https://github.com/thqby/vscode-autohotkey2-lsp/issues/228) -- 增强[#229](https://github.com/thqby/vscode-autohotkey2-lsp/issues/229) +- 修复[#227](https://github.com/thqby/vscode-autohotkey2-lsp/issues/227) +- 修复[#228](https://github.com/thqby/vscode-autohotkey2-lsp/issues/228) +- 增强[#229](https://github.com/thqby/vscode-autohotkey2-lsp/issues/229) ## 1.7.8 -- 修复格式化错误 -- 修复[#224](https://github.com/thqby/vscode-autohotkey2-lsp/issues/224) -- 修复[#225](https://github.com/thqby/vscode-autohotkey2-lsp/issues/225) +- 修复格式化错误 +- 修复[#224](https://github.com/thqby/vscode-autohotkey2-lsp/issues/224) +- 修复[#225](https://github.com/thqby/vscode-autohotkey2-lsp/issues/225) ## 1.7.7 -- 修复格式化错误 -- 加入简单返回值检查[#221](https://github.com/thqby/vscode-autohotkey2-lsp/issues/221) -- 对一部分无效的函数调用进行提示`a := MsgBox b` +- 修复格式化错误 +- 加入简单返回值检查[#221](https://github.com/thqby/vscode-autohotkey2-lsp/issues/221) +- 对一部分无效的函数调用进行提示`a := MsgBox b` ## 1.7.6 -- 增加v1/v2切换命令`ahk2.switch` -- 从其他语言切换到ahk2将不触发SwitchToV1 -- 修复格式化和查找所有引用的错误 -- 减少类似警告[#220](https://github.com/thqby/vscode-autohotkey2-lsp/issues/220) +- 增加v1/v2切换命令`ahk2.switch` +- 从其他语言切换到ahk2将不触发SwitchToV1 +- 修复格式化和查找所有引用的错误 +- 减少类似警告[#220](https://github.com/thqby/vscode-autohotkey2-lsp/issues/220) ## 1.7.5 -- 优化v1脚本识别并切换 +- 优化v1脚本识别并切换 ## 1.7.4 -- 支持指定在检测到v1脚本时触发的行为(切换至v1, 跳过触发行, 停止解析, 警告选择框)[#214](https://github.com/thqby/vscode-autohotkey2-lsp/issues/214) -- 修复[#217](https://github.com/thqby/vscode-autohotkey2-lsp/issues/217) -- 关闭未被引用的v1缓存 +- 支持指定在检测到v1脚本时触发的行为(切换至v1, 跳过触发行, 停止解析, 警告选择框)[#214](https://github.com/thqby/vscode-autohotkey2-lsp/issues/214) +- 修复[#217](https://github.com/thqby/vscode-autohotkey2-lsp/issues/217) +- 关闭未被引用的v1缓存 ## 1.7.3 -- 修复[#212](https://github.com/thqby/vscode-autohotkey2-lsp/issues/212) -- 修复[#213](https://github.com/thqby/vscode-autohotkey2-lsp/issues/213) +- 修复[#212](https://github.com/thqby/vscode-autohotkey2-lsp/issues/212) +- 修复[#213](https://github.com/thqby/vscode-autohotkey2-lsp/issues/213) ## 1.7.2 -- 修复[#208](https://github.com/thqby/vscode-autohotkey2-lsp/issues/208) -- 修复[#210](https://github.com/thqby/vscode-autohotkey2-lsp/issues/210) -- 支持`case`和`default`块折叠[#209](https://github.com/thqby/vscode-autohotkey2-lsp/issues/209) +- 修复[#208](https://github.com/thqby/vscode-autohotkey2-lsp/issues/208) +- 修复[#210](https://github.com/thqby/vscode-autohotkey2-lsp/issues/210) +- 支持`case`和`default`块折叠[#209](https://github.com/thqby/vscode-autohotkey2-lsp/issues/209) ## 1.7.1 -- 修复[#205](https://github.com/thqby/vscode-autohotkey2-lsp/issues/205) -- 修复[#206](https://github.com/thqby/vscode-autohotkey2-lsp/issues/206) +- 修复[#205](https://github.com/thqby/vscode-autohotkey2-lsp/issues/205) +- 修复[#206](https://github.com/thqby/vscode-autohotkey2-lsp/issues/206) ## 1.7.0 -- 更新lsp for sublime text4设置 +- 更新lsp for sublime text4设置 ## 1.6.8 -- 修复[#200](https://github.com/thqby/vscode-autohotkey2-lsp/issues/200) -- 修复[#202](https://github.com/thqby/vscode-autohotkey2-lsp/issues/202) -- 修复[#203](https://github.com/thqby/vscode-autohotkey2-lsp/issues/203) -- 修复`MsgBox []`格式化错误 +- 修复[#200](https://github.com/thqby/vscode-autohotkey2-lsp/issues/200) +- 修复[#202](https://github.com/thqby/vscode-autohotkey2-lsp/issues/202) +- 修复[#203](https://github.com/thqby/vscode-autohotkey2-lsp/issues/203) +- 修复`MsgBox []`格式化错误 ## 1.6.6 -- 增加了对在资源文件中的库的读取支持, `#include *libname` -- 在ahk.exe选取列表移除有UIAccess特权的exe -- 修复[#198](https://github.com/thqby/vscode-autohotkey2-lsp/issues/198) +- 增加了对在资源文件中的库的读取支持, `#include *libname` +- 在ahk.exe选取列表移除有UIAccess特权的exe +- 修复[#198](https://github.com/thqby/vscode-autohotkey2-lsp/issues/198) ## 1.6.5 -- 增强jsdoc类型标注 -- 修复热键定义处补全丢失 -- 修复[#195](https://github.com/thqby/vscode-autohotkey2-lsp/issues/195) -- 修复[#196](https://github.com/thqby/vscode-autohotkey2-lsp/issues/196) -- 修复递归超出最大调用栈[#197](https://github.com/thqby/vscode-autohotkey2-lsp/issues/197) +- 增强jsdoc类型标注 +- 修复热键定义处补全丢失 +- 修复[#195](https://github.com/thqby/vscode-autohotkey2-lsp/issues/195) +- 修复[#196](https://github.com/thqby/vscode-autohotkey2-lsp/issues/196) +- 修复递归超出最大调用栈[#197](https://github.com/thqby/vscode-autohotkey2-lsp/issues/197) ## 1.6.4 -- 增加jsdoc类型标注 -- 增加brace样式, `brace_style=-1` -- 修复函数定义未应用`brace_style`样式 -- 代码块补全应用格式化设置指定的样式[#194](https://github.com/thqby/vscode-autohotkey2-lsp/issues/194) -- 修复[#191](https://github.com/thqby/vscode-autohotkey2-lsp/issues/191) -- 修复[#193](https://github.com/thqby/vscode-autohotkey2-lsp/issues/193) +- 增加jsdoc类型标注 +- 增加brace样式, `brace_style=-1` +- 修复函数定义未应用`brace_style`样式 +- 代码块补全应用格式化设置指定的样式[#194](https://github.com/thqby/vscode-autohotkey2-lsp/issues/194) +- 修复[#191](https://github.com/thqby/vscode-autohotkey2-lsp/issues/191) +- 修复[#193](https://github.com/thqby/vscode-autohotkey2-lsp/issues/193) ## 1.6.3 -- `formatOnType`支持换行时格式化代码行并缩进 -- jsdoc支持重载函数提示 -- 修复[#185](https://github.com/thqby/vscode-autohotkey2-lsp/issues/185) -- 修复[#186](https://github.com/thqby/vscode-autohotkey2-lsp/issues/186) -- 修复[#188](https://github.com/thqby/vscode-autohotkey2-lsp/issues/188) +- `formatOnType`支持换行时格式化代码行并缩进 +- jsdoc支持重载函数提示 +- 修复[#185](https://github.com/thqby/vscode-autohotkey2-lsp/issues/185) +- 修复[#186](https://github.com/thqby/vscode-autohotkey2-lsp/issues/186) +- 修复[#188](https://github.com/thqby/vscode-autohotkey2-lsp/issues/188) ## 1.6.2 -- 优化局部格式化 -- 增加格式化选项`brace_style` -- 修复自定义设置未生效 +- 优化局部格式化 +- 增加格式化选项`brace_style` +- 修复自定义设置未生效 ## 1.6.1 -- 输入时替换中文标点 -- 优化代码格式化 -- 修复[#181](https://github.com/thqby/vscode-autohotkey2-lsp/issues/181) -- 修复[#182](https://github.com/thqby/vscode-autohotkey2-lsp/issues/182) -- 修复[#183](https://github.com/thqby/vscode-autohotkey2-lsp/issues/183) +- 输入时替换中文标点 +- 优化代码格式化 +- 修复[#181](https://github.com/thqby/vscode-autohotkey2-lsp/issues/181) +- 修复[#182](https://github.com/thqby/vscode-autohotkey2-lsp/issues/182) +- 修复[#183](https://github.com/thqby/vscode-autohotkey2-lsp/issues/183) ## 1.6.0 -- 修复[#176-#180](https://github.com/thqby/vscode-autohotkey2-lsp/issues/176) -- 修复静态函数部分bug +- 修复[#176-#180](https://github.com/thqby/vscode-autohotkey2-lsp/issues/176) +- 修复静态函数部分bug ## 1.5.9 -- 修复部分格式化错误 -- 修复符号搜索错误 -- 增加延续片段、热字串选项着色 -- 增加设置项[#173](https://github.com/thqby/vscode-autohotkey2-lsp/issues/173) -- 修复[#171](https://github.com/thqby/vscode-autohotkey2-lsp/issues/171) -- 修复[#172](https://github.com/thqby/vscode-autohotkey2-lsp/issues/172) -- 修复[#174](https://github.com/thqby/vscode-autohotkey2-lsp/issues/174) +- 修复部分格式化错误 +- 修复符号搜索错误 +- 增加延续片段、热字串选项着色 +- 增加设置项[#173](https://github.com/thqby/vscode-autohotkey2-lsp/issues/173) +- 修复[#171](https://github.com/thqby/vscode-autohotkey2-lsp/issues/171) +- 修复[#172](https://github.com/thqby/vscode-autohotkey2-lsp/issues/172) +- 修复[#174](https://github.com/thqby/vscode-autohotkey2-lsp/issues/174) ## 1.5.8 -- 修复[#169](https://github.com/thqby/vscode-autohotkey2-lsp/issues/169) -- 修复[#170](https://github.com/thqby/vscode-autohotkey2-lsp/issues/170) -- 增加`代码格式化`、`类静态成员检查`选项 +- 修复[#169](https://github.com/thqby/vscode-autohotkey2-lsp/issues/169) +- 修复[#170](https://github.com/thqby/vscode-autohotkey2-lsp/issues/170) +- 增加`代码格式化`、`类静态成员检查`选项 ## 1.5.7 -- 修复[#164](https://github.com/thqby/vscode-autohotkey2-lsp/issues/164) -- 修复[#165](https://github.com/thqby/vscode-autohotkey2-lsp/issues/165) -- 修复[#166](https://github.com/thqby/vscode-autohotkey2-lsp/issues/166) -- 修复[#167](https://github.com/thqby/vscode-autohotkey2-lsp/issues/167) -- 修复[#168](https://github.com/thqby/vscode-autohotkey2-lsp/issues/168) -- 当选择`AutoHotkeyUX.exe`时, 使用UX Launcher启动脚本 [#157](https://github.com/thqby/vscode-autohotkey2-lsp/issues/157) +- 修复[#164](https://github.com/thqby/vscode-autohotkey2-lsp/issues/164) +- 修复[#165](https://github.com/thqby/vscode-autohotkey2-lsp/issues/165) +- 修复[#166](https://github.com/thqby/vscode-autohotkey2-lsp/issues/166) +- 修复[#167](https://github.com/thqby/vscode-autohotkey2-lsp/issues/167) +- 修复[#168](https://github.com/thqby/vscode-autohotkey2-lsp/issues/168) +- 当选择`AutoHotkeyUX.exe`时, 使用UX Launcher启动脚本 [#157](https://github.com/thqby/vscode-autohotkey2-lsp/issues/157) ## 1.5.6 -- 修复[#158](https://github.com/thqby/vscode-autohotkey2-lsp/issues/158) -- 修复[#159](https://github.com/thqby/vscode-autohotkey2-lsp/issues/159) -- 修复[#160](https://github.com/thqby/vscode-autohotkey2-lsp/issues/160) -- 修复[#161](https://github.com/thqby/vscode-autohotkey2-lsp/issues/161) -- 修复[#162](https://github.com/thqby/vscode-autohotkey2-lsp/issues/162) -- 修复延续片段字符串 +- 修复[#158](https://github.com/thqby/vscode-autohotkey2-lsp/issues/158) +- 修复[#159](https://github.com/thqby/vscode-autohotkey2-lsp/issues/159) +- 修复[#160](https://github.com/thqby/vscode-autohotkey2-lsp/issues/160) +- 修复[#161](https://github.com/thqby/vscode-autohotkey2-lsp/issues/161) +- 修复[#162](https://github.com/thqby/vscode-autohotkey2-lsp/issues/162) +- 修复延续片段字符串 ## 1.5.5 -- 修复[#154](https://github.com/thqby/vscode-autohotkey2-lsp/issues/154) -- 修复[#155](https://github.com/thqby/vscode-autohotkey2-lsp/issues/155) -- 修复[#156](https://github.com/thqby/vscode-autohotkey2-lsp/issues/156) +- 修复[#154](https://github.com/thqby/vscode-autohotkey2-lsp/issues/154) +- 修复[#155](https://github.com/thqby/vscode-autohotkey2-lsp/issues/155) +- 修复[#156](https://github.com/thqby/vscode-autohotkey2-lsp/issues/156) ## 1.5.4 -- 修复[#145-#152] -- 增加支持简单`延续部分`, `::abc::\n(\nstr\n)` +- 修复[#145-#152] +- 增加支持简单`延续部分`, `::abc::\n(\nstr\n)` ## 1.5.3 -- 修复[#143](https://github.com/thqby/vscode-autohotkey2-lsp/issues/143) -- 修复[#144](https://github.com/thqby/vscode-autohotkey2-lsp/issues/144) +- 修复[#143](https://github.com/thqby/vscode-autohotkey2-lsp/issues/143) +- 修复[#144](https://github.com/thqby/vscode-autohotkey2-lsp/issues/144) ## 1.5.2 -- 修复[#139](https://github.com/thqby/vscode-autohotkey2-lsp/issues/139) -- 修复[#140](https://github.com/thqby/vscode-autohotkey2-lsp/issues/140) -- 修复[#141](https://github.com/thqby/vscode-autohotkey2-lsp/issues/141) +- 修复[#139](https://github.com/thqby/vscode-autohotkey2-lsp/issues/139) +- 修复[#140](https://github.com/thqby/vscode-autohotkey2-lsp/issues/140) +- 修复[#141](https://github.com/thqby/vscode-autohotkey2-lsp/issues/141) ## 1.5.1 -- 修复[#133](https://github.com/thqby/vscode-autohotkey2-lsp/issues/133) -- 修复[#134](https://github.com/thqby/vscode-autohotkey2-lsp/issues/134) -- 修复[#135](https://github.com/thqby/vscode-autohotkey2-lsp/issues/135) -- 修复[#136](https://github.com/thqby/vscode-autohotkey2-lsp/issues/136) -- 修复[#137](https://github.com/thqby/vscode-autohotkey2-lsp/issues/137) -- 修复[#138](https://github.com/thqby/vscode-autohotkey2-lsp/issues/138) -- 识别stdout,stderr输出的字符编码 -- `ahk2exe`的`/base`命令行参数现在是可选的 +- 修复[#133](https://github.com/thqby/vscode-autohotkey2-lsp/issues/133) +- 修复[#134](https://github.com/thqby/vscode-autohotkey2-lsp/issues/134) +- 修复[#135](https://github.com/thqby/vscode-autohotkey2-lsp/issues/135) +- 修复[#136](https://github.com/thqby/vscode-autohotkey2-lsp/issues/136) +- 修复[#137](https://github.com/thqby/vscode-autohotkey2-lsp/issues/137) +- 修复[#138](https://github.com/thqby/vscode-autohotkey2-lsp/issues/138) +- 识别stdout,stderr输出的字符编码 +- `ahk2exe`的`/base`命令行参数现在是可选的 ## 1.5.0 -- 检测到v1脚本, 词法解析器将停止解析 +- 检测到v1脚本, 词法解析器将停止解析 ## 1.4.9 -- 修复[#130](https://github.com/thqby/vscode-autohotkey2-lsp/issues/130) +- 修复[#130](https://github.com/thqby/vscode-autohotkey2-lsp/issues/130) ## 1.4.7 -- 修复[#127](https://github.com/thqby/vscode-autohotkey2-lsp/issues/127) -- 修复[#128](https://github.com/thqby/vscode-autohotkey2-lsp/issues/128) +- 修复[#127](https://github.com/thqby/vscode-autohotkey2-lsp/issues/127) +- 修复[#128](https://github.com/thqby/vscode-autohotkey2-lsp/issues/128) ## 1.4.6 -- 修复[#125](https://github.com/thqby/vscode-autohotkey2-lsp/issues/125) -- 修复[#126](https://github.com/thqby/vscode-autohotkey2-lsp/issues/126) -- 增加`[]`,`()`折叠 +- 修复[#125](https://github.com/thqby/vscode-autohotkey2-lsp/issues/125) +- 修复[#126](https://github.com/thqby/vscode-autohotkey2-lsp/issues/126) +- 增加`[]`,`()`折叠 ## 1.4.5 -- 修复[#118](https://github.com/thqby/vscode-autohotkey2-lsp/issues/118) -- 修复[#119](https://github.com/thqby/vscode-autohotkey2-lsp/issues/119) -- 修复[#120](https://github.com/thqby/vscode-autohotkey2-lsp/issues/120) -- 修复[#121](https://github.com/thqby/vscode-autohotkey2-lsp/issues/121) -- 增加beta.7函数信息 +- 修复[#118](https://github.com/thqby/vscode-autohotkey2-lsp/issues/118) +- 修复[#119](https://github.com/thqby/vscode-autohotkey2-lsp/issues/119) +- 修复[#120](https://github.com/thqby/vscode-autohotkey2-lsp/issues/120) +- 修复[#121](https://github.com/thqby/vscode-autohotkey2-lsp/issues/121) +- 增加beta.7函数信息 ## 1.4.4 -- 修复[#117](https://github.com/thqby/vscode-autohotkey2-lsp/issues/117) -- 修复部分`寻找所有引用`不正确 +- 修复[#117](https://github.com/thqby/vscode-autohotkey2-lsp/issues/117) +- 修复部分`寻找所有引用`不正确 ## 1.4.3 -- 修复解析时部分变量丢失 +- 修复解析时部分变量丢失 ## 1.4.2 -- 修复[#116](https://github.com/thqby/vscode-autohotkey2-lsp/issues/116) -- 优化关联脚本识别 +- 修复[#116](https://github.com/thqby/vscode-autohotkey2-lsp/issues/116) +- 优化关联脚本识别 ## 1.4.1 -- 修复[#114](https://github.com/thqby/vscode-autohotkey2-lsp/issues/114) -- 修复[#115](https://github.com/thqby/vscode-autohotkey2-lsp/issues/115) +- 修复[#114](https://github.com/thqby/vscode-autohotkey2-lsp/issues/114) +- 修复[#115](https://github.com/thqby/vscode-autohotkey2-lsp/issues/115) ## 1.4.0 -- 适配beta.6语法解析 -- 增加遗漏的内置函数[#111](https://github.com/thqby/vscode-autohotkey2-lsp/issues/111) -- 修复格式化错误[#110](https://github.com/thqby/vscode-autohotkey2-lsp/issues/110) +- 适配beta.6语法解析 +- 增加遗漏的内置函数[#111](https://github.com/thqby/vscode-autohotkey2-lsp/issues/111) +- 修复格式化错误[#110](https://github.com/thqby/vscode-autohotkey2-lsp/issues/110) ## 1.3.7 -- 增加空值合并运算符`??`和可选参数操作符`?` -- 修复部分dllcall补全未触发 -- 修复[#106](https://github.com/thqby/vscode-autohotkey2-lsp/issues/106) -- 修复[#107](https://github.com/thqby/vscode-autohotkey2-lsp/issues/107) -- 修复[#108](https://github.com/thqby/vscode-autohotkey2-lsp/issues/108) +- 增加空值合并运算符`??`和可选参数操作符`?` +- 修复部分dllcall补全未触发 +- 修复[#106](https://github.com/thqby/vscode-autohotkey2-lsp/issues/106) +- 修复[#107](https://github.com/thqby/vscode-autohotkey2-lsp/issues/107) +- 修复[#108](https://github.com/thqby/vscode-autohotkey2-lsp/issues/108) ## 1.3.6 -- 修复格式化错误 -- 修复部分类型推导失败 -- 修复在`coc.nvim`中获取配置失败导致语言服务器无法启动 -- 修复[#102](https://github.com/thqby/vscode-autohotkey2-lsp/issues/102) -- 修复[#104](https://github.com/thqby/vscode-autohotkey2-lsp/issues/104) -- 修复[#105](https://github.com/thqby/vscode-autohotkey2-lsp/issues/105) +- 修复格式化错误 +- 修复部分类型推导失败 +- 修复在`coc.nvim`中获取配置失败导致语言服务器无法启动 +- 修复[#102](https://github.com/thqby/vscode-autohotkey2-lsp/issues/102) +- 修复[#104](https://github.com/thqby/vscode-autohotkey2-lsp/issues/104) +- 修复[#105](https://github.com/thqby/vscode-autohotkey2-lsp/issues/105) ## 1.3.5 -- 修复[#99](https://github.com/thqby/vscode-autohotkey2-lsp/issues/99) -- 修复语法高亮的错误 [#101](https://github.com/thqby/vscode-autohotkey2-lsp/issues/101) +- 修复[#99](https://github.com/thqby/vscode-autohotkey2-lsp/issues/99) +- 修复语法高亮的错误 [#101](https://github.com/thqby/vscode-autohotkey2-lsp/issues/101) ## 1.3.4 -- 修复部分行语句无法触发参数提示 -- 修复格式化错误 [#95](https://github.com/thqby/vscode-autohotkey2-lsp/issues/95) +- 修复部分行语句无法触发参数提示 +- 修复格式化错误 [#95](https://github.com/thqby/vscode-autohotkey2-lsp/issues/95) ## 1.3.3 -- 功能移至上下文菜单 [#94](https://github.com/thqby/vscode-autohotkey2-lsp/issues/94) +- 功能移至上下文菜单 [#94](https://github.com/thqby/vscode-autohotkey2-lsp/issues/94) ## 1.3.2 -- 修复[#92](https://github.com/thqby/vscode-autohotkey2-lsp/issues/92) -- 增加打开工作区时, 子目录存在`lib`文件夹时, 将被视为脚本入口目录 [#91](https://github.com/thqby/vscode-autohotkey2-lsp/issues/91) +- 修复[#92](https://github.com/thqby/vscode-autohotkey2-lsp/issues/92) +- 增加打开工作区时, 子目录存在`lib`文件夹时, 将被视为脚本入口目录 [#91](https://github.com/thqby/vscode-autohotkey2-lsp/issues/91) ## 1.3.1 -- 修复[#84](https://github.com/thqby/vscode-autohotkey2-lsp/issues/84) -- 修复[#85](https://github.com/thqby/vscode-autohotkey2-lsp/issues/85) +- 修复[#84](https://github.com/thqby/vscode-autohotkey2-lsp/issues/84) +- 修复[#85](https://github.com/thqby/vscode-autohotkey2-lsp/issues/85) ## 1.2.9 -- 修复`try ... catch ... catch`诊断错误 -- 修复`this()`参数提示错误, 着色错误 -- 修复`prop => ...`着色错误 -- 优化代码格式化 -- 修正头文件 +- 修复`try ... catch ... catch`诊断错误 +- 修复`this()`参数提示错误, 着色错误 +- 修复`prop => ...`着色错误 +- 优化代码格式化 +- 修正头文件 ## 1.2.8 -- 修复[#79](https://github.com/thqby/vscode-autohotkey2-lsp/issues/79) -- 修复[#80](https://github.com/thqby/vscode-autohotkey2-lsp/issues/80) +- 修复[#79](https://github.com/thqby/vscode-autohotkey2-lsp/issues/79) +- 修复[#80](https://github.com/thqby/vscode-autohotkey2-lsp/issues/80) ## 1.2.7 -- 修复[#75](https://github.com/thqby/vscode-autohotkey2-lsp/issues/75) -- 修复[#76](https://github.com/thqby/vscode-autohotkey2-lsp/issues/76) -- 修复[#77](https://github.com/thqby/vscode-autohotkey2-lsp/issues/77) -- 修复[#78](https://github.com/thqby/vscode-autohotkey2-lsp/issues/78) -- 增加`#DllLoad `补全支持, `DllCall`对`#DllLoad`加载的dll提供补全及导出函数解析 -- `;@include custom.d.ahk`导入头文件增加自定义补全 +- 修复[#75](https://github.com/thqby/vscode-autohotkey2-lsp/issues/75) +- 修复[#76](https://github.com/thqby/vscode-autohotkey2-lsp/issues/76) +- 修复[#77](https://github.com/thqby/vscode-autohotkey2-lsp/issues/77) +- 修复[#78](https://github.com/thqby/vscode-autohotkey2-lsp/issues/78) +- 增加`#DllLoad `补全支持, `DllCall`对`#DllLoad`加载的dll提供补全及导出函数解析 +- `;@include custom.d.ahk`导入头文件增加自定义补全 ## 1.2.6 -- 修复[#71](https://github.com/thqby/vscode-autohotkey2-lsp/issues/71) -- 修复[#72](https://github.com/thqby/vscode-autohotkey2-lsp/issues/72) -- 修复[#73](https://github.com/thqby/vscode-autohotkey2-lsp/issues/73) -- 修复[#74](https://github.com/thqby/vscode-autohotkey2-lsp/issues/74) +- 修复[#71](https://github.com/thqby/vscode-autohotkey2-lsp/issues/71) +- 修复[#72](https://github.com/thqby/vscode-autohotkey2-lsp/issues/72) +- 修复[#73](https://github.com/thqby/vscode-autohotkey2-lsp/issues/73) +- 修复[#74](https://github.com/thqby/vscode-autohotkey2-lsp/issues/74) ## 1.2.5 -- 修复[#70](https://github.com/thqby/vscode-autohotkey2-lsp/issues/70) -- 优化代码格式化 -- 增加静态函数调用的参数检查[#23](https://github.com/thqby/vscode-autohotkey2-lsp/issues/23) +- 修复[#70](https://github.com/thqby/vscode-autohotkey2-lsp/issues/70) +- 优化代码格式化 +- 增加静态函数调用的参数检查[#23](https://github.com/thqby/vscode-autohotkey2-lsp/issues/23) ## 1.2.4 -- 修复[#69](https://github.com/thqby/vscode-autohotkey2-lsp/issues/69) +- 修复[#69](https://github.com/thqby/vscode-autohotkey2-lsp/issues/69) ## 1.2.3 -- 修复[#68](https://github.com/thqby/vscode-autohotkey2-lsp/issues/68) +- 修复[#68](https://github.com/thqby/vscode-autohotkey2-lsp/issues/68) ## 1.2.2 -- 修复[#64](https://github.com/thqby/vscode-autohotkey2-lsp/issues/64) -- 修复[#66](https://github.com/thqby/vscode-autohotkey2-lsp/issues/66) -- 修复[#67](https://github.com/thqby/vscode-autohotkey2-lsp/issues/67) -- 诊断控制流语句[#21](https://github.com/thqby/vscode-autohotkey2-lsp/issues/21) +- 修复[#64](https://github.com/thqby/vscode-autohotkey2-lsp/issues/64) +- 修复[#66](https://github.com/thqby/vscode-autohotkey2-lsp/issues/66) +- 修复[#67](https://github.com/thqby/vscode-autohotkey2-lsp/issues/67) +- 诊断控制流语句[#21](https://github.com/thqby/vscode-autohotkey2-lsp/issues/21) ## 1.2.1 -- 修复[#63](https://github.com/thqby/vscode-autohotkey2-lsp/issues/63) +- 修复[#63](https://github.com/thqby/vscode-autohotkey2-lsp/issues/63) ## 1.2.0 -- 修复一些bug +- 修复一些bug ## 1.1.9 -- 修复[#61](https://github.com/thqby/vscode-autohotkey2-lsp/issues/61) -- 修复格式化时丢失部分行 +- 修复[#61](https://github.com/thqby/vscode-autohotkey2-lsp/issues/61) +- 修复格式化时丢失部分行 ## 1.1.8 -- 修复一些问题 +- 修复一些问题 ## 1.1.6 -- 增加`DllCall`补全支持 -- 增加`WorkspaceSymbolProvider` [#60](https://github.com/thqby/vscode-autohotkey2-lsp/issues/60) +- 增加`DllCall`补全支持 +- 增加`WorkspaceSymbolProvider` [#60](https://github.com/thqby/vscode-autohotkey2-lsp/issues/60) ## 1.1.5 -- 修复[#59](https://github.com/thqby/vscode-autohotkey2-lsp/issues/59) -- 调整`AutoHotkey2.AutoLibInclude`设置项值为`'Disabled','Local','User and Standard','All'` [#58](https://github.com/thqby/vscode-autohotkey2-lsp/issues/58) -- 取消补全自动导入被`.`和`(`触发 -- 修复在无标题文件`Untitled`中,部分功能异常 +- 修复[#59](https://github.com/thqby/vscode-autohotkey2-lsp/issues/59) +- 调整`AutoHotkey2.AutoLibInclude`设置项值为`'Disabled','Local','User and Standard','All'` [#58](https://github.com/thqby/vscode-autohotkey2-lsp/issues/58) +- 取消补全自动导入被`.`和`(`触发 +- 修复在无标题文件`Untitled`中,部分功能异常 ## 1.1.4 -- 修复[#54](https://github.com/thqby/vscode-autohotkey2-lsp/issues/54) -- 修复[#55](https://github.com/thqby/vscode-autohotkey2-lsp/issues/55) -- 修复[#56](https://github.com/thqby/vscode-autohotkey2-lsp/issues/56) -- 修复[#57](https://github.com/thqby/vscode-autohotkey2-lsp/issues/57) +- 修复[#54](https://github.com/thqby/vscode-autohotkey2-lsp/issues/54) +- 修复[#55](https://github.com/thqby/vscode-autohotkey2-lsp/issues/55) +- 修复[#56](https://github.com/thqby/vscode-autohotkey2-lsp/issues/56) +- 修复[#57](https://github.com/thqby/vscode-autohotkey2-lsp/issues/57) ## 1.1.3 -- 修复关键字着色错误 +- 修复关键字着色错误 ## 1.1.2 -- 修复Node版服务器启动失败 -- 增加`给函数补全添加括号`设置项 +- 修复Node版服务器启动失败 +- 增加`给函数补全添加括号`设置项 ## 1.1.0 -- 修复[#49](https://github.com/thqby/vscode-autohotkey2-lsp/issues/49) -- 修复[#50](https://github.com/thqby/vscode-autohotkey2-lsp/issues/50) -- 支持类静态属性符号重命名, 查找所有引用 -- 插件适配web端编辑器 https://vscode.dev 和 https://github.dev +- 修复[#49](https://github.com/thqby/vscode-autohotkey2-lsp/issues/49) +- 修复[#50](https://github.com/thqby/vscode-autohotkey2-lsp/issues/50) +- 支持类静态属性符号重命名, 查找所有引用 +- 插件适配web端编辑器 https://vscode.dev 和 https://github.dev ## 1.0.8 -- 修复[#47](https://github.com/thqby/vscode-autohotkey2-lsp/issues/47)`/**\n...\n*/`将按照JSDoc格式化 -- 修复[#48](https://github.com/thqby/vscode-autohotkey2-lsp/issues/48) +- 修复[#47](https://github.com/thqby/vscode-autohotkey2-lsp/issues/47)`/**\n...\n*/`将按照JSDoc格式化 +- 修复[#48](https://github.com/thqby/vscode-autohotkey2-lsp/issues/48) ## 1.0.7 -- 优化代码格式化 -- 修复类动态属性未能准确识别this +- 优化代码格式化 +- 修复类动态属性未能准确识别this ## 1.0.6 -- 修复未能准确识别非类变量this -- 修复[#46](https://github.com/thqby/vscode-autohotkey2-lsp/issues/46) +- 修复未能准确识别非类变量this +- 修复[#46](https://github.com/thqby/vscode-autohotkey2-lsp/issues/46) ## 1.0.5 -- 修复类型推导存在的死循环 -- 修复英文版`ahk2.json`文件存在的错误 -- 修复`switch`中的`default:`着色不正确 -- 修复词法分析中胖箭头函数的局部变量识别错误 +- 修复类型推导存在的死循环 +- 修复英文版`ahk2.json`文件存在的错误 +- 修复`switch`中的`default:`着色不正确 +- 修复词法分析中胖箭头函数的局部变量识别错误 ## 1.0.4 -- 修复语法高亮的错误 -- 增加对`{prop:val}`对象定义处的属性补全支持 +- 修复语法高亮的错误 +- 增加对`{prop:val}`对象定义处的属性补全支持 ## 1.0.3 -- 加入英文版头文件([dmtr99](https://github.com/dmtr99)提供)[#45](https://github.com/thqby/vscode-autohotkey2-lsp/issues/45) +- 加入英文版头文件([dmtr99](https://github.com/dmtr99)提供)[#45](https://github.com/thqby/vscode-autohotkey2-lsp/issues/45) ## 1.0.2 -- 修复[#44](https://github.com/thqby/vscode-autohotkey2-lsp/issues/44) -- 修复`catch Error {`提示为错误 +- 修复[#44](https://github.com/thqby/vscode-autohotkey2-lsp/issues/44) +- 修复`catch Error {`提示为错误 ## 1.0.0 -- 优化快捷帮助稳定性 -- 增加语义着色对类静态成员的支持 -- 修复`#include *i `中`*i`选项未生效 -- 修复换行符为LF时, 代码格式化存在错误的问题 -- 修复`[(*)=>1]`数组中的匿名函数被识别为错误 +- 优化快捷帮助稳定性 +- 增加语义着色对类静态成员的支持 +- 修复`#include *i `中`*i`选项未生效 +- 修复换行符为LF时, 代码格式化存在错误的问题 +- 修复`[(*)=>1]`数组中的匿名函数被识别为错误 ## 0.9.3 -- 修复[#43](https://github.com/thqby/vscode-autohotkey2-lsp/issues/43) -- 增加语义着色支持 -- 修复低版本v2获取A\_环境变量失败 -- 调整文档过滤器, 插件对临时文件`Untitled`也能生效 -- `#include`增加对`A_LineFile`的解析, 增加对``补全支持 +- 修复[#43](https://github.com/thqby/vscode-autohotkey2-lsp/issues/43) +- 增加语义着色支持 +- 修复低版本v2获取A\_环境变量失败 +- 调整文档过滤器, 插件对临时文件`Untitled`也能生效 +- `#include`增加对`A_LineFile`的解析, 增加对``补全支持 ## 0.9.2 -- `coc.nvim插件`增加环境设置项, README中增加插件配置说明 +- `coc.nvim插件`增加环境设置项, README中增加插件配置说明 ## 0.9.1 -- 修复[#40](https://github.com/thqby/vscode-autohotkey2-lsp/issues/40) -- 修复[#41](https://github.com/thqby/vscode-autohotkey2-lsp/issues/41) -- 修复[#42](https://github.com/thqby/vscode-autohotkey2-lsp/issues/42) +- 修复[#40](https://github.com/thqby/vscode-autohotkey2-lsp/issues/40) +- 修复[#41](https://github.com/thqby/vscode-autohotkey2-lsp/issues/41) +- 修复[#42](https://github.com/thqby/vscode-autohotkey2-lsp/issues/42) ## 0.8.9 -- 修复胖箭头函数的局部变量出现在函数外的bug +- 修复胖箭头函数的局部变量出现在函数外的bug ## 0.8.8 -- 加入自定义折叠`;{`和`;}` -- 更新AHK_H补全项 [AHK_H beta.1下载](https://github.com/thqby/AutoHotkey_H/releases/tag/v2.0-beta.1) -- 修复switch语句中部分case高亮不正确 -- 修复`catch TypeError, ValueError`高亮不正确 +- 加入自定义折叠`;{`和`;}` +- 更新AHK_H补全项 [AHK_H beta.1下载](https://github.com/thqby/AutoHotkey_H/releases/tag/v2.0-beta.1) +- 修复switch语句中部分case高亮不正确 +- 修复`catch TypeError, ValueError`高亮不正确 ## 0.8.7 -- 修复一些可能的热键提示为错误 -- 修复函数的参数高亮不正确 -- 修复连续多个热键定义高亮不正确 [#35](https://github.com/thqby/vscode-autohotkey2-lsp/issues/35) +- 修复一些可能的热键提示为错误 +- 修复函数的参数高亮不正确 +- 修复连续多个热键定义高亮不正确 [#35](https://github.com/thqby/vscode-autohotkey2-lsp/issues/35) ## 0.8.6 -- 修复用户库标准库自动导入异常 -- 修复include可能引发的错误 [#31](https://github.com/thqby/vscode-autohotkey2-lsp/issues/31) -- 支持含特殊符号的变量 [#33](https://github.com/thqby/vscode-autohotkey2-lsp/issues/33) +- 修复用户库标准库自动导入异常 +- 修复include可能引发的错误 [#31](https://github.com/thqby/vscode-autohotkey2-lsp/issues/31) +- 支持含特殊符号的变量 [#33](https://github.com/thqby/vscode-autohotkey2-lsp/issues/33) ## 0.8.5 -- 调整配置项名, 原设置选项`Path`更名为`InterpreterPath` -- 打开文件夹或工作区时增加保存当前解释器路径 -- 修复单行热键定义`a::global b := 0`的提示错误 +- 调整配置项名, 原设置选项`Path`更名为`InterpreterPath` +- 打开文件夹或工作区时增加保存当前解释器路径 +- 修复单行热键定义`a::global b := 0`的提示错误 ## 0.8.4 -- 增加遗漏的内置变量 -- 删除废弃的指令 -- 修复属性定义中`ByRef`参数不正确的错误诊断 [#29](https://github.com/thqby/vscode-autohotkey2-lsp/issues/29) -- 增加识别h版的内置变量, 不在大纲中显示 -- 增加设置编译器额外的命令行选项 -- 修复一些赋值语句中保留词作为对象键名被提示为错误 [#32](https://github.com/thqby/vscode-autohotkey2-lsp/issues/32) -- 增加脚本解释器切换 +- 增加遗漏的内置变量 +- 删除废弃的指令 +- 修复属性定义中`ByRef`参数不正确的错误诊断 [#29](https://github.com/thqby/vscode-autohotkey2-lsp/issues/29) +- 增加识别h版的内置变量, 不在大纲中显示 +- 增加设置编译器额外的命令行选项 +- 修复一些赋值语句中保留词作为对象键名被提示为错误 [#32](https://github.com/thqby/vscode-autohotkey2-lsp/issues/32) +- 增加脚本解释器切换 ## 0.8.3 -- 更新高亮文件 [#24](https://github.com/thqby/vscode-autohotkey2-lsp/issues/24) +- 更新高亮文件 [#24](https://github.com/thqby/vscode-autohotkey2-lsp/issues/24) ## 0.8.2 -- 诊断继承类的存在 [#19](https://github.com/thqby/vscode-autohotkey2-lsp/issues/19) -- 更新类成员语法高亮 [#20](https://github.com/thqby/vscode-autohotkey2-lsp/issues/20) -- 诊断catch语句格式错误和语法高亮 [#22](https://github.com/thqby/vscode-autohotkey2-lsp/issues/22) +- 诊断继承类的存在 [#19](https://github.com/thqby/vscode-autohotkey2-lsp/issues/19) +- 更新类成员语法高亮 [#20](https://github.com/thqby/vscode-autohotkey2-lsp/issues/20) +- 诊断catch语句格式错误和语法高亮 [#22](https://github.com/thqby/vscode-autohotkey2-lsp/issues/22) ## 0.8.1 -- 修复行末尾的%被识别为行延续 -- 修复部分对象字面量被识别为错误 [#18](https://github.com/thqby/vscode-autohotkey2-lsp/issues/18) -- 修复setter中的隐藏变量提示缺少默认参数 +- 修复行末尾的%被识别为行延续 +- 修复部分对象字面量被识别为错误 [#18](https://github.com/thqby/vscode-autohotkey2-lsp/issues/18) +- 修复setter中的隐藏变量提示缺少默认参数 ## 0.8.0 -- 增加检查函数定义中的参数重复 [#12](https://github.com/thqby/vscode-autohotkey2-lsp/issues/12) -- 检查无效的胖箭头函数声明 [#13](https://github.com/thqby/vscode-autohotkey2-lsp/issues/13) -- 修复不正确的可选参数提示 [#14](https://github.com/thqby/vscode-autohotkey2-lsp/issues/14) -- 修复数值识别和高亮问题 [#15](https://github.com/thqby/vscode-autohotkey2-lsp/issues/15) [#16](https://github.com/thqby/vscode-autohotkey2-lsp/issues/16) -- 修复未识别'`s'转义字符 [#17](https://github.com/thqby/vscode-autohotkey2-lsp/issues/17) +- 增加检查函数定义中的参数重复 [#12](https://github.com/thqby/vscode-autohotkey2-lsp/issues/12) +- 检查无效的胖箭头函数声明 [#13](https://github.com/thqby/vscode-autohotkey2-lsp/issues/13) +- 修复不正确的可选参数提示 [#14](https://github.com/thqby/vscode-autohotkey2-lsp/issues/14) +- 修复数值识别和高亮问题 [#15](https://github.com/thqby/vscode-autohotkey2-lsp/issues/15) [#16](https://github.com/thqby/vscode-autohotkey2-lsp/issues/16) +- 修复未识别'`s'转义字符 [#17](https://github.com/thqby/vscode-autohotkey2-lsp/issues/17) ## 0.7.9 -- 修复h版#dllimport函数选择范围不正确, 并增加类型提示 -- 支持a136版的行延续 -- 修复一些代码格式化问题 -- 诊断与内置类/函数的冲突 +- 修复h版#dllimport函数选择范围不正确, 并增加类型提示 +- 支持a136版的行延续 +- 修复一些代码格式化问题 +- 诊断与内置类/函数的冲突 ## 0.7.8 -- 同步a137 -- 修复字符串延续bug +- 同步a137 +- 修复字符串延续bug ## 0.7.7 -- 增加解析字符串延续段`(\n'str1\nstr2'\n)` -- 更新语法高亮文件 +- 增加解析字符串延续段`(\n'str1\nstr2'\n)` +- 更新语法高亮文件 ## 0.7.6 -- 增加ahk_h补全项 +- 增加ahk_h补全项 ## 0.7.5 -- 修复格式化错误 [#11](https://github.com/thqby/vscode-autohotkey2-lsp/issues/11) -- 修复悬浮提示等不能正常显示与内置函数同名的用户函数 +- 修复格式化错误 [#11](https://github.com/thqby/vscode-autohotkey2-lsp/issues/11) +- 修复悬浮提示等不能正常显示与内置函数同名的用户函数 ## 0.7.4 -- 取消粘贴/键入时自动格式化(editor.formatOnPaste,editor.formatOnType中设置启用) -- 修复无法正确识别某些字符串('string ;comment'...) -- 修复格式化未能识别设置的缩进格式 +- 取消粘贴/键入时自动格式化(editor.formatOnPaste,editor.formatOnType中设置启用) +- 修复无法正确识别某些字符串('string ;comment'...) +- 修复格式化未能识别设置的缩进格式 ## 0.7.3 -- 粘贴格式化将在字符串/备注中不生效 [#10](https://github.com/thqby/vscode-autohotkey2-lsp/issues/10) -- 修复备注被错误的关联 +- 粘贴格式化将在字符串/备注中不生效 [#10](https://github.com/thqby/vscode-autohotkey2-lsp/issues/10) +- 修复备注被错误的关联 ## 0.7.2 -- 增加换行时自动缩进(if/while/loop ...) [#9](https://github.com/thqby/vscode-autohotkey2-lsp/issues/9) -- 变量上一行的注释将对多个变量生效(;...\na:=1, b:=2) [#8](https://github.com/thqby/vscode-autohotkey2-lsp/issues/8#issuecomment-848663235) +- 增加换行时自动缩进(if/while/loop ...) [#9](https://github.com/thqby/vscode-autohotkey2-lsp/issues/9) +- 变量上一行的注释将对多个变量生效(;...\na:=1, b:=2) [#8](https://github.com/thqby/vscode-autohotkey2-lsp/issues/8#issuecomment-848663235) ## 0.7.1 -- 修复变量的注释错乱问题 [#8](https://github.com/thqby/vscode-autohotkey2-lsp/issues/8) -- 修复getter/setter中函数无法显示参数提示 -- 注释支持多行格式的(;...\n;...) -- 修复部分class被识别为关键字 +- 修复变量的注释错乱问题 [#8](https://github.com/thqby/vscode-autohotkey2-lsp/issues/8) +- 修复getter/setter中函数无法显示参数提示 +- 注释支持多行格式的(;...\n;...) +- 修复部分class被识别为关键字 ## 0.7.0 -- 修复bug[#4](https://github.com/thqby/vscode-autohotkey2-lsp/issues/4) -- 修复对象字面量中含有in,and等提示为无效[#7](https://github.com/thqby/vscode-autohotkey2-lsp/issues/7) -- 字符串/备注中不在触发悬浮提示/定义跳转 -- 其他bug +- 修复bug[#4](https://github.com/thqby/vscode-autohotkey2-lsp/issues/4) +- 修复对象字面量中含有in,and等提示为无效[#7](https://github.com/thqby/vscode-autohotkey2-lsp/issues/7) +- 字符串/备注中不在触发悬浮提示/定义跳转 +- 其他bug ## 0.6.9 -- 修复悬浮提示/自动补全功能存在堆栈溢出的bug [#3](https://github.com/thqby/vscode-autohotkey2-lsp/issues/3) -- 修复字符串延长段未能正确地结束 [#4](https://github.com/thqby/vscode-autohotkey2-lsp/issues/4) -- 修复部分关键字被标记为错误 [#5](https://github.com/thqby/vscode-autohotkey2-lsp/issues/5) -- 减少.触发的自动补全 [#6](https://github.com/thqby/vscode-autohotkey2-lsp/issues/6) -- 更新高亮文件 +- 修复悬浮提示/自动补全功能存在堆栈溢出的bug [#3](https://github.com/thqby/vscode-autohotkey2-lsp/issues/3) +- 修复字符串延长段未能正确地结束 [#4](https://github.com/thqby/vscode-autohotkey2-lsp/issues/4) +- 修复部分关键字被标记为错误 [#5](https://github.com/thqby/vscode-autohotkey2-lsp/issues/5) +- 减少.触发的自动补全 [#6](https://github.com/thqby/vscode-autohotkey2-lsp/issues/6) +- 更新高亮文件 ## 0.6.8 -- 修复继承类的构造函数参数提示错误 +- 修复继承类的构造函数参数提示错误 ## 0.6.7 -- 修复继承内置类时, 类型推导错误的问题 -- 修复动态属性getter参数多一个的问题 -- 修复在动态属性中参数提示无法触发 -- 修复快捷帮助偶尔弹出ahk错误 +- 修复继承内置类时, 类型推导错误的问题 +- 修复动态属性getter参数多一个的问题 +- 修复在动态属性中参数提示无法触发 +- 修复快捷帮助偶尔弹出ahk错误 ## 0.6.6 -- 修复codeinchinese.chineseinputassistant插件(中文代码快速补全)的补全功能失效问题 -- 修复在函数名/方法名处无法生成注释模板 +- 修复codeinchinese.chineseinputassistant插件(中文代码快速补全)的补全功能失效问题 +- 修复在函数名/方法名处无法生成注释模板 ## 0.6.5 -- 修复函数定义参数值为unset时错误的错误诊断 +- 修复函数定义参数值为unset时错误的错误诊断 ## 0.6.4 -- 同步a133 -- 增加一些设置选项 -- 增加;TODO:标记 +- 同步a133 +- 增加一些设置选项 +- 增加;TODO:标记 ## 0.6.2 -- 增加自定义折叠;#region/;#endregion -- 修复部分错误诊断问题 -- 修复类动态属性无法折叠的问题 +- 增加自定义折叠;#region/;#endregion +- 修复部分错误诊断问题 +- 修复类动态属性无法折叠的问题 ## 0.6.1 -- 同步a131 +- 同步a131 ## 0.6.0 -- 修复函数调用[]()和()()代码格式化错误地插入空格 -- 修复类的属性定义错误的识别为其他类型的同名变量 +- 修复函数调用[]()和()()代码格式化错误地插入空格 +- 修复类的属性定义错误的识别为其他类型的同名变量 ## 0.5.9 -- 大纲中移除函数、方法的参数 -- 修复部分补全项丢失 +- 大纲中移除函数、方法的参数 +- 修复部分补全项丢失 ## 0.5.8 -- 增加a130补全项 +- 增加a130补全项 ## 0.5.7 -- 增加标签重命名和重定义错误诊断 +- 增加标签重命名和重定义错误诊断 ## 0.5.6 -- 修复闭包函数内跳转到定义、查找所有引用、符号重命名等不正确的bug +- 修复闭包函数内跳转到定义、查找所有引用、符号重命名等不正确的bug ## 0.5.4 -- 修复编译脚本在目标exe文件不存在时失败 +- 修复编译脚本在目标exe文件不存在时失败 ## 0.5.3 -- 修复代码块折叠错误的bug -- 修复代码格式化时, 空{}换行的bug +- 修复代码块折叠错误的bug +- 修复代码格式化时, 空{}换行的bug ## 0.5.2 -- 增加遗漏的函数补全 -- 增加内置函数参数提示信息 -- 修复一些bug +- 增加遗漏的函数补全 +- 增加内置函数参数提示信息 +- 修复一些bug ## 0.5.0 -- 语法解析同步a129 -- 增加多文件符号重定义错误诊断 +- 语法解析同步a129 +- 增加多文件符号重定义错误诊断 ## 0.4.8 (ahk version <= a127) -- 修复类型推导的bug -- 增加参数提示参数说明(@param 参数 说明)抽取显示 -- 修复类中的单行方法被识别为函数的bug +- 修复类型推导的bug +- 增加参数提示参数说明(@param 参数 说明)抽取显示 +- 修复类中的单行方法被识别为函数的bug ## 0.4.6 -- 修复一些bug +- 修复一些bug ## 0.4.4 -- 增加插件多语言国际化支持(中文,English) -- 增加对AutoHotkey_H版的补全支持 -- 增加库函数自动include +- 增加插件多语言国际化支持(中文,English) +- 增加对AutoHotkey_H版的补全支持 +- 增加库函数自动include ## 0.4.3 -- 修复一些bug -- 增加debug聚合,一个配置使用其他已安装的debug插件 -- 修复代码格式化后无括号函数调用省略参数时,前的空格丢失 -- 增加脚本编译功能 +- 修复一些bug +- 增加debug聚合,一个配置使用其他已安装的debug插件 +- 修复代码格式化后无括号函数调用省略参数时,前的空格丢失 +- 增加脚本编译功能 ## 0.4.2 -- 修复一些bug +- 修复一些bug ## 0.4.1 -- 修复类型推导的一些bug -- 增加自定义函数的类型推导 +- 修复类型推导的一些bug +- 增加自定义函数的类型推导 ## 0.4.0 -- 增加简单类型推导,提供相关方法、属性补全 -- 增加方法参数提示、定义跳转等支持 -- 增加颜色选择器功能 -- 增加文件保存时对当前文件信息头(/_ ... _/)中的版本号、日期自动更新 -- 增加查找所用引用和符号重命名(支持变量/函数) +- 增加简单类型推导,提供相关方法、属性补全 +- 增加方法参数提示、定义跳转等支持 +- 增加颜色选择器功能 +- 增加文件保存时对当前文件信息头(/_ ... _/)中的版本号、日期自动更新 +- 增加查找所用引用和符号重命名(支持变量/函数) ## 0.3.0 -- 修复代码格式化的一些bug -- 修复语法解析的一些bug,并增加了一些错误提示 -- 增加代码运行功能(支持运行选择部分的代码) -- 增加快速打开帮助功能(AutoHotkey.exe目录下的chm文件),并搜索关键词 +- 修复代码格式化的一些bug +- 修复语法解析的一些bug,并增加了一些错误提示 +- 增加代码运行功能(支持运行选择部分的代码) +- 增加快速打开帮助功能(AutoHotkey.exe目录下的chm文件),并搜索关键词 diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 00000000..6f582c62 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,363 @@ +[English](./README.md) | **中文** + +# AutoHotkey v2 语言支持 + +(此软件源是 https://github.com/thqby/vscode-autohotkey2-lsp 的分叉) + +[![installs](https://img.shields.io/visual-studio-marketplace/i/thqby.vscode-autohotkey2-lsp?label=Extension%20Install&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) +[![version](https://img.shields.io/visual-studio-marketplace/v/thqby.vscode-autohotkey2-lsp?label=Extension%20Version&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) +[![](https://img.shields.io/badge/Compatibility-autohotkey%20v2.0+-green?style=for-the-badge&logo=autohotkey)](https://www.autohotkey.com/) + +**仓库**: [Github](https://github.com/thqby/vscode-autohotkey2-lsp) | [Gitee](https://gitee.com/orz707/vscode-autohotkey2-lsp) + +AutoHotkey v2 语言支持 for VS Code, 功能实现基于 v2 语法分析。 +支持在`Chrome/Edge`等浏览器中使用 https://vscode.dev 或 https://github.dev/github/dev + +- [AutoHotkey v2 语言支持](#autohotkey-v2-语言支持) + - [语言特性](#语言特性) + - [重命名符号](#重命名符号) + - [错误诊断](#错误诊断) + - [智能感知](#智能感知) + - [智能提示](#智能提示) + - [大纲](#大纲) + - [语义高亮](#语义高亮) + - [代码标记](#代码标记) + - [颜色提示](#颜色提示) + - [悬停提示](#悬停提示) + - [转到定义](#转到定义) + - [查找所有引用](#查找所有引用) + - [代码格式化](#代码格式化) + - [自定义折叠](#自定义折叠) + - [声明文件](#声明文件) + - [上下文菜单](#上下文菜单) + - [快速帮助](#快速帮助) + - [运行脚本](#运行脚本) + - [运行选定的脚本](#运行选定的脚本) + - [编译脚本](#编译脚本) + - [调试脚本](#调试脚本) + - [生成注释](#生成注释) + - [在其他编辑器中使用](#在其他编辑器中使用) + - [Sublime Text 4](#sublime-text-4) + - [Vim 和 Neovim](#vim-和-neovim) + - [Emacs](#Emacs) + - [在 Web 浏览器中使用](#在-web-浏览器中使用) + +## 语言特性 + +### 重命名符号 + +作用域范围内的变量、函数名批量重命名。 + +![rename](./pic/rename.gif) + +### 错误诊断 + +简单语法错误诊断。 + +![diagnostics](./pic/diagnostics.png) + +### 智能感知 + +支持对作用域范围内的变量、函数、参数、类名、方法名智能补全(简单的类型推导),支持对 include 文件和函数库补全。 + +![snippet1](./pic/snippet.png) + +![snippet2](./pic/snippet.gif) + +### 智能提示 + +支持对函数、方法参数的智能提示。 + +![signature](./pic/signature.gif) + +### 大纲 + +1. 在左侧大纲栏目显示类、方法、函数、变量、标签、热键、热字串、区块信息 +2. 按 Ctrl + P, 输入@符号名检索并跳转 +3. 您可以在函数、变量的上一行使用分号或/\* \*/向方法添加注释, jsdoc 样式的注释可以标记变量类型 + + + +```js +/** + * @param {Array} a - a param + * @return {Integer} + */ +fn(a*) { + /** @type {Map} */ + d := Map() + /** + * @var {Map} e + * @var {Object} f + */ + e := Map(), f := {} + /** @type {(a,b)=>Integer} */ + cb := (a, b) => a + b + /** @type {ComObject} */ + wb := ComObject('Excel.Sheet.12') + return a[1] + a[2] +} +class abc { + /** @type {Map} */ + p := dosomethingandreturnmap() +} +``` + +### 语义高亮 + +语义高亮显示是语法高亮显示的补充,改进和改进语法中的语法突出显示。编辑器在来自语法的高亮显示之上应用来自语义标记的高亮显示。 +![semanticTokens](./pic/semanticTokens.png) + +### 代码标记 + +用法: 在注释代码块中添加`;;`(默认)或`; TODO ` +![codeSymbole](./pic/codeSymbol.png) + +### 颜色提示 + +计算并解析文档中的颜色,并提供颜色选择器更直观地修改颜色数据。 + +![documentcolor](./pic/documentcolor.png) + +### 悬停提示 + +支持对作用域范围内变量、函数、全局类、标签的悬停提示并显示相关备注。 +用法: 移动鼠标到相关符号上。 +![hover](./pic/hover.png) + +### 转到定义 + +1. 支持跳转到作用域范围内变量、函数、全局类、标签的声明位置。 +2. 用法: 按住 ctrl 然后移动鼠标到代码处点击。 + +![gotoDefinition](./pic/gotoDefinition.png) + +### 查找所有引用 + +查看正在使用某个变量/函数的所有源代码位置。 + +### 代码格式化 + +用法: + +- 右键弹出菜单然后点击 格式化文档。 +- 或按 `Shift+Alt+F`。 +- 支持在键入`}`时格式化代码块,在代码行结束处键入`\n`时格式化行并缩进。支持在代码区(非注释、字符串)输入中文标点时替换为英文标点。 (需要开启`editor.format OnType`) +- 支持使用格式化指令`;@format array_style: collapse, object_style: expand`改变不同块的对象样式 + +![codeFormat](./pic/codeFormat.gif) + +### 自定义折叠 + +折叠`;@region tag`和`;@endregion`之间部分, `;{`和`;}`之间部分 + +```ini +;@region tag +code +;@endregion +``` + +### 声明文件 + +声明文件是以 .d.ahk 为文件名后缀的文件, 用来描述已实现的函数或类等, 不包含代码的实现部分, 默认被同名的ahk文件引用, 语法参考扩展提供的 `ahk2.d.ahk`. 声明文件可以扩展或改写ahk内置函数或类的声明, 也可以将注释文档从源码中分离来提供多语言版本的智能感知等. + +``` +; array.d.ahk +; #ClsName represents the ahk built-in class +/** @extends {#Array} */ +class Array { + /** jsdoc-默认 */ + Filter(FilterFunc) => Array +} + +; array.zh-cn.d.ahk +; #ClsName 表示ahk内置类 +/** @extends {#Array} */ +class Array { + /** jsdoc-zh */ + Filter(FilterFunc) => Array +} + +; array.ahk +; %A_Locale% 是VSCode的显示语言 +;@reference array.%A_Locale%.d.ahk +Array.Prototype.DefineProp('Filter', { call: Array_Filter_impl }) +``` + +## 上下文菜单 + +### 快速帮助 + +打开帮助文件并导航到当前光标处的关键字。 + +### 运行脚本 + +运行当前打开的脚本。 + +### 运行选定的脚本 + +运行光标选择范围的代码片段。 + +### 编译脚本 + +编译脚本生成可执行的 EXE 文件。 + +### 调试脚本 + +无需额外配置即可启动已安装的调试扩展,支持带参数调试。 + +### 生成注释 + +为函数或方法生成 JSDOC 样式的注释文档。 + +## 在其他编辑器中使用 + +1. 安装[Node.js](https://nodejs.org/en/download/)。 +2. 用命令行下载 vscode-autohotkey2-lsp 服务端, 或通过[vscode marketplace](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp)下载并解包。 + +```shell +mkdir vscode-autohotkey2-lsp +cd vscode-autohotkey2-lsp +curl.exe -L -o install.js https://raw.githubusercontent.com/thqby/vscode-autohotkey2-lsp/main/tools/install.js +node install.js +``` + +3. 设置支持[LSP(语言服务器协议)](https://microsoft.github.io/language-server-protocol/)的编辑器的 LSP 配置, 例如 Sublime Text4, Vim, Neovim, Emacs, [等](https://microsoft.github.io/language-server-protocol/implementors/tools/)。 + +### Sublime Text 4 + +- `Package Control: Install Package`, 安装[Sublime LSP](https://github.com/sublimelsp/LSP)插件 +- `Preferences: LSP Settings`, 增加 lsp 配置、语言选择器和语法高亮. 这是一个简单的[语法高亮示例](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), 存放在类似路径下 `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax` + +```json +{ + "clients": { + "lsp-ahk2": { + "enabled": true, + "command": [ + "node", + "/server/dist/server.js", + "--stdio" + ], // 更新node.exe的路径(可能已经在环境变量中,所以你不需要设置)和vscode-autohotkey2-lsp的文件夹 + "selector": "source.ahk2", // 与AutoHotkey2.sublime-syntax中的scope相同 + "schemes": ["file", "buffer", "res"], + "initializationOptions": { + "locale": "en-us", // or "zh-cn" + "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" + "CommentTags": "^;;\\s*(?.+)", + "CompleteFunctionParens": false, + "Diagnostics": { + "ClassStaticMemberCheck": true, + "ParamsCheck": true + }, + "ActionWhenV1IsDetected": "Continue", + "FormatOptions": { + "array_style": "none", // or "collapse" or "expand" + "break_chained_methods": false, + "ignore_comment": false, + "indent_string": "\t", + "max_preserve_newlines": 2, + "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" + "object_style": "none", // or "collapse" or "expand" + "preserve_newlines": true, + "space_after_double_colon": true, + "space_before_conditional": true, + "space_in_empty_paren": false, + "space_in_other": true, + "space_in_paren": false, + "wrap_line_length": 0 + }, + "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + "WorkingDirs": [], + "SymbolFoldingFromOpenBrace": false + } + } + }, + "semantic_highlighting": true +} +``` + +### Vim 和 Neovim + +#### COC + +- 下载[coc.nvim 插件](https://github.com/neoclide/coc.nvim)。 + +```bat +cd $VIMRUNTIME\plugin +git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 +``` + +- 打开(n)vim, 输入命令 `:CocConfig` 进入`coc.nvim`配置文件增加配置信息。 + +```json +{ + "languageserver": { + "lsp-ahk2": { + "module": "/server/dist/server.js", + "filetypes": ["autohotkey"], + "args": ["--node-ipc"], + "initializationOptions": { + // Same as initializationOptions for Sublime Text4 + } + } + } +} +``` + +#### nvim-lspconfig + +- 下载[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)。 +- 将以下内容添加到您的NVIM配置中(init.lua 等). 确定`cmd`指向vscode-autohotkey2-lsp的安装路径,`InterpreterPath`指向AHK exe. + +```lua +local function custom_attach(client, bufnr) + require("lsp_signature").on_attach({ + bind = true, + use_lspsaga = false, + floating_window = true, + fix_pos = true, + hint_enable = true, + hi_parameter = "Search", + handler_opts = { "double" }, + }) +end + +local ahk2_configs = { + autostart = true, + cmd = { + "node", + vim.fn.expand("$HOME/vscode-autohotkey2-lsp/server/dist/server.js"), + "--stdio" + }, + filetypes = { "ahk", "autohotkey", "ah2" }, + init_options = { + locale = "en-us", + InterpreterPath = "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + -- Same as initializationOptions for Sublime Text4, convert json literal to lua dictionary literal + }, + single_file_support = true, + flags = { debounce_text_changes = 500 }, + capabilities = capabilities, + on_attach = custom_attach, +} +local configs = require "lspconfig.configs" +configs["ahk2"] = { default_config = ahk2_configs } +local nvim_lsp = require("lspconfig") +nvim_lsp.ahk2.setup({}) +``` + +### Emacs + +#### Eglot + +- 将以下内容添加到您的emacs配置文件中 + +```emacs-lisp +(add-to-list 'eglot-server-programs '(ahk-mode "node" "/server/dist/server.js" "--stdio")) + +``` + +## 在 Web 浏览器中使用 + +在`Chrome/Edge`中打开 https://github.dev 或 https://vscode.dev, 然后安装`thqby.vscode-autohotkey2-lsp`。 diff --git a/client/src/browserClientMain.ts b/client/src/browserClientMain.ts index 7b9a2408..1ce794b0 100644 --- a/client/src/browserClientMain.ts +++ b/client/src/browserClientMain.ts @@ -1,5 +1,7 @@ import { commands, ExtensionContext, languages, Range, RelativePattern, SnippetString, Uri, window, workspace, WorkspaceEdit } from 'vscode'; import { LanguageClient } from 'vscode-languageclient/browser'; +import { configPrefix } from '../../util/src/config'; +import { ClientCommand, clientGetActiveEditorInfo, clientGetWorkspaceFileContent, clientGetWorkspaceFiles, clientInsertSnippet, clientSetTextDocumentLanguage, extSwitchAHKVersion, extUpdateVersionInfo, languageClientId, languageClientName, serverGetVersionInfo } from '../../util/src/env'; let client: LanguageClient; @@ -7,14 +9,14 @@ let client: LanguageClient; export function activate(context: ExtensionContext) { const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browserServerMain.js'); /* eslint-disable-next-line */ - const request_handlers: Record any> = { - 'ahk2.getActiveTextEditorUriAndPosition': () => { + const request_handlers: Record any> = { + [clientGetActiveEditorInfo]: () => { const editor = window.activeTextEditor; if (!editor) return; const uri = editor.document.uri.toString(), position = editor.selection.end; return { uri, position: { line: position.line, character: position.character } }; }, - 'ahk2.insertSnippet': async (params: [string, Range?]) => { + [clientInsertSnippet]: async (params: [string, Range?]) => { const editor = window.activeTextEditor; if (!editor) return; if (params[1]) { @@ -23,7 +25,7 @@ export function activate(context: ExtensionContext) { } else editor.insertSnippet(new SnippetString(params[0])); }, - 'ahk2.setTextDocumentLanguage': async (params: [string, string?]) => { + [clientSetTextDocumentLanguage]: async (params: [string, string?]) => { const lang = params[1] || 'ahk'; if (!(await languages.getLanguages()).includes(lang)) { window.showErrorMessage(`Unknown language id: ${lang}`); @@ -32,7 +34,11 @@ export function activate(context: ExtensionContext) { const uri = params[0], it = workspace.textDocuments.find(it => it.uri.toString() === uri); it && languages.setTextDocumentLanguage(it, lang); }, - 'ahk2.getWorkspaceFiles': async (params: string[]) => { + /** + * Returns the list of AHK files in the workspace matching the specified folders. + * Returns all AHK files if no folders are specified. + */ + [clientGetWorkspaceFiles]: async (params: string[]): Promise => { const all = !params.length; if (workspace.workspaceFolders) { if (all) @@ -46,22 +52,23 @@ export function activate(context: ExtensionContext) { } } }, - 'ahk2.getWorkspaceFileContent': async (params: string[]) => (await workspace.openTextDocument(Uri.parse(params[0]))).getText() + /** Returns the content of the provided file. */ + [clientGetWorkspaceFileContent]: async (params: string[]): Promise => (await workspace.openTextDocument(Uri.parse(params[0]))).getText() }; - client = new LanguageClient('AutoHotkey2', 'AutoHotkey2', { + client = new LanguageClient(languageClientId, languageClientName, { documentSelector: [{ language: 'ahk2' }], markdown: { isTrusted: true, supportHtml: true }, initializationOptions: { extensionUri: !process.env.DEBUG ? context.extensionUri.toString() : unpkg_url(context), commands: Object.keys(request_handlers), - ...JSON.parse(JSON.stringify(workspace.getConfiguration('AutoHotkey2'))) + ...JSON.parse(JSON.stringify(workspace.getConfiguration(configPrefix))) } }, new Worker(serverMain.toString())); context.subscriptions.push( - commands.registerTextEditorCommand('ahk2.update.versioninfo', async textEditor => { - const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest('ahk2.getVersionInfo', textEditor.document.uri.toString()); + commands.registerTextEditorCommand(extUpdateVersionInfo, async textEditor => { + const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest(serverGetVersionInfo, textEditor.document.uri.toString()); if (!infos?.length) { await textEditor.insertSnippet(new SnippetString([ "/************************************************************************", @@ -100,7 +107,7 @@ export function activate(context: ExtensionContext) { ed.size && workspace.applyEdit(ed); } }), - commands.registerTextEditorCommand('ahk2.switch', textEditor => { + commands.registerTextEditorCommand(extSwitchAHKVersion, textEditor => { const doc = textEditor.document; languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); }), diff --git a/client/src/config.ts b/client/src/config.ts index 4ec36c0d..245a2738 100644 --- a/client/src/config.ts +++ b/client/src/config.ts @@ -1,38 +1,19 @@ -// Very similar to ahk2/server/src/config.ts -// todo dedupe config.ts +//* IDE-specific config functions import * as vscode from 'vscode'; +import { CfgKey, configPrefix } from '../../util/src/config'; -/** Defined in package.json */ -export type ShowOutput = 'always' | 'never'; - -export enum CfgKey { - //* AHK++ values - // DebugConfiguration = 'v2.debugConfiguration', - InterpreterPathV1 = 'v1.file.interpreterPath', - // InterpreterPathV2 = 'v2.file.interpreterPath', - ShowOutput = 'general.showOutput', - // Syntaxes = 'v2.general.syntaxes', - - //* thqby values - DebugConfiguration = 'debugConfiguration', - // InterpreterPathV1 = 'v1.file.interpreterPath', - InterpreterPathV2 = 'InterpreterPath', - // ShowOutput = 'general.showOutput', - Syntaxes = 'Syntaxes', -} - -// const configPrefix = 'AHK++'; // AHK++ -const configPrefix = 'AutoHotkey2'; // thqby - -/** - * Gets AHK++ config value from VS Code. - * Use `getAhkppConfig` to get the full config object. - */ -export function getCfg(key: CfgKey): T | undefined { - return getAhkppConfig().get(key); +/** Get the root config object currently persisted in the IDE */ +export function getConfigRoot() { + return vscode.workspace.getConfiguration(configPrefix); } -export function getAhkppConfig() { - return vscode.workspace.getConfiguration(configPrefix); +/** Get the config value currently persisted in the IDE */ +export function getConfigIDE( + key: CfgKey, + defaultValue: T, +): typeof defaultValue { + const rawResult = getConfigRoot().get(key); + if (rawResult === undefined) return defaultValue; + return rawResult; } diff --git a/client/src/extension.ts b/client/src/extension.ts index 4b368742..a431028c 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -28,13 +28,41 @@ import { import { resolve } from 'path'; import { ChildProcess, execSync, spawn } from 'child_process'; import { readdirSync, readFileSync, lstatSync, readlinkSync, unlinkSync, writeFileSync } from 'fs'; -import { CfgKey, getAhkppConfig, getCfg, ShowOutput } from './config'; -import { resolvePath } from './utils'; +import { CfgKey, configPrefix, ShowOutput } from '../../util/src/config'; +import { + ClientCommand, + languageClientId, + languageClientName, + outputChannelName, + clientExecuteCommand, + clientGetActiveEditorInfo, + clientInsertSnippet, + clientSetTextDocumentLanguage, + clientUpdateStatusBar, + extRun, + extSetInterpreter, + extRunSelection, + extStop, + extDebugAttach, + extDebugConfig, + extDebugParams, + extSelectSyntaxes, + extUpdateVersionInfo, + serverExportSymbols, + serverGetAHKVersion, + serverGetContent, + serverGetVersionInfo, + extExtractSymbols, + extSwitchAHKVersion, + serverResetInterpreterPath, +} from '../../util/src/env'; +import { getConfigIDE, getConfigRoot } from './config'; let client: LanguageClient, outputchannel: OutputChannel, ahkStatusBarItem: StatusBarItem; const ahkprocesses = new Map(); -let v2Interpreter = getCfg(CfgKey.InterpreterPathV2), server_is_ready = false -const textdecoders: TextDecoder[] = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; +let interpreterPath: string = getConfigIDE(CfgKey.InterpreterPath, ''), server_is_ready = false; +const textdecoders = [new TextDecoder('utf8', { fatal: true }), new TextDecoder('utf-16le', { fatal: true })]; +const isWindows = process.platform === 'win32'; let extlist: string[] = [], debugexts: Record = {}, langs: string[] = []; const loadedCollection = { 'ahk2.browse': 'Browse your file system to find AutoHotkey2 interpreter', @@ -57,8 +85,9 @@ const loadedCollection = { export function activate(context: ExtensionContext): Promise { /** Absolute path to `server.js` */ - // todo needs to start with `ahk2` for compatibility with AHK++ - const defaultServerModule = context.asAbsolutePath(`server/dist/server.js`); + const extId = context.extension.id; + // todo should be able to run as part of AHK++ and standalone (external commands will not work standalone) + const defaultServerModule = context.asAbsolutePath(`${extId.startsWith('mark-wiemer') ? 'ahk2/' : ''}server/dist/server.js`); const serverModule = process.env.VSCODE_AHK_SERVER_PATH ? context.asAbsolutePath(process.env.VSCODE_AHK_SERVER_PATH) : defaultServerModule; // If the extension is launched in debug mode then the debug server options are used @@ -73,15 +102,15 @@ export function activate(context: ExtensionContext): Promise { }; // eslint-disable-next-line @typescript-eslint/no-explicit-any - const request_handlers: Record = { - 'ahk++.executeCommand': (params: string[]) => commands.executeCommand(params.shift() as string, ...params), - 'ahk++.getActiveTextEditorUriAndPosition': () => { + const requestHandlers: Record = { + [clientExecuteCommand]: (params: string[]) => commands.executeCommand(params.shift() as string, ...params), + [clientGetActiveEditorInfo]: () => { const editor = window.activeTextEditor; if (!editor) return; const uri = editor.document.uri.toString(), position = editor.selection.end; return { uri, position }; }, - 'ahk++.insertSnippet': async (params: [string, Range?]) => { + [clientInsertSnippet]: async (params: [string, Range?]) => { const editor = window.activeTextEditor; if (!editor) return; if (params[1]) { @@ -90,7 +119,7 @@ export function activate(context: ExtensionContext): Promise { } else editor.insertSnippet(new SnippetString(params[0])); }, - 'ahk++.setTextDocumentLanguage': async (params: [string, string?]) => { + [clientSetTextDocumentLanguage]: async (params: [string, string?]) => { const lang = params[1] || 'ahk'; if (!langs.includes(lang)) { window.showErrorMessage(`Unknown language id: ${lang}`); @@ -99,9 +128,9 @@ export function activate(context: ExtensionContext): Promise { const uri = params[0], it = workspace.textDocuments.find(it => it.uri.toString() === uri); it && languages.setTextDocumentLanguage(it, lang); }, - 'ahk++.updateStatusBar': async (params: [string]) => { - v2Interpreter = params[0]; - onDidChangegetInterpreter(); + [clientUpdateStatusBar]: async (params: [string]) => { + interpreterPath = params[0]; + onDidChangeInterpreter(); } }; @@ -110,26 +139,29 @@ export function activate(context: ExtensionContext): Promise { const clientOptions: LanguageClientOptions = { documentSelector: [{ language: 'ahk2' }], markdown: { isTrusted: true, supportHtml: true }, - outputChannel: outputchannel = window.createOutputChannel('AHK++', '~ahk2-output'), - outputChannelName: 'AHK++', + outputChannel: outputchannel = window.createOutputChannel(outputChannelName, '~ahk2-output'), + outputChannelName: outputChannelName, synchronize: { fileEvents: fsw }, initializationOptions: { - commands: Object.keys(request_handlers), + commands: Object.keys(requestHandlers), GlobalStorage: context.globalStorageUri.fsPath, - ...getAhkppConfig() - } + ...getConfigRoot() + }, }; + if (getConfigIDE(CfgKey.OneTrueBrace, undefined) !== undefined) + window.showWarningMessage(`Configuration "${configPrefix}.FormatOptions.one_true_brace" is no longer supported.\nPlease use "${configPrefix}.${CfgKey.BraceStyle}"`); + // Create the language client and start the client. - client = new LanguageClient('AHK++', 'AHK++', serverOptions, clientOptions); - loadlocalize(context.extensionPath + '/package.nls'); + client = new LanguageClient(languageClientId, languageClientName, serverOptions, clientOptions); + loadLocalize(context.extensionPath + '/package.nls'); textdecoders.push(new TextDecoder(env.language.startsWith('zh-') ? 'gbk' : 'windows-1252')); // Start the client. This will also launch the server let onInitialized: undefined | ((value: LanguageClient) => void); client.start().then(() => { - Object.entries(request_handlers).forEach(handler => client.onRequest(...handler)); - onDidChangegetInterpreter(); + Object.entries(requestHandlers).forEach(handler => client.onRequest(...handler)); + onDidChangeInterpreter(); if (window.activeTextEditor?.document.languageId === 'ahk2') ahkStatusBarItem.show(); server_is_ready = true; @@ -158,14 +190,15 @@ export function activate(context: ExtensionContext): Promise { let runtime: string | undefined; if (!config.__ahk2debug) { config.request ||= 'launch'; - const match_config = get_debug_configs()?.filter(it => + /** The most-populated debug config saved to the IDE */ + const bestSavedConfig = getDebugConfigs()?.filter(it => Object.entries(it).every(([k, v]) => equal(v, config[k])) )?.sort((a, b) => Object.keys(a).length - Object.keys(b).length).pop(); - const def = { ...getCfg(CfgKey.DebugConfiguration) as Partial }; + const def = getConfigIDE>(CfgKey.DebugConfiguration, {}); delete def.request, delete def.type; - Object.assign(config, def, match_config); - if (match_config?.type === 'autohotkey') - runtime = match_config.runtime_v2; + Object.assign(config, def, bestSavedConfig); + if (bestSavedConfig?.type === 'autohotkey') + runtime = bestSavedConfig.runtime_v2; // eslint-disable-next-line @typescript-eslint/no-explicit-any function equal(a: any, b: any): boolean { if (a === b) @@ -180,7 +213,7 @@ export function activate(context: ExtensionContext): Promise { } else if (config.runtime === 'autohotkey') runtime = config.runtime_v2; if (!(config.runtime ||= runtime)) { - config.runtime = resolvePath(v2Interpreter, folder?.uri.fsPath); + config.runtime = resolvePath(interpreterPath, folder?.uri.fsPath); if (ahkStatusBarItem.text.endsWith('[UIAccess]')) config.useUIAVersion = true; } @@ -198,28 +231,26 @@ export function activate(context: ExtensionContext): Promise { commands.executeCommand('setContext', 'ahk:isRunning', false); ahkStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 75); - ahkStatusBarItem.command = 'ahk++.setv2Interpreter'; + ahkStatusBarItem.command = extSetInterpreter; for (const it of [ - { text: '$(folder)syntaxes', command: { title: localize('ahk2.select'), command: 'ahk++.select.syntaxes' } }, + { text: '$(folder)syntaxes', command: { title: localize('ahk2.select'), command: extSelectSyntaxes } }, ]) - context.subscriptions.push(Object.assign(languages.createLanguageStatusItem(it.command.command, { language: 'ahk2' }), it)); - const ahkLanguageStatusItem = languages.createLanguageStatusItem('ahk++', { language: 'ahk2' }); - ahkLanguageStatusItem.text = '$(folder)syntaxes'; - ahkLanguageStatusItem.command = { title: 'Select AHK Syntaxes', command: 'ahk++.selectSyntaxes' }; + context.subscriptions.push(Object.assign(languages.createLanguageStatusItem(it.command.command, { language: 'ahk2' }), it)); context.subscriptions.push( ahkStatusBarItem, outputchannel, fsw, extensions.onDidChange(update_extensions_info), - commands.registerTextEditorCommand('ahk++.run', textEditor => runScript(textEditor)), - commands.registerTextEditorCommand('ahk++.runSelection', textEditor => runScript(textEditor, true)), - commands.registerCommand('ahk++.stop', stopRunningScript), - commands.registerCommand('ahk++.debugConfigs', () => beginDebug('c')), - commands.registerCommand('ahk++.debugParams', () => beginDebug('p')), - commands.registerCommand('ahk++.debugAttach', () => beginDebug('a')), - commands.registerCommand('ahk++.selectSyntaxes', selectSyntaxes), - commands.registerTextEditorCommand('ahk++.updateVersionInfo', async textEditor => { + commands.registerTextEditorCommand(extRun, textEditor => runScript(textEditor)), + commands.registerTextEditorCommand(extRunSelection, textEditor => runScript(textEditor, true)), + commands.registerCommand(extStop, stopRunningScript), + commands.registerCommand(extSetInterpreter, setInterpreter), + commands.registerCommand(extDebugConfig, () => beginDebug('c')), + commands.registerCommand(extDebugParams, () => beginDebug('p')), + commands.registerCommand(extDebugAttach, () => beginDebug('a')), + commands.registerCommand(extSelectSyntaxes, selectSyntaxes), + commands.registerTextEditorCommand(extUpdateVersionInfo, async textEditor => { if (!server_is_ready) return; - const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest('ahk++.getVersionInfo', textEditor.document.uri.toString()); + const infos: { content: string, uri: string, range: Range, single: boolean }[] | null = await client.sendRequest(serverGetVersionInfo, textEditor.document.uri.toString()); if (!infos?.length) { await textEditor.insertSnippet(new SnippetString([ "/************************************************************************", @@ -258,15 +289,15 @@ export function activate(context: ExtensionContext): Promise { ed.size && workspace.applyEdit(ed); } }), - commands.registerTextEditorCommand('ahk++.switchAhkVersion', textEditor => { + commands.registerTextEditorCommand(extSwitchAHKVersion, textEditor => { const doc = textEditor.document; languages.setTextDocumentLanguage(doc, doc.languageId === 'ahk2' ? 'ahk' : 'ahk2'); }), - commands.registerTextEditorCommand('ahk++.exportSymbols', textEditor => { + commands.registerTextEditorCommand(extExtractSymbols, textEditor => { const doc = textEditor.document; if (doc.languageId !== 'ahk2') return; - client.sendRequest('ahk++.exportSymbols', doc.uri.toString()) + client.sendRequest(serverExportSymbols, doc.uri.toString()) .then(result => workspace.openTextDocument({ language: 'json', content: JSON.stringify(result, undefined, 2) }).then(d => window.showTextDocument(d, 2))); @@ -275,7 +306,7 @@ export function activate(context: ExtensionContext): Promise { provideTextDocumentContent(uri, token) { if (token.isCancellationRequested) return; - return client.sendRequest('ahk++.getContent', uri.toString()).then(content => { + return client.sendRequest(serverGetContent, uri.toString()).then(content => { setTimeout(() => { const it = workspace.textDocuments.find(it => it.uri.scheme === 'ahkres' && it.uri.path === uri.path); it && it.languageId !== 'ahk2' && languages.setTextDocumentLanguage(it, 'ahk2'); @@ -320,17 +351,17 @@ const isV1 = (): boolean => * Does not work on never-saved files (new untitled documents) */ async function runScript(textEditor: TextEditor, runSelection = false) { - const interpreter: string | undefined = isV1() ? getCfg(CfgKey.InterpreterPathV1) : getCfg(CfgKey.InterpreterPathV2); + const interpreter: string | undefined = isV1() ? getConfigIDE(CfgKey.InterpreterPathV1, '') : getConfigIDE(CfgKey.InterpreterPath, ''); const executePath = resolvePath(interpreter, workspace.getWorkspaceFolder(textEditor.document.uri)?.uri.fsPath); if (!executePath) { const s = interpreter || 'AutoHotkey.exe'; window.showErrorMessage(localize('ahk2.filenotexist', s), localize('ahk2.set.interpreter')) - .then(r => r ? setInterpreterV2() : undefined); + .then(r => r ? setInterpreter() : undefined); return; } let selectedText = '', path = '*', command = `"${executePath}" /ErrorStdOut=utf-8 `; let startTime: Date; - const showOutput = getCfg(CfgKey.ShowOutput); + const showOutput = getConfigIDE(CfgKey.ShowOutput, 'always'); if (showOutput === 'always') outputchannel.show(true); if (!ahkprocesses.size) @@ -417,9 +448,8 @@ async function stopRunningScript() { } } - - -function get_debug_configs() { +/** Return the debug configs for the installed AHK debug extensions */ +function getDebugConfigs() { const allconfigs = workspace.getConfiguration('launch').inspect('configurations'); return allconfigs && [ ...allconfigs.workspaceFolderValue ?? [], @@ -427,11 +457,22 @@ function get_debug_configs() { ...allconfigs.globalValue ?? []].filter(it => it.type in debugexts); } -// todo validate calls -async function beginDebug(type: string) { +/** + * Begins debugging with the provided debug type. + * @param type 'f' for file, 'c' for configs, 'p' for params, 'a' for attach + * - f: Debug the current file. + * - c: Debug with the selected configuration. + * - p: Debug with the specified parameters. Only available for `zero-plusplus.vscode-autohotkey-debug`. + * - a: Attach to the process. Only available for `zero-plusplus.vscode-autohotkey-debug`. + */ +async function beginDebug(type: 'f' | 'c' | 'p' | 'a') { let extname: string | undefined; const editor = window.activeTextEditor; - let config = { ...getCfg(CfgKey.DebugConfiguration), request: 'launch', __ahk2debug: true } as DebugConfiguration; + let debugConfig = { + ...getConfigIDE>(CfgKey.DebugConfiguration, {}), + request: 'launch', + __ahk2debug: true, + } as DebugConfiguration; if (!extlist.length) { window.showErrorMessage(localize('ahk2.debugextnotexist')); extname = await window.showQuickPick(['zero-plusplus.vscode-autohotkey-debug', 'helsmy.autohotkey-debug', 'mark-wiemer.vscode-autohotkey-plus-plus', 'cweijan.vscode-autohotkey-plus']); @@ -444,7 +485,7 @@ async function beginDebug(type: string) { window.showErrorMessage('zero-plusplus.vscode-autohotkey-debug was not found!'); return; } - config.type = Object.entries(debugexts).find(([, v]) => v === extname)![0]; + debugConfig.type = Object.entries(debugexts).find(([, v]) => v === extname)![0]; if (type === 'p') { let input = await window.showInputBox({ prompt: localize('ahk2.entercmd') }); if (input === undefined) @@ -455,29 +496,28 @@ async function beginDebug(type: string) { args.push(m[4] || m[2]); return ''; }); - config.args = args; + debugConfig.args = args; } - } else config.request = 'attach'; + } else debugConfig.request = 'attach'; } else if (type === 'c') { - const configs = get_debug_configs(); + const configs = getDebugConfigs(); if (configs?.length) { - const pick = window.createQuickPick(); + const pick = window.createQuickPick<{ label: string, data: DebugConfiguration }>(); pick.items = configs.map(it => ({ label: it.name, data: it })); pick.show(); - const it = await new Promise(resolve => { - pick.onDidAccept(() => resolve( - (pick.selectedItems[0] as unknown as { data: DebugConfiguration })?.data)); + const pickedDebugConfig = await new Promise(resolve => { + pick.onDidAccept(() => resolve(pick.selectedItems[0]?.data)); pick.onDidHide(() => resolve(undefined)); }); pick.dispose(); - if (!it) + if (!pickedDebugConfig) return; - config = it as DebugConfiguration; + debugConfig = pickedDebugConfig; } - } else config.program = '${file}'; - config.type ||= Object.keys(debugexts).sort().pop()!; - config.name ||= `AutoHotkey ${config.request === 'attach' ? 'Attach' : 'Debug'}`; - debug.startDebugging(editor && workspace.getWorkspaceFolder(editor.document.uri), config); + } else debugConfig.program = '${file}'; + debugConfig.type ||= Object.keys(debugexts).sort().pop()!; + debugConfig.name ||= `AutoHotkey ${debugConfig.request === 'attach' ? 'Attach' : 'Debug'}`; + debug.startDebugging(editor && workspace.getWorkspaceFolder(editor.document.uri), debugConfig); } /** @@ -485,10 +525,10 @@ async function beginDebug(type: string) { * Updates the most local configuration target that has a custom interpreter path. * If no target has a custom path, updates workspace folder config. */ -async function setInterpreterV2() { +async function setInterpreter() { // eslint-disable-next-line prefer-const - let index = -1, { path: ahkpath, from } = getInterpreterV2Path(); - const list: QuickPickItem[] = [], _ = (ahkpath = resolvePath(v2Interpreter || ahkpath, undefined, false)).toLowerCase(); + let index = -1, { path: ahkpath, from } = getInterpreterPath(); + const list: QuickPickItem[] = [], _ = (ahkpath = resolvePath(interpreterPath || ahkpath, undefined, false)).toLowerCase(); const pick = window.createQuickPick(); let it: QuickPickItem, active: QuickPickItem | undefined, sel: QuickPickItem = { label: '' }; list.push({ alwaysShow: true, label: localize('ahk2.enterahkpath') + '...', detail: localize('ahk2.enterorfind') }); @@ -497,7 +537,7 @@ async function setInterpreterV2() { await addpath(resolve(ahkpath, '..'), _.includes('autohotkey') ? 20 : 5); if (!_.includes('c:\\program files\\autohotkey\\')) await addpath('C:\\Program Files\\AutoHotkey\\', 20); - index = list.map(it => it.detail?.toLowerCase()).indexOf((v2Interpreter || ahkpath).toLowerCase()); + index = list.map(it => it.detail?.toLowerCase()).indexOf((interpreterPath || ahkpath).toLowerCase()); if (index !== -1) active = list[index]; @@ -505,7 +545,7 @@ async function setInterpreterV2() { pick.title = localize('ahk2.set.interpreter'); if (active) pick.activeItems = [active]; - pick.placeholder = localize('ahk2.current', v2Interpreter); + pick.placeholder = localize('ahk2.current', interpreterPath); pick.show(); pick.onDidAccept(async () => { if (pick.selectedItems[0] === list[0]) { @@ -530,11 +570,11 @@ async function setInterpreterV2() { } pick.dispose(); if (sel.detail) { - ahkStatusBarItem.tooltip = v2Interpreter = sel.detail; - getAhkppConfig().update(CfgKey.InterpreterPathV2, v2Interpreter, from); - ahkStatusBarItem.text = sel.label ||= (await getAHKversion([v2Interpreter]))[0]; + ahkStatusBarItem.tooltip = interpreterPath = sel.detail; + getConfigRoot().update(CfgKey.InterpreterPath, interpreterPath, from); + ahkStatusBarItem.text = sel.label ||= (await getAHKVersion([interpreterPath]))[0]; if (server_is_ready) - commands.executeCommand('ahk++.v2.setIntepreterPath', v2Interpreter); + commands.executeCommand(serverResetInterpreterPath, interpreterPath); } }); pick.onDidHide(() => pick.dispose()); @@ -558,7 +598,7 @@ async function setInterpreterV2() { break; } catch { } } - (await getAHKversion(paths)).forEach((label, i) => { + (await getAHKVersion(paths)).forEach((label, i) => { if (label.match(/\bautohotkey.*?2\./i) && !label.endsWith('[UIAccess]')) list.push({ label, detail: paths[i] }); }); @@ -567,7 +607,7 @@ async function setInterpreterV2() { async function selectSyntaxes() { const path = (await window.showOpenDialog({ canSelectFiles: false, canSelectFolders: true }))?.[0].fsPath; - const t = getAhkppConfig().inspect(CfgKey.Syntaxes); + const t = getConfigRoot().inspect(CfgKey.Syntaxes); let v = '', f = ConfigurationTarget.Global; if (t) { v = ((f = ConfigurationTarget.WorkspaceFolder, t.workspaceFolderValue) ?? @@ -576,41 +616,36 @@ async function selectSyntaxes() { } if (path === undefined || v.toLowerCase() === path.toLowerCase()) return; - getAhkppConfig().update(CfgKey.Syntaxes, path || undefined, f); + getConfigRoot().update(CfgKey.Syntaxes, path || undefined, f); } -function getAHKversion(paths: string[]): Thenable { - return client.sendRequest('ahk++.getAHKversion', paths.map(p => resolvePath(p, undefined, true) || p)); +function getAHKVersion(paths: string[]): Thenable { + return client.sendRequest(serverGetAHKVersion, paths.map(p => resolvePath(p, undefined, true) || p)); } -/** - * Gets the interpreter v2 path from the folder, workspace, global, or default value. - * Returns both the value and the target it was retrieved from. - * `from` is undefined if default value was used. - */ -function getInterpreterV2Path(): { path: string, from?: ConfigurationTarget } { - const configDetails = getAhkppConfig().inspect(CfgKey.InterpreterPathV2); +function getInterpreterPath() { + const t = getConfigRoot().inspect(CfgKey.InterpreterPath); let path = ''; - if (configDetails) - if ((path = configDetails.workspaceFolderValue as string)) + if (t) + if ((path = t.workspaceFolderValue as string)) return { path, from: ConfigurationTarget.WorkspaceFolder }; - else if ((path = configDetails.workspaceValue as string)) + else if ((path = t.workspaceValue as string)) return { path, from: ConfigurationTarget.Workspace }; - else if ((path = configDetails.globalValue as string)) + else if ((path = t.globalValue as string)) return { path, from: ConfigurationTarget.Global }; - else path = configDetails.defaultValue as string ?? ''; + else path = t.defaultValue as string ?? ''; return { path }; } -async function onDidChangegetInterpreter() { +async function onDidChangeInterpreter() { const uri = window.activeTextEditor?.document.uri; const ws = uri ? workspace.getWorkspaceFolder(uri)?.uri.fsPath : undefined; - let ahkPath = resolvePath(v2Interpreter, ws, false); + let ahkPath = resolvePath(interpreterPath, ws, false); if (ahkPath.toLowerCase().endsWith('.exe') && existsSync(ahkPath)) { // ahkStatusBarItem.tooltip is the current saved interpreter path if (ahkPath !== ahkStatusBarItem.tooltip) { ahkStatusBarItem.tooltip = ahkPath; - ahkStatusBarItem.text = (await getAHKversion([ahkPath]))[0] || localize('ahk2.unknownversion'); + ahkStatusBarItem.text = (await getAHKVersion([ahkPath]))[0] || localize('ahk2.unknownversion'); } } else { ahkStatusBarItem.text = localize('ahk2.set.interpreter') @@ -618,6 +653,32 @@ async function onDidChangegetInterpreter() { } } +/** + * Resolves a given path to an absolute path. + * Returns empty string if the file does not exist or has no access rights. + */ +function resolvePath(path: string | undefined, workspace?: string, resolveSymbolicLink = true): string { + if (!path) + return ''; + const paths: string[] = []; + // If the path does not contain a colon, resolve it relative to the workspace + if (!path.includes(':')) + paths.push(resolve(workspace ?? '', path)); + // If there are no slashes or backslashes in the path and the platform is Windows + if (!/[\\/]/.test(path) && isWindows) + paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); + paths.push(path); + for (let path of paths) { + if (!path) continue; + try { + if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) + path = resolve(path, '..', readlinkSync(path)); + return path; + } catch { } + } + return ''; +} + /** * Returns whether the given path exists. * Only returns false if lstatSync give an ENOENT error. @@ -640,7 +701,7 @@ function statSync(path: string) { return st; } -function loadlocalize(nls: string) { +function loadLocalize(nls: string) { let s = `${nls}.${env.language}.json`; if (!existsSync(s)) { if (!env.language.startsWith('zh-') || !existsSync(s = `${nls}.zh-cn.json`)) @@ -654,10 +715,10 @@ function loadlocalize(nls: string) { } catch { } } -function localize(key: keyof typeof loadedCollection, ...args: unknown[]) { +function localize(key: keyof typeof loadedCollection, ...args: string[]) { const val = loadedCollection[key]; if (args.length) - return format(val, ...args as string[]); + return format(val, ...args); return val; } diff --git a/client/src/test/extension.test.ts b/client/src/test/extension.test.ts index c75dfabc..c0c86b41 100644 --- a/client/src/test/extension.test.ts +++ b/client/src/test/extension.test.ts @@ -3,152 +3,240 @@ import * as vscode from 'vscode'; import { resolve } from 'path'; import { LanguageClient, - CompletionRequest, CompletionParams, CompletionItem, - DocumentSymbolRequest, DocumentSymbolParams, SymbolInformation, - DefinitionRequest, DefinitionParams, LocationLink, - DocumentFormattingRequest, DocumentFormattingParams, TextEdit, - FoldingRangeRequest, FoldingRangeParams, FoldingRange, - HoverRequest, HoverParams, Hover, - PrepareRenameRequest, PrepareRenameParams, - ReferencesRequest, ReferenceParams, Location, - RenameRequest, RenameParams, WorkspaceEdit, - SignatureHelpRequest, SignatureHelpParams, SignatureHelp, - SemanticTokensRequest, SemanticTokensParams, SemanticTokens, - WorkspaceSymbolRequest, WorkspaceSymbolParams, - ExecuteCommandRequest, ExecuteCommandParams, + CompletionRequest, + CompletionParams, + CompletionItem, + DocumentSymbolRequest, + DocumentSymbolParams, + SymbolInformation, + DefinitionRequest, + DefinitionParams, + LocationLink, + DocumentFormattingRequest, + DocumentFormattingParams, + TextEdit, + FoldingRangeRequest, + FoldingRangeParams, + FoldingRange, + HoverRequest, + HoverParams, + Hover, + PrepareRenameRequest, + PrepareRenameParams, + ReferencesRequest, + ReferenceParams, + Location, + RenameRequest, + RenameParams, + WorkspaceEdit, + SignatureHelpRequest, + SignatureHelpParams, + SignatureHelp, + SemanticTokensRequest, + SemanticTokensParams, + SemanticTokens, + WorkspaceSymbolRequest, + WorkspaceSymbolParams, + ExecuteCommandRequest, + ExecuteCommandParams, DidChangeConfigurationNotification, } from 'vscode-languageclient/node'; import { readdirSync } from 'fs'; +import { suite, before, test } from 'mocha'; +import { serverGetContent } from '../../../util/src/env'; +import { newConfig } from '../../../util/src/config'; + +let client: LanguageClient; +before(async () => { + client = await vscode.extensions + .getExtension('thqby.vscode-autohotkey2-lsp') + ?.activate(); + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); +}); -suite('Start ahk language server', () => { - test('should be running', async () => { - await vscode.commands.executeCommand('workbench.action.closeAllEditors'); - const client: LanguageClient = await vscode.extensions.getExtension('thqby.vscode-autohotkey2-lsp')?.activate(); - assert.equal(client?.isRunning(), true); - - suite('Open ahk file', () => { - test('should be opened', async () => { - const path = resolve(__dirname, '../../../server/dist/ahkProvider.ahk'); - let document = await vscode.workspace.openTextDocument(path); - const uri = document.uri.toString(); - await vscode.window.showTextDocument(document); - if (document.languageId !== 'ahk2') - document = await vscode.languages.setTextDocumentLanguage(document, 'ahk2'); - const content = await client.sendRequest('ahk++.getContent', uri) as string; - assert.equal(document.getText() === content, true); - - suite('Test language server features', () => { - const textDocument = { uri }; - const position = { line: 10, character: 5 }; - - test.skip(CompletionRequest.method, async function () { - const params: CompletionParams = { textDocument, position }; - const result: CompletionItem[] | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.length); - }); - - test.skip(DefinitionRequest.method, async function () { - const params: DefinitionParams = { textDocument, position }; - const result: LocationLink[] | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.length); - }); - - test.skip(DocumentFormattingRequest.method, async function () { - const params: DocumentFormattingParams = { textDocument, options: { insertSpaces: false, tabSize: 4 } }; - const result: TextEdit[] | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.length); - }); - - test.skip(DocumentSymbolRequest.method, async function () { - const params: DocumentSymbolParams = { textDocument }; - const result: SymbolInformation[] | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.length); - }); - - test.skip(FoldingRangeRequest.method, async function () { - const params: FoldingRangeParams = { textDocument }; - const result: FoldingRange[] | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.length); - }); - - test.skip(HoverRequest.method, async function () { - const params: HoverParams = { textDocument, position }; - const result: Hover | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.contents); - }); - - test.skip(PrepareRenameRequest.method, async function () { - const params: PrepareRenameParams = { textDocument, position }; - const result: unknown | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result); - }); - - test.skip(ReferencesRequest.method, async function () { - const params: ReferenceParams = { textDocument, position, context: { includeDeclaration: true } }; - const result: Location[] | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.length); - }); - - test.skip(RenameRequest.method, async function () { - const params: RenameParams = { textDocument, position, newName: '' }; - const result: WorkspaceEdit | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.changes); - }); - - test.skip(SignatureHelpRequest.method, async function () { - const params: SignatureHelpParams = { textDocument, position: { line: 8, character: 36 } }; - const result: SignatureHelp | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.signatures); - }); - - test.skip(ExecuteCommandRequest.method, async function () { - const params: ExecuteCommandParams = { command: 'ahk++.diagnostic.full' }; - await client.sendRequest(this.runnable().title, params); - }); - - test.skip(WorkspaceSymbolRequest.method, async function () { - const params: WorkspaceSymbolParams = { query: 'msg' }; - const result: SymbolInformation[] | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.length); - }); - - test.skip(SemanticTokensRequest.method, async function () { - const params: SemanticTokensParams = { textDocument }; - const result: SemanticTokens | undefined = await client.sendRequest(this.runnable().title, params); - assert.ok(result?.data); - }); - }); - - await client.sendNotification( - DidChangeConfigurationNotification.method, - { settings: { FormatOptions: {} } }); - test_formatting(client); - }); - }); - }); +test('should be running', async () => { + assert.equal(client?.isRunning(), true); }); -// todo AHK++ does not handle formatter directives yet -function test_formatting(client: LanguageClient) { - suite('Test formatting', () => { - const dir = resolve(__dirname, '../../src/test/formatting'); - const files = readdirSync(dir); - for (const file of files) { - if (!file.endsWith('.ahk')) - continue; - test.skip(file.slice(0, -4), async function () { - let document = await vscode.workspace.openTextDocument(resolve(dir, file)); - if (document.languageId !== 'ahk2') - document = await vscode.languages.setTextDocumentLanguage(document, 'ahk2'); - const uri = document.uri.toString(); +suite('Language client request handlers', () => {}); + +suite('Open AHK file', () => { + test('opens', async () => { + const path = resolve(__dirname, '../../../server/dist/ahkProvider.ahk'); + let document = await vscode.workspace.openTextDocument(path); + const uri = document.uri.toString(); + await vscode.window.showTextDocument(document); + if (document.languageId !== 'ahk2') + document = await vscode.languages.setTextDocumentLanguage( + document, + 'ahk2', + ); + const content = (await client.sendRequest(serverGetContent, uri)) as string; + assert.equal(document.getText() === content, true); + + suite('Send language server requests', () => { + const textDocument = { uri }; + const position = { line: 10, character: 5 }; + + test(CompletionRequest.method, async function () { + const params: CompletionParams = { textDocument, position }; + const result: CompletionItem[] | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(DefinitionRequest.method, async function () { + const params: DefinitionParams = { textDocument, position }; + const result: LocationLink[] | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(DocumentFormattingRequest.method, async function () { const params: DocumentFormattingParams = { - textDocument: { uri }, - options: { insertSpaces: false, tabSize: 4 } + textDocument, + options: { insertSpaces: false, tabSize: 4 }, + }; + const result: TextEdit[] | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(DocumentSymbolRequest.method, async function () { + const params: DocumentSymbolParams = { textDocument }; + const result: SymbolInformation[] | undefined = + await client.sendRequest(this.runnable().title, params); + assert.ok(result?.length); + }); + + test(FoldingRangeRequest.method, async function () { + const params: FoldingRangeParams = { textDocument }; + const result: FoldingRange[] | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); + }); + + test(HoverRequest.method, async function () { + const params: HoverParams = { textDocument, position }; + const result: Hover | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.contents); + }); + + test(PrepareRenameRequest.method, async function () { + const params: PrepareRenameParams = { textDocument, position }; + const result: unknown | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result); + }); + + test(ReferencesRequest.method, async function () { + const params: ReferenceParams = { + textDocument, + position, + context: { includeDeclaration: true }, }; - const content = document.getText().replaceAll('\r\n', '\n'); - const result: TextEdit[] | undefined = await client.sendRequest(DocumentFormattingRequest.method, params); - assert.ok(result?.[0].newText === content); + const result: Location[] | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.length); }); - } + + test(RenameRequest.method, async function () { + const params: RenameParams = { + textDocument, + position, + newName: '', + }; + const result: WorkspaceEdit | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.changes); + }); + + test(SignatureHelpRequest.method, async function () { + const params: SignatureHelpParams = { + textDocument, + position: { line: 8, character: 36 }, + }; + const result: SignatureHelp | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.signatures); + }); + + test(ExecuteCommandRequest.method, async function () { + const params: ExecuteCommandParams = { + command: 'ahk2.diagnose.all', + }; + await client.sendRequest(this.runnable().title, params); + }); + + test(WorkspaceSymbolRequest.method, async function () { + const params: WorkspaceSymbolParams = { query: 'msg' }; + const result: SymbolInformation[] | undefined = + await client.sendRequest(this.runnable().title, params); + assert.ok(result?.length); + }); + + test(SemanticTokensRequest.method, async function () { + const params: SemanticTokensParams = { textDocument }; + const result: SemanticTokens | undefined = await client.sendRequest( + this.runnable().title, + params, + ); + assert.ok(result?.data); + }); + }); }); -} \ No newline at end of file +}); + +suite('Formatting', async () => { + before(async () => { + await client.sendNotification(DidChangeConfigurationNotification.method, { + settings: newConfig(), + }); + }); + const dir = resolve(__dirname, '../../src/test/formatting'); + const files = readdirSync(dir); + const inSuffix = '.in.ahk'; + const outSuffix = '.out.ahk'; + for (const file of files) { + if (!file.endsWith(inSuffix)) continue; + const filenameRoot = file.slice(0, -inSuffix.length); + test(filenameRoot, async function () { + let inDoc = await vscode.workspace.openTextDocument(resolve(dir, file)); + if (inDoc.languageId !== 'ahk2') + inDoc = await vscode.languages.setTextDocumentLanguage(inDoc, 'ahk2'); + const outDoc = await vscode.workspace.openTextDocument( + resolve(dir, filenameRoot + outSuffix), + ); + const uri = inDoc.uri.toString(); + const params: DocumentFormattingParams = { + textDocument: { uri }, + options: { insertSpaces: false, tabSize: 4 }, + }; + const content = outDoc.getText().replaceAll('\r\n', '\n'); + const result: TextEdit[] | undefined = await client.sendRequest( + DocumentFormattingRequest.method, + params, + ); + assert.strictEqual(result?.[0].newText, content); + }); + } +}); diff --git a/client/src/test/formatting/array_object_style.in.ahk b/client/src/test/formatting/array_object_style.in.ahk new file mode 100644 index 00000000..798cc756 --- /dev/null +++ b/client/src/test/formatting/array_object_style.in.ahk @@ -0,0 +1,10 @@ +;* No directive +list := [{name: 1,age: 2},{name: 2,age: 3}] +;@format array_style: expand, object_style: expand +list := [{name: 1,age: 2},{name: 2,age: 3}] +;@format array_style: collapse, object_style: expand +list := [{name: 1,age: 2},{name: 2,age: 3}] +;@format array_style: expand, object_style: collapse +list := [{ name: 1, age: 2 },{ name: 2, age: 3 }] +;@format array_style: collapse, object_style: collapse +list := [{ name: 1, age: 2 },{ name: 2, age: 3 }] \ No newline at end of file diff --git a/client/src/test/formatting/array_object_style.ahk b/client/src/test/formatting/array_object_style.out.ahk similarity index 54% rename from client/src/test/formatting/array_object_style.ahk rename to client/src/test/formatting/array_object_style.out.ahk index 896273f9..d8c32b13 100644 --- a/client/src/test/formatting/array_object_style.ahk +++ b/client/src/test/formatting/array_object_style.out.ahk @@ -1,26 +1,30 @@ +;* No directive +list := [{ name: 1, age: 2 +}, { name: 2, age: 3 +}] ;@format array_style: expand, object_style: expand list := [ - { - name: 1, - age: 2 - }, - { - name: 2, - age: 3 - } + { + name: 1, + age: 2 + }, + { + name: 2, + age: 3 + } ] ;@format array_style: collapse, object_style: expand list := [{ - name: 1, - age: 2 + name: 1, + age: 2 }, { - name: 2, - age: 3 + name: 2, + age: 3 }] ;@format array_style: expand, object_style: collapse list := [ - { name: 1, age: 2 }, - { name: 2, age: 3 } + { name: 1, age: 2 }, + { name: 2, age: 3 } ] ;@format array_style: collapse, object_style: collapse list := [{ name: 1, age: 2 }, { name: 2, age: 3 }] \ No newline at end of file diff --git a/client/src/test/formatting/autoclicker.in.ahk b/client/src/test/formatting/autoclicker.in.ahk new file mode 100644 index 00000000..b0374062 --- /dev/null +++ b/client/src/test/formatting/autoclicker.in.ahk @@ -0,0 +1,17 @@ +#Requires AutoHotkey v2 +#SingleInstance Force +#MaxThreadsPerHotkey 3 + +global ClickerToggle := false +ClicksPerSecond := 10 +^z:: +{ +global ClickerToggle := !ClickerToggle +Loop +{ +If (!ClickerToggle) +Break +Click +Sleep 1000/ClicksPerSecond +} +} \ No newline at end of file diff --git a/client/src/test/formatting/autoclicker.out.ahk b/client/src/test/formatting/autoclicker.out.ahk new file mode 100644 index 00000000..fbefab15 --- /dev/null +++ b/client/src/test/formatting/autoclicker.out.ahk @@ -0,0 +1,16 @@ +#Requires AutoHotkey v2 +#SingleInstance Force +#MaxThreadsPerHotkey 3 + +global ClickerToggle := false +ClicksPerSecond := 10 +^z:: +{ + global ClickerToggle := !ClickerToggle + loop { + if (!ClickerToggle) + break + Click + Sleep 1000 / ClicksPerSecond + } +} diff --git a/client/src/test/formatting/braceStyle.in.ahk b/client/src/test/formatting/braceStyle.in.ahk new file mode 100644 index 00000000..d3301ba9 --- /dev/null +++ b/client/src/test/formatting/braceStyle.in.ahk @@ -0,0 +1,26 @@ +#Requires AutoHotkey v2.0 + +;;* AHK++.v2.formatter +; settings should be accessible via Settings GUI, not just settings.json + +;* braceStyle +; Defaults to OTB +; if true { +; x := 1 +; } else { +; x := 2 +; } +global x +if true +{ +x := 1 +} else { +x := 2 +} + +;* wrapLineLength 120 +MyFunc(argument1, argument2, argument3, argument4, argument5, argument6, argument7, argument8, argument9, argument10, arg11) { + +} + +; todo other v2 formatter settings untested for now diff --git a/client/src/test/formatting/braceStyle.out.ahk b/client/src/test/formatting/braceStyle.out.ahk new file mode 100644 index 00000000..6056e840 --- /dev/null +++ b/client/src/test/formatting/braceStyle.out.ahk @@ -0,0 +1,26 @@ +#Requires AutoHotkey v2.0 + +;;* AHK++.v2.formatter +; settings should be accessible via Settings GUI, not just settings.json + +;* braceStyle +; Defaults to OTB +; if true { +; x := 1 +; } else { +; x := 2 +; } +global x +if true { + x := 1 +} else { + x := 2 +} + +;* wrapLineLength 120 +MyFunc(argument1, argument2, argument3, argument4, argument5, argument6, argument7, argument8, argument9, argument10, + arg11) { + +} + +; todo other v2 formatter settings untested for now diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 00000000..ea8b8be2 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,11 @@ +# Development + +To startup the extension similar to how it'll be when published, go to the Run and Debug View (Ctrl+Shift+D), select the "Launch Client" option, and start debugging (F5). + +To troubleshoot issues, you can look at reported problems: + +1. Open the extension development host (the new VS Code window that opens when debugging) +1. Go to the Output View (Ctrl+Shift+U) +1. Select the output channel that matches `outputChannelName` in [env.ts](../util/src/env.ts), usually "AutoHotkey2" or "AHK++" + +Other launch configs in [launch.json](../.vscode/launch.json) can be used for advanced debugging. diff --git a/esbuild.mjs b/esbuild.mjs index ae90771a..e74807d8 100644 --- a/esbuild.mjs +++ b/esbuild.mjs @@ -14,6 +14,8 @@ const server_opt = { platform: 'node', sourcemap: true, }; + +/** @type {import('esbuild').BuildOptions} */ const client_opt = { ...server_opt, entryPoints: ['client/src/extension.ts', 'client/src/test/*.ts'], @@ -21,36 +23,74 @@ const client_opt = { outdir: 'client/dist', }; +/** @type {import('esbuild').BuildOptions} */ +const util_opt = { + ...server_opt, + entryPoints: ['util/src/*.ts'], + outbase: 'util/src', + // build in-place as files are only imported incrementally + outdir: 'util/src', +}; + switch (process.argv[2]) { - case '--cli': build_cli(); break; - case '--dev': build_watch(); break; - case '--web': build_watch(true); break; - default: build_prod(); break; + case '--cli': + build_cli(); + break; + case '--dev': + build_watch(); + break; + case '--e2e': + build_e2e(); + break; + case '--web': + build_watch(true); + break; + default: + build_prod(); + break; } +/** Build the server to be installed via CLI */ async function build_cli() { server_opt.bundle = true; server_opt.minify = true; server_opt.outdir = 'server/cli'; - const start = new Date; + const start = new Date(); await build(server_opt); - console.log(`build finished in ${new Date - start} ms`); + console.log(`build finished in ${new Date() - start} ms`); } -async function build_prod() { +/** Build the client and server for e2e testing (include tests) */ +async function build_e2e() { const opts = [ - client_opt, server_opt, - { ...client_opt, entryPoints: [client_opt.entryPoints.pop()] } + client_opt, + server_opt, + { ...client_opt, entryPoints: [client_opt.entryPoints.pop()] }, + util_opt, ]; client_opt.external = ['vscode']; client_opt.bundle = server_opt.bundle = true; client_opt.minify = server_opt.minify = true; opts.push(...browser_opts(true)); - const start = new Date; - await Promise.all(opts.map(o => build(o))); - console.log(`build finished in ${new Date - start} ms`); + const start = new Date(); + await Promise.all(opts.map((o) => build(o))); + console.log(`build finished in ${new Date() - start} ms`); } +/** Build the client and server for production (excludes tests) */ +async function build_prod() { + client_opt.entryPoints.pop(); // remove the test endpoints for prod + const opts = [client_opt, server_opt]; + client_opt.external = ['vscode']; + client_opt.bundle = server_opt.bundle = true; + client_opt.minify = server_opt.minify = true; + opts.push(...browser_opts(true)); + const start = new Date(); + await Promise.all(opts.map((o) => build(o))); + console.log(`build finished in ${new Date() - start} ms`); +} + +/** Build incrementally, non-bundling, for local development */ function build_watch(web = false) { let start, timer, opts; /** @type {import('esbuild').Plugin} */ @@ -58,13 +98,15 @@ function build_watch(web = false) { name: 'esbuild-problem-matcher', setup(build) { build.onStart(() => { - start ??= (console.log('\x1bc[watch] build started'), new Date); + start ??= (console.log('\x1bc[watch] build started'), new Date()); }); - build.onEnd(result => { - const end = new Date; + build.onEnd((result) => { + const end = new Date(); result.errors.forEach(({ text, location }) => { console.error(`✘ [ERROR] ${text}`); - console.error(` ${location.file}:${location.line}:${location.column}:`); + console.error( + ` ${location.file}:${location.line}:${location.column}:`, + ); }); timer && clearTimeout(timer); timer = setTimeout(() => { @@ -72,23 +114,27 @@ function build_watch(web = false) { start = timer = undefined; }, 500); }); - } + }, }; - client_opt.logLevel = server_opt.logLevel = 'silent'; + client_opt.entryPoints.push('client/src/**/*.ts'); + client_opt.logLevel = server_opt.logLevel = util_opt.logLevel = 'silent'; server_opt.define['process.env.DEBUG'] = 'true'; - if (web) - opts = browser_opts(false); + if (web) opts = browser_opts(false); else { server_opt.entryPoints = ['server/src/*.ts']; - server_opt.outdir = 'server/out'; - opts = [client_opt, server_opt]; + server_opt.outdir = 'server/dist'; + opts = [client_opt, server_opt, util_opt]; } for (const opt of opts) { opt.plugins = [plugin]; - context(opt).then(ctx => ctx.watch()); + context(opt).then((ctx) => ctx.watch()); } } -/** @returns {Array} */ + +/** + * Returns the options for building the browser extension + * @returns {Array} + */ function browser_opts(minify) { const browser_opt = { bundle: true, @@ -100,17 +146,20 @@ function browser_opts(minify) { minify, platform: 'browser', }; - return [{ - ...client_opt, - ...browser_opt, - entryPoints: ['client/src/browserClientMain.ts'], - external: ['vscode'], - }, { - ...server_opt, - ...browser_opt, - entryPoints: ['server/src/browserServerMain.ts'], - footer: { - js: 'function process_cwd(){return""}' + return [ + { + ...client_opt, + ...browser_opt, + entryPoints: ['client/src/browserClientMain.ts'], + external: ['vscode'], + }, + { + ...server_opt, + ...browser_opt, + entryPoints: ['server/src/browserServerMain.ts'], + footer: { + js: 'function process_cwd(){return""}', + }, }, - }]; -} \ No newline at end of file + ]; +} diff --git a/eslint.config.mjs b/eslint.config.mjs index 449991df..2d2374a6 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,25 +1,33 @@ -import pluginJs from "@eslint/js"; -import tseslint from "typescript-eslint"; +import pluginJs from '@eslint/js'; +import tseslint from 'typescript-eslint'; /** @type {typeof tseslint.configs.recommended} */ export default [ - pluginJs.configs.recommended, - ...tseslint.configs.recommended, - { - ignores: ['**/*.{js,mjs}', '**/*.d.ts', '**/.vscode-test-web/*', '**/.vscode-test/*'], - }, - { - rules: { - 'no-control-regex': 'off', - 'no-empty': 'off', - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-expressions': 'off', - '@typescript-eslint/no-unused-vars': ['error', { - args: 'none', - varsIgnorePattern: '^_', - caughtErrors: 'none', - ignoreRestSiblings: true - }], - } - } + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + ignores: [ + '**/*.{js,mjs}', + '**/*.d.ts', + '**/.vscode-test-web/*', + '**/.vscode-test/*', + ], + }, + { + rules: { + 'no-control-regex': 'off', + 'no-empty': 'off', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-expressions': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + args: 'none', + varsIgnorePattern: '^_', + caughtErrors: 'none', + ignoreRestSiblings: true, + }, + ], + }, + }, ]; diff --git a/package-lock.json b/package-lock.json index b0025a8b..a59df277 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "2.5.3", "license": "LGPLv3.0", "dependencies": { + "klona": "^2.0.6", "path-browserify": "^1.0.1", "vscode-languageclient": "^9.0.1", "vscode-languageserver": "^9.0.1", @@ -16,19 +17,24 @@ "vscode-uri": "^3.0.8" }, "devDependencies": { + "@types/mocha": "^10.0.8", "@types/node": "^20.14.0", "@types/vscode": "1.93.0", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", - "@vscode/vsce": "^2.32.0", + "@vscode/vsce": "^3.1.1", + "del-cli": "^5.1.0", "esbuild": "^0.24.0", "eslint": "^9.11.0", + "mocha": "^10.7.3", + "prettier": "3.3.3", + "sort-package-json": "^2.10.1", "typescript": "5.5.4", "typescript-eslint": "^8.7.0", "vscode-tmgrammar-test": "^0.1.3" }, "engines": { - "vscode": "^1.82.0" + "vscode": "^1.93.0" } }, "node_modules/@azure/abort-controller": { @@ -239,6 +245,46 @@ "node": ">=16" } }, + "node_modules/@babel/code-frame": { + "version": "7.25.7", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.25.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.7", + "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -422,7 +468,6 @@ "resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", "dev": true, - "license": "Apache-2.0", "dependencies": { "levn": "^0.4.1" }, @@ -597,11 +642,19 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/mocha": { "version": "10.0.8", "resolved": "https://registry.npmmirror.com/@types/mocha/-/mocha-10.0.8.tgz", "integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { "version": "20.16.10", @@ -612,6 +665,13 @@ "undici-types": "~6.19.2" } }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/vscode": { "version": "1.93.0", "resolved": "https://registry.npmmirror.com/@types/vscode/-/vscode-1.93.0.tgz", @@ -852,10 +912,11 @@ } }, "node_modules/@vscode/vsce": { - "version": "2.32.0", - "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-2.32.0.tgz", - "integrity": "sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==", + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-3.1.1.tgz", + "integrity": "sha512-N62Ca9ElRPLUUzf7l9CeEBlLrYzFPRQq7huKk4pVW+LjIOSXfFIPudixn5QvZcz+yXDOh15IopI3K2o3y9666Q==", "dev": true, + "license": "MIT", "dependencies": { "@azure/identity": "^4.1.0", "@vscode/vsce-sign": "^2.0.0", @@ -865,17 +926,17 @@ "cockatiel": "^3.1.2", "commander": "^6.2.1", "form-data": "^4.0.0", - "glob": "^7.0.6", + "glob": "^11.0.0", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", "leven": "^3.1.0", - "markdown-it": "^12.3.2", + "markdown-it": "^14.1.0", "mime": "^1.3.4", "minimatch": "^3.0.3", "parse-semver": "^1.1.1", "read": "^1.0.7", "semver": "^7.5.2", - "tmp": "^0.2.1", + "tmp": "^0.2.3", "typed-rest-client": "^1.8.4", "url-join": "^4.0.1", "xml2js": "^0.5.0", @@ -886,7 +947,7 @@ "vsce": "vsce" }, "engines": { - "node": ">= 16" + "node": ">= 20" }, "optionalDependencies": { "keytar": "^7.7.0" @@ -923,42 +984,78 @@ "win32" ] }, - "node_modules/@vscode/vsce/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@vscode/vsce/node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", "dev": true, + "license": "ISC", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vscode/vsce/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, + "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@vscode/vsce/node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/lru-cache": { + "version": "11.0.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.0.1.tgz", + "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@vscode/vsce/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -966,6 +1063,34 @@ "node": "*" } }, + "node_modules/@vscode/vsce/node_modules/minimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@vscode/vsce/node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.12.1.tgz", @@ -999,6 +1124,23 @@ "node": ">= 14" } }, + "node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", @@ -1064,6 +1206,16 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", @@ -1284,6 +1436,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", @@ -1383,12 +1554,40 @@ "dev": true, "optional": true }, + "node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clean-stack/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-cursor": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, - "license": "MIT", "dependencies": { "restore-cursor": "^4.0.0" }, @@ -1632,6 +1831,43 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz", @@ -1690,6 +1926,126 @@ "node": ">=8" } }, + "node_modules/del": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/del/-/del-7.1.0.tgz", + "integrity": "sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "^13.1.2", + "graceful-fs": "^4.2.10", + "is-glob": "^4.0.3", + "is-path-cwd": "^3.0.0", + "is-path-inside": "^4.0.0", + "p-map": "^5.5.0", + "rimraf": "^3.0.2", + "slash": "^4.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del-cli": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/del-cli/-/del-cli-5.1.0.tgz", + "integrity": "sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "del": "^7.1.0", + "meow": "^10.1.3" + }, + "bin": { + "del": "cli.js", + "del-cli": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/del/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/del/node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/del/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1699,6 +2055,16 @@ "node": ">=0.4.0" } }, + "node_modules/detect-indent": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.3.tgz", @@ -1709,6 +2075,19 @@ "node": ">=8" } }, + "node_modules/detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmmirror.com/diff/-/diff-5.2.0.tgz", @@ -1718,6 +2097,19 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -1799,7 +2191,6 @@ "resolved": "https://registry.npmmirror.com/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", "dev": true, - "license": "MIT", "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" @@ -1843,6 +2234,16 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz", @@ -2428,6 +2829,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-hooks-list": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/git-hooks-list/-/git-hooks-list-3.1.0.tgz", + "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmmirror.com/github-from-package/-/github-from-package-0.0.0.tgz", @@ -2467,6 +2891,26 @@ "node": ">= 6" } }, + "node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmmirror.com/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz", @@ -2491,6 +2935,16 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", @@ -2692,6 +3146,19 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", @@ -2716,6 +3183,13 @@ "dev": true, "optional": true }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2728,6 +3202,22 @@ "node": ">=8" } }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", @@ -2794,6 +3284,19 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-path-cwd/-/is-path-cwd-3.0.0.tgz", + "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -2920,6 +3423,13 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2938,6 +3448,13 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3053,6 +3570,25 @@ "json-buffer": "3.0.1" } }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz", @@ -3080,18 +3616,25 @@ "resolved": "https://registry.npmmirror.com/lie/-/lie-3.3.0.tgz", "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "dev": true, - "license": "MIT", "dependencies": { "immediate": "~3.0.5" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, + "license": "MIT", "dependencies": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "node_modules/locate-path": { @@ -3270,36 +3813,93 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "version": "14.1.0", + "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, "bin": { - "markdown-it": "bin/markdown-it.js" + "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "dev": true, + "license": "MIT" + }, + "node_modules/meow": { + "version": "10.1.5", + "resolved": "https://registry.npmmirror.com/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true + "node_modules/meow/node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, "node_modules/merge2": { "version": "1.4.1", @@ -3378,6 +3978,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", @@ -3403,6 +4013,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minimist-options/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz", @@ -3675,6 +4310,22 @@ "dev": true, "optional": true }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3909,6 +4560,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-5.5.0.tgz", + "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "dev": true, + "dependencies": { + "aggregate-error": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", @@ -3933,6 +4599,25 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse-semver": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/parse-semver/-/parse-semver-1.1.1.tgz", @@ -4042,12 +4727,29 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", @@ -4096,6 +4798,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4127,6 +4845,16 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz", @@ -4162,6 +4890,19 @@ } ] }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", @@ -4209,6 +4950,42 @@ "node": ">=0.8" } }, + "node_modules/read-pkg": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", @@ -4242,6 +5019,23 @@ "node": ">=8.10.0" } }, + "node_modules/redent": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", @@ -4339,8 +5133,7 @@ "version": "2.1.2", "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/sax": { "version": "1.4.1", @@ -4489,12 +5282,100 @@ "simple-concat": "^1.0.0" } }, + "node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sort-package-json": { + "version": "2.10.1", + "resolved": "https://registry.npmmirror.com/sort-package-json/-/sort-package-json-2.10.1.tgz", + "integrity": "sha512-d76wfhgUuGypKqY72Unm5LFnMpACbdxXsLPcL27pOsSrmVqH3PztFp1uq+Z22suk15h7vXmTesuh2aEjdCqb5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.0", + "get-stdin": "^9.0.0", + "git-hooks-list": "^3.0.0", + "globby": "^13.1.2", + "is-plain-obj": "^4.1.0", + "semver": "^7.6.0", + "sort-object-keys": "^1.1.3" + }, + "bin": { + "sort-package-json": "cli.js" + } + }, + "node_modules/sort-package-json/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.20", + "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/stdin-discarder": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", "dev": true, - "license": "MIT", "dependencies": { "bl": "^5.0.0" }, @@ -4620,6 +5501,21 @@ "node": ">=8" } }, + "node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4819,6 +5715,19 @@ "node": ">=8.0" } }, + "node_modules/trim-newlines": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -4871,6 +5780,19 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-rest-client": { "version": "1.8.11", "resolved": "https://registry.npmmirror.com/typed-rest-client/-/typed-rest-client-1.8.11.tgz", @@ -4919,10 +5841,11 @@ } }, "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" }, "node_modules/underscore": { "version": "1.13.7", @@ -4935,7 +5858,6 @@ "resolved": "https://registry.npmmirror.com/undici/-/undici-6.19.8.tgz", "integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==", "dev": true, - "license": "MIT", "engines": { "node": ">=18.17" } @@ -4990,6 +5912,17 @@ "node": ">=10.12.0" } }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", diff --git a/package.json b/package.json index e2cd5f78..0f948ed1 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,8 @@ { "name": "vscode-autohotkey2-lsp", "displayName": "AutoHotkey v2 Language Support", - "description": "AutoHotkey v2 Language Support, based on vscode-lsp.", - "author": "thqby", - "publisher": "thqby", "version": "2.5.3", - "license": "LGPLv3.0", + "description": "AutoHotkey v2 Language Support, based on vscode-lsp.", "categories": [ "Formatters", "Programming Languages", @@ -17,187 +14,425 @@ "autohotkey", "autohotkey2" ], - "repository": { - "type": "git", - "url": "https://github.com/thqby/vscode-autohotkey2-lsp" - }, "homepage": "https://github.com/thqby/vscode-autohotkey2-lsp/blob/main/README.md", - "icon": "icon.png", "bugs": { "url": "https://github.com/thqby/vscode-autohotkey2-lsp/issues" }, - "engines": { - "vscode": "^1.82.0" + "repository": { + "type": "git", + "url": "https://github.com/thqby/vscode-autohotkey2-lsp" }, + "license": "LGPLv3.0", + "author": "thqby", + "publisher": "thqby", "main": "./client/dist/extension", "browser": "./client/dist/browserClientMain", + "scripts": { + "prebuild": "npm run clean:dist", + "build": "node esbuild.mjs", + "build:cli": "npm run build -- --cli", + "build:e2e": "npm run build -- --e2e", + "check-types": "tsc", + "clean": "npm run clean:dist && npm run clean:out && npm run clean:watch", + "clean:dist": "del-cli client/dist && del-cli server/dist/*.js(.map)?", + "clean:out": "del-cli out", + "clean:watch": "del-cli client/dist && del-cli server/out && del-cli util/src/*.js*", + "clean:watch//": "echo If watch is running, files will reappear instantly!", + "precompile-ts": "npm run clean:out", + "compile-ts": "tsc --noEmit false --outDir out", + "eslint": "eslint --max-warnings 0", + "eslint:fix": "eslint --fix --max-warnings 0", + "format": "prettier --check .", + "format:fix": "prettier --write .", + "lint": "npm run sort-package-json && npm run format && npm run eslint", + "lint:fix": "npm run sort-package-json:fix && npm run format:fix && npm run eslint:fix", + "package": "vsce package", + "publish": "vsce publish", + "sort-package-json": "sort-package-json --check", + "sort-package-json:fix": "sort-package-json", + "test": "npm run test:grammar && npm run test:unit && npm run test:e2e", + "pretest:e2e": "npm run build:e2e", + "test:e2e": "vscode-test", + "test:grammar": "vscode-tmgrammar-snap tmgrammar-test/*.ahk", + "pretest:unit": "npm run compile-ts", + "test:unit": "mocha", + "prevalidate": "npm run clean", + "validate": "npm run lint && npm run test && echo ✅ All checks passed", + "prevalidate:fix": "npm run clean", + "validate:fix": "npm run lint:fix && npm run test && echo ✅ All checks passed", + "vscode:prepublish": "npm run validate", + "watch": "npm run build -- --dev", + "watch-web": "npm run build -- --web" + }, "contributes": { "breakpoints": [ { "language": "ahk2" } ], - "languages": [ + "commands": [ { - "id": "ahk2", - "aliases": [ - "AutoHotkey2", - "autohotkey2", - "ahk2" - ], - "extensions": [ - ".ahk", - ".ah2", - ".ahk2" - ], - "configuration": "./ahk2.configuration.json", - "icon": { - "dark": "icon_filetype.png", - "light": "icon_filetype.png" - } + "command": "ahk++.compile", + "enablement": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported", + "title": "Compile AHK Script", + "category": "AHK++" }, { - "id": "ahk", - "aliases": [ - "AutoHotkey" - ] + "command": "ahk++.compilerGui", + "enablement": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported", + "title": "Compile AHK Script (GUI)", + "category": "AHK++" }, { - "id": "~ahk2-output" - } - ], - "grammars": [ + "command": "ahk++.openHelp", + "enablement": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported", + "title": "Open AutoHotkey Help", + "category": "AHK++" + }, { - "language": "ahk2", - "scopeName": "source.ahk2", - "path": "./syntaxes/ahk2.tmLanguage.json", - "embeddedLanguages": { - "meta.embedded.ahk2": "ahk2" - }, - "unbalancedBracketScopes": [ - "keyword.keys.ahk2" - ] + "command": "ahk++.debug", + "title": "Debug AHK Script", + "enablement": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported", + "category": "AHK++", + "icon": "$(debug-alt)" }, { - "language": "~ahk2-output", - "scopeName": "ahk2.output", - "path": "./syntaxes/ahk2-output.tmLanguage.json" + "command": "ahk++.debugConfigs", + "title": "%ahk++.command.debugConfigs%", + "enablement": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported", + "icon": "$(debug-all)", + "category": "AHK++" + }, + { + "command": "ahk++.debugAttach", + "title": "%ahk++.command.debugAttach%", + "enablement": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported", + "icon": "$(debug-alt)", + "category": "AHK++" + }, + { + "command": "ahk++.debugParams", + "title": "%ahk++.command.debugParams%", + "enablement": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported", + "icon": "$(debug-console)", + "category": "AHK++" + }, + { + "command": "ahk++.diagnostic.full", + "title": "%ahk++.command.diagnostic.full%", + "category": "AHK++" + }, + { + "command": "ahk++.exportSymbols", + "title": "%ahk++.command.exportSymbols%", + "enablement": "editorLangId == ahk2", + "category": "AHK++" + }, + { + "command": "ahk++.run", + "title": "%ahk++.command.run%", + "enablement": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported", + "icon": "$(play)", + "category": "AHK++" + }, + { + "command": "ahk++.runSelection", + "title": "%ahk++.command.runSelection%", + "enablement": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported", + "category": "AHK++" + }, + { + "command": "ahk++.stop", + "title": "%ahk++.command.stop%", + "icon": "$(stop)", + "category": "AHK++" + }, + { + "command": "ahk++.addDocComment", + "title": "%ahk++.command.addDocComment%", + "enablement": "editorLangId == ahk || editorLangId == ahk2", + "category": "AHK++" + }, + { + "command": "ahk++.setV2Interpreter", + "title": "%ahk++.command.setV2Interpreter%", + "enablement": "editorLangId == ahk || editorLangId == ahk2", + "category": "AHK++" + }, + { + "command": "ahk++.updateVersionInfo", + "title": "%ahk++.command.updateVersionInfo%", + "enablement": "editorLangId == ahk || editorLangId == ahk2", + "category": "AHK++" + }, + { + "command": "ahk++.switchAhkVersion", + "title": "Switch AHK Version", + "enablement": "editorLangId == ahk || editorLangId == ahk2", + "category": "AHK++" + }, + { + "command": "ahk++.selectSyntaxes", + "title": "Select AHK v2 Syntaxes", + "enablement": "editorLangId == ahk2", + "category": "AHK++" + }, + { + "command": "ahk++.setAScriptDir", + "title": "%ahk++.command.setAScriptDir%", + "enablement": "editorLangId == ahk2 && resourceScheme == file", + "category": "AHK++" } ], "configuration": { - "title": "AutoHotkey2", + "type": "object", + "title": "AHK++ (AutoHotkey Plus Plus)", "properties": { - "AutoHotkey2.AutoLibInclude": { - "scope": "window", - "type": "string", - "enum": [ - "Disabled", - "Local", - "User and Standard", - "All" - ], - "default": "Disabled", - "description": "%ahk2.autolibinclude%" - }, - "AutoHotkey2.CommentTags": { - "scope": "window", - "type": "string", - "default": "^;;\\s*(?.+)", - "description": "%ahk2.commenttags%" - }, - "AutoHotkey2.CompilerCMD": { - "scope": "window", - "type": "string", - "default": "/compress 0 /base ${execPath}", - "markdownDescription": "%ahk2.compilercmd%" - }, - "AutoHotkey2.CompleteFunctionParens": { - "scope": "window", - "type": "boolean", - "default": false, - "markdownDescription": "%ahk2.completefunctionparens%" + "AHK++.compiler": { + "type": "object", + "properties": { + "compileIcon": { + "type": "string", + "default": "", + "description": "Icon path for the compiled AHK file (optional)." + }, + "useMpress": { + "type": "boolean", + "default": false, + "markdownDescription": "Use MPRESS (if available) to compress the resulting executable." + }, + "compilerPath": { + "type": "string", + "default": "C:/Program Files/AutoHotkey/Compiler/Ahk2Exe.exe", + "description": "Path to the AHK compiler. This is the same for both v1 and v2." + } + }, + "additionalProperties": { + "type": "string" + }, + "default": { + "compileIcon": "", + "compilerPath": "C:/Program Files/AutoHotkey/Compiler/Ahk2Exe.exe", + "useMpress": false + }, + "markdownDescription": "Learn more about [MPRESS](https://www.autohotkey.com/mpress/mpress_web.htm)" }, - "AutoHotkey2.DebugConfiguration": { - "scope": "window", + "AHK++.general": { "type": "object", + "properties": { + "showOutput": { + "type": "string", + "enum": [ + "always", + "never" + ], + "enumDescriptions": [ + "%ahk++.config.general.showOutput.always%", + "%ahk++.config.general.showOutput.never%" + ], + "default": "always", + "description": "%ahk++.config.general.showOutput%" + } + }, "default": { - "port": "9002-9100", - "useAnnounce": "detail", - "useAutoJumpToError": true, - "useDebugDirective": true, - "usePerfTips": true + "showOutput": "always" }, - "description": "%ahk2.debugconfiguration%" + "additionalProperties": { + "type": "string" + } }, - "AutoHotkey2.Diagnostics.ClassNonDynamicMemberCheck": { - "scope": "window", - "type": "boolean", - "default": true, - "description": "%ahk2.diagnostics.class-non-dynamic-member-check%" + "AHK++.menu": { + "type": "object", + "properties": { + "showDebugButton": { + "type": "boolean", + "default": true, + "description": "Show the debug buttons in the editor title menu." + } + }, + "default": { + "showDebugButton": true + }, + "additionalProperties": { + "type": "string" + } }, - "AutoHotkey2.Diagnostics.ParamsCheck": { - "scope": "window", - "type": "boolean", - "default": true, - "description": "%ahk2.diagnostics.paramscheck%" + "AHK++.v1.file": { + "type": "object", + "markdownDescription": "[Learn more about the template snippet](https://github.com/mark-wiemer-org/ahkpp/tree/main/docs/TemplateSnippet.md)", + "properties": { + "compileBaseFile": { + "type": "string", + "default": "", + "description": "Base file path for compiling v1 scripts (optional)." + }, + "helpPath": { + "type": "string", + "default": "C:/Program Files/AutoHotkey/AutoHotkey.chm", + "description": "Path to the AHK v1 help document." + }, + "interpreterPath": { + "type": "string", + "default": "C:/Program Files/AutoHotkey/AutoHotkeyU64.exe", + "description": "Path to the AHK v1 interpreter." + }, + "templateSnippetName": { + "type": "string", + "default": "AhkTemplateV1", + "description": "The name of the snippet to populate new AHK v1 files. If blank, no snippet will be applied." + } + }, + "default": { + "compileBaseFile": "", + "helpPath": "C:/Program Files/AutoHotkey/AutoHotkey.chm", + "interpreterPath": "C:/Program Files/AutoHotkey/AutoHotkeyU64.exe", + "templateSnippetName": "AhkTemplateV1" + }, + "additionalProperties": { + "type": "string" + } }, - "AutoHotkey2.Warn.VarUnset": { - "scope": "window", - "type": "boolean", - "default": true, - "description": "%ahk2.warn.varunset%" + "AHK++.v1.formatter": { + "type": "object", + "properties": { + "allowedNumberOfEmptyLines": { + "type": "integer", + "default": 1, + "minimum": -1, + "description": "Allowed number of empty lines.\n- -1: Ignore empty lines.\n- 0: No empty lines." + }, + "indentCodeAfterIfDirective": { + "type": "boolean", + "default": true, + "description": "Indent code after a directive that creates context-sensitive hotkeys or hotstrings (#If, #IfWinActive, #IfWinNotActive, #IfWinExist, #IfWinNotExist)." + }, + "indentCodeAfterLabel": { + "type": "boolean", + "default": true, + "description": "Indent code after hotkeys and labels in top-level code blocks." + }, + "preserveIndent": { + "type": "boolean", + "default": false, + "description": "Preserve indentation on empty line." + }, + "trimExtraSpaces": { + "type": "boolean", + "default": true, + "description": "Trim extra spaces between words." + } + }, + "default": { + "allowedNumberOfEmptyLines": 1, + "indentCodeAfterIfDirective": true, + "indentCodeAfterLabel": true, + "preserveIndent": false, + "trimExtraSpaces": true + }, + "additionalProperties": { + "type": "string" + } }, - "AutoHotkey2.Warn.LocalSameAsGlobal": { - "scope": "window", - "type": "boolean", - "default": false, - "description": "%ahk2.warn.localsameasglobal%" + "AHK++.v1.intellisense": { + "type": "object", + "markdownDescription": "Number of lines to parse each AHK file for IntelliSense.\n- -1: Unlimited parsing\n- 0: No parsing\n\nChanges take effect after restart.", + "properties": { + "maximumParseLength": { + "type": "number", + "default": 10000, + "minimum": -1 + } + }, + "default": { + "maximumParseLength": 10000 + }, + "additionalProperties": { + "type": "string" + } }, - "AutoHotkey2.Warn.CallWithoutParentheses": { - "scope": "window", - "type": "string", - "enum": [ - "Off", - "Parentheses", - "On" - ], - "default": "Off", - "description": "%ahk2.warn.callwithoutparentheses%" - }, - "AutoHotkey2.ActionWhenV1IsDetected": { - "scope": "window", - "type": "string", - "default": "Warn", - "enum": [ - "Continue", - "Warn", - "StopParsing", - "SwitchToV1", - "SkipLine" - ], - "description": "%ahk2.actionwhenv1isdetected%" - }, - "AutoHotkey2.CompletionCommitCharacters": { + "AHK++.v2.completionCommitCharacters": { + "markdownDescription": "%ahk++.config.v2.completionCommitCharacters%", "scope": "window", "type": "object", "properties": { "Class": { - "type": "string" + "type": "string", + "default": ".(" }, "Function": { - "type": "string" + "type": "string", + "default": "(" } }, + "default": { + "Class": ".(", + "Function": "(" + }, "additionalProperties": { "type": "string" + } + }, + "AHK++.v2.debugConfiguration": { + "markdownDescription": "%ahk++.config.v2.debugConfiguration%", + "scope": "window", + "type": "object", + "properties": { + "port": { + "type": "string", + "default": "9002-9100" + }, + "useAnnounce": { + "type": "string", + "default": "detail" + }, + "useAutoJumpToError": { + "type": "boolean", + "default": true + }, + "useDebugDirective": { + "type": "boolean", + "default": true + }, + "usePerfTips": { + "type": "boolean", + "default": true + } }, "default": { - "Class": ".(", - "Function": "(" + "port": "9002-9100", + "useAnnounce": "detail", + "useAutoJumpToError": true, + "useDebugDirective": true, + "usePerfTips": true + }, + "additionalProperties": { + "type": "string" + } + }, + "AHK++.v2.diagnostics": { + "scope": "window", + "type": "object", + "properties": { + "classNonDynamicMemberCheck": { + "type": "boolean", + "default": true, + "description": "%ahk++.config.v2.diagnostics.classNonDynamicMemberCheck%" + }, + "paramsCheck": { + "type": "boolean", + "default": true, + "description": "%ahk++.config.v2.diagnostics.paramsCheck%" + } + }, + "default": { + "classNonDynamicMemberCheck": true, + "paramsCheck": true }, - "markdownDescription": "%ahk2.completioncommitcharacters%" + "additionalProperties": { + "type": "string" + } }, - "AutoHotkey2.Files.Exclude": { + "AHK++.v2.exclude": { "scope": "window", "type": "array", "default": [], @@ -205,19 +440,54 @@ "type": "string" }, "uniqueItems": true, - "description": "%ahk2.files.exclude%" + "markdownDescription": "%ahk++.config.v2.file.exclude%" }, - "AutoHotkey2.Files.ScanMaxDepth": { - "scope": "window", - "type": "integer", - "default": 2, - "description": "%ahk2.files.scanmaxdepth%" + "AHK++.v2.file": { + "type": "object", + "properties": { + "compileBaseFile": { + "type": "string", + "default": "", + "description": "Base file path for compiling v2 scripts (optional)." + }, + "helpPath": { + "type": "string", + "default": "C:/Program Files/AutoHotkey/v2/AutoHotkey.chm", + "description": "Path to the AHK v2 help document." + }, + "interpreterPath": { + "type": "string", + "default": "C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe", + "description": "%ahk++.config.v2.file.interpreterPath%" + }, + "maxScanDepth": { + "scope": "window", + "type": "integer", + "default": 2, + "description": "%ahk++.config.v2.file.maxScanDepth%" + }, + "templateSnippetName": { + "type": "string", + "default": "AhkTemplateV2", + "description": "The name of the snippet to populate new AHK v2 files. If blank, no snippet will be applied." + } + }, + "default": { + "compileBaseFile": "", + "helpPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.chm", + "interpreterPath": "C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe", + "maxScanDepth": 2, + "templateSnippetName": "AhkTemplateV2" + }, + "additionalProperties": { + "type": "string" + } }, - "AutoHotkey2.FormatOptions": { + "AHK++.v2.formatter": { "scope": "window", "type": "object", "properties": { - "array_style": { + "arrayStyle": { "type": "string", "enum": [ "collapse", @@ -226,7 +496,7 @@ ], "default": "none" }, - "brace_style": { + "braceStyle": { "type": "string", "enum": [ "One True Brace", @@ -239,31 +509,31 @@ "if 1 {\n}\nelse {\n}" ] }, - "break_chained_methods": { + "breakChainedMethods": { "type": "boolean", "default": false }, - "ignore_comment": { + "ignoreComment": { "type": "boolean", "default": false }, - "indent_string": { + "indentString": { "type": "string", - "default": "\t" + "default": " " }, - "indent_between_hotif_directive": { + "indentBetweenHotIfDirectives": { "type": "boolean", "default": false }, - "keyword_start_with_uppercase": { + "keywordStartWithUppercase": { "type": "boolean", "default": false }, - "max_preserve_newlines": { + "maxPreserveNewlines": { "type": "number", "default": 2 }, - "object_style": { + "objectStyle": { "type": "string", "enum": [ "collapse", @@ -272,64 +542,137 @@ ], "default": "none" }, - "preserve_newlines": { + "preserveNewlines": { "type": "boolean", "default": true }, - "space_before_conditional": { + "spaceBeforeConditional": { "type": "boolean", "default": true }, - "space_after_double_colon": { + "spaceAfterDoubleColon": { "type": "boolean", "default": true }, - "space_in_empty_paren": { + "spaceInEmptyParen": { "type": "boolean", "default": false }, - "space_in_other": { + "spaceInOther": { "type": "boolean", "default": true }, - "space_in_paren": { + "spaceInParen": { "type": "boolean", "default": false }, - "switch_case_alignment": { + "switchCaseAlignment": { "type": "boolean", "default": false }, - "symbol_with_same_case": { + "symbolWithSameCase": { "type": "boolean", "default": false }, - "white_space_before_inline_comment": { + "whitespaceBeforeInlineComment": { "type": "string" }, - "wrap_line_length": { + "wrapLineLength": { "type": "number", - "default": 0 + "default": 0, + "description": "0 to disable wrapping" } }, "additionalProperties": { "type": "string" }, - "default": {} - }, - "AutoHotkey2.InterpreterPath": { - "scope": "window", - "type": "string", - "default": "C:\\Program Files\\Autohotkey\\v2\\AutoHotkey.exe", - "markdownDescription": "%ahk2.interpreterpath%" - }, - "AutoHotkey2.SymbolFoldingFromOpenBrace": { + "default": { + "arrayStyle": "none", + "braceStyle": "One True Brace", + "breakChainedMethods": false, + "ignoreComment": false, + "indentString": " ", + "indentBetweenHotIfDirectives": false, + "keywordStartWithUppercase": false, + "maxPreserveNewlines": 2, + "objectStyle": "none", + "preserveNewlines": true, + "spaceBeforeConditional": true, + "spaceAfterDoubleColon": true, + "spaceInEmptyParen": false, + "spaceInOther": true, + "spaceInParen": false, + "switchCaseAlignment": false, + "symbolWithSameCase": false, + "whitespaceBeforeInlineComment": "", + "wrapLineLength": 120 + } + }, + "AHK++.v2.general": { + "type": "object", "scope": "window", - "type": "boolean", - "default": false, - "description": "%ahk2.symbolfoldingfromopenbrace%" + "properties": { + "actionWhenV1Detected": { + "scope": "window", + "type": "string", + "default": "SwitchToV1", + "enum": [ + "Continue", + "Warn", + "StopParsing", + "SwitchToV1", + "SkipLine" + ], + "description": "%ahk++.config.v2.actionWhenV1Detected%" + }, + "commentTagRegex": { + "type": "string", + "default": "^;;\\s*(?.+)", + "description": "%ahk++.config.v2.commentTagRegex%" + }, + "completeFunctionCalls": { + "type": "boolean", + "default": false, + "description": "%ahk++.config.v2.completeFunctionCalls%" + }, + "librarySuggestions": { + "scope": "window", + "type": "string", + "enum": [ + "Disabled", + "Local", + "User and Standard", + "All" + ], + "default": "Disabled", + "description": "%ahk++.config.v2.librarySuggestions%" + }, + "symbolFoldingFromOpenBrace": { + "scope": "window", + "type": "boolean", + "default": false, + "description": "%ahk++.config.v2.symbolFoldingFromOpenBrace%" + }, + "syntaxes": { + "scope": "window", + "type": "string", + "default": "", + "description": "%ahk++.config.v2.syntaxes%" + } + }, + "default": { + "actionWhenV1Detected": "SwitchToV1", + "commentTagRegex": "^;;\\s*(?.+)", + "completeFunctionCalls": false, + "librarySuggestions": "Disabled", + "symbolFoldingFromOpenBrace": false, + "syntaxes": "" + }, + "additionalProperties": { + "type": "string" + } }, - "AutoHotkey2.WorkingDirs": { + "AHK++.v2.workingDirectories": { "scope": "window", "type": "array", "default": [], @@ -337,12 +680,43 @@ "type": "string" }, "uniqueItems": true, - "description": "%ahk2.workingdirs%" + "description": "%ahk++.config.v2.workingDirectories%" }, - "AutoHotkey2.Syntaxes": { - "scope": "window", - "type": "string", - "markdownDescription": "%ahk2.syntaxes%" + "AHK++.v2.warn": { + "type": "object", + "properties": { + "callWithoutParentheses": { + "scope": "window", + "type": "string", + "enum": [ + "Off", + "Parentheses", + "On" + ], + "default": "Off", + "description": "%ahk++.config.v2.warn.callWithoutParentheses%" + }, + "localSameAsGlobal": { + "scope": "window", + "type": "boolean", + "default": false, + "description": "%ahk++.config.v2.warn.localSameAsGlobal%" + }, + "varUnset": { + "scope": "window", + "type": "boolean", + "default": true, + "description": "%ahk++.config.v2.warn.varUnset%" + } + }, + "default": { + "callWithoutParentheses": "Off", + "localSameAsGlobal": false, + "varUnset": true + }, + "additionalProperties": { + "type": "string" + } } } }, @@ -356,114 +730,88 @@ } } }, - "commands": [ - { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk2.debug.file", - "title": "%ahk2.debug.file%", - "icon": "$(debug)", - "category": "ahk2" - }, - { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk2.debug.configs", - "title": "%ahk2.debug.configs%", - "icon": "$(debug-all)", - "category": "ahk2" - }, - { - "enablement": "shellExecutionSupported", - "command": "ahk2.debug.attach", - "title": "%ahk2.debug.attach%", - "icon": "$(debug-alt)", - "category": "ahk2" - }, - { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", - "command": "ahk2.debug.params", - "title": "%ahk2.debug.params%", - "icon": "$(debug-console)", - "category": "ahk2" - }, + "grammars": [ { - "enablement": "editorLangId == ahk2", - "command": "ahk2.diagnose.all", - "title": "%ahk2.diagnose.all%", - "category": "ahk2" + "language": "ahk2", + "scopeName": "source.ahk2", + "path": "./syntaxes/ahk2.tmLanguage.json", + "embeddedLanguages": { + "meta.embedded.ahk2": "ahk2" + }, + "unbalancedBracketScopes": [ + "keyword.keys.ahk2" + ] }, { - "enablement": "editorLangId == ahk2", - "command": "ahk2.extract.symbols", - "title": "%ahk2.extract.symbols%", - "category": "ahk2" - }, + "language": "~ahk2-output", + "scopeName": "ahk2.output", + "path": "./syntaxes/ahk2-output.tmLanguage.json" + } + ], + "keybindings": [ { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", "command": "ahk2.run", - "title": "%ahk2.run%", - "icon": "$(play)", - "category": "ahk2" + "key": "ctrl+f5", + "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection" }, { - "enablement": "editorLangId == ahk2 && !isWeb", "command": "ahk2.run.selection", - "title": "%ahk2.run.selection%", - "category": "ahk2" - }, - { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.stop", - "title": "%ahk2.stop%", - "icon": "$(stop)", - "category": "ahk2" + "key": "ctrl+f5", + "when": "editorLangId == ahk2 && !isWeb && editorHasSelection" }, { - "enablement": "editorLangId == ahk2 && shellExecutionSupported", "command": "ahk2.compile", - "title": "%ahk2.compile%", - "category": "ahk2" + "key": "ctrl+shift+f5", + "when": "editorLangId == ahk2 && !isWeb" }, { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.help", - "title": "%ahk2.help%", - "category": "ahk2" + "command": "ahk2.debug.file", + "key": "f5", + "when": "editorLangId == ahk2 && debuggersAvailable && debugState == 'inactive'" }, { - "enablement": "editorLangId == ahk2", - "command": "ahk2.generate.comment", - "title": "%ahk2.generate.comment%", - "category": "ahk2" + "command": "ahk2.debug.params", + "key": "shift+f5", + "when": "editorLangId == ahk2 && debuggersAvailable && debugState == 'inactive'" }, { - "enablement": "!isWeb", - "command": "ahk2.set.interpreter", - "title": "%ahk2.set.interpreter%", - "category": "ahk2" + "command": "ahk2.help", + "key": "ctrl+f1", + "when": "editorLangId == ahk2 && !isWeb" }, { - "enablement": "editorLangId == ahk2", - "command": "ahk2.update.versioninfo", - "title": "%ahk2.update.versioninfo%", - "category": "ahk2" - }, + "command": "ahk2.stop", + "key": "ctrl+f6", + "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning" + } + ], + "languages": [ { - "enablement": "editorLangId == ahk2 || editorLangId == ahk", - "command": "ahk2.switch", - "title": "Switch v1/v2", - "category": "ahk2" + "id": "ahk2", + "aliases": [ + "AutoHotkey2", + "autohotkey2", + "ahk2" + ], + "extensions": [ + ".ahk", + ".ah2", + ".ahk2" + ], + "configuration": "./ahk2.configuration.json", + "icon": { + "dark": "icon_filetype.png", + "light": "icon_filetype.png" + } }, { - "enablement": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.select.syntaxes", - "title": "%ahk2.select.syntaxes%", - "category": "ahk2" + "id": "ahk", + "aliases": [ + "AutoHotkey" + ] }, { - "enablement": "editorLangId == ahk2 && resourceScheme == file", - "command": "ahk2.set.scriptdir", - "title": "%ahk2.set.scriptdir%", - "category": "ahk2" + "id": "~ahk2-output" } ], "menus": { @@ -578,49 +926,6 @@ } ] }, - "submenus": [ - { - "id": "ahk2.context", - "label": "AutoHotkey v2" - } - ], - "keybindings": [ - { - "command": "ahk2.run", - "key": "ctrl+f5", - "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection" - }, - { - "command": "ahk2.run.selection", - "key": "ctrl+f5", - "when": "editorLangId == ahk2 && !isWeb && editorHasSelection" - }, - { - "command": "ahk2.compile", - "key": "ctrl+shift+f5", - "when": "editorLangId == ahk2 && !isWeb" - }, - { - "command": "ahk2.debug.file", - "key": "f5", - "when": "editorLangId == ahk2 && debuggersAvailable && debugState == 'inactive'" - }, - { - "command": "ahk2.debug.params", - "key": "shift+f5", - "when": "editorLangId == ahk2 && debuggersAvailable && debugState == 'inactive'" - }, - { - "command": "ahk2.help", - "key": "ctrl+f1", - "when": "editorLangId == ahk2 && !isWeb" - }, - { - "command": "ahk2.stop", - "key": "ctrl+f6", - "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning" - } - ], "semanticTokenScopes": [ { "language": "ahk2", @@ -630,37 +935,49 @@ ] } } + ], + "submenus": [ + { + "id": "ahk2.context", + "label": "AutoHotkey v2" + } ] }, - "scripts": { - "check-types": "tsc", - "build-cli": "node esbuild.mjs --cli", - "eslint": "eslint --fix", - "package": "vsce package", - "publish": "vsce publish", - "test": "vscode-test", - "test-grammar": "vscode-tmgrammar-snap tmgrammar-test/*.ahk", - "vscode:prepublish": "node esbuild.mjs && npm run test && npm run test-grammar", - "watch": "node esbuild.mjs --dev", - "watch-web": "node esbuild.mjs --web" + "prettier": { + "singleQuote": true, + "trailingComma": "all", + "useTabs": true + }, + "mocha": { + "spec": "out/**/*.spec.js" + }, + "dependencies": { + "klona": "^2.0.6", + "path-browserify": "^1.0.1", + "vscode-languageclient": "^9.0.1", + "vscode-languageserver": "^9.0.1", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-uri": "^3.0.8" }, "devDependencies": { + "@types/mocha": "^10.0.8", "@types/node": "^20.14.0", "@types/vscode": "1.93.0", "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", - "@vscode/vsce": "^2.32.0", + "@vscode/vsce": "^3.1.1", + "del-cli": "^5.1.0", "esbuild": "^0.24.0", "eslint": "^9.11.0", + "mocha": "^10.7.3", + "prettier": "3.3.3", + "sort-package-json": "^2.10.1", "typescript": "5.5.4", "typescript-eslint": "^8.7.0", "vscode-tmgrammar-test": "^0.1.3" }, - "dependencies": { - "path-browserify": "^1.0.1", - "vscode-languageclient": "^9.0.1", - "vscode-languageserver": "^9.0.1", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-uri": "^3.0.8" - } -} \ No newline at end of file + "engines": { + "vscode": "^1.93.0" + }, + "icon": "icon.png" +} diff --git a/package.nls.json b/package.nls.json index f82ad6af..c9049eeb 100644 --- a/package.nls.json +++ b/package.nls.json @@ -34,4 +34,4 @@ "ahk2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", "ahk2.update.versioninfo": "Update File Version Info", "ahk2.workingdirs": "Sets the working directory for the script" -} \ No newline at end of file +} diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index ed30b04f..97b62fc1 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -124,4 +124,4 @@ "setting.getenverr": "获取环境变量失败", "setting.uialimit": "由于安全限制, UIA可执行文件不允许重定向stdin/stdout, 因此依赖于此的一些功能将无法工作", "setting.versionerr": "当前AutoHotkey.exe不是v2版本, 无法获得正确的语法解析、补全等功能" -} \ No newline at end of file +} diff --git a/readme.md b/readme.md index 6e4d1702..3ac98bdf 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,366 @@ +**English** | [中文](./README.zh-CN.md) + # AutoHotkey v2 Language Support -This codebase is not meant for independent use, but rather as a submodule of [AHK++](https://github.com/mark-wiemer-org/ahkpp). +(This repo is a fork of https://github.com/thqby/vscode-autohotkey2-lsp) + +[![installs](https://img.shields.io/visual-studio-marketplace/i/thqby.vscode-autohotkey2-lsp?label=Extension%20Install&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) +[![version](https://img.shields.io/visual-studio-marketplace/v/thqby.vscode-autohotkey2-lsp?label=Extension%20Version&style=for-the-badge&logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp) +[![](https://img.shields.io/badge/Compatibility-autohotkey%20v2.0+-green?style=for-the-badge&logo=autohotkey)](https://www.autohotkey.com/) + +**Repositories**: [Github](https://github.com/thqby/vscode-autohotkey2-lsp) | [Gitee](https://gitee.com/orz707/vscode-autohotkey2-lsp) + +AutoHotkey v2 Language support for VS Code, features realization based on v2 syntax analysis. +Supports running on the Web, such as `Chrome/Edge`. https://vscode.dev or https://github.dev/github/dev + +- [AutoHotkey v2 Language Support](#autohotkey-v2-language-support) + - [Language Features](#language-features) + - [Rename Symbol](#rename-symbol) + - [Diagnostics](#diagnostics) + - [IntelliSense](#intellisense) + - [Signature](#signature) + - [Document Symbol](#document-symbol) + - [Semantic Highlight](#semantic-highlight) + - [Tags](#tags) + - [Document Color](#document-color) + - [Hover](#hover) + - [Goto Definition](#goto-definition) + - [Find All References](#find-all-references) + - [CodeFormat](#codeformat) + - [Custom folding](#custom-folding) + - [Declaration document](#declaration-document) + - [Context Menu](#context-menu) + - [Quick Help](#quick-help) + - [Run Script](#run-script) + - [Run Selected Script](#run-selected-script) + - [Compile Script](#compile-script) + - [Debug Script](#debug-script) + - [Generate Comment](#generate-comment) + - [Use in other editors](#use-in-other-editors) + - [Sublime Text4](#sublime-text4) + - [Vim and Neovim](#vim-and-neovim) + - [Emacs](#Emacs) + - [Use in Web Browser](#use-in-web-browser) + +## Language Features + +### Rename Symbol + +Rename variables and function names in the scope in batches. + +![rename](./pic/rename.gif) + +### Diagnostics + +Simple syntax error diagnosis. + +![diagnostics](./pic/diagnostics2.png) + +### IntelliSense + +Supports intelligent completion of variables, functions, parameters, class names, and method names within the scope (by simple type deduction), and supports the completion of include files and function libraries. + +![snippet1](./pic/snippet.png) + +![snippet2](./pic/snippet.gif) + +### Signature + +Support for intelligent prompts for function parameters. + +![signature](./pic/signature.gif) + +### Document Symbol + +1. Displays class, method, function, variable, label, hotkey, hot string, block information in the left outline column. +2. press Ctrl + P, Input @symbol_name to retrieve and jump +3. You can comment a method with a semicolon or /\* \*/ on the top line of a function, variable. Jsdoc-style annotations can mark variable types. + + + +```js +/** + * @param {Array} a - a param + * @return {Integer} + */ +fn(a*) { + /** @type {Map} */ + d := Map() + /** + * @var {Map} e + * @var {Object} f + */ + e := Map(), f := {} + /** @type {(a,b)=>Integer} */ + cb := (a, b) => a + b + /** @type {ComObject} */ + wb := ComObject('Excel.Sheet.12') + return a[1] + a[2] +} +class abc { + /** @type {Map} */ + p := dosomethingandreturnmap() +} +``` + +### Semantic Highlight + +Semantic highlighting is an addition to syntax highlighting, resolves symbols in the context of a project. The editor applies the highlighting from semantic tokens on top of the highlighting from grammars. + +![semanticTokens](./pic/semanticTokens.png) + +### Tags + +usage: Add `;;`(default) or `; TODO ` to the comment code Tags. + +![codeSymbole](./pic/codeSymbol.png) + +### Document Color + +Compute and resolve colors inside a document to provide color picker in editor. + +![documentcolor](./pic/documentcolor.png) + +### Hover + +Supports hover prompts and comments for scoped variables, functions, global classes, and labels. +usage: Move the mouse over the symbol. + +![hover](./pic/hover.png) + +### Goto Definition + +1. Support for jumping to the declaration location of scoped variables, functions, global classes, and labels. +2. usage: Press ctrl Then move the mouse over to the code and click. + +![gotoDefinition](./pic/gotoDefinition.png) + +### Find All References + +See all the source code locations where a certain variable/function is being used. + +### CodeFormat + +usage: + +- Right-click the popup menu and click "Format document". +- Press `Shift+Alt+F`. +- Supports formatting code blocks when typing '}', formatting lines and indenting lines when typing '\n'. (`editor.formatOnType` needs to be enabled) +- Supports the use of formatting instructions `;@format array_style: collapse, object_style: expand` to change the object style of different blocks + +![codeFormat](./pic/codeFormat.gif) + +### Custom folding + +Fold the part between `;@region tag` and `;@endregion`, `;{` and `;}` + +```ini +;#region tag +code +;#endregion +``` + +### Declaration document + +The declaration file is a file with the suffix of `.d.ahk` as the file name, which is used to describe the implemented functions or classes, etc., does not contain the implementation part of the code, and is referenced by the ahk file with the same name by default, and the syntax refers to `ahk2.d.ahk` provided by the extension. The declaration file can extend or rewrite the declaration of ahk built-in functions or classes, and the annotation document can be separated from the source code to provide a multilingual version of intellisense. + +``` +; array.d.ahk +; #ClsName represents the ahk built-in class +/** @extends {#Array} */ +class Array { + /** jsdoc-default */ + Filter(FilterFunc) => Array +} + +; array.zh-cn.d.ahk +; #ClsName 表示ahk内置类 +/** @extends {#Array} */ +class Array { + /** jsdoc-zh */ + Filter(FilterFunc) => Array +} + +; array.ahk +; %A_Locale% is VSCode's Display Language +;@reference array.%A_Locale%.d.ahk +Array.Prototype.DefineProp('Filter', { call: Array_Filter_impl }) +``` + +## Context Menu + +### Quick Help + +Open the help file and navigate to the keyword at the current cursor. + +### Run Script + +Run the currently open script. + +### Run Selected Script + +Run the code snippet at the cursor selection. + +### Compile Script + +Compile the script to generate executable EXE files. + +### Debug Script + +No additional configuration is required to start the installed Debug extensions, and support debugging with parameters. + +### Generate Comment + +Generate JSDOC-style comments for a function or method. + +## Use in other editors + +1. Install [Node.js](https://nodejs.org/en/download/). +2. Download vscode-autohotkey2-lsp server using command line, or download and unpack through [vscode marketplace](https://marketplace.visualstudio.com/items?itemName=thqby.vscode-autohotkey2-lsp). + +```shell +mkdir vscode-autohotkey2-lsp +cd vscode-autohotkey2-lsp +curl.exe -L -o install.js https://raw.githubusercontent.com/thqby/vscode-autohotkey2-lsp/main/tools/install.js +node install.js +``` + +3. Set the LSP configuration of the editor that support [LSP(Language Server Protocol)](https://microsoft.github.io/language-server-protocol/), such as Sublime Text4, Vim, Neovim, Emacs, [etc](https://microsoft.github.io/language-server-protocol/implementors/tools/). + +### Sublime Text4 + +- `Package Control: Install Package`, and install [Sublime LSP](https://github.com/sublimelsp/LSP) plug-in. +- `Preferences: LSP Settings`, add lsp configuration, language selector, and syntax highlighting. This is a simple example [syntax highlighting](https://github.com/thqby/vscode-autohotkey2-lsp/files/9843973/AutoHotkey2.sublime-syntax.zip), save the file in a similar path `C:\Users\\AppData\Roaming\Sublime Text\Packages\User\LSP-ahk2\AutoHotkey2.sublime-syntax`. + +```json +{ + "clients": { + "lsp-ahk2": { + "enabled": true, + "command": [ + "node", + "/server/dist/server.js", + "--stdio" + ], // Update the path of node.exe(maybe it's already in PATH, so you don't need to set it) and the folder of vscode-autohotkey2-lsp + "selector": "source.ahk2", // Same as scope in AutoHotkey2.sublime-syntax + "schemes": ["file", "buffer", "res"], + "initializationOptions": { + "locale": "en-us", // or "zh-cn" + "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" + "CommentTags": "^;;\\s*(?.+)", + "CompleteFunctionParens": false, + "Diagnostics": { + "ClassStaticMemberCheck": true, + "ParamsCheck": true + }, + "ActionWhenV1IsDetected": "Continue", + "FormatOptions": { + "array_style": "none", // or "collapse" or "expand" + "break_chained_methods": false, + "ignore_comment": false, + "indent_string": "\t", + "max_preserve_newlines": 2, + "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" + "object_style": "none", // or "collapse" or "expand" + "preserve_newlines": true, + "space_after_double_colon": true, + "space_before_conditional": true, + "space_in_empty_paren": false, + "space_in_other": true, + "space_in_paren": false, + "wrap_line_length": 0 + }, + "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + "WorkingDirs": [], + "SymbolFoldingFromOpenBrace": false + } + } + }, + "semantic_highlighting": true +} +``` + +### Vim and Neovim + +#### COC + +- Download [coc.nvim plugin](https://github.com/neoclide/coc.nvim). + +```bat +cd $VIMRUNTIME\plugin +git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 +``` + +- Open (n)vim and enter the command `:CocConfig` to enter the `coc.nvim` configuration file to add configuration information. + +```json +{ + "languageserver": { + "lsp-ahk2": { + "module": "/server/dist/server.js", + "filetypes": ["autohotkey"], + "args": ["--node-ipc"], + "initializationOptions": { + // Same as initializationOptions for Sublime Text4 + } + } + } +} +``` + +#### nvim-lspconfig + +- Download [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). +- Add the following to your NVIM configuration (init.lua e.g.). Ensure that `cmd` points to the path of your vscode-autohotkey2-lsp installation and `InterpreterPath` points to your AHK exe. + +```lua +local function custom_attach(client, bufnr) + require("lsp_signature").on_attach({ + bind = true, + use_lspsaga = false, + floating_window = true, + fix_pos = true, + hint_enable = true, + hi_parameter = "Search", + handler_opts = { "double" }, + }) +end + +local ahk2_configs = { + autostart = true, + cmd = { + "node", + vim.fn.expand("$HOME/vscode-autohotkey2-lsp/server/dist/server.js"), + "--stdio" + }, + filetypes = { "ahk", "autohotkey", "ah2" }, + init_options = { + locale = "en-us", + InterpreterPath = "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + -- Same as initializationOptions for Sublime Text4, convert json literal to lua dictionary literal + }, + single_file_support = true, + flags = { debounce_text_changes = 500 }, + capabilities = capabilities, + on_attach = custom_attach, +} +local configs = require "lspconfig.configs" +configs["ahk2"] = { default_config = ahk2_configs } +local nvim_lsp = require("lspconfig") +nvim_lsp.ahk2.setup({}) +``` + +### Emacs + +#### Eglot + +- Add the following lines to your emacs config file + +```emacs-lisp +(add-to-list 'eglot-server-programs '(ahk-mode "node" "/server/dist/server.js" "--stdio")) + +``` + +## Use in Web Browser -It provides AHK v2 language support via the [Language Server Protocol](https://microsoft.github.io/language-server-protocol). +visit https://github.dev or https://vscode.dev in `Chrome/Edge`, and install `thqby.vscode-autohotkey2-lsp` diff --git a/server/cli/cli.ts b/server/cli/cli.ts index 05dd3b9a..0ebf9ec9 100644 --- a/server/cli/cli.ts +++ b/server/cli/cli.ts @@ -1,20 +1,18 @@ import { openFile } from '../src/common'; -import { Lexer } from '../src/Lexer'; +import { Lexer } from '../src/lexer'; function main() { const options: Record = {}; - process.argv.slice(2).forEach(s => { + process.argv.slice(2).forEach((s) => { const arr = s.split('='); options[arr[0]] = arr[1]; }); let path: string = options.path ?? ''; path = path.replace(/^(['"])(.*)\1$/, '$2'); - if (!path) - return; + if (!path) return; try { const td = openFile(path, false); - if (!td) - return; + if (!td) return; const sc = new Lexer(td).beautify({}); console.log(sc); } catch (e) { @@ -22,4 +20,4 @@ function main() { } } -main() \ No newline at end of file +main(); diff --git a/server/package.json b/server/package.json index 8d224825..4a6b5828 100644 --- a/server/package.json +++ b/server/package.json @@ -4,4 +4,4 @@ "fs": false, "path": "path-browserify" } -} \ No newline at end of file +} diff --git a/server/src/ahkProvider.ts b/server/src/ahkProvider.ts index 91d158f6..0407ec7e 100644 --- a/server/src/ahkProvider.ts +++ b/server/src/ahkProvider.ts @@ -1,13 +1,13 @@ import { createClientSocketTransport, createMessageConnection, createServerSocketTransport, MessageConnection } from 'vscode-languageserver/node'; import { spawn } from 'child_process'; import { resolvePath } from './scriptrunner'; -import { interpreterPathV2, rootdir } from './common'; +import { interpreterPath, rootdir } from './common'; let ahk_server: MessageConnection | undefined | null; async function get_ahkProvider_port(): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async resolve => { - const executePath = resolvePath(interpreterPathV2); + const executePath = resolvePath(interpreterPath); if (!executePath) return resolve(0); let server, port = 1200; diff --git a/server/src/browserServerMain.ts b/server/src/browserServerMain.ts index 17c8bef7..3fa858a6 100644 --- a/server/src/browserServerMain.ts +++ b/server/src/browserServerMain.ts @@ -6,12 +6,13 @@ import { import { chinese_punctuations, colorPresentation, colorProvider, commands, completionProvider, defintionProvider, documentFormatting, enumNames, executeCommandProvider, exportSymbols, getVersionInfo, - hoverProvider, initahk2cache, Lexer, lexers, loadahk2, loadlocalize, prepareRename, rangeFormatting, + hoverProvider, initahk2cache, Lexer, lexers, loadAHK2, loadlocalize, prepareRename, rangeFormatting, referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, - signatureProvider, symbolProvider, typeFormatting, updateAhkppConfig, workspaceSymbolProvider + signatureProvider, symbolProvider, typeFormatting, updateConfig, workspaceSymbolProvider } from './common'; -import { AhkppConfig } from './config'; +import { AHKLSConfig, CfgKey, configPrefix, getCfg } from '../../util/src/config'; +import { serverExportSymbols, serverGetContent, serverGetVersionInfo } from '../../util/src/env'; const languageServer = 'ahk2-language-server'; const messageReader = new BrowserMessageReader(self); @@ -75,18 +76,18 @@ connection.onInitialize(params => { result.capabilities.workspace = { workspaceFolders: { supported: true } }; } - const configs: AhkppConfig = params.initializationOptions; + const initialConfig: AHKLSConfig = params.initializationOptions; set_ahk_h(true); set_locale(params.locale); - set_dirname(configs.extensionUri!); + set_dirname(getCfg(CfgKey.ExtensionUri, initialConfig)); loadlocalize(); - updateAhkppConfig(configs); + updateConfig(initialConfig); set_WorkspaceFolders(workspaceFolders); set_version('3.0.0'); initahk2cache(); - loadahk2(); - loadahk2('ahk2_h'); - loadahk2('winapi', 4); + loadAHK2(); + loadAHK2('ahk2_h'); + loadAHK2('winapi', 4); return result; }); @@ -105,14 +106,14 @@ connection.onInitialized(() => { }); connection.onDidChangeConfiguration(async change => { - let newset: AhkppConfig | undefined = change?.settings; + let newset: AHKLSConfig | undefined = change?.settings; if (hasConfigurationCapability && !newset) - newset = await connection.workspace.getConfiguration('AutoHotkey2'); + newset = await connection.workspace.getConfiguration(configPrefix); if (!newset) { connection.window.showWarningMessage('Failed to obtain the configuration'); return; } - updateAhkppConfig(newset); + updateConfig(newset); set_WorkspaceFolders(workspaceFolders); }); @@ -148,9 +149,9 @@ connection.onExecuteCommand(executeCommandProvider); connection.onWorkspaceSymbol(workspaceSymbolProvider); connection.languages.semanticTokens.on(semanticTokensOnFull); connection.languages.semanticTokens.onRange(semanticTokensOnRange); -connection.onRequest('ahk2.exportSymbols', exportSymbols); -connection.onRequest('ahk++.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); -connection.onRequest('ahk2.getVersionInfo', getVersionInfo); +connection.onRequest(serverExportSymbols, exportSymbols); +connection.onRequest(serverGetContent, (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); +connection.onRequest(serverGetVersionInfo, getVersionInfo); connection.onNotification('onDidCloseTextDocument', (params: { uri: string, id: string }) => { if (params.id === 'ahk2') diff --git a/server/src/commandProvider.ts b/server/src/commandProvider.ts index 5ab62303..a0cba8ec 100644 --- a/server/src/commandProvider.ts +++ b/server/src/commandProvider.ts @@ -1,13 +1,15 @@ import { CancellationToken, ExecuteCommandParams, Position, Range, SymbolKind } from 'vscode-languageserver'; import { AhkSymbol, ClassNode, FuncNode, Lexer, Property, Token, Variable, - connection, ahkppConfig, find_class, generate_type_annotation, + connection, find_class, generate_type_annotation, join_types, lexers, parse_include, restorePath, semanticTokensOnFull, traverse_include, update_include_cache } from './common'; +import { CfgKey, getCfg } from '../../util/src/config'; +import { clientGetActiveEditorInfo, clientInsertSnippet, clientSetTextDocumentLanguage, ExtensionCommand, extDiagnoseAll, extGenerateComment, extSetScriptDir } from '../../util/src/env'; function checkCommand(cmd: string) { - if (ahkppConfig.commands?.includes(cmd)) + if (getCfg(CfgKey.Commands)?.includes(cmd)) return true; connection?.console.warn(`Command '${cmd}' is not implemented!`); return false; @@ -19,15 +21,15 @@ function trim_jsdoc(detail?: string) { } function insertSnippet(value: string, range?: Range) { - if (!checkCommand('ahk++.insertSnippet')) + if (!checkCommand(clientInsertSnippet)) return; - connection?.sendRequest('ahk++.insertSnippet', [value, range]); + connection?.sendRequest(clientInsertSnippet, [value, range]); } export function setTextDocumentLanguage(uri: string, lang?: string) { - if (!checkCommand('ahk++.setTextDocumentLanguage')) + if (!checkCommand(clientSetTextDocumentLanguage)) return; - return connection?.sendRequest('ahk++.setTextDocumentLanguage', [uri, lang]); + return connection?.sendRequest(clientSetTextDocumentLanguage, [uri, lang]); } export function generate_fn_comment(doc: Lexer, fn: FuncNode, detail?: string) { @@ -76,9 +78,9 @@ export function generate_fn_comment(doc: Lexer, fn: FuncNode, detail?: string) { /** Add a function header comment for the currently active function */ async function generateComment() { - if (!checkCommand('ahk++.getActiveTextEditorUriAndPosition') || !checkCommand('ahk++.insertSnippet')) + if (!checkCommand(clientGetActiveEditorInfo) || !checkCommand(clientInsertSnippet)) return; - const { uri, position } = await connection?.sendRequest('ahk++.getActiveTextEditorUriAndPosition') as { uri: string, position: Position }; + const { uri, position } = await connection?.sendRequest(clientGetActiveEditorInfo) as { uri: string, position: Position }; const doc = lexers[uri.toLowerCase()]; let scope = doc.searchScopedNode(position); const ts = scope?.children || doc.children; @@ -207,9 +209,9 @@ export function exportSymbols(uri: string) { } async function diagnoseAll() { - if (!checkCommand('ahk++.getActiveTextEditorUriAndPosition')) + if (!checkCommand(clientGetActiveEditorInfo)) return; - const { uri } = await connection?.sendRequest('ahk++.getActiveTextEditorUriAndPosition') as { uri: string }; + const { uri } = await connection?.sendRequest(clientGetActiveEditorInfo) as { uri: string }; const doc = lexers[uri.toLowerCase()]; if (!doc) return; update_include_cache(); @@ -219,9 +221,9 @@ async function diagnoseAll() { } async function setscriptdir() { - if (!checkCommand('ahk++.getActiveTextEditorUriAndPosition')) + if (!checkCommand(clientGetActiveEditorInfo)) return; - const { uri } = await connection?.sendRequest('ahk++.getActiveTextEditorUriAndPosition') as { uri: string }; + const { uri } = await connection?.sendRequest(clientGetActiveEditorInfo) as { uri: string }; const lex = lexers[uri.toLowerCase()]; if (!lex) return; if (lex.scriptdir !== lex.scriptpath) @@ -264,14 +266,23 @@ export function getVersionInfo(uri: string) { return info; } +/** + * Also modified in `server.ts`, this holds all the commands that the server supports. + */ // eslint-disable-next-line @typescript-eslint/no-explicit-any -export const commands: { [command: string]: (args: any[]) => any } = { - 'ahk++.diagnostic.full': () => diagnoseAll(), - 'ahk++.addDocComment': () => generateComment(), - 'ahk++.setAScriptDir': setscriptdir +export const commands: Record any> = { + [extDiagnoseAll]: () => diagnoseAll(), + [extGenerateComment]: () => generateComment(), + [extSetScriptDir]: process.env.BROWSER ? () => 0 : setscriptdir }; +/** + * Executes the provided command. + * Only works for `ExtensionCommand` values. + * Does nothing if command not recognized. + * Ignores cancellation tokens. + */ export function executeCommandProvider(params: ExecuteCommandParams, token?: CancellationToken) { if (!token?.isCancellationRequested) - return commands[params.command](params.arguments ?? []); + return commands[params.command as ExtensionCommand]?.(params.arguments ?? []); } \ No newline at end of file diff --git a/server/src/common.spec.ts b/server/src/common.spec.ts new file mode 100644 index 00000000..560afb44 --- /dev/null +++ b/server/src/common.spec.ts @@ -0,0 +1,202 @@ +import { suite, test } from 'mocha'; +import { updateConfig } from './common'; +import * as assert from 'assert'; +import { + BraceStyle, + CallWithoutParentheses, + CfgKey, + getCfg, + LibIncludeType, + newConfig, + setCfg, +} from '../../util/src/config'; + +suite('updateConfig', () => { + suite('LibrarySuggestions', () => { + beforeEach(() => { + setCfg(CfgKey.LibrarySuggestions, LibIncludeType.Disabled); + }); + + test('LibIncludeType', () => { + const config = newConfig(); + setCfg( + CfgKey.LibrarySuggestions, + LibIncludeType.All, + config, + ); + + updateConfig(config); + + assert.strictEqual(getCfg(CfgKey.LibrarySuggestions), LibIncludeType.All); + }); + + test('string', () => { + const config = newConfig(); + setCfg(CfgKey.LibrarySuggestions, 'All', config); + + updateConfig(config); + + assert.strictEqual(getCfg(CfgKey.LibrarySuggestions), LibIncludeType.All); + }); + + test('boolean', () => { + const config = newConfig(); + setCfg(CfgKey.LibrarySuggestions, true, config); + + updateConfig(config); + + assert.strictEqual(getCfg(CfgKey.LibrarySuggestions), LibIncludeType.All); + }); + }); + + suite('Exclude', () => { + test('works', () => { + const config = newConfig(); + setCfg(CfgKey.Exclude, ['potato'], config); + + updateConfig(config); + + assert.deepStrictEqual(getCfg(CfgKey.Exclude), ['potato']); + }); + }); + + suite('MaxScanDepth', () => { + test('positive', () => { + const config = newConfig(); + setCfg(CfgKey.MaxScanDepth, 3, config); + + updateConfig(config); + + assert.strictEqual(getCfg(CfgKey.MaxScanDepth), 3); + }); + + test('negative', () => { + const config = newConfig(); + setCfg(CfgKey.MaxScanDepth, -3, config); + + updateConfig(config); + + assert.strictEqual(getCfg(CfgKey.MaxScanDepth), Infinity); + }); + }); + + suite('CallWithoutParentheses', () => { + beforeEach(() => { + setCfg(CfgKey.CallWithoutParentheses, undefined); + }); + + const theories: [value: CallWithoutParentheses][] = [ + [CallWithoutParentheses.On], + [CallWithoutParentheses.Off], + [CallWithoutParentheses.Parentheses], + ]; + + theories.forEach(([value]) => { + test(value, () => { + const config = newConfig(); + setCfg(CfgKey.CallWithoutParentheses, value, config); + + updateConfig(config); + + assert.strictEqual( + getCfg(CfgKey.CallWithoutParentheses), + value, + ); + }); + }); + }); + + suite('WorkingDirectories', () => { + beforeEach(() => { + setCfg(CfgKey.WorkingDirectories, undefined); + }); + + const theories: [ + name: string, + value: undefined | string[] | string, + expected: string[], + ][] = [ + ['undefined', undefined, []], + ['one string[]', ['C:\\'], ['file:///c%3a/']], + ['two string[]', ['C:\\', 'D:\\'], ['file:///c%3a/', 'file:///d%3a/']], + ['string', 'C:\\', []], + ]; + + theories.forEach(([name, value, expected]) => { + test(name, () => { + const config = newConfig(); + setCfg(CfgKey.WorkingDirectories, value, config); + + updateConfig(config); + + assert.deepStrictEqual( + getCfg(CfgKey.WorkingDirectories), + expected, + ); + }); + }); + }); + + suite('Syntaxes', () => { + beforeEach(() => { + setCfg(CfgKey.Syntaxes, undefined); + }); + + const theories: [ + name: string, + value: string | undefined, + expected: string | undefined, + ][] = [ + ['absolute path with forward slashes', 'C:/ahk.json', 'c:\\ahk.json'], + ['undefined', undefined, undefined], + ]; + + theories.forEach(([name, value, expected]) => { + test(name, () => { + const config = newConfig(); + setCfg(CfgKey.Syntaxes, value, config); + + updateConfig(config); + + assert.strictEqual(getCfg(CfgKey.Syntaxes), expected); + }); + }); + }); + + suite('BraceStyle', () => { + beforeEach(() => { + setCfg(CfgKey.BraceStyle, undefined); + }); + + const theories: [ + name: string, + value: string | undefined, + expected: BraceStyle, + ][] = [ + ['Allman', 'Allman', 'Allman'], + ['One True Brace', 'One True Brace', 'One True Brace'], + [ + 'One True Brace Variant', + 'One True Brace Variant', + 'One True Brace Variant', + ], + ['Preserve', 'Preserve', 'Preserve'], + ['undefined', undefined, 'Preserve'], + ['0', '0', 'Allman'], + ['1', '1', 'One True Brace'], + ['-1', '-1', 'One True Brace Variant'], + ['other value', 'potato', 'Preserve'], + ]; + + theories.forEach(([name, value, expected]) => { + test(name, () => { + const config = newConfig(); + setCfg(CfgKey.BraceStyle, value, config); + + updateConfig(config); + + assert.strictEqual(getCfg(CfgKey.BraceStyle), expected); + }); + }); + }); +}); diff --git a/server/src/common.ts b/server/src/common.ts index fe49975d..003e6513 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -4,11 +4,10 @@ import { readdirSync, readFileSync, existsSync, statSync, promises as fs } from import { Connection, MessageConnection } from 'vscode-languageserver'; import { TextDocument } from 'vscode-languageserver-textdocument'; import { CompletionItem, CompletionItemKind, Hover, InsertTextFormat, Range, SymbolKind } from 'vscode-languageserver-types'; -import { AhkSymbol, Lexer, setCommentTagRegex } from './Lexer'; +import { AhkSymbol, Lexer, fixupFormatConfig, updateCommentTagRegex } from './lexer'; import { diagnostic } from './localize'; import { jsDocTagNames } from './constants'; -import { AhkppConfig, CfgKey, getCfg, newAhkppConfig } from './config'; - +import { AHKLSConfig, CfgKey, getCfg, LibIncludeType, setCfg, setConfigRoot } from '../../util/src/config'; export * from './codeActionProvider'; export * from './colorProvider'; export * from './commandProvider'; @@ -17,7 +16,7 @@ export * from './constants'; export * from './definitionProvider'; export * from './formattingProvider'; export * from './hoverProvider'; -export * from './Lexer'; +export * from './lexer'; export * from './localize'; export * from './referencesProvider'; export * from './renameProvider'; @@ -28,7 +27,6 @@ export * from './symbolProvider'; export const winapis: string[] = []; export const lexers: Record = {}; export const alpha_3 = encode_version('2.1-alpha.3'); -export const ahkppConfig: AhkppConfig = newAhkppConfig(); export const utils = { get_DllExport: (_paths: string[] | Set, _onlyone = false) => Promise.resolve([] as string[]), get_RCDATA: (_path?: string) => undefined as { uri: string, path: string, paths?: string[] } | undefined, @@ -36,8 +34,8 @@ export const utils = { }; export type Maybe = T | undefined; -export let connection: Connection; -export let interpreterPathV2 = '', locale = 'en-us', rootdir = '', isahk2_h = false; +export let connection: Connection | undefined; +export let interpreterPath = '', locale = 'en-us', rootdir = '', isahk2_h = false; export let ahk_version = encode_version('3.0.0.0'); export let ahkuris: Record = {}; export let ahkvars: Record = {}; @@ -190,8 +188,7 @@ export function initahk2cache() { } /** Loads IntelliSense hover text */ -// (proven by skipping this func and seeing the results) -export function loadahk2(filename = 'ahk2', d = 3) { +export function loadAHK2(filename = 'ahk2', d = 3) { let path: string | undefined; const syntaxesPath = process.env.SYNTAXES_PATH || 'syntaxes'; const file = `${rootdir}/${syntaxesPath}/<>/${filename}`; @@ -208,9 +205,8 @@ export function loadahk2(filename = 'ahk2', d = 3) { if ((data = getwebfile(file + '.json'))) build_item_cache(JSON.parse(data.text)); } else { - const cfgSyntaxes: string = getCfg(ahkppConfig, CfgKey.Syntaxes); - /** The validated syntax path. Empty string if config syntax path failed to validate. */ - const syntaxes = cfgSyntaxes && existsSync(cfgSyntaxes) ? cfgSyntaxes : ''; + const syntaxConfig = getCfg(CfgKey.Syntaxes); + const syntaxes = syntaxConfig && existsSync(syntaxConfig) ? syntaxConfig : ''; const file2 = syntaxes ? `${syntaxes}/<>/${filename}` : file; let td: TextDocument | undefined; if ((path = getfilepath('.d.ahk')) && (td = openFile(restorePath(path)))) { @@ -347,7 +343,7 @@ export function loadahk2(filename = 'ahk2', d = 3) { let scanExclude: { file?: RegExp[], folder?: RegExp[] } = {}; export function enum_ahkfiles(dirpath: string) { - const maxScanDepth = getCfg(ahkppConfig, CfgKey.MaxScanDepth); + const maxScanDepth = getCfg(CfgKey.MaxScanDepth); const { file: fileExclude, folder: folderExclude } = scanExclude; return enumfile(restorePath(dirpath), 0); async function* enumfile(dirpath: string, depth: number): AsyncGenerator { @@ -369,38 +365,53 @@ export function enum_ahkfiles(dirpath: string) { } /** - * Updates `extsettings` with the provided config values - * Formerly `update_settings` + * Update the extension config (`ahklsConfig`) in-memory. + * Does not update user settings. */ -export function updateAhkppConfig(newConfig: AhkppConfig) { +export function updateConfig(newConfig: AHKLSConfig): void { + const newConfigLibSuggestions = getCfg(CfgKey.LibrarySuggestions, newConfig); + if (typeof newConfigLibSuggestions === 'boolean') + setCfg(CfgKey.LibrarySuggestions, newConfigLibSuggestions ? LibIncludeType.All : LibIncludeType.Disabled, newConfig); + fixupFormatConfig(getCfg(CfgKey.Formatter, newConfig) ?? {}); try { - setCommentTagRegex(getCfg(newConfig, CfgKey.CommentTagRegex)); + updateCommentTagRegex(getCfg(CfgKey.CommentTagRegex, newConfig)); } catch (e) { - delete (e as { stack: unknown }).stack; - // reset to default if invalid - setCommentTagRegex(getCfg(newAhkppConfig(), CfgKey.CommentTagRegex)) - connection.console.error(e as string); + delete (e as { stack?: string }).stack; + // reset value of `newConfig` to avoid corrupting `ahklsConfig` + setCfg(CfgKey.CommentTagRegex, getCfg(CfgKey.CommentTagRegex), newConfig); + console.log(e); } - (newConfig as any)[CfgKey.WorkingDirectories] = getCfg(newConfig, CfgKey.WorkingDirectories).map(dir => - (dir = URI.file(dir.includes(':') ? dir : resolve(dir)).toString().toLowerCase()) - .endsWith('/') ? dir : dir + '/'); + const newConfigWorkingDirs = getCfg(CfgKey.WorkingDirectories, newConfig); + if (newConfigWorkingDirs instanceof Array) + setCfg(CfgKey.WorkingDirectories, newConfigWorkingDirs.map(dir => + (dir = URI.file(dir.includes(':') ? dir : resolve(dir)).toString().toLowerCase()) + .endsWith('/') ? dir : dir + '/'), newConfig); + else setCfg(CfgKey.WorkingDirectories, [], newConfig); scanExclude = {}; - const file: RegExp[] = [], folder: RegExp[] = []; - for (const s of getCfg(newConfig, CfgKey.Exclude) ?? []) - try { - (/[\\/]$/.test(s) ? folder : file).push(glob2regexp(s)); - } catch (e) { - console.log(`[Error] Invalid glob pattern: ${s}`); + if (getCfg(CfgKey.Exclude, newConfig)) { + const file: RegExp[] = [], folder: RegExp[] = []; + for (const s of getCfg(CfgKey.Exclude, newConfig)) + try { + (/[\\/]$/.test(s) ? folder : file).push(glob2regexp(s)); + } catch (e) { + console.log(`[Error] Invalid glob pattern: ${s}`); + } + if (file.length) + scanExclude.file = file; + if (folder.length) + scanExclude.folder = folder; + let maxScanDepth = getCfg(CfgKey.MaxScanDepth, newConfig); + if (maxScanDepth === undefined) { + maxScanDepth = 2; } - if (file.length) - scanExclude.file = file; - if (folder.length) - scanExclude.folder = folder; - if (getCfg(newConfig, CfgKey.MaxScanDepth) < 0) - (newConfig as any)[CfgKey.MaxScanDepth] = Infinity; - if (getCfg(newConfig, CfgKey.Syntaxes)) - (newConfig as any)[CfgKey.Syntaxes] = resolve(getCfg(newConfig, CfgKey.Syntaxes)).toLowerCase(); - Object.assign(ahkppConfig, newConfig); + if (maxScanDepth < 0) + maxScanDepth = Infinity; + setCfg(CfgKey.MaxScanDepth, maxScanDepth, newConfig); + } + const newSyntaxes = getCfg(CfgKey.Syntaxes, newConfig); + if (newSyntaxes) + setCfg(CfgKey.Syntaxes, resolve(newSyntaxes).toLowerCase(), newConfig); + setConfigRoot(newConfig); } function encode_version(version: string) { @@ -438,7 +449,7 @@ export function arrayEqual(a: string[], b: string[]) { export function clearLibfuns() { libfuncs = {}; } export function set_ahk_h(v: boolean) { isahk2_h = v; } -export function setInterpreterPathV2(path: string) { interpreterPathV2 = path.replace(/^.:/, s => s.toLowerCase()); } +export function setInterpreterPath(path: string) { interpreterPath = path.replace(/^.:/, s => s.toLowerCase()); } export function set_Connection(conn: Connection) { return connection = conn; } export function set_dirname(dir: string) { rootdir = dir.replace(/[/\\]$/, ''); } export function set_locale(str?: string) { if (str) locale = str.toLowerCase(); } @@ -446,7 +457,7 @@ export function set_version(version: string) { ahk_version = encode_version(vers export function set_WorkspaceFolders(folders: Set) { const old = workspaceFolders; workspaceFolders = [...folders]; - getCfg(ahkppConfig, CfgKey.WorkingDirectories).forEach(dir => { if (!folders.has(dir)) workspaceFolders.push(dir) }); + getCfg(CfgKey.WorkingDirectories).forEach(it => !folders.has(it) && workspaceFolders.push(it)); workspaceFolders.sort().reverse(); if (old.length === workspaceFolders.length && !old.some((v, i) => workspaceFolders[i] !== v)) diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index 34a43f80..910eddae 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -8,12 +8,11 @@ import { URI } from 'vscode-uri'; import { $DIRPATH, $DLLFUNC, $FILEPATH, ANY, AhkSymbol, ClassNode, FuncNode, Maybe, Property, STRING, SemanticTokenTypes, Token, Variable, a_vars, ahkuris, ahkvars, allIdentifierChar, completionItemCache, completionitem, - decltype_expr, dllcalltpe, ahkppConfig, find_class, find_symbol, find_symbols, get_detail, + decltype_expr, dllcalltpe, find_class, find_symbol, find_symbols, get_detail, generate_fn_comment, get_callinfo, get_class_constructor, get_class_member, get_class_members, lexers, libfuncs, make_search_re, sendAhkRequest, utils, winapis } from './common'; -import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; -import { BraceStyle, CompletionCommitCharacters, CfgKey, FormatterConfig, getCfg, LibrarySuggestions } from './config'; +import { BraceStyle, CfgKey, getCfg, shouldIncludeLocalLib, shouldIncludeUserStdLib } from '../../util/src/config'; export async function completionProvider(params: CompletionParams, _token: CancellationToken): Promise> { let { position, textDocument: { uri } } = params; @@ -23,7 +22,6 @@ export async function completionProvider(params: CompletionParams, _token: Cance let l: string, path: string, pt: Token | undefined, scope: AhkSymbol | undefined, temp; const { triggerKind, triggerCharacter } = params.context ?? {}; let cls2index = (name: string) => name; - const formatterConfig = getCfg(ahkppConfig, CfgKey.Formatter); //#region /**| if (triggerCharacter === '*') { @@ -79,16 +77,10 @@ export async function completionProvider(params: CompletionParams, _token: Cance return; } //#endregion - - const commitCharacters = Object.fromEntries( - Object.entries( - getCfg( - ahkppConfig, - CfgKey.CompletionCommitCharacters, - ), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ).map((v: any) => ((v[1] = (v[1] || undefined)?.split('')), v)), - ); + + const commitCharacters = Object.fromEntries(Object.entries(getCfg(CfgKey.CompletionCommitCharacters) ?? {}) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .map((v: any) => (v[1] = (v[1] || undefined)?.split(''), v))); // eslint-disable-next-line prefer-const let { text, word, token, range, linetext, kind, symbol } = doc.getContext(position, true); const list = doc.relevance, { line, character } = position; @@ -508,7 +500,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance } let right_is_paren = '(['.includes(linetext[range.end.character] || '\0'); - const join_c = formatterConfig.braceStyle === BraceStyle.Allman ? '\n' : ' '; + const join_c = getCfg(CfgKey.BraceStyle) === 'Allman' ? '\n' : ' '; // fn|()=>... if (symbol) { @@ -631,7 +623,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance } // keyword - const keywordStartWithUppercase = formatterConfig.keywordStartWithUppercase; + const keywordStartWithUppercase = getCfg(CfgKey.KeywordStartWithUppercase); const addkeyword = keywordStartWithUppercase ? function (it: CompletionItem) { items.push(it = Object.assign({}, it)); it.insertText = (it.insertText ?? it.label).replace(/(?<=^(loop\s)?)[a-z]/g, m => m.toUpperCase()); @@ -646,7 +638,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance let uppercase = (s: string) => s, remove_indent = uppercase; if (keywordStartWithUppercase) uppercase = (s: string) => s.replace(/\b[a-z](?=\w)/g, m => m.toUpperCase()); - if (formatterConfig.switchCaseAlignment) + if (getCfg(CfgKey.SwitchCaseAlignment)) remove_indent = (s: string) => s.replace(/^\t/gm, ''); for (const [label, arr] of [ ['switch', ['switch ${1:[SwitchValue, CaseSense]}', remove_indent('{\n\tcase ${2:}:\n\t\t${3:}\n\tdefault:\n\t\t$0\n}')]], @@ -695,21 +687,18 @@ export async function completionProvider(params: CompletionParams, _token: Cance }); } - // library suggestions - if (getCfg(ahkppConfig, CfgKey.LibrarySuggestions)) { - const librarySuggestions = getCfg(ahkppConfig, CfgKey.LibrarySuggestions); + // auto-include + const includeUserStdLib = shouldIncludeUserStdLib(); + const includeLocalLib = shouldIncludeLocalLib(); + if (includeUserStdLib || includeLocalLib) { const libdirs = doc.libdirs, caches: Record = {}; let exportnum = 0, line = -1, first_is_comment: boolean | undefined, cm: Token; let dir = doc.workspaceFolder; dir = (dir ? URI.parse(dir).fsPath : doc.scriptdir).toLowerCase(); doc.includedir.forEach((v, k) => line = k); for (const u in libfuncs) { - if ( - !list[u] && (path = libfuncs[u].fsPath) - && ( - (includeUserAndStandardLibrary(librarySuggestions) && libfuncs[u].islib) - || (includeLocalLibrary(librarySuggestions) && path.toLowerCase().startsWith(dir))) - ) { + if (!list[u] && (path = libfuncs[u].fsPath) && ((includeUserStdLib && libfuncs[u].islib) || + (includeLocalLib && path.toLowerCase().startsWith(dir)))) { for (const it of libfuncs[u]) { expg.test(l = it.name) && (vars[l.toUpperCase()] ??= ( cpitem = convertNodeCompletion(it), exportnum++, @@ -938,7 +927,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance // fall through case SymbolKind.Function: ci.kind = info.kind === SymbolKind.Method ? CompletionItemKind.Method : CompletionItemKind.Function; - if (getCfg(ahkppConfig, CfgKey.CompleteFunctionCalls)) { + if (getCfg(CfgKey.CompleteFunctionCalls)) { const fn = info as FuncNode; if (right_is_paren) ci.command = { title: 'cursorRight', command: 'cursorRight' }; diff --git a/server/src/config.ts b/server/src/config.ts deleted file mode 100644 index b7e2b96d..00000000 --- a/server/src/config.ts +++ /dev/null @@ -1,253 +0,0 @@ -// Same as ahk2/client/src/config.ts -// todo dedupe config.ts - -/** Defined in package.json */ -export type ActionType = - | 'Continue' - | 'Warn' - | 'SkipLine' - | 'SwitchToV1' - | 'Stop'; - -/** Defined in package.json */ -export enum ObjectOrArrayStyle { - Collapse = 'collapse', - Expand = 'expand', - None = 'none', -} - -/** Defined in package.json */ -export enum BraceStyle { - OneTrueBrace = 'One True Brace', - Allman = 'Allman', - OneTrueBraceVariant = 'One True Brace Variant', -} - -export interface FormatterConfig { - // AHK++ values - arrayStyle: ObjectOrArrayStyle; - braceStyle: BraceStyle; - breakChainedMethods: boolean; - ignoreComment: boolean; - indentString: string; - indentBetweenHotIfDirectives: boolean; - keywordStartWithUppercase: boolean; - maxPreserveNewlines: number; - objectStyle: ObjectOrArrayStyle; - preserveNewlines: boolean; - spaceBeforeConditional: boolean; - spaceAfterDoubleColon: boolean; - spaceInEmptyParen: boolean; - spaceInOther: boolean; - spaceInParen: boolean; - switchCaseAlignment: boolean; - symbolWithSameCase: boolean; - whitespaceBeforeInlineComment: string; - wrapLineLength: number; - - // thqby values - array_style?: 'collapse' | 'expand' | 'none'; - brace_style?: 'One True Brace' | 'Allman' | 'One True Brace Variant'; - break_chained_methods?: boolean; - ignore_comment?: boolean; - indent_string?: string; - indent_between_hot_if_directives?: boolean; - keyword_start_with_uppercase?: boolean; - max_preserve_newlines?: number; - object_style?: 'collapse' | 'expand' | 'none'; - preserve_newlines?: boolean; - space_before_conditional?: boolean; - space_after_double_colon?: boolean; - space_in_empty_paren?: boolean; - space_in_other?: boolean; - space_in_paren?: boolean; - switch_case_alignment?: boolean; - symbol_with_same_case?: boolean; - whitespace_before_inline_comment?: string; - wrap_line_length?: number; -} - -/** Defined in package.json */ -export enum LibrarySuggestions { - Off = 'Off', - Local = 'Local', - UserAndStandard = 'User and Standard', - All = 'All', -} - -/** Defined in package.json */ -export enum CallWithoutParentheses { - Off = 'Off', - Parentheses = 'Parentheses', - On = 'On', -} - -export enum CfgKey { - //* ahkpp values - // ActionWhenV1Detected = 'v2.general.actionWhenV1Detected', - // CallWithoutParentheses = 'v2.warn.callWithoutParentheses', - // ClassNonDynamicMemberCheck = 'v2.diagnostics.classNonDynamicMemberCheck', - // CommentTagRegex = 'v2.general.commentTagRegex', - // CompleteFunctionCalls = 'v2.general.completeFunctionCalls', - // CompletionCommitCharacters = 'v2.completionCommitCharacters', - // Exclude = 'v2.exclude', - // Formatter = 'v2.formatter', - // InterpreterPath = 'v2.file.interpreterPath', - // LibrarySuggestions = 'v2.general.librarySuggestions', - // LocalSameAsGlobal = 'v2.warn.localSameAsGlobal', - // MaxScanDepth = 'v2.file.maxScanDepth', - // ParamsCheck = 'v2.diagnostics.paramsCheck', - // SymbolFoldingFromOpenBrace = 'v2.general.symbolFoldingFromOpenBrace', - // Syntaxes = 'v2.general.syntaxes', - // VarUnset = 'v2.warn.varUnset', - // WorkingDirectories = 'v2.workingDirectories', - - //* thqby values - ActionWhenV1Detected = 'ActionWhenV1IsDetected', - CallWithoutParentheses = 'Warn.CallWithoutParentheses', - ClassNonDynamicMemberCheck = 'Diagnostics.ClassNonDynamicMemberCheck', - CommentTagRegex = 'CommentTags', - CompleteFunctionCalls = 'CompleteFunctionParens', - CompletionCommitCharacters = 'CompletionCommitCharacters', - Exclude = 'Files.Exclude', - Formatter = 'FormatOptions', - InterpreterPath = 'InterpreterPath', - LibrarySuggestions = 'AutoLibInclude', - LocalSameAsGlobal = 'Warn.LocalSameAsGlobal', - MaxScanDepth = 'Files.ScanMaxDepth', - ParamsCheck = 'Diagnostics.ParamsCheck', - SymbolFoldingFromOpenBrace = 'SymbolFoldingFromOpenBrace', - Syntaxes = 'Syntaxes', - VarUnset = 'Warn.varUnset', - WorkingDirectories = 'WorkingDirs', -} - -export interface CompletionCommitCharacters { - Class: string; - Function: string; -} - -/** Defined in package.json */ -export interface AhkppConfig { - v2: { - general: { - actionWhenV1Detected: ActionType; - /** The regex denoting a custom symbol. Defaults to `;;` */ - commentTagRegex?: string; - /** Automatically insert parentheses on function call */ - completeFunctionCalls: boolean; - /** Suggest library functions */ - librarySuggestions: LibrarySuggestions; - symbolFoldingFromOpenBrace: boolean; - syntaxes: string; - }; - completionCommitCharacters: CompletionCommitCharacters; - diagnostics: { - classNonDynamicMemberCheck: boolean; - paramsCheck: boolean; - }; - /** Glob pattern of files to ignore */ - exclude: string[]; - file: { - /** Path to the AHK v2 intepreter */ - interpreterPath: string; - /** Depth of folders to scan for IntelliSense */ - maxScanDepth: number; - }; - /** Config of the v2 formatter */ - formatter: FormatterConfig; - warn: { - /** Ref to a potentially-unset variable */ - varUnset: boolean; - /** Undeclared local has same name as global */ - localSameAsGlobal: boolean; - /** Function call without parentheses */ - callWithoutParentheses: CallWithoutParentheses; - }; - /** Directories containing AHK files that can be #included */ - workingDirectories: string[]; - }; - locale?: string; - commands?: string[]; - extensionUri?: string; - GlobalStorage?: string; -} - -/** - * Returns a formatter config built from the given config and defaults. - * Defaults defined in package.json - */ -export const newFormatterConfig = ( - config: Partial = {}, -): FormatterConfig => ({ - arrayStyle: ObjectOrArrayStyle.None, - braceStyle: BraceStyle.OneTrueBrace, - breakChainedMethods: false, - ignoreComment: false, - indentString: ' ', - indentBetweenHotIfDirectives: false, - keywordStartWithUppercase: false, - maxPreserveNewlines: 2, - objectStyle: ObjectOrArrayStyle.None, - preserveNewlines: true, - spaceBeforeConditional: true, - spaceAfterDoubleColon: true, - spaceInEmptyParen: false, - spaceInOther: true, - spaceInParen: false, - switchCaseAlignment: false, - symbolWithSameCase: false, - whitespaceBeforeInlineComment: '', - wrapLineLength: 120, - ...config, -}); - -/** Defaults according to package.json */ -export const newAhkppConfig = ( - config: Partial = {}, -): AhkppConfig => ({ - v2: { - general: { - actionWhenV1Detected: 'SwitchToV1', - commentTagRegex: '^;;\\s*(.*)', - completeFunctionCalls: false, - librarySuggestions: LibrarySuggestions.Off, - symbolFoldingFromOpenBrace: false, - syntaxes: '', - }, - completionCommitCharacters: { - Class: '.(', - Function: '(', - }, - diagnostics: { - classNonDynamicMemberCheck: true, - paramsCheck: true, - }, - exclude: [], - file: { - interpreterPath: - 'C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey.exe', - maxScanDepth: 2, - }, - formatter: newFormatterConfig(), - warn: { - varUnset: true, - localSameAsGlobal: false, - callWithoutParentheses: CallWithoutParentheses.Off, - }, - workingDirectories: [], - }, - ...config, -}); - -/** Gets a single config value from the given config */ -export const getCfg = (config: AhkppConfig, key: CfgKey): T => { - const keyPath = key.split('.'); - // ConfigKey values are guaranteed to work ;) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let value: any = config; - for (const k of keyPath) { - value = value[k]; - } - return value; -}; diff --git a/server/src/formattingProvider.ts b/server/src/formattingProvider.ts index 43c906c3..cec164df 100644 --- a/server/src/formattingProvider.ts +++ b/server/src/formattingProvider.ts @@ -1,10 +1,10 @@ import { DocumentFormattingParams, DocumentOnTypeFormattingParams, DocumentRangeFormattingParams, Position, Range, TextEdit } from 'vscode-languageserver'; -import { chinese_punctuations, ahkppConfig, lexers, Token } from './common'; -import { CfgKey, FormatterConfig, getCfg } from './config'; +import { chinese_punctuations, lexers, Token } from './common'; +import { CfgKey, FormatOptions, getCfg } from '../../util/src/config'; export async function documentFormatting(params: DocumentFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], range = Range.create(0, 0, doc.document.lineCount, 0); - const opts = getCfg(ahkppConfig, CfgKey.Formatter); + const opts = getCfg(CfgKey.Formatter); opts.indentString ??= params.options.insertSpaces ? ' '.repeat(params.options.tabSize) : '\t'; const newText = doc.beautify(opts); return [{ range, newText }]; @@ -12,7 +12,7 @@ export async function documentFormatting(params: DocumentFormattingParams): Prom export async function rangeFormatting(params: DocumentRangeFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], range = params.range; - const opts = getCfg(ahkppConfig, CfgKey.Formatter); + const opts = getCfg(CfgKey.Formatter); opts.indentString = params.options.insertSpaces ? ' '.repeat(params.options.tabSize) : '\t'; const newText = doc.beautify(opts, range).trim(); return [{ range, newText }]; @@ -20,7 +20,7 @@ export async function rangeFormatting(params: DocumentRangeFormattingParams): Pr export async function typeFormatting(params: DocumentOnTypeFormattingParams): Promise { const doc = lexers[params.textDocument.uri.toLowerCase()], { ch, position } = params; - const options = getCfg(ahkppConfig, CfgKey.Formatter); + const options = getCfg(CfgKey.Formatter); let tk: Token, s: string, pp: number | undefined, result: TextEdit[] | undefined; options.indentString = ' '.repeat(params.options.tabSize); s = doc.document.getText({ start: { line: 0, character: 0 }, end: { line: 0, character: 1 } }); diff --git a/server/src/lexer.spec.ts b/server/src/lexer.spec.ts new file mode 100644 index 00000000..27107383 --- /dev/null +++ b/server/src/lexer.spec.ts @@ -0,0 +1,113 @@ +import { suite, test } from 'mocha'; +import * as assert from 'assert'; +import { + applyFormatDirective, + fixupFormatConfig, + Flag, + parseFormatDirective, + updateCommentTagRegex, +} from './lexer'; +import { BraceStyle } from '../../util/src/config'; + +suite('updateCommentTagRegex', () => { + test('should update the comment tag regex', () => { + const newRegex = '^;;;\\s*(.*)'; + assert.deepStrictEqual( + updateCommentTagRegex(newRegex), + new RegExp(newRegex, 'i'), + ); + }); + + test('invalid regex', () => { + const newRegex = '^;;;\\s*(.*)'; + let regex = updateCommentTagRegex(newRegex); + assert.throws(() => (regex = updateCommentTagRegex('['))); + // doesn't update the regex + assert.deepStrictEqual(regex, new RegExp(newRegex, 'i')); + }); +}); + +suite('parseFormatDirective', () => { + const tests: [ + name: string, + directive: string, + expected: Record, + ][] = [ + ['empty directive', '', {}], + ['one directive', ';@format key:value', { key: 'value' }], + [ + 'two directives', + ';@format key1: value1, key2: value2', + { key1: 'value1', key2: 'value2' }, + ], + ['extra whitespace', '; @format key: value ', { key: 'value' }], + ]; + + tests.forEach(([name, directive, expected]) => { + test(name, () => { + assert.deepStrictEqual(parseFormatDirective(directive), expected); + }); + }); +}); + +suite('applyFormatDirective', () => { + const tests: [ + name: string, + directive: string, + expectedFlag: Partial, + expectedFormatOptions: Record, + ][] = [ + [ + 'generic directive', + ';@format key1: value1, key2: value2', + {}, + { key1: 'value1', key2: 'value2' }, + ], + [ + 'uses flags only', + ';@format array_style: expand, object_style: expand', + { array_style: 'expand', object_style: 'expand' }, + {}, + ], + ]; + + tests.forEach(([name, directive, expectedFlag, expectedFormatOptions]) => { + test(name, () => { + const flag = {}; + const opt = {}; + applyFormatDirective(directive, flag, opt); + assert.deepStrictEqual(flag, expectedFlag); + assert.deepStrictEqual(opt, expectedFormatOptions); + }); + }); +}); + +suite('fixupFormatConfig', () => { + const tests: [ + name: string, + value: string | undefined, + expected: BraceStyle, + ][] = [ + ['One True Brace', 'One True Brace', 'One True Brace'], + [ + 'One True Brace Variant', + 'One True Brace Variant', + 'One True Brace Variant', + ], + ['Preserve', 'Preserve', 'Preserve'], + ['undefined', undefined, 'Preserve'], + ['0', '0', 'Allman'], + ['1', '1', 'One True Brace'], + ['-1', '-1', 'One True Brace Variant'], + ['other value', 'potato', 'Preserve'], + ]; + + tests.forEach(([name, value, expected]) => { + test(name, () => { + assert.deepStrictEqual( + fixupFormatConfig({ braceStyle: value }).braceStyle, + expected, + ); + }); + }); +}); diff --git a/server/src/Lexer.ts b/server/src/lexer.ts similarity index 96% rename from server/src/Lexer.ts rename to server/src/lexer.ts index a510b3f7..809c470f 100644 --- a/server/src/Lexer.ts +++ b/server/src/lexer.ts @@ -21,11 +21,11 @@ import { URI } from 'vscode-uri'; import { builtin_ahkv1_commands, builtin_variable, builtin_variable_h } from './constants'; import { action, completionitem, diagnostic, warn } from './localize'; import { - a_vars, ahk_version, ahkuris, ahkvars, alpha_3, connection, ahkppConfig, + a_vars, ahk_version, ahkuris, ahkvars, alpha_3, connection, hoverCache, isahk2_h, lexers, libdirs, libfuncs, locale, openAndParse, openFile, restorePath, rootdir, setTextDocumentLanguage, symbolProvider, utils, workspaceFolders } from './common'; -import { newFormatterConfig, FormatterConfig, BraceStyle, ActionType, newAhkppConfig, CallWithoutParentheses, getCfg, CfgKey } from './config'; +import { ActionType, BlockStyle, BraceStyle, CallWithoutParentheses, CfgKey, FormatOptions, getCfg } from '../../util/src/config'; export interface ParamInfo { offset: number @@ -204,6 +204,108 @@ interface ParamList extends Array { full?: string variadic?: boolean } +/** Flags used for formatter directives and other lexer conditions. */ +export interface Flag { + array_style?: BlockStyle, + case_body: boolean | null, + catch_block: boolean, + declaration_statement: boolean, + else_block: boolean, + finally_block: boolean, + had_comment: number, + hotif_block?: boolean, + if_block: boolean, + in_case_statement: boolean, + in_case: boolean, + in_expression: boolean, + in_fat_arrow?: boolean, + indentation_level: number, + last_text: string, + last_word: string, + loop_block: number, + mode: string, + object_style?: BlockStyle, + parent: Flag, + start_line_index: number, + ternary_depth?: number, + ternary_indent?: number, + try_block: boolean +}; + +export interface InternalFormatOptions { + array_style: BlockStyle; + brace_style: BraceStyle; + break_chained_methods: boolean; + ignore_comment: boolean; + indent_string: string; + indent_between_hotif_directive: boolean; + keyword_start_with_uppercase: boolean; + max_preserve_newlines: number; + object_style: BlockStyle; + preserve_newlines: boolean; + space_before_conditional: boolean; + space_after_double_colon: boolean; + space_in_empty_paren: boolean; + space_in_other: boolean; + space_in_paren: boolean; + switch_case_alignment: boolean; + symbol_with_same_case: boolean; + white_space_before_inline_comment: string; + wrap_line_length: number; +} + +/** + * When not provided a value, returns the default internal formatter options. + * Otherwise, properties of the provided value are preserved and merged with the defaults. + */ +export const newInternalFormatOptions = (partial: Partial = {}): InternalFormatOptions => ({ + array_style: 'expand', + brace_style: 'Preserve', + break_chained_methods: false, + ignore_comment: false, + indent_string: '\t', + indent_between_hotif_directive: false, + keyword_start_with_uppercase: false, + max_preserve_newlines: 3, + object_style: 'expand', + preserve_newlines: true, + space_before_conditional: true, + space_after_double_colon: true, + space_in_empty_paren: false, + space_in_other: true, + space_in_paren: false, + switch_case_alignment: false, + symbol_with_same_case: false, + white_space_before_inline_comment: '', + wrap_line_length: 0, + ...partial +}); + +export const mapToInternalFormatOptions = (extOptions: Partial): InternalFormatOptions => { + const defaultOptions = newInternalFormatOptions(); + const result = { + array_style: extOptions.arrayStyle ?? defaultOptions.array_style, + brace_style: extOptions.braceStyle ?? defaultOptions.brace_style, + break_chained_methods: extOptions.breakChainedMethods ?? defaultOptions.break_chained_methods, + ignore_comment: extOptions.ignoreComment ?? defaultOptions.ignore_comment, + indent_string: extOptions.indentString ?? defaultOptions.indent_string, + indent_between_hotif_directive: extOptions.indentBetweenHotIfDirectives ?? defaultOptions.indent_between_hotif_directive, + keyword_start_with_uppercase: extOptions.keywordStartWithUppercase ?? defaultOptions.keyword_start_with_uppercase, + max_preserve_newlines: extOptions.maxPreserveNewlines ?? defaultOptions.max_preserve_newlines, + object_style: extOptions.objectStyle ?? defaultOptions.object_style, + preserve_newlines: extOptions.preserveNewlines ?? defaultOptions.preserve_newlines, + space_before_conditional: extOptions.spaceBeforeConditional ?? defaultOptions.space_before_conditional, + space_after_double_colon: extOptions.spaceAfterDoubleColon ?? defaultOptions.space_after_double_colon, + space_in_empty_paren: extOptions.spaceInEmptyParen ?? defaultOptions.space_in_empty_paren, + space_in_other: extOptions.spaceInOther ?? defaultOptions.space_in_other, + space_in_paren: extOptions.spaceInParen ?? defaultOptions.space_in_paren, + switch_case_alignment: extOptions.switchCaseAlignment ?? defaultOptions.switch_case_alignment, + symbol_with_same_case: extOptions.symbolWithSameCase ?? defaultOptions.symbol_with_same_case, + white_space_before_inline_comment: extOptions.whitespaceBeforeInlineComment ?? defaultOptions.white_space_before_inline_comment, + wrap_line_length: extOptions.wrapLineLength ?? defaultOptions.wrap_line_length, + } + return result; +}; namespace SymbolNode { export function create(name: string, kind: SymbolKind, range: Range, selectionRange: Range, children?: AhkSymbol[]): AhkSymbol { @@ -268,7 +370,7 @@ const MODE = { BlockStatement: 'BlockStatement', Statement: 'Statement', ObjectL const KEYS_RE = /^(alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab|shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton1|xbutton2|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\d]{1,2}(sc[a-f\d]+)?|sc[a-f\d]+|`[;{]|[\x21-\x7E])$/i; const EMPTY_TOKEN: Token = { type: '', content: '', offset: 0, length: 0, topofline: 0, next_token_offset: -1 }; export const ASSIGN_TYPE = [':=', '??=']; -const OBJECT_STYLE = { collapse: 2, expand: 1, none: 0 }; +const OBJECT_STYLE: Record = { collapse: 'collapse', expand: 'expand', none: 'none' }; const ZERO_RANGE = { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } }; const META_FUNCNAME = ['__NEW', '__INIT', '__ITEM', '__ENUM', '__GET', '__CALL', '__SET', '__DELETE']; export const ANY = create_prototype('Any'); @@ -321,9 +423,9 @@ class ParseStopError { } export class Lexer { - public actionWhenV1Detected?: ActionType = getCfg(newAhkppConfig(), CfgKey.ActionWhenV1Detected); + public actionWhenV1Detected?: ActionType = 'Continue'; public actived = false; - public beautify: (options: FormatterConfig, range?: Range) => string; + public beautify: (options: Partial, range?: Range) => string; public checkmember: boolean | undefined; public children: AhkSymbol[] = []; public d = 0; @@ -372,35 +474,8 @@ export class Lexer { const _this = this, uri = URI.parse(document.uri); let allow_$ = true, block_mode = true, format_mode = false, h = isahk2_h; let in_loop = false, maybev1 = 0, requirev2 = false, string_mode = false; - - interface Flag { - arrayStyle?: number, - case_body: boolean | null, - catch_block: boolean, - declaration_statement: boolean, - else_block: boolean, - finally_block: boolean, - had_comment: number, - hotif_block?: boolean, - if_block: boolean, - in_case_statement: boolean, - in_case: boolean, - in_expression: boolean, - in_fat_arrow?: boolean, - indentation_level: number, - last_text: string, - last_word: string, - loop_block: number, - mode: string, - objectStyle?: number, - parent: Flag, - start_line_index: number, - ternary_depth?: number, - ternary_indent?: number, - try_block: boolean - }; let output_lines: { text: string[], indent: number }[], flags: Flag, previous_flags: Flag, flag_store: Flag[]; - let opt: FormatterConfig, preindentString: string, indentString: string, space_in_other: boolean, ck: Token; + let opt: InternalFormatOptions, preindent_string: string, indent_string: string, space_in_other: boolean, ck: Token; let token_text: string, token_text_low: string, token_type: string, last_type: string, last_text: string; let output_space_before_token: boolean | undefined, is_conditional: boolean; const handlers: Record void> = { @@ -492,29 +567,29 @@ export class Lexer { return !ignore && _this.findStrOrComment(offset) || eof; } - this.beautify = function (options: FormatterConfig, range?: Range) { + this.beautify = function (options: Partial, range?: Range) { let end_pos: number; !_this.isparsed && _this.parseScript(); - opt = newFormatterConfig(options); + opt = mapToInternalFormatOptions(options); last_type = last_text = '', begin_line = true, lst = { ...EMPTY_TOKEN }; last_LF = -1, end_pos = input_length, ck = _this.get_token(0); - preindentString = input.substring(input.lastIndexOf('\n', parser_pos = ck.offset) + 1, parser_pos); + preindent_string = input.substring(input.lastIndexOf('\n', parser_pos = ck.offset) + 1, parser_pos); is_conditional = output_space_before_token = false, format_mode = true; - indentString = opt.indentString ?? '\t', space_in_other = opt.spaceInOther ?? true; + indent_string = opt.indent_string ?? '\t', space_in_other = opt.space_in_other ?? true; output_lines = [create_output_line()]; flag_store = [], flags = undefined as unknown as Flag; set_mode(MODE.BlockStatement); - if (opt.symbolWithSameCase) + if (opt.symbol_with_same_case) symbolProvider({ textDocument: _this.document }); if (range) { end_pos = _this.document.offsetAt(range.end); ck = _this.find_token(_this.document.offsetAt(range.start)); range.start = _this.document.positionAt(parser_pos = ck.offset); - preindentString = input.substring(input.lastIndexOf('\n', parser_pos) + 1, parser_pos).match(/^[ \t]*/)![0]; + preindent_string = input.substring(input.lastIndexOf('\n', parser_pos) + 1, parser_pos).match(/^[ \t]*/)![0]; } while (true) { @@ -542,7 +617,6 @@ export class Lexer { output_lines.pop(); } range.end = _this.document.positionAt(end); - options.indentString = preindentString + indentString.repeat(flags.indentation_level); } while (flags.mode === MODE.Statement) restore_mode(); @@ -562,8 +636,8 @@ export class Lexer { } else if (!is_conditional && !flags.in_expression) { if ((ck.type.endsWith('COMMENT') || !is_line_continue(flags.mode === MODE.Statement ? ck.previous_token ?? EMPTY_TOKEN : {} as Token, ck)) && !(last_type === 'TK_RESERVED' && ['catch', 'else', 'finally', 'until'].includes(last_text))) { - if (opt.maxPreserveNewlines && n_newlines > opt.maxPreserveNewlines) - n_newlines = opt.maxPreserveNewlines; + if (opt.max_preserve_newlines && n_newlines > opt.max_preserve_newlines) + n_newlines = opt.max_preserve_newlines; if (!just_added_newline()) output_lines.push(create_output_line()); @@ -626,9 +700,9 @@ export class Lexer { }; function format_params_default_val(tokens: Record, params: ParamList) { - opt = newFormatterConfig({ maxPreserveNewlines: 1 }); - space_in_other = true, indentString = '\t'; - format_mode = true, preindentString = ''; + opt = newInternalFormatOptions({ max_preserve_newlines: 1 }); + space_in_other = true, indent_string = '\t'; + format_mode = true, preindent_string = ''; delete params.format; for (const param of params) { if (!param.range_offset) @@ -1143,7 +1217,7 @@ export class Lexer { begin_line = true, requirev2 = false, maybev1 = 0, lst = { ...EMPTY_TOKEN }, currsymbol = last_comment_fr = undefined; parser_pos = 0, last_LF = -1, customblocks = { region: [], bracket: [] }, continuation_sections_mode = false, h = isahk2_h; this.clear(), includetable = this.include, comments = {}, sharp_offsets = []; - callWithoutParentheses = getCfg(ahkppConfig, CfgKey.CallWithoutParentheses); + callWithoutParentheses = getCfg(CfgKey.CallWithoutParentheses); try { const rs = utils.get_RCDATA('#2'); rs && (includetable[rs.uri] = rs.path); @@ -1182,7 +1256,7 @@ export class Lexer { if (requirev2) return false; _this.maybev1 ??= maybev1 = 1; - switch (_this.actionWhenV1Detected ??= getCfg(ahkppConfig, CfgKey.ActionWhenV1Detected)) { + switch (_this.actionWhenV1Detected ??= getCfg(CfgKey.ActionWhenV1Detected)) { case 'SkipLine': { if (!allow_skip) return true; @@ -2347,7 +2421,7 @@ export class Lexer { } if (type === SymbolKind.Method) maybeclassprop(fc, true); - if (callWithoutParentheses != CallWithoutParentheses.Off && (callWithoutParentheses == CallWithoutParentheses.On || tp === 'TK_START_EXPR')) + if (callWithoutParentheses !== CallWithoutParentheses.Off && (callWithoutParentheses === CallWithoutParentheses.On || tp === 'TK_START_EXPR')) _this.diagnostics.push({ message: warn.callwithoutparentheses(), range: tn.selectionRange, severity: DiagnosticSeverity.Warning }); } @@ -3658,7 +3732,7 @@ export class Lexer { addvariable(tk); nexttoken(), parse_pair('(', ')'); const pc = tokens[tk.previous_pair_pos!]?.paraminfo?.count ?? 0; - if (pc !== 1 && getCfg(ahkppConfig, CfgKey.ParamsCheck)) + if (pc !== 1 && getCfg(CfgKey.ParamsCheck)) _this.addDiagnostic(diagnostic.paramcounterr(1, pc), fc.offset, parser_pos - fc.offset); else if (result.length > l && lk.type === 'TK_WORD') { const vr = result.at(-1) as Variable; @@ -4471,7 +4545,7 @@ export class Lexer { function create_flags(flags_base: Flag | undefined, mode: string) { let indentation_level = 0, had_comment = 0, ternary_depth; - let last_text = '', last_word = '', arrayStyle, objectStyle; + let last_text = '', last_word = '', array_style, object_style; let in_expression = [MODE.ArrayLiteral, MODE.Expression, MODE.ObjectLiteral].includes(mode); if (flags_base) { indentation_level = flags_base.indentation_level; @@ -4479,12 +4553,12 @@ export class Lexer { last_text = flags_base.last_text; last_word = flags_base.last_word; in_expression ||= flags_base.in_expression; - arrayStyle = flags_base.arrayStyle; - objectStyle = flags_base.objectStyle; + array_style = flags_base.array_style; + object_style = flags_base.object_style; } const next_flags: Flag = { - arrayStyle, + array_style: array_style, case_body: false, catch_block: false, declaration_statement: false, @@ -4500,7 +4574,7 @@ export class Lexer { last_word, loop_block: 0, mode, - objectStyle, + object_style: object_style, parent: flags_base!, start_line_index: output_lines.length, ternary_depth, @@ -4530,19 +4604,19 @@ export class Lexer { } function allow_wrap_or_preserved_newline(force_linewrap = false): void { - if (opt.wrapLineLength && !force_linewrap) { + if (opt.wrap_line_length && !force_linewrap) { const line = output_lines.at(-1)!; let proposed_line_length = 0; // never wrap the first token of a line. if (line.text.length > 0) { proposed_line_length = line.text.join('').length + token_text.length + (output_space_before_token ? 1 : 0); - if (proposed_line_length >= opt.wrapLineLength) { + if (proposed_line_length >= opt.wrap_line_length) { force_linewrap = true; } } } - if (((opt.preserveNewlines && input_wanted_newline) || force_linewrap) && !just_added_newline()) { + if (((opt.preserve_newlines && input_wanted_newline) || force_linewrap) && !just_added_newline()) { print_newline(true); } } @@ -4565,8 +4639,8 @@ export class Lexer { function print_token(printable_token?: string): void { const line = output_lines.at(-1)!; if (!line.text.length) { - if (preindentString) - line.text.push(preindentString); + if (preindent_string) + line.text.push(preindent_string); flags.indentation_level = print_indentString(flags.indentation_level); } else if (output_space_before_token) line.text.push(' '); @@ -4580,7 +4654,7 @@ export class Lexer { level = Math.min(output_lines[i].indent + 1, level); break; } - line.text.push(indentString.repeat(line.indent = level)); + line.text.push(indent_string.repeat(line.indent = level)); } return level; } @@ -5344,9 +5418,9 @@ export class Lexer { function get_style() { if (flags.mode === MODE.ObjectLiteral) - return flags.objectStyle ?? opt.objectStyle; + return flags.object_style ?? opt.object_style; if (flags.mode === MODE.ArrayLiteral) - return flags.arrayStyle ?? opt.arrayStyle; + return flags.array_style ?? opt.array_style; } function handle_start_expr(): void { @@ -5369,7 +5443,7 @@ export class Lexer { print_token(); flags.last_word = ''; flags.indentation_level = real_indentation_level() + 1; - if (opt.spaceInParen) { + if (opt.space_in_paren) { output_space_before_token = true; } return; @@ -5389,12 +5463,12 @@ export class Lexer { if (last_text.match(/^(break|continue|goto)$/i)) output_space_before_token = false; else if (['if', 'for', 'while', 'loop', 'case', 'catch', 'switch'].includes(last_text)) - output_space_before_token = Boolean(opt.spaceBeforeConditional); + output_space_before_token = Boolean(opt.space_before_conditional); else output_space_before_token = space_in_other; } if (!start_of_object_property()) { - if (input_wanted_newline && opt.preserveNewlines) + if (input_wanted_newline && opt.preserve_newlines) print_newline(true); else if (last_type === 'TK_EQUALS' || last_type === 'TK_COMMA' || last_type === 'TK_OPERATOR') allow_wrap_or_preserved_newline(); @@ -5412,13 +5486,13 @@ export class Lexer { const c = (ck.data as Token).content; if (c) print_token(c); - } else if (opt.spaceInParen) + } else if (opt.space_in_paren) output_space_before_token = true; // In all cases, if we newline while inside an expression it should be indented. indent(); - if (token_text === '[' && (flags.arrayStyle ?? opt.arrayStyle) === OBJECT_STYLE.expand) + if (token_text === '[' && (flags.array_style ?? opt.array_style) === OBJECT_STYLE.expand) print_newline(true); } @@ -5431,17 +5505,17 @@ export class Lexer { const is_array = token_text === ']' && flags.mode === MODE.ArrayLiteral; restore_mode(); if (is_array) { - const style = flags.arrayStyle ?? opt.arrayStyle; + const style = flags.array_style ?? opt.array_style; if (style === OBJECT_STYLE.collapse || last_text === '[' || flags.indentation_level >= previous_flags.indentation_level) trim_newlines(); - else if (style || input_wanted_newline && opt.preserveNewlines) + else if (style || input_wanted_newline && opt.preserve_newlines) print_newline(true); } else if ((last_type === 'TK_END_EXPR' || last_type === 'TK_END_BLOCK') && flags.indentation_level >= previous_flags.indentation_level) trim_newlines(); else if (last_type !== 'TK_START_EXPR') allow_wrap_or_preserved_newline(); - output_space_before_token = Boolean(opt.spaceInParen && !(last_type === 'TK_START_EXPR' && !opt.spaceInEmptyParen)); + output_space_before_token = Boolean(opt.space_in_paren && !(last_type === 'TK_START_EXPR' && !opt.space_in_empty_paren)); print_token(); continuation_sections_mode ??= false; } @@ -5455,7 +5529,7 @@ export class Lexer { output_space_before_token ||= space_in_other && last_type !== 'TK_START_EXPR'; print_token(), indent(); - if ((flags.objectStyle ?? opt.objectStyle) === OBJECT_STYLE.expand) + if ((flags.object_style ?? opt.object_style) === OBJECT_STYLE.expand) print_newline(true); else output_space_before_token = space_in_other; } else { @@ -5473,18 +5547,20 @@ export class Lexer { flags.indentation_level = level ??= flags.indentation_level; output_space_before_token ??= space_in_other; - if (previous_flags.in_case_statement && last_type === 'TK_LABEL' && /^(default)?:$/.test(last_text)) + const firstCondition = previous_flags.in_case_statement && last_type === 'TK_LABEL' && /^(default)?:$/.test(last_text); + const secondCondition = opt.brace_style === 'Allman' || input_wanted_newline && opt.preserve_newlines && opt.brace_style === 'Preserve'; + if (firstCondition) flags.case_body = null, print_newline(), flags.indentation_level--; - else if (opt.braceStyle === BraceStyle.Allman || input_wanted_newline && opt.preserveNewlines && !opt.braceStyle) + else if (secondCondition) if (ck.in_expr === undefined || flags.mode === MODE.Expression) print_newline(true); const need_newline = !just_added_newline(); print_token(); previous_flags.indentation_level = Math.min(previous_flags.indentation_level, flags.indentation_level); - if (!(opt.switchCaseAlignment && flags.last_word === 'switch')) + if (!(opt.switch_case_alignment && flags.last_word === 'switch')) indent(); - if (need_newline || opt.braceStyle !== undefined) + if (need_newline || opt.brace_style !== 'Preserve') print_newline(true); else output_space_before_token = space_in_other; } @@ -5497,14 +5573,15 @@ export class Lexer { restore_mode(); const is_obj = flags.mode === MODE.ObjectLiteral, is_exp = is_obj || (ck.in_expr !== undefined); + const secondCondition = opt.brace_style !== 'Preserve' || input_wanted_newline; if (is_obj) { - const style = flags.objectStyle ?? opt.objectStyle; + const style = flags.object_style ?? opt.object_style; if (style === OBJECT_STYLE.collapse || last_text === '{') trim_newlines(); - else if (style || input_wanted_newline && opt.preserveNewlines) + else if (style || input_wanted_newline && opt.preserve_newlines) print_newline(true); output_space_before_token = space_in_other && last_text !== '{'; - } else if (opt.braceStyle !== undefined || input_wanted_newline) + } else if (secondCondition) print_newline(true); restore_mode(); @@ -5512,7 +5589,7 @@ export class Lexer { if (!is_exp) { if (previous_flags.case_body === null) indent(); - if (opt.braceStyle !== undefined) + if (opt.brace_style !== 'Preserve') print_newline(true); output_space_before_token = space_in_other; } @@ -5531,8 +5608,8 @@ export class Lexer { } if (token_type === 'TK_RESERVED') { - if (opt.keywordStartWithUppercase !== undefined) - token_text = opt.keywordStartWithUppercase ? + if (opt.keyword_start_with_uppercase !== undefined) + token_text = opt.keyword_start_with_uppercase ? token_text_low.replace(/^./, s => s.toUpperCase()) : token_text_low; if (is_special_word(token_text_low)) { if (input_wanted_newline) @@ -5625,11 +5702,17 @@ export class Lexer { } if (maybe_need_newline) { trim_newlines(); - if (flags.last_text !== '}' || opt.braceStyle !== BraceStyle.OneTrueBrace || input_wanted_newline && opt.preserveNewlines && !opt.braceStyle) + const condition = flags.last_text !== '}' + || opt.brace_style === 'Allman' + || opt.brace_style === 'One True Brace Variant' + || input_wanted_newline + && opt.preserve_newlines + && opt.brace_style !== 'Preserve'; + if (condition) print_newline(true); else output_space_before_token = space_in_other; } else if (input_wanted_newline) - if (last_text === 'else' && !opt.preserveNewlines && ['if', 'for', 'loop', 'while', 'try', 'switch'].includes(token_text_low)) + if (last_text === 'else' && !opt.preserve_newlines && ['if', 'for', 'loop', 'while', 'try', 'switch'].includes(token_text_low)) deindent(); else print_newline(preserve_statement_flags); @@ -5656,7 +5739,7 @@ export class Lexer { if (input_wanted_newline && flags.mode === MODE.Statement && !flags.in_expression && !is_line_continue(ck.previous_token ?? EMPTY_TOKEN, ck)) print_newline(preserve_statement_flags); - else if (input_wanted_newline && (opt.preserveNewlines || ck.symbol)) { + else if (input_wanted_newline && (opt.preserve_newlines || ck.symbol)) { if (ck.symbol || get_style() !== OBJECT_STYLE.collapse) print_newline(!ck.symbol); } else if (['TK_COMMA', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR'].includes(last_type)) @@ -5665,7 +5748,7 @@ export class Lexer { if (!is_conditional && flags.mode === MODE.BlockStatement && ck.symbol?.children) set_mode(MODE.Statement), is_conditional = true; flags.last_word = '_'; - if (opt.symbolWithSameCase) + if (opt.symbol_with_same_case) token_text = ck.definition?.name || token_text; } @@ -5674,7 +5757,7 @@ export class Lexer { function handle_string() { if (start_of_statement()) { - if (input_wanted_newline && opt.preserveNewlines) + if (input_wanted_newline && opt.preserve_newlines) print_newline(true); else { if (flags.declaration_statement) @@ -5702,7 +5785,7 @@ export class Lexer { if (ck.ignore) { let p: number; print_newline(true); - if (opt.ignoreComment && token_text.trimStart().startsWith('(') && (p = token_text.indexOf('\n')) > 0) { + if (opt.ignore_comment && token_text.trimStart().startsWith('(') && (p = token_text.indexOf('\n')) > 0) { const t = token_text.slice(0, p).trimEnd().replace(/[ \t]+;.*$/, ''); if (/(^[ \t]*\(|[ \t])c(om(ments?)?)?/i.test(t)) token_text = `${t}\n${token_text.slice(p + 1).replace(/^[ \t]*;.*\r?\n/gm, '').replace(/[ \t]+;.*/gm, '')}`; @@ -5735,12 +5818,12 @@ export class Lexer { set_mode(MODE.Statement), indent(); if (last_type === 'TK_WORD' && whitespace.includes(ck.prefix_is_whitespace || '\0') && ck.previous_token?.callsite) - input_wanted_newline && opt.preserveNewlines ? print_newline(true) : output_space_before_token = true; + input_wanted_newline && opt.preserve_newlines ? print_newline(true) : output_space_before_token = true; else { output_space_before_token = space_in_other && last_type === 'TK_COMMA' || last_text === 'for' && last_type === 'TK_RESERVED'; if (flags.mode === MODE.Statement && flags.parent.mode === MODE.ObjectLiteral) restore_mode(); - if (input_wanted_newline && opt.preserveNewlines) + if (input_wanted_newline && opt.preserve_newlines) print_newline(true); else if (!just_added_newline()) input_wanted_newline = false; @@ -5788,7 +5871,7 @@ export class Lexer { if (token_text === '%') { space_after = Boolean(ck.previous_pair_pos !== undefined && ' \t'.includes(input.charAt(ck.offset + 1) || '\0')); output_space_before_token ||= Boolean(ck.next_pair_pos && ' \t'.includes(ck.prefix_is_whitespace || '\0')); - if (input_wanted_newline && opt.preserveNewlines) + if (input_wanted_newline && opt.preserve_newlines) if (flags.mode === MODE.Statement && is_line_continue(ck.previous_token ?? EMPTY_TOKEN, ck)) print_newline(true); print_token(); @@ -5813,7 +5896,7 @@ export class Lexer { return; } - if (input_wanted_newline && opt.preserveNewlines) + if (input_wanted_newline && opt.preserve_newlines) print_newline(true); else if (last_type === 'TK_OPERATOR' && !last_text.match(/^(--|\+\+|%|!|~|not)$/)) allow_wrap_or_preserved_newline(); @@ -5869,7 +5952,7 @@ export class Lexer { else if (flags.had_comment < 2) trim_newlines(); } - if (opt.ignoreComment) + if (opt.ignore_comment) return; const lines = token_text.split('\n'); @@ -5897,13 +5980,14 @@ export class Lexer { } function handle_inline_comment() { - if (opt.ignoreComment) + applyFormatDirective(token_text, flags, opt); + if (opt.ignore_comment) return; if (just_added_newline() && output_lines.length > 1) output_lines.pop(); let t; output_lines[output_lines.length - 1].text.push( - opt.whitespaceBeforeInlineComment || + opt.white_space_before_inline_comment || (((t = ck.previous_token)) ? input.substring(t.skip_pos ?? t.offset + t.length, ck.offset) : '\t'), token_text); print_newline(true); @@ -5918,7 +6002,8 @@ export class Lexer { else if (flags.had_comment < 2) trim_newlines(); } - if (opt.ignoreComment) + applyFormatDirective(token_text, flags, opt); + if (opt.ignore_comment) return; token_text.split('\n').forEach(s => { print_newline(true); @@ -5935,7 +6020,7 @@ export class Lexer { // allow preserved newlines before dots in general // force newlines on dots after close paren when break_chained - for bar().baz() - allow_wrap_or_preserved_newline(flags.last_text === ')' && opt.breakChainedMethods); + allow_wrap_or_preserved_newline(flags.last_text === ')' && opt.break_chained_methods); print_token(); } @@ -5946,9 +6031,9 @@ export class Lexer { function handle_sharp() { print_newline(); - if (opt.symbolWithSameCase && token_type === 'TK_SHARP') + if (opt.symbol_with_same_case && token_type === 'TK_SHARP') token_text = hoverCache[token_text_low]?.[0] || token_text; - if (token_text_low === '#hotif' && opt.indentBetweenHotIfDirectives) { + if (token_text_low === '#hotif' && opt.indent_between_hotif_directive) { if (flags.hotif_block) deindent(), flags.hotif_block = false; print_token(); @@ -5962,7 +6047,7 @@ export class Lexer { if (t) print_token(token_type === 'TK_HOTLINE' ? t : ' ' + t); else if (token_type === 'TK_HOT') - output_space_before_token = !!opt.spaceAfterDoubleColon; + output_space_before_token = !!opt.space_after_double_colon; else output_space_before_token = space_in_other || token_type === 'TK_SHARP'; } @@ -6288,7 +6373,7 @@ export class Lexer { return; let workDir: string; if (!dir) { - for (workDir of getCfg(ahkppConfig, CfgKey.WorkingDirectories)) + for (workDir of getCfg(CfgKey.WorkingDirectories)) if (this.uri.startsWith(workDir)) { dir = restorePath(URI.parse(workDir).fsPath.replace(/[\\/]$/, '')); break; @@ -6346,7 +6431,7 @@ export class Lexer { } private addSymbolFolding(symbol: AhkSymbol, first_brace: number) { - const l1 = getCfg(ahkppConfig, CfgKey.SymbolFoldingFromOpenBrace) ? this.document.positionAt(first_brace).line : symbol.range.start.line; + const l1 = getCfg(CfgKey.SymbolFoldingFromOpenBrace) ? this.document.positionAt(first_brace).line : symbol.range.start.line; const l2 = symbol.range.end.line - 1; const ranges = this.foldingranges; if (l1 < l2) { @@ -7837,12 +7922,72 @@ export function is_line_continue(lk: Token, tk: Token, parent?: AhkSymbol): bool } } -export function setCommentTagRegex(regex: string) { - const old = commentTagRegex; +/** + * Tries to update the commentTagRegex to the provided value. + * If a new regex cannot be made from the provied value, throws an error. + */ +export function updateCommentTagRegex(newCommentTagRegex: string): RegExp { + const oldCommentTagRegex = commentTagRegex; try { - commentTagRegex = new RegExp(regex, 'i'); + if (newCommentTagRegex) { + commentTagRegex = new RegExp(newCommentTagRegex, 'i'); + } } catch (e) { - commentTagRegex = old; + commentTagRegex = oldCommentTagRegex; throw e; } + return commentTagRegex; } + +/** + * Updates the provided options in-place (not pure). + * Convert the provided format config from user settings to in-memory interface. + */ +export function fixupFormatConfig(options: { braceStyle?: string | undefined }) { + switch (options.braceStyle) { + case 'Allman': + case '0': options.braceStyle = 'Allman'; break; + case 'One True Brace': + case '1': options.braceStyle = 'One True Brace'; break; + case 'One True Brace Variant': + case '-1': options.braceStyle = 'One True Brace Variant'; break; + default: options.braceStyle = 'Preserve'; break; + } + return options; +} + +/** + * Parse a directive of the form `; @format key1: value1, key2: value2, ...` + * Returns an object with the key-value pairs. + * Whitespace-insensitive. + * Does not validate that keys are valid FormatOptions keys. + */ +export function parseFormatDirective(directive: string): Record { + // Run regex against the directive to confirm it matches + const m = directive.match(/^;\s*@format\b/i); + if (!m) return {}; + + // Get all the key-value pairs of the directive + const record = Object.fromEntries(directive.substring(m[0].length).split(',').map(s => { + const p = s.indexOf(':'); + return [s.substring(0, p).trim(), s.substring(p + 1).trim()]; + })); + + return record; +} + +/** + * Handle format directives. Format directives dictate options for every line below them. + * Example: `;@format array_style: expand, object_style: expand` + * See `client/src/test/formatting/array_object_style.ahk` for an in-code example. + */ +export function applyFormatDirective(directive: string, flags: Partial, opt: Partial) { + const parsedDirective = parseFormatDirective(directive); + for (const k of ['array_style', 'object_style'] as const) { + if (k in parsedDirective) { + flags[k] = parsedDirective[k] as BlockStyle; + delete parsedDirective[k]; + } + } + Object.assign(opt, parsedDirective); +} \ No newline at end of file diff --git a/server/src/localize.ts b/server/src/localize.ts index 1fe2fdc1..a6929c7c 100644 --- a/server/src/localize.ts +++ b/server/src/localize.ts @@ -1,5 +1,5 @@ +import { CfgKey, configPrefix } from '../../util/src/config'; import { rootdir, getlocalefile, getwebfile } from './common'; -import { CfgKey } from './config'; let loadedCollection: Record = {}; @@ -84,7 +84,7 @@ export const warn = { } export const setting = { - ahkpatherr: localize('setting.ahkpatherr', `AutoHotkey interpreter not found, check settings: AHK++.${CfgKey.InterpreterPath}`), + ahkpatherr: localize('setting.ahkpatherr', `Couldn't resolve AHK v2 interpreter, please check settings: ${configPrefix}.${CfgKey.InterpreterPath}`), getenverr: localize('setting.getenverr', 'Failed to get environment variables'), uialimit: localize('setting.uialimit', 'The UIA executable does not allow redirection to stdin/stdout due to security restrictions, so some features that depend on this will not work'), versionerr: localize('setting.versionerr', 'The current AutoHotkey.exe is not the v2 version, and cannot get the correct syntax analysis, completion and other functions'), diff --git a/server/src/scriptrunner.ts b/server/src/scriptrunner.ts index 890ded05..253b802c 100644 --- a/server/src/scriptrunner.ts +++ b/server/src/scriptrunner.ts @@ -1,5 +1,5 @@ import { execSync, spawnSync } from 'child_process'; -import { interpreterPathV2 } from './common'; +import { interpreterPath } from './common'; import { lstatSync, readlinkSync } from 'fs'; import { resolve } from 'path'; @@ -8,7 +8,7 @@ import { resolve } from 'path'; * Not used for running user-defined scripts. */ export function runscript(script: string) { - const executePath = resolvePath(interpreterPathV2, true); + const executePath = resolvePath(interpreterPath, true); if (!executePath) return; const process = spawnSync(`"${executePath}" /CP65001 /ErrorStdOut=utf-8 *`, [], { cwd: executePath.replace(/[\\/].+?$/, ''), shell: true, input: script }); @@ -27,7 +27,11 @@ export function existsSync(path: string): boolean { return true; } -export function resolvePath(path: string, resolveSymbolicLink = false): string { +/** + * Resolves the provided path. + * If the path is empty, undefined, or not found, returns an empty string. + */ +export function resolvePath(path: string | undefined, resolveSymbolicLink = false): string { if (!path) return ''; const paths: string[] = []; diff --git a/server/src/semanticTokensProvider.ts b/server/src/semanticTokensProvider.ts index 08187d19..ef0bb0c0 100644 --- a/server/src/semanticTokensProvider.ts +++ b/server/src/semanticTokensProvider.ts @@ -1,9 +1,9 @@ import { CancellationToken, DocumentSymbol, Range, SemanticTokens, SemanticTokensParams, SemanticTokensRangeParams, SymbolKind } from 'vscode-languageserver'; import { ASSIGN_TYPE, AhkSymbol, ClassNode, FuncNode, Lexer, Property, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, Token, Variable, - checkParams, diagnostic, ahkppConfig, get_class_member, get_class_members, globalsymbolcache, lexers, symbolProvider + checkParams, diagnostic, get_class_member, get_class_members, globalsymbolcache, lexers, symbolProvider } from './common'; -import { CfgKey, getCfg } from './config'; +import { CfgKey, getCfg } from '../../util/src/config'; let curclass: ClassNode | undefined; const memscache = new Map>(); @@ -124,7 +124,7 @@ function resolveSemanticType(name: string, tk: Token, doc: Lexer) { return sem.type = SemanticTokenTypes.property; } case undefined: - if ((curclass.checkmember ?? doc.checkmember) !== false && getCfg(ahkppConfig, CfgKey.ClassNonDynamicMemberCheck)) { + if ((curclass.checkmember ?? doc.checkmember) !== false && getCfg(CfgKey.ClassNonDynamicMemberCheck)) { const tt = doc.tokens[tk.next_token_offset]; if (ASSIGN_TYPE.includes(tt?.content)) { cls_add_prop(curclass, tk.content, tk.offset); diff --git a/server/src/server.ts b/server/src/server.ts index 83b3e77a..9c4dd5c2 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -12,67 +12,20 @@ import { import { URI } from 'vscode-uri'; import { get_ahkProvider } from './ahkProvider'; import { - a_vars, - interpreterPathV2, - chinese_punctuations, - clearLibfuns, - codeActionProvider, - colorPresentation, - colorProvider, - commands, - completionProvider, - defintionProvider, - documentFormatting, - enum_ahkfiles, - executeCommandProvider, - exportSymbols, - ahkppConfig, - hoverProvider, - initahk2cache, - isahk2_h, - Lexer, - lexers, - libdirs, - libfuncs, - loadahk2, - loadlocalize, - openFile, - parse_include, - prepareRename, - rangeFormatting, - referenceProvider, - renameProvider, - SemanticTokenModifiers, - semanticTokensOnFull, - semanticTokensOnRange, - SemanticTokenTypes, - set_ahk_h, - setInterpreterPathV2, - set_Connection, - set_dirname, - set_locale, - set_version, - set_WorkspaceFolders, - setting, - signatureProvider, - sleep, - symbolProvider, - traverse_include, - typeFormatting, - updateAhkppConfig, - utils, - winapis, - workspaceSymbolProvider, - read_ahk_file, - getVersionInfo, - builtin_variable, - builtin_variable_h, + a_vars, interpreterPath, builtin_variable, builtin_variable_h, chinese_punctuations, clearLibfuns, codeActionProvider, + colorPresentation, colorProvider, commands, completionProvider, defintionProvider, + documentFormatting, enum_ahkfiles, executeCommandProvider, exportSymbols, getVersionInfo, hoverProvider, + initahk2cache, isahk2_h, Lexer, lexers, libdirs, libfuncs, loadAHK2, loadlocalize, openFile, + parse_include, prepareRename, rangeFormatting, read_ahk_file, referenceProvider, renameProvider, SemanticTokenModifiers, + semanticTokensOnFull, semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, setInterpreterPath, set_Connection, + set_dirname, set_locale, set_version, set_WorkspaceFolders, setting, signatureProvider, sleep, symbolProvider, + traverse_include, typeFormatting, updateConfig, utils, winapis, workspaceSymbolProvider } from './common'; import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; import { resolvePath, runscript } from './scriptrunner'; -import { TextDecoder } from 'util'; -import { includeLocalLibrary, includeUserAndStandardLibrary } from './utils'; -import { AhkppConfig, CfgKey, getCfg, LibrarySuggestions } from './config'; +import { AHKLSConfig, CfgKey, configPrefix, getCfg, shouldIncludeUserStdLib, shouldIncludeLocalLib, setCfg } from '../../util/src/config'; +import { klona } from 'klona/json'; +import { clientExecuteCommand, clientUpdateStatusBar, extSetInterpreter, serverExportSymbols, serverGetAHKVersion, serverGetContent, serverGetVersionInfo, serverResetInterpreterPath } from '../../util/src/env'; const languageServer = 'ahk2-language-server'; const documents = new TextDocuments(TextDocument); @@ -82,8 +35,9 @@ let hasConfigurationCapability = false, hasWorkspaceFolderCapability = false; let uri_switch_to_ahk2 = ''; -commands['ahk++.v2.setIntepreterPath'] = (args: string[]) => - setInterpreter(args[0].replace(/^[A-Z]:/, (m) => m.toLowerCase())); +// Cannot be done on browser, so added here +commands[serverResetInterpreterPath] = (args: string[]) => + setInterpreter((args[0]).replace(/^[A-Z]:/, m => m.toLowerCase())); connection.onInitialize(async (params) => { const capabilities = params.capabilities; @@ -152,32 +106,26 @@ connection.onInitialize(async (params) => { }; } - let envAhkppConfig: AhkppConfig | undefined; + let initialConfig: AHKLSConfig | undefined; const env = process.env; if (env.AHK2_LS_CONFIG) - try { - envAhkppConfig = JSON.parse(env.AHK2_LS_CONFIG); - } catch { - /* do nothing */ - } + try { initialConfig = JSON.parse(env.AHK2_LS_CONFIG); } catch { } if (params.initializationOptions) - envAhkppConfig = Object.assign(envAhkppConfig ?? {}, params.initializationOptions); + initialConfig = Object.assign(initialConfig ?? {}, params.initializationOptions); set_dirname(resolve(__dirname, '../..')); - set_locale(envAhkppConfig?.locale ?? params.locale); + set_locale((initialConfig ? getCfg(CfgKey.Locale, initialConfig) : undefined) ?? params.locale); utils.get_RCDATA = getRCDATA; utils.get_DllExport = getDllExport; utils.get_ahkProvider = get_ahkProvider; loadlocalize(); initahk2cache(); - if (envAhkppConfig) updateAhkppConfig(envAhkppConfig); - if ( - !(await setInterpreter( - resolvePath(getCfg(ahkppConfig, CfgKey.InterpreterPath) ?? ''), - )) - ) + if (initialConfig) + updateConfig(initialConfig); + if (!getCfg(CfgKey.InterpreterPath)) setCfg(CfgKey.InterpreterPath, ''); + if (!(await setInterpreter(resolvePath(getCfg(CfgKey.InterpreterPath))))) patherr(setting.ahkpatherr()); set_WorkspaceFolders(workspaceFolders); - loadahk2(); + loadAHK2(); return result; }); @@ -204,40 +152,33 @@ connection.onInitialized(() => { ).then((val) => winapis.push(...val)); }); -connection.onDidChangeConfiguration(async (change) => { - let newAhkppConfig: AhkppConfig | undefined = change?.settings; - if (hasConfigurationCapability && !newAhkppConfig) - newAhkppConfig = await connection.workspace.getConfiguration('AHK++'); - if (!newAhkppConfig) { - connection.window.showWarningMessage('Failed to obtain the AHK++ configuration'); +connection.onDidChangeConfiguration(async change => { + let newConfig: AHKLSConfig | undefined = change?.settings; + if (hasConfigurationCapability && !newConfig) + newConfig = await connection.workspace.getConfiguration(configPrefix); + if (!newConfig) { + connection.window.showWarningMessage('Failed to obtain the configuration'); return; } - const oldCfg = ahkppConfig; - updateAhkppConfig(newAhkppConfig); - const newCfg = ahkppConfig; + // clone the old config to compare + const oldConfig = klona(getCfg()); + updateConfig(newConfig); // this updates the object in-place, hence the clone above set_WorkspaceFolders(workspaceFolders); - - const newInterpreterPath: string = getCfg(newCfg, CfgKey.InterpreterPath); - if (getCfg(oldCfg, CfgKey.InterpreterPath) !== newInterpreterPath) { + const newInterpreterPath = getCfg(CfgKey.InterpreterPath); + if (newInterpreterPath !== getCfg(CfgKey.InterpreterPath, oldConfig)) { if (await setInterpreter(resolvePath(newInterpreterPath))) - connection.sendRequest('ahk++.updateStatusBar', [newInterpreterPath]); + connection.sendRequest(clientUpdateStatusBar, [newInterpreterPath]); } - - const oldLibSuggestions: LibrarySuggestions = getCfg(oldCfg, CfgKey.LibrarySuggestions); - const newLibSuggestions: LibrarySuggestions = getCfg(newCfg, CfgKey.LibrarySuggestions); - if (oldLibSuggestions !== newLibSuggestions) { - if (includeUserAndStandardLibrary(newLibSuggestions) && !includeUserAndStandardLibrary(oldLibSuggestions)) + if (getCfg(CfgKey.LibrarySuggestions) !== getCfg(CfgKey.LibrarySuggestions, oldConfig)) { + if (shouldIncludeUserStdLib() && !shouldIncludeUserStdLib(oldConfig)) parseuserlibs(); - if (includeLocalLibrary(newLibSuggestions) && !includeLocalLibrary(oldLibSuggestions)) - documents.all().forEach((e) => parseproject(e.uri.toLowerCase())); + if (shouldIncludeLocalLib() && !shouldIncludeLocalLib(oldConfig)) + documents.all().forEach(e => parseproject(e.uri.toLowerCase())); } - if (getCfg(oldCfg, CfgKey.Syntaxes) !== getCfg(newCfg, CfgKey.Syntaxes)) { - initahk2cache(); - loadahk2(); - if (isahk2_h) { - loadahk2('ahk_h'); - loadahk2('winapi', 4); - } + if (getCfg(CfgKey.Syntaxes) !== getCfg(CfgKey.Syntaxes, oldConfig)) { + initahk2cache(), loadAHK2(); + if (isahk2_h) + loadAHK2('ahk_h'), loadAHK2('winapi', 4); } }); @@ -259,19 +200,16 @@ connection.onDidChangeWatchedFiles((change) => { documents.onDidOpen(e => { const to_ahk2 = uri_switch_to_ahk2 === e.document.uri; const uri = e.document.uri.toLowerCase(); - let doc = lexers[uri]; - if (doc) doc.document = e.document; - else lexers[uri] = doc = new Lexer(e.document); - Object.defineProperty(doc.include, '', { value: '', enumerable: false }); - doc.actived = true; - if (to_ahk2) doc.actionWhenV1Detected = 'Continue'; - if (includeLocalLibrary(getCfg(ahkppConfig, CfgKey.LibrarySuggestions))) - parseproject(uri).then( - () => - doc.last_diags && - Object.keys(doc.included).length && - doc.update(), - ); + let lexer = lexers[uri]; + if (lexer) lexer.document = e.document; + else lexers[uri] = lexer = new Lexer(e.document); + Object.defineProperty(lexer.include, '', { value: '', enumerable: false }); + lexer.actived = true; + if (to_ahk2) + lexer.actionWhenV1Detected = 'Continue'; + if (shouldIncludeLocalLib()) + parseproject(uri).then(() => lexer.last_diags && + Object.keys(lexer.included).length && lexer.update()); }); documents.onDidClose(e => lexers[e.document.uri.toLowerCase()]?.close()); @@ -296,10 +234,10 @@ connection.onExecuteCommand(executeCommandProvider); connection.onWorkspaceSymbol(workspaceSymbolProvider); connection.languages.semanticTokens.on(semanticTokensOnFull); connection.languages.semanticTokens.onRange(semanticTokensOnRange); -connection.onRequest('ahk++.exportSymbols', (uri: string) => exportSymbols(uri)); -connection.onRequest('ahk++.getAHKversion', getAHKversion); -connection.onRequest('ahk++.getContent', (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); -connection.onRequest('ahk++.getVersionInfo', getVersionInfo); +connection.onRequest(serverExportSymbols, (uri: string) => exportSymbols(uri)); +connection.onRequest(serverGetAHKVersion, getAHKversion); +connection.onRequest(serverGetContent, (uri: string) => lexers[uri.toLowerCase()]?.document.getText()); +connection.onRequest(serverGetVersionInfo, getVersionInfo); connection.onNotification('onDidCloseTextDocument', (params: { uri: string, id: string }) => { if (params.id === 'ahk2') lexers[params.uri.toLowerCase()]?.close(true); @@ -308,11 +246,15 @@ connection.onNotification('onDidCloseTextDocument', (params: { uri: string, id: documents.listen(connection); connection.listen(); +/** + * Shows error message indicating the path could not be resolved. + * If possible, prompts the user to set their AHK v2 interpreter. + */ async function patherr(msg: string) { - if (!ahkppConfig.commands?.includes('ahk++.executeCommand')) + if (!getCfg(CfgKey.Commands)?.includes(clientExecuteCommand)) return connection.window.showErrorMessage(msg); - if (await connection.window.showErrorMessage(msg, { title: 'Select Interpreter' })) - connection.sendRequest('ahk++.executeCommand', ['ahk++.setV2Interpreter']); + if (await connection.window.showErrorMessage(msg, { title: 'Select AHK v2 interpreter' })) + connection.sendRequest(clientExecuteCommand, [extSetInterpreter]); } async function initpathenv(samefolder = false, retry = true): Promise { @@ -335,7 +277,7 @@ async function initpathenv(samefolder = false, retry = true): Promise { return false; } if (!(data = data.trim())) { - const path = interpreterPathV2; + const path = interpreterPath; if ((await getAHKversion([path]))[0].endsWith('[UIAccess]')) { let ret = false, n = path.replace(/_uia\.exe$/i, '.exe'); @@ -345,9 +287,10 @@ async function initpathenv(samefolder = false, retry = true): Promise { (n = resolvePath(n, true)) && !(await getAHKversion([n]))[0].endsWith('[UIAccess]') ) { - setInterpreterPathV2(n); - if ((ret = await initpathenv(samefolder))) fail = 0; - setInterpreterPathV2(path); + setInterpreterPath(n); + if ((ret = await initpathenv(samefolder))) + fail = 0; + setInterpreterPath(path); } if (fail) connection.window.showWarningMessage(setting.uialimit()); await update_rcdata(); @@ -359,7 +302,7 @@ async function initpathenv(samefolder = false, retry = true): Promise { return false; } Object.assign(a_vars, Object.fromEntries(data.replace(/|[A-Z]:\\/g, m => m.toLowerCase()).split('\n').map(l => l.split('|')))); - a_vars.ahkpath ??= interpreterPathV2; + a_vars.ahkpath ??= interpreterPath; set_version(a_vars.ahkversion ??= '2.0.0'); if (a_vars.ahkversion.startsWith('1.')) patherr(setting.versionerr()); @@ -373,14 +316,19 @@ async function initpathenv(samefolder = false, retry = true): Promise { for (lb of Object.values(libfuncs)) lb.islib = inlibdirs(lb.fsPath); } if (a_vars.threadid) { - if (!isahk2_h) - set_ahk_h(true), samefolder = false, loadahk2('ahk2_h'), loadahk2('winapi', 4); + if (!isahk2_h) { + set_ahk_h(true); + samefolder = false; + loadAHK2('ahk2_h'); + loadAHK2('winapi', 4); + } } else { - if (isahk2_h) { + if (isahk2_h) + { set_ahk_h(false); samefolder = false; initahk2cache(); - loadahk2(); + loadAHK2(); } } Object.assign(a_vars, { index: '0', clipboard: '', threadid: '' }); @@ -395,10 +343,11 @@ async function initpathenv(samefolder = false, retry = true): Promise { } } clearLibfuns(); - if (includeUserAndStandardLibrary(getCfg(ahkppConfig, CfgKey.LibrarySuggestions))) parseuserlibs(); + if (shouldIncludeUserStdLib()) + parseuserlibs(); return true; async function update_rcdata() { - const pe = new PEFile(interpreterPathV2); + const pe = new PEFile(interpreterPath); try { const rc = await pe.getResource(RESOURCE_TYPE.RCDATA); curPERCDATA = rc; @@ -461,16 +410,19 @@ async function changeInterpreter(oldpath: string, newpath: string) { const doc = lexers[td.uri.toLowerCase()]; if (!doc) return; doc.initLibDirs(doc.scriptdir); - if (includeLocalLibrary(getCfg(ahkppConfig, CfgKey.LibrarySuggestions))) parseproject(doc.uri); + if (shouldIncludeLocalLib()) + parseproject(doc.uri); }); return true; } async function setInterpreter(path: string) { - const old = interpreterPathV2; - if (!path || path.toLowerCase() === old.toLowerCase()) return false; - setInterpreterPathV2(path); - if (!(await changeInterpreter(old, path))) setInterpreterPathV2(old); + const old = interpreterPath; + if (!path || path.toLowerCase() === old.toLowerCase()) + return false; + setInterpreterPath(path); + if (!(await changeInterpreter(old, path))) + setInterpreterPath(old); return true; } @@ -558,7 +510,7 @@ async function getDllExport(paths: string[] | Set, onlyone = false) { let curPERCDATA: Record | undefined = undefined; function getRCDATA(name?: string) { - const exe = resolvePath(interpreterPathV2, true); + const exe = resolvePath(interpreterPath, true); if (!exe) return; if (!name) return { uri: '', path: '', paths: Object.keys(curPERCDATA ?? {}) }; diff --git a/server/src/symbolProvider.ts b/server/src/symbolProvider.ts index 6136385b..84ddb9f3 100644 --- a/server/src/symbolProvider.ts +++ b/server/src/symbolProvider.ts @@ -8,10 +8,11 @@ import { ANY, AhkSymbol, CallSite, ClassNode, FuncNode, FuncScope, Lexer, Property, SUPER, SemanticToken, SemanticTokenModifiers, SemanticTokenTypes, THIS, Token, VARREF, Variable, ahkuris, ahkvars, check_same_name_error, connection, decltype_expr, - diagnostic, enum_ahkfiles, ahkppConfig, find_class, get_class_constructor, + diagnostic, enum_ahkfiles, find_class, get_class_constructor, is_line_continue, lexers, make_same_name_error, openFile, warn, workspaceFolders } from './common'; -import { CfgKey, getCfg } from './config'; +import { CfgKey, getCfg } from '../../util/src/config'; +import { clientGetWorkspaceFileContent, clientGetWorkspaceFiles } from '../../util/src/env'; export let globalsymbolcache: Record = {}; @@ -41,7 +42,7 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio return doc.symbolInformation; if (ahkuris.winapi && !list.includes(ahkuris.winapi)) winapis = lexers[ahkuris.winapi]?.declaration ?? winapis; - const warnLocalSameAsGlobal = getCfg(ahkppConfig, CfgKey.LocalSameAsGlobal); + const warnLocalSameAsGlobal = getCfg(CfgKey.LocalSameAsGlobal); const result: AhkSymbol[] = [], unset_vars = new Map(); const filter_types: SymbolKind[] = [SymbolKind.Method, SymbolKind.Property, SymbolKind.Class]; for (const [k, v] of Object.entries(doc.declaration)) { @@ -55,7 +56,7 @@ export function symbolProvider(params: DocumentSymbolParams, token?: Cancellatio result.push(v), converttype(v, v, islib || v === ahkvars[k]).definition = v; } flatTree(doc); - if (getCfg(ahkppConfig, CfgKey.VarUnset)) + if (getCfg(CfgKey.VarUnset)) for (const [k, v] of unset_vars) { if (k.assigned) continue; @@ -294,7 +295,7 @@ function get_func_param_count(fn: FuncNode) { export function checkParams(doc: Lexer, node: FuncNode, info: CallSite) { const paraminfo = info.paraminfo; let is_cls: boolean, params; - if (!paraminfo || !getCfg(ahkppConfig, CfgKey.ParamsCheck)) return; + if (!paraminfo || !getCfg(CfgKey.ParamsCheck)) return; if ((is_cls = node?.kind === SymbolKind.Class)) node = get_class_constructor(node as unknown as ClassNode) as FuncNode; if (!(params = node?.params)) return; @@ -387,12 +388,12 @@ export async function workspaceSymbolProvider(params: WorkspaceSymbolParams, tok } } } else { - const uris = (await connection?.sendRequest('ahk2.getWorkspaceFiles', []) || []) as string[]; + const uris = (await connection?.sendRequest(clientGetWorkspaceFiles, []) || []) as string[]; for (const uri_ of uris) { const uri = uri_.toLowerCase(); let d: Lexer; if (!lexers[uri]) { - const content = (await connection?.sendRequest('ahk2.getWorkspaceFileContent', [uri_])) as string; + const content = (await connection?.sendRequest(clientGetWorkspaceFileContent, [uri_])) as string; d = new Lexer(TextDocument.create(uri_, 'ahk2', -10, content)); d.parseScript(), lexers[uri] = d; if (filterSymbols(uri)) return symbols; diff --git a/server/src/utils.ts b/server/src/utils.ts deleted file mode 100644 index 30ff2ff0..00000000 --- a/server/src/utils.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { LibrarySuggestions } from './config'; - -export function includeUserAndStandardLibrary( - librarySuggestions: LibrarySuggestions, -): boolean { - return ( - librarySuggestions === LibrarySuggestions.All || - librarySuggestions === LibrarySuggestions.UserAndStandard - ); -} - -export function includeLocalLibrary( - librarySuggestions: LibrarySuggestions, -): boolean { - return ( - librarySuggestions === LibrarySuggestions.All || - librarySuggestions === LibrarySuggestions.Local - ); -} diff --git a/syntaxes/ahk2-output.tmLanguage.json b/syntaxes/ahk2-output.tmLanguage.json index 63eadaa2..b29ae0e2 100644 --- a/syntaxes/ahk2-output.tmLanguage.json +++ b/syntaxes/ahk2-output.tmLanguage.json @@ -15,7 +15,7 @@ } }, "match": "^(\\[Running\\])(.*)$", - "name": "ahk++.running" + "name": "ahk2.running" }, { "captures": { diff --git a/syntaxes/ahk2.tmLanguage.json b/syntaxes/ahk2.tmLanguage.json index e828e16f..8824da5f 100644 --- a/syntaxes/ahk2.tmLanguage.json +++ b/syntaxes/ahk2.tmLanguage.json @@ -1,2361 +1,2361 @@ { - "name": "autohotkey2", - "scopeName": "source.ahk2", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "include": "#hotkey_hotstring" - }, - { - "include": "#switch_statement" - }, - { - "include": "#object_property" - }, - { - "include": "#reserved" - }, - { - "include": "#numbers" - }, - { - "include": "#operators" - }, - { - "include": "#strings" - }, - { - "include": "#pre_definition" - }, - { - "include": "#class_block" - }, - { - "include": "#block" - }, - { - "include": "#continuation_section" - }, - { - "include": "#parens" - }, - { - "include": "#function_call" - }, - { - "include": "#property" - }, - { - "include": "#variables" - } - ], - "repository": { - "block": { - "patterns": [ - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.ahk2" - } - }, - "patterns": [ - { - "include": "#block_innards" - } - ] - } - ] - }, - "block_innards": { - "patterns": [ - { - "include": "#object_property" - }, - { - "name": "meta.initialization.ahk2", - "begin": "(?x)\n(?:\n (?:\n\t(?=[ \t])(?=+!]+ | \\(\\) | \\[\\]))\n)\n[ \t]*(\\() # opening bracket", - "beginCaptures": { - "1": { - "name": "variable.other.ahk2" - }, - "2": { - "name": "punctuation.section.parens.begin.bracket.round.initialization.ahk2" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.section.parens.end.bracket.round.initialization.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.ahk2" - } - }, - "patterns": [ - { - "include": "#block_innards" - } - ] - }, - { - "include": "$base" - } - ] - }, - "case_statement": { - "name": "meta.conditional.case.ahk2", - "begin": "(?<=^[ \t]*\\{?[ \t]*)((?i:case))(?!\\w)", - "beginCaptures": { - "1": { - "name": "keyword.control.case.ahk2" - } - }, - "end": "(:)", - "endCaptures": { - "1": { - "name": "punctuation.separator.colon.case.ahk2" - } - }, - "patterns": [ - { - "include": "#strings" - }, - { - "include": "#numbers" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "\\.(?=\\w)", - "name": "punctuation.accessor.ahk2" - }, - { - "include": "#function_call" - }, - { - "match": "{", - "name": "punctuation.section.block.begin.ahk2" - }, - { - "match": "}", - "name": "punctuation.section.block.end.ahk2" - }, - { - "match": "\\[|\\(", - "name": "punctuation.section.parens.begin.ahk2" - }, - { - "match": "\\]|\\)", - "name": "punctuation.section.parens.end.ahk2" - }, - { - "include": "#operators" - }, - { - "include": "#variables" - }, - { - "include": "#comments" - } - ] - }, - "class_block": { - "name": "meta.block.class.ahk2", - "begin": "(^|(?<=^[ \t]*\\*/))[ \t]*((?i:class))[ \t]+(\\$?\\w+(\\.\\w+)*)", - "beginCaptures": { - "2": { - "name": "storage.type.class.ahk2" - }, - "3": { - "name": "entity.name.type.class.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.class.end.ahk2" - } - }, - "patterns": [ - { - "begin": "\\G(?!\\{)", - "end": "(?=\\{)", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "\\G[ \t]*(<)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.begin.ahk2" - } - }, - "end": ">", - "endCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.end.ahk2" - } - }, - "patterns": [ - { - "match": "\\w+", - "name": "entity.name.type.parameter" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "=", - "name": "keyword.operator.assignment.ahk2" - }, - { - "match": "\\.", - "name": "punctuation.accessor.ahk2" - }, - { - "match": "\\|", - "name": "keyword.operator.ahk2" - } - ] - }, - { - "match": "\\b((?i:extends))([ \t]+([\\w.]+))?", - "captures": { - "1": { - "name": "storage.modifier.ahk2" - }, - "3": { - "patterns": [ - { - "match": "\\.(?=\\w)", - "name": "punctuation.accessor.ahk2" - }, - { - "include": "#default_classes" - }, - { - "match": "\\b[^.]+\\b", - "name": "entity.name.type.class.ahk2" - } - ] - } - } - } - ] - }, - { - "begin": "\\{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.class.begin.ahk2" - } - }, - "end": "(?=})", - "name": "meta.block.class.body.ahk2", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "match": "(?<=^[ \t]*)(?i:static)(?=[ \t]+\\w)", - "name": "storage.modifier.ahk2" - }, - { - "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)[ \t]*(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "patterns": [ - { - "match": "\\b(?i:__item)\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "variable.other.property.ahk2" - }, - "2": { - "name": "storage.type.function.arrow.ahk2" - }, - "4": { - "name": "comment.line.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.block.prototype.body.ahk2", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - { - "match": "(?<=(^[ \t]*(?i:static[ \t]+)?|,[ \t]*))\\w+(?=[ \t]*:=)", - "captures": { - "0": { - "patterns": [ - { - "match": "\\b(?i:__item)\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "variable.other.property.ahk2" - } - } - }, - { - "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)(?=\\()", - "beginCaptures": { - "1": { - "patterns": [ - { - "match": "\\b(__(?i:new|init|enum|get|call|set|delete))\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "entity.name.function.method.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.block.method.ahk2", - "patterns": [ - { - "begin": "\\G\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.ahk2" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.method.begin.ahk2" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.method.end.ahk2" - } - }, - "name": "meta.block.method.body.ahk2", - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.block.method.body.ahk2", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - } - ] - }, - { - "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)\\b\\w+\\b(?=(\\[|[ \t]*\\{?([ \t];.*)?\\n))", - "beginCaptures": { - "0": { - "patterns": [ - { - "match": "\\b(?i:__item)\\b", - "name": "storage.type.metafunction.ahk2" - } - ], - "name": "variable.other.property.ahk2" - } - }, - "name": "meta.block.property.ahk2", - "end": "(?=\\n)", - "endCaptures": { - "1": { - "name": "punctuation.definition.block.property.end.ahk2" - } - }, - "patterns": [ - { - "begin": "\\G\\[", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.ahk2" - } - }, - "end": "\\]", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.property.begin.ahk2" - } - }, - "end": "(?=})", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.property.end.ahk2" - } - }, - "name": "meta.block.property.body.ahk2", - "patterns": [ - { - "begin": "(?<=^[ \t]*)(?i:set)\\b", - "beginCaptures": { - "0": { - "name": "storage.type.setter.ahk2" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.property.setter.begin.ahk2" - } - }, - "name": "meta.block.property.setter.body.ahk2", - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.property.setter.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "name": "meta.block.property.setter.body.ahk2", - "end": "(?=\\n)", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - } - ] - }, - { - "begin": "(?<=^[ \t]*)(?i:get)\\b", - "beginCaptures": { - "0": { - "name": "storage.type.getter.ahk2" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.block.property.getter.begin.ahk2" - } - }, - "name": "meta.block.property.getter.body.ahk2", - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.property.getter.end.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "name": "meta.block.property.getter.body.ahk2", - "end": "(?=\\n)", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - } - ] - }, - { - "include": "$base" - } - ] - }, - { - "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", - "beginCaptures": { - "1": { - "name": "storage.type.function.arrow.ahk2" - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "name": "meta.block.property.getter.body.ahk2", - "end": "(?=\\n)", - "patterns": [ - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - { - "include": "#variables" - } - ] - }, - { - "include": "#class_block" - }, - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - } - ] - }, - "comments": { - "patterns": [ - { - "name": "comment.block.jsdoc.ahk2", - "begin": "^[ \t]*(\\/\\*\\*)(?!\\/)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.begin.ahk2" - } - }, - "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.comment.end.ahk2" - } - }, - "patterns": [ - { - "include": "#docblock" - } - ] - }, - { - "name": "comment.block.ahk2", - "begin": "(?<=^[ \t]*)(\\/\\*)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.begin.ahk2" - } - }, - "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.comment.end.ahk2" - } - } - }, - { - "name": "comment.line.ahk2", - "match": "(?<=(^[ \t]*|[ \t]))(;.*)" - } - ] - }, - "compiler_directive": { - "patterns": [ - { - "name": "comment.block.ahk2", - "begin": "^[ \t]*(\\/\\*)((?i:@ahk2exe-keep))", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.begin.ahk2" - }, - "2": { - "name": "keyword.control.directive.conditional.ahk2" - } - }, - "end": "^[ \t]*(\\*\\/)", - "endCaptures": { - "1": { - "name": "punctuation.definition.comment.end.ahk2" - } - } - }, - { - "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-ignore(begin|end))", - "name": "keyword.control.directive.ahk2" - }, - { - "begin": "^[ \t]*(;[ \t]*@(?i:ahk2exe-let))\\b", - "beginCaptures": { - "0": { - "name": "keyword.control.directive.ahk2" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "include": "#strings" - }, - { - "include": "#numbers" - }, - { - "match": "\\b([_[:alpha:]][_[:alnum:]]*)(?=[ \t]*=)", - "name": "constant.language.ahk2" - }, - { - "match": "=", - "name": "keyword.operator.assignment.ahk2" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - } - ] - }, - { - "begin": "^[ \t]*((;[ \t]*@)(?i:include))\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - }, - "end": "(?=\\n)", - "name": "meta.preprocessor.include.ahk2", - "patterns": [ - { - "begin": "[^ \t;]", - "end": "(?=(?:[ \t]+;))|(?=\\n)", - "name": "string.literal.include.ahk2" - }, - { - "match": "(?:[ \t]+);.*", - "name": "comment.line.ahk2" - } - ] - }, - { - "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-\\w+)\\b([ \t].*)?", - "name": "keyword.control.directive.ahk2", - "captures": { - "1": { - "name": "string.literal.ahk2" - } - } - }, - { - "match": "(?<=^|[ \t]);[ \t]*@(?:[\\w\\-]+)\\b([ \t]+(.*))?", - "name": "keyword.control.directive.ahk2", - "captures": { - "2": { - "name": "comment.line.ahk2" - } - } - } - ] - }, - "conditional_context": { - "patterns": [ - { - "include": "$self" - }, - { - "include": "#block_innards" - } - ] - }, - "continuation_section": { - "name": "meta.parens.continuation_section.ahk2", - "begin": "(?<=^[ \t]*)(\\()((((?i:join)[^ \t]*|[^ \t();]+)(?=[ \t]|$)|[ \t]+)*)((?<=[ \t]);.*)?$", - "beginCaptures": { - "1": { - "name": "punctuation.section.parens.begin.ahk2" - }, - "2": { - "patterns": [ - { - "match": "(?<=[ \t]|^[ \t]*\\()(?i:c(om(ments?)?)?|[lr]trim0?|`|join(`s|[^ \t]){0,15})(?=[ \t]|$)", - "name": "string.options.ahk2 markup.italic" - }, - { - "match": "[^ \t]+", - "name": "invalid.options.ahk2 markup.strikethrough" - } - ] - }, - "5": { - "name": "comment.line.ahk2" - } - }, - "end": "^[ \t]*(\\))", - "endCaptures": { - "1": { - "name": "punctuation.section.parens.end.ahk2" - } - }, - "patterns": [ - { - "include": "#continuation_section_innards" - } - ] - }, - "continuation_section_innards": { - "patterns": [ - { - "begin": "('|\")", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin.ahk2" - } - }, - "end": "(\\1)|(?=^[ \t]*\\))", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.ahk2" - } - }, - "name": "string.continuation_section_innards.ahk2", - "patterns": [ - { - "include": "#string_escaped_char" - } - ] - }, - { - "include": "#variables" - }, - { - "match": "{", - "name": "punctuation.section.block.begin.ahk2" - }, - { - "match": "}", - "name": "punctuation.section.block.end.ahk2" - }, - { - "match": "\\[", - "name": "punctuation.section.parens.begin.ahk2" - }, - { - "match": "\\]", - "name": "punctuation.section.parens.end.ahk2" - }, - { - "include": "#parens" - }, - { - "include": "$base" - } - ] - }, - "default_classes": { - "patterns": [ - { - "begin": "(?*/]\n (?:[^@<>*/]|\\*[^/])*\n)\n(?:\n \\s*\n (<)\n ([^>\\s]+)\n (>)\n)?", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - }, - "4": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "5": { - "name": "constant.other.email.link.underline.jsdoc" - }, - "6": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)borrows) \\s+\n((?:[^@\\s*/]|\\*[^/])+) # \n\\s+ (as) \\s+ # as\n((?:[^@\\s*/]|\\*[^/])+) # ", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - }, - "4": { - "name": "keyword.operator.control.jsdoc" - }, - "5": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "name": "meta.embedded.ahk2 meta.example.jsdoc", - "begin": "((@)example)\\s+", - "end": "(?=@|\\*+/)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "patterns": [ - { - "match": "^\\s*\\*\\s+", - "name": "comment.block.ahk2" - }, - { - "contentName": "constant.other.description.jsdoc", - "begin": "\\G(<)caption(>)", - "beginCaptures": { - "0": { - "name": "entity.name.tag.inline.jsdoc" - }, - "1": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - }, - "end": "()|(?=\\*/)", - "endCaptures": { - "0": { - "name": "entity.name.tag.inline.jsdoc" - }, - "1": { - "name": "punctuation.definition.bracket.angle.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.angle.end.jsdoc" - } - }, - "patterns": [ - { - "match": "^\\s*\\*\\s", - "name": "comment.block.ahk2" - } - ] - }, - { - "include": "$base" - } - ] - }, - { - "name": "meta.overload.ahk2", - "begin": "((@)overload)\\s+", - "end": "(?=\\n|^\\s*\\*)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - { - "match": "(?x) ((@)kind) \\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\b", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "constant.language.symbol-type.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)see)\n\\s+\n(?:\n # URL\n (\n (?=https?://)\n (?:[^\\s*]|\\*[^/])+\n )\n |\n # JSDoc namepath\n (\n (?!\n # Avoid matching bare URIs (also acceptable as links)\n https?://\n |\n # Avoid matching {@inline tags}; we match those below\n (?:\\[[^\\[\\]]*\\])? # Possible description [preceding]{@tag}\n {@(?:link|linkcode|linkplain|tutorial)\\b\n )\n # Matched namepath\n (?:[^@\\s*/]|\\*[^/])+\n )\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.link.underline.jsdoc" - }, - "4": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "match": "(?x)\n((@)template)\n\\s+\n# One or more valid identifiers\n(\n [A-Za-z_$] # First character: non-numeric word character\n [\\w$.\\[\\]]* # Rest of identifier\n (?: # Possible list of additional identifiers\n \\s* , \\s*\n [A-Za-z_$]\n [\\w$.\\[\\]]*\n )*\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - } - } - }, - { - "begin": "((@)typedef)\\s+(?={)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", - "patterns": [ - { - "include": "#jsdoctype" - }, - { - "name": "entity.name.type.instance.jsdoc", - "match": "(?:[^@\\s*/]|\\*[^/])+" - } - ] - }, - { - "begin": "((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\s+(?=[\\[{]|(?!\\d)\\w)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]\\w])", - "patterns": [ - { - "include": "#jsdoctype" - }, - { - "name": "variable.other.jsdoc", - "match": "((?!\\d)\\w[\\w.\\[\\]]*)" - }, - { - "name": "variable.other.jsdoc", - "match": "(?x)\n(\\[)\\s*\n\\w+\n(?:\n (?:\\[\\])? # Foo[ ].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [\\w$]+\n)*\n(?:\n \\s*\n (=) # [foo=bar] Default parameter value\n \\s*\n (\n # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\n (?>\n \"(?:(?:\\*(?!/))|(?:\\\\(?!\"))|[^*\\\\])*?\" | # [foo=\"bar\"] Double-quoted\n '(?:(?:\\*(?!/))|(?:\\\\(?!'))|[^*\\\\])*?' | # [foo='bar'] Single-quoted\n \\[ (?:(?:\\*(?!/))|[^*])*? \\] | # [foo=[1,2]] Array literal\n (?:(?:\\*(?!/))|\\s(?!\\s*\\])|\\[.*?(?:\\]|(?=\\*/))|[^*\\s\\[\\]])* # Everything else\n )*\n )\n)?\n\\s*(?:(\\])((?:[^*\\s]|\\*[^\\s/])+)?|(?=\\*/))", - "captures": { - "1": { - "name": "punctuation.definition.optional-value.begin.bracket.square.jsdoc" - }, - "2": { - "name": "keyword.operator.assignment.jsdoc" - }, - "3": { - "name": "meta.embedded.ahk2" - }, - "4": { - "name": "punctuation.definition.optional-value.end.bracket.square.jsdoc" - }, - "5": { - "name": "invalid.illegal.syntax.jsdoc" - } - } - } - ] - }, - { - "begin": "(?x)\n(\n (@)\n (?:define|enum|exception|export|extends|lends|implements|modifies\n |namespace|private|protected|returns?|suppress|this|throws|type\n |yields?)\n)\n\\s+(?={)", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - }, - "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", - "patterns": [ - { - "include": "#jsdoctype" - } - ] - }, - { - "match": "((@)method)\\b\\s*((\\w|[^\\x00-\\x7f])+)?", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.function.method.ahk2" - } - } - }, - { - "match": "(?x)\n(\n (@)\n (?:alias|augments|callback|constructs|emits|event|fires|exports?\n |extends|external|function|func|host|lends|listens|interface|memberof!?\n |module|mixes|mixin|name|requires|see|this|typedef|uses)\n)\n\\s+\n(\n (?:\n [^{}@\\s*] | \\*[^/]\n )+\n)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "entity.name.type.instance.jsdoc" - } - } - }, - { - "contentName": "variable.other.jsdoc", - "begin": "((@)(?:default(?:value)?|license|version))\\s+(([''\"]))", - "beginCaptures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - }, - "4": { - "name": "punctuation.definition.string.begin.jsdoc" - } - }, - "end": "(\\3)|(?=$|\\*/)", - "endCaptures": { - "0": { - "name": "variable.other.jsdoc" - }, - "1": { - "name": "punctuation.definition.string.end.jsdoc" - } - } - }, - { - "match": "((@)(?:default(?:value)?|license|tutorial|variation|version))\\s+([^\\s*]+)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - }, - "3": { - "name": "variable.other.jsdoc" - } - } - }, - { - "name": "storage.type.class.jsdoc", - "match": "(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\b", - "captures": { - "1": { - "name": "punctuation.definition.block.tag.jsdoc" - } - } - }, - { - "include": "#inline-tags" - }, - { - "match": "((@)(?:[_$[:alpha:]][_$[:alnum:]]*))(?=\\s+)", - "captures": { - "1": { - "name": "storage.type.class.jsdoc" - }, - "2": { - "name": "punctuation.definition.block.tag.jsdoc" - } - } - } - ] - }, - "function_call": { - "match": "([_[:alpha:]][[:alnum:]_]*+)(?=\\()", - "captures": { - "1": { - "name": "entity.name.function.ahk2", - "patterns": [ - { - "match": "(?<=\\.).+", - "name": "entity.name.function.method.ahk2" - }, - { - "include": "#variables_language" - } - ] - } - } - }, - "function_call_notparens": { - "patterns": [ - { - "match": "(?<=^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\b(?>=|\\?|\\{))|$))", - "name": "entity.name.function.ahk2", - "captures": { - "0": { - "patterns": [ - { - "include": "#function_defaultLibrary" - } - ] - } - } - }, - { - "match": "(?<=(^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\.)+)([[:alpha:]_][[:alnum:]_]*\\b)(?=$|[ \t]((?!([ \t]*[+\\-*/^&:.|]?=|<<=|>>=|\\?|\\{))|$))", - "name": "entity.name.function.method.ahk2" - } - ] - }, - "function_defaultLibrary": { - "patterns": [ - { - "match": "(?$~*!+#^]*?)(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))|~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+)[ \t]+&[ \t]+~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))([ \t]+up)?)(::)", - "beginCaptures": { - "1": { - "name": "hotkey.ahk2", - "patterns": [ - { - "match": "(?<=[ \t])&(?=[ \t]+[^ \t]+(?i:[ \t]+up)?$)", - "name": "keyword.operator.ahk2" - }, - { - "match": "(?<=(&[ \t]+|^[ \t]*))([<>$~*!+#^]*?)(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+|`[;{]|[\\x21-\\x3A\\x3C-\\x7E]|(?<=[^ \t]);)(?=([ \t]|$))", - "name": "keyword.keys.ahk2" - } - ] - }, - "7": { - "name": "keyword.keys.up.ahk2" - }, - "8": { - "name": "punctuation.definition.colon" - } - }, - "end": "(?=\\n)", - "patterns": [ - { - "match": "(?<=\\G[ \t]*)((?i:alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab)\\b|([<>]?[!+#^]){0,4}(`[{;]|(?<=\\G);|[^{;]|(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))(?=([ \t]+;.*|[ \t]*)\\n))", - "name": "keyword.keys.ahk2" - }, - { - "include": "$base" - } - ] - }, - { - "match": "(?<=^[ \t]*\\{?[ \t]*)(\\w+)(:)(?=[ \t]*([ \t];.*)?$)", - "captures": { - "1": { - "name": "entity.name.label.ahk2" - }, - "2": { - "name": "punctuation.definition.colon" - } - } - } - ] - }, - "hotstring_execute": { - "match": "^[ \t]*(:)([^:]*)(:)((`.|[^`])*?)(::)", - "captures": { - "1": { - "name": "punctuation.definition.colon" - }, - "2": { - "patterns": [ - { - "match": "(?i:(s[ipe]|[*?borstz]0?|c[01]?|k-1|[kp]\\d+|x1?))", - "name": "string.options.ahk2 markup.italic" - }, - { - "match": "[^ \t]", - "name": "invalid.options.ahk2 markup.strikethrough" - } - ] - }, - "3": { - "name": "punctuation.definition.colon" - }, - "4": { - "name": "keyword.keys.ahk2 markup.underline" - }, - "6": { - "name": "punctuation.definition.colon" - } - }, - "name": "hotstring.ahk2" - }, - "inline-tags": { - "patterns": [ - { - "name": "constant.other.description.jsdoc", - "match": "(\\[)[^\\]]+(\\])(?={@(?:link|linkcode|linkplain|tutorial))", - "captures": { - "1": { - "name": "punctuation.definition.bracket.square.begin.jsdoc" - }, - "2": { - "name": "punctuation.definition.bracket.square.end.jsdoc" - } - } - }, - { - "name": "entity.name.type.instance.jsdoc", - "begin": "({)((@)(?:link(?:code|plain)?|tutorial))\\s*", - "beginCaptures": { - "1": { - "name": "punctuation.definition.bracket.curly.begin.jsdoc" - }, - "2": { - "name": "storage.type.class.jsdoc" - }, - "3": { - "name": "punctuation.definition.inline.tag.jsdoc" - } - }, - "end": "}|(?=\\*/)", - "endCaptures": { - "0": { - "name": "punctuation.definition.bracket.curly.end.jsdoc" - } - }, - "patterns": [ - { - "match": "\\G((?=https?://)(?:[^|}\\s*]|\\*[/])+)(\\|)?", - "captures": { - "1": { - "name": "variable.other.link.underline.jsdoc" - }, - "2": { - "name": "punctuation.separator.pipe.jsdoc" - } - } - }, - { - "match": "\\G((?:[^{}@\\s|*]|\\*[^/])+)(\\|)?", - "captures": { - "1": { - "name": "variable.other.description.jsdoc" - }, - "2": { - "name": "punctuation.separator.pipe.jsdoc" - } - } - } - ] - } - ] - }, - "brackets": { - "patterns": [ - { - "match": "^\\s*\\*\\s+", - "name": "comment.block.ahk2" - }, - { - "match": "(['\"])(`\\1|.(??:=.&|^]+|[~+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or)))[ \t]*([ \t];.*)?\\n", - "beginCaptures": { - "1": { - "patterns": [ - { - "include": "#operators" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "=>", - "name": "storage.type.function.arrow.ahk2" - } - ] - }, - "3": { - "name": "comment.line.ahk2" - } - }, - "end": "(?!([*/<>?:=.]+|[+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or))))[ \t]*([ \t];.*)?(?=\\n)|(?<=^[ \t]*(?i:class|static|if|try|loop|while)[ \t]+\\w+)", - "endCaptures": { - "3": { - "name": "comment.line.ahk2" - } - }, - "patterns": [ - { - "match": "(?<=^[ \t]*)\\w+(?=(\\n|[ \t]))", - "captures": { - "0": { - "patterns": [ - { - "include": "#variables" - } - ] - } - } - }, - { - "include": "#line_continue" - }, - { - "include": "$base" - } - ] - }, - "numbers": { - "match": "(?", - "name": "storage.type.function.arrow.ahk2" - }, - { - "match": "\\.=|\\+=|-=|\\*=|/?/=", - "name": "keyword.operator.assignment.compound.ahk2" - }, - { - "match": "&=|\\^=|<<=|>>>=|>>=|\\|=", - "name": "keyword.operator.assignment.compound.bitwise.ahk2" - }, - { - "match": "<<|>>>|>>", - "name": "keyword.operator.bitwise.shift.ahk2" - }, - { - "match": "!=|<=|>=|=?=|<|>", - "name": "keyword.operator.comparison.ahk2" - }, - { - "match": "~=", - "name": "keyword.operator.regexp.ahk2" - }, - { - "match": "\\?\\?|&&|!|\\|\\|", - "name": "keyword.operator.logical.ahk2" - }, - { - "match": "&|\\||\\^|~", - "name": "keyword.operator.ahk2" - }, - { - "match": ":=", - "name": "keyword.operator.assignment.ahk2" - }, - { - "match": "\\.(?=\\w)", - "name": "punctuation.accessor.ahk2" - }, - { - "match": "\\*|/|-|\\+|\\.", - "name": "keyword.operator.ahk2" - }, - { - "match": "%", - "name": "punctuation.parens.percent.ahk2" - }, - { - "match": "\\[", - "name": "punctuation.square.begin.ahk2" - }, - { - "match": "\\]", - "name": "punctuation.square.end.ahk2" - }, - { - "match": "\\?(?=[ \t]*[,)\\]}])", - "name": "keyword.operator.optional.ahk2" - }, - { - "match": "\\?|:(?!\\:)", - "name": "keyword.operator.ternary.ahk2" - }, - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - } - ] - }, - "parens": { - "name": "meta.parens.ahk2", - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "punctuation.section.parens.begin.bracket.round.ahk2" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.section.parens.end.bracket.round.ahk2" - } - }, - "patterns": [ - { - "include": "$base" - } - ] - }, - "property": { - "patterns": [ - { - "name": "variable.other.property.ahk2", - "match": "\\b(?<=\\.)[_[:alnum:]]+\\b" - } - ] - }, - "pre_definition": { - "patterns": [ - { - "begin": "^[ \t]*((#)(?i:dllload|hotstring|include(again)?|mapcasesense|requires|errorstdout|definedefault(array|map|object)value|windowclass(gui|main)|singleinstance|targetcontrolerror|targetwindowerror))\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - }, - "end": "\\n", - "name": "meta.preprocessor.ahk2", - "patterns": [ - { - "match": "[^ \t;].*?(?=([ \t]+;|[ \t]*\\n))", - "name": "string.literal.ahk2" - }, - { - "match": "(?<=[ \t]);.*", - "name": "comment.line.ahk2" - } - ] - }, - { - "begin": "^[ \t]*((#)(?i:warn))\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - }, - "end": "\\n", - "name": "meta.preprocessor.ahk2", - "patterns": [ - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "\\w+", - "name": "string.literal.ahk2" - }, - { - "match": "(?<=[ \t]);.*", - "name": "comment.line.ahk2" - } - ] - }, - { - "match": "^[ \t]*((#)(?i:clipboardtimeout|criticalobject(sleeptime|timeout)|hotif|hotiftimeout|inputlevel|initexec|maxthreads|maxthreadsbuffer|maxthreadsperhotkey|notrayicon|suspendexempt|usehook|usestdlib|warn|warncontinuableexception|winactivateforce))\\b", - "captures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - } - } - }, - { - "begin": "^[ \t]*((#)(?i:dllimport))([ \t]+(\\w+)[ \t]*(,?))?", - "beginCaptures": { - "1": { - "name": "keyword.control.directive.ahk2" - }, - "2": { - "name": "punctuation.definition.directive.ahk2" - }, - "4": { - "name": "entity.name.function.ahk2" - }, - "5": { - "name": "punctuation.separator.comma.ahk2" - } - }, - "end": "\\n", - "name": "meta.preprocessor.ahk2", - "patterns": [ - { - "match": ",", - "name": "punctuation.separator.comma.ahk2" - }, - { - "match": "[^,\\n\\r]+", - "name": "string.literal.ahk2" - } - ] - } - ] - }, - "reserved": { - "patterns": [ - { - "match": "(?(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))(\\()", - "beginCaptures": { - "1": { - "patterns": [ - { - "include": "#compiler_directive" - }, - { - "include": "#comments" - } - ] - }, - "2": { - "name": "comment.block.ahk2 punctuation.definition.comment.begin.ahk2" - }, - "3": { - "name": "comment.block.ahk2" - }, - "4": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.ahk2 punctuation.definition.comment.end.ahk2" - }, - { - "match": "\\*", - "name": "comment.block.ahk2" - } - ] - }, - "5": { - "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.ahk2" - } - }, - "end": "(\\))", - "endCaptures": { - "1": { - "name": "punctuation.section.parens.end.bracket.round.conditional.switch.ahk2" - } - }, - "patterns": [ - { - "include": "#conditional_context" - } - ] - }, - "switch_statement": { - "name": "meta.block.switch.ahk2", - "begin": "(((?>(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))((?\\[\\]=]))", - "patterns": [ - { - "name": "meta.head.switch.ahk2", - "begin": "\\G ?", - "end": "(?=+!]+ | \\(\\) | \\[\\]))\n)\n[ \t]*(\\() # opening bracket", + "beginCaptures": { + "1": { + "name": "variable.other.ahk2" + }, + "2": { + "name": "punctuation.section.parens.begin.bracket.round.initialization.ahk2" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.initialization.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.ahk2" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.ahk2" + } + }, + "patterns": [ + { + "include": "#block_innards" + } + ] + }, + { + "include": "$base" + } + ] + }, + "case_statement": { + "name": "meta.conditional.case.ahk2", + "begin": "(?<=^[ \t]*\\{?[ \t]*)((?i:case))(?!\\w)", + "beginCaptures": { + "1": { + "name": "keyword.control.case.ahk2" + } + }, + "end": "(:)", + "endCaptures": { + "1": { + "name": "punctuation.separator.colon.case.ahk2" + } + }, + "patterns": [ + { + "include": "#strings" + }, + { + "include": "#numbers" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "\\.(?=\\w)", + "name": "punctuation.accessor.ahk2" + }, + { + "include": "#function_call" + }, + { + "match": "{", + "name": "punctuation.section.block.begin.ahk2" + }, + { + "match": "}", + "name": "punctuation.section.block.end.ahk2" + }, + { + "match": "\\[|\\(", + "name": "punctuation.section.parens.begin.ahk2" + }, + { + "match": "\\]|\\)", + "name": "punctuation.section.parens.end.ahk2" + }, + { + "include": "#operators" + }, + { + "include": "#variables" + }, + { + "include": "#comments" + } + ] + }, + "class_block": { + "name": "meta.block.class.ahk2", + "begin": "(^|(?<=^[ \t]*\\*/))[ \t]*((?i:class))[ \t]+(\\$?\\w+(\\.\\w+)*)", + "beginCaptures": { + "2": { + "name": "storage.type.class.ahk2" + }, + "3": { + "name": "entity.name.type.class.ahk2" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.class.end.ahk2" + } + }, + "patterns": [ + { + "begin": "\\G(?!\\{)", + "end": "(?=\\{)", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "\\G[ \t]*(<)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.typeparameters.begin.ahk2" + } + }, + "end": ">", + "endCaptures": { + "0": { + "name": "punctuation.definition.typeparameters.end.ahk2" + } + }, + "patterns": [ + { + "match": "\\w+", + "name": "entity.name.type.parameter" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "=", + "name": "keyword.operator.assignment.ahk2" + }, + { + "match": "\\.", + "name": "punctuation.accessor.ahk2" + }, + { + "match": "\\|", + "name": "keyword.operator.ahk2" + } + ] + }, + { + "match": "\\b((?i:extends))([ \t]+([\\w.]+))?", + "captures": { + "1": { + "name": "storage.modifier.ahk2" + }, + "3": { + "patterns": [ + { + "match": "\\.(?=\\w)", + "name": "punctuation.accessor.ahk2" + }, + { + "include": "#default_classes" + }, + { + "match": "\\b[^.]+\\b", + "name": "entity.name.type.class.ahk2" + } + ] + } + } + } + ] + }, + { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.class.begin.ahk2" + } + }, + "end": "(?=})", + "name": "meta.block.class.body.ahk2", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "match": "(?<=^[ \t]*)(?i:static)(?=[ \t]+\\w)", + "name": "storage.modifier.ahk2" + }, + { + "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)[ \t]*(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "patterns": [ + { + "match": "\\b(?i:__item)\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "variable.other.property.ahk2" + }, + "2": { + "name": "storage.type.function.arrow.ahk2" + }, + "4": { + "name": "comment.line.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.block.prototype.body.ahk2", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + { + "match": "(?<=(^[ \t]*(?i:static[ \t]+)?|,[ \t]*))\\w+(?=[ \t]*:=)", + "captures": { + "0": { + "patterns": [ + { + "match": "\\b(?i:__item)\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "variable.other.property.ahk2" + } + } + }, + { + "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)(\\w+)(?=\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "match": "\\b(__(?i:new|init|enum|get|call|set|delete))\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "entity.name.function.method.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.block.method.ahk2", + "patterns": [ + { + "begin": "\\G\\(", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.ahk2" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.method.begin.ahk2" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.method.end.ahk2" + } + }, + "name": "meta.block.method.body.ahk2", + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.block.method.body.ahk2", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + } + ] + }, + { + "begin": "(?<=^[ \t]*(?i:static[ \t]+)?)\\b\\w+\\b(?=(\\[|[ \t]*\\{?([ \t];.*)?\\n))", + "beginCaptures": { + "0": { + "patterns": [ + { + "match": "\\b(?i:__item)\\b", + "name": "storage.type.metafunction.ahk2" + } + ], + "name": "variable.other.property.ahk2" + } + }, + "name": "meta.block.property.ahk2", + "end": "(?=\\n)", + "endCaptures": { + "1": { + "name": "punctuation.definition.block.property.end.ahk2" + } + }, + "patterns": [ + { + "begin": "\\G\\[", + "beginCaptures": { + "0": { + "name": "punctuation.definition.parameters.begin.ahk2" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "punctuation.definition.parameters.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.property.begin.ahk2" + } + }, + "end": "(?=})", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.property.end.ahk2" + } + }, + "name": "meta.block.property.body.ahk2", + "patterns": [ + { + "begin": "(?<=^[ \t]*)(?i:set)\\b", + "beginCaptures": { + "0": { + "name": "storage.type.setter.ahk2" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.property.setter.begin.ahk2" + } + }, + "name": "meta.block.property.setter.body.ahk2", + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.property.setter.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "name": "meta.block.property.setter.body.ahk2", + "end": "(?=\\n)", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + } + ] + }, + { + "begin": "(?<=^[ \t]*)(?i:get)\\b", + "beginCaptures": { + "0": { + "name": "storage.type.getter.ahk2" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.block.property.getter.begin.ahk2" + } + }, + "name": "meta.block.property.getter.body.ahk2", + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.block.property.getter.end.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "name": "meta.block.property.getter.body.ahk2", + "end": "(?=\\n)", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "begin": "(=>)([ \t]+(;.*)\\n|[ \t]*\\n)?", + "beginCaptures": { + "1": { + "name": "storage.type.function.arrow.ahk2" + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "name": "meta.block.property.getter.body.ahk2", + "end": "(?=\\n)", + "patterns": [ + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + { + "include": "#variables" + } + ] + }, + { + "include": "#class_block" + }, + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + } + ] + }, + "comments": { + "patterns": [ + { + "name": "comment.block.jsdoc.ahk2", + "begin": "^[ \t]*(\\/\\*\\*)(?!\\/)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.ahk2" + } + }, + "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.ahk2" + } + }, + "patterns": [ + { + "include": "#docblock" + } + ] + }, + { + "name": "comment.block.ahk2", + "begin": "(?<=^[ \t]*)(\\/\\*)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.ahk2" + } + }, + "end": "(^[ \t]*\\*\\/|(\\*\\/)[ \t]*$)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.ahk2" + } + } + }, + { + "name": "comment.line.ahk2", + "match": "(?<=(^[ \t]*|[ \t]))(;.*)" + } + ] + }, + "compiler_directive": { + "patterns": [ + { + "name": "comment.block.ahk2", + "begin": "^[ \t]*(\\/\\*)((?i:@ahk2exe-keep))", + "beginCaptures": { + "1": { + "name": "punctuation.definition.comment.begin.ahk2" + }, + "2": { + "name": "keyword.control.directive.conditional.ahk2" + } + }, + "end": "^[ \t]*(\\*\\/)", + "endCaptures": { + "1": { + "name": "punctuation.definition.comment.end.ahk2" + } + } + }, + { + "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-ignore(begin|end))", + "name": "keyword.control.directive.ahk2" + }, + { + "begin": "^[ \t]*(;[ \t]*@(?i:ahk2exe-let))\\b", + "beginCaptures": { + "0": { + "name": "keyword.control.directive.ahk2" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "include": "#strings" + }, + { + "include": "#numbers" + }, + { + "match": "\\b([_[:alpha:]][_[:alnum:]]*)(?=[ \t]*=)", + "name": "constant.language.ahk2" + }, + { + "match": "=", + "name": "keyword.operator.assignment.ahk2" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + } + ] + }, + { + "begin": "^[ \t]*((;[ \t]*@)(?i:include))\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + }, + "end": "(?=\\n)", + "name": "meta.preprocessor.include.ahk2", + "patterns": [ + { + "begin": "[^ \t;]", + "end": "(?=(?:[ \t]+;))|(?=\\n)", + "name": "string.literal.include.ahk2" + }, + { + "match": "(?:[ \t]+);.*", + "name": "comment.line.ahk2" + } + ] + }, + { + "match": "(?<=^[ \t]*);[ \t]*@(?i:ahk2exe-\\w+)\\b([ \t].*)?", + "name": "keyword.control.directive.ahk2", + "captures": { + "1": { + "name": "string.literal.ahk2" + } + } + }, + { + "match": "(?<=^|[ \t]);[ \t]*@(?:[\\w\\-]+)\\b([ \t]+(.*))?", + "name": "keyword.control.directive.ahk2", + "captures": { + "2": { + "name": "comment.line.ahk2" + } + } + } + ] + }, + "conditional_context": { + "patterns": [ + { + "include": "$self" + }, + { + "include": "#block_innards" + } + ] + }, + "continuation_section": { + "name": "meta.parens.continuation_section.ahk2", + "begin": "(?<=^[ \t]*)(\\()((((?i:join)[^ \t]*|[^ \t();]+)(?=[ \t]|$)|[ \t]+)*)((?<=[ \t]);.*)?$", + "beginCaptures": { + "1": { + "name": "punctuation.section.parens.begin.ahk2" + }, + "2": { + "patterns": [ + { + "match": "(?<=[ \t]|^[ \t]*\\()(?i:c(om(ments?)?)?|[lr]trim0?|`|join(`s|[^ \t]){0,15})(?=[ \t]|$)", + "name": "string.options.ahk2 markup.italic" + }, + { + "match": "[^ \t]+", + "name": "invalid.options.ahk2 markup.strikethrough" + } + ] + }, + "5": { + "name": "comment.line.ahk2" + } + }, + "end": "^[ \t]*(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.ahk2" + } + }, + "patterns": [ + { + "include": "#continuation_section_innards" + } + ] + }, + "continuation_section_innards": { + "patterns": [ + { + "begin": "('|\")", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.begin.ahk2" + } + }, + "end": "(\\1)|(?=^[ \t]*\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.ahk2" + } + }, + "name": "string.continuation_section_innards.ahk2", + "patterns": [ + { + "include": "#string_escaped_char" + } + ] + }, + { + "include": "#variables" + }, + { + "match": "{", + "name": "punctuation.section.block.begin.ahk2" + }, + { + "match": "}", + "name": "punctuation.section.block.end.ahk2" + }, + { + "match": "\\[", + "name": "punctuation.section.parens.begin.ahk2" + }, + { + "match": "\\]", + "name": "punctuation.section.parens.end.ahk2" + }, + { + "include": "#parens" + }, + { + "include": "$base" + } + ] + }, + "default_classes": { + "patterns": [ + { + "begin": "(?*/]\n (?:[^@<>*/]|\\*[^/])*\n)\n(?:\n \\s*\n (<)\n ([^>\\s]+)\n (>)\n)?", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.type.instance.jsdoc" + }, + "4": { + "name": "punctuation.definition.bracket.angle.begin.jsdoc" + }, + "5": { + "name": "constant.other.email.link.underline.jsdoc" + }, + "6": { + "name": "punctuation.definition.bracket.angle.end.jsdoc" + } + } + }, + { + "match": "(?x)\n((@)borrows) \\s+\n((?:[^@\\s*/]|\\*[^/])+) # \n\\s+ (as) \\s+ # as\n((?:[^@\\s*/]|\\*[^/])+) # ", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.type.instance.jsdoc" + }, + "4": { + "name": "keyword.operator.control.jsdoc" + }, + "5": { + "name": "entity.name.type.instance.jsdoc" + } + } + }, + { + "name": "meta.embedded.ahk2 meta.example.jsdoc", + "begin": "((@)example)\\s+", + "end": "(?=@|\\*+/)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "patterns": [ + { + "match": "^\\s*\\*\\s+", + "name": "comment.block.ahk2" + }, + { + "contentName": "constant.other.description.jsdoc", + "begin": "\\G(<)caption(>)", + "beginCaptures": { + "0": { + "name": "entity.name.tag.inline.jsdoc" + }, + "1": { + "name": "punctuation.definition.bracket.angle.begin.jsdoc" + }, + "2": { + "name": "punctuation.definition.bracket.angle.end.jsdoc" + } + }, + "end": "()|(?=\\*/)", + "endCaptures": { + "0": { + "name": "entity.name.tag.inline.jsdoc" + }, + "1": { + "name": "punctuation.definition.bracket.angle.begin.jsdoc" + }, + "2": { + "name": "punctuation.definition.bracket.angle.end.jsdoc" + } + }, + "patterns": [ + { + "match": "^\\s*\\*\\s", + "name": "comment.block.ahk2" + } + ] + }, + { + "include": "$base" + } + ] + }, + { + "name": "meta.overload.ahk2", + "begin": "((@)overload)\\s+", + "end": "(?=\\n|^\\s*\\*)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + { + "match": "(?x) ((@)kind) \\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\b", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "constant.language.symbol-type.jsdoc" + } + } + }, + { + "match": "(?x)\n((@)see)\n\\s+\n(?:\n # URL\n (\n (?=https?://)\n (?:[^\\s*]|\\*[^/])+\n )\n |\n # JSDoc namepath\n (\n (?!\n # Avoid matching bare URIs (also acceptable as links)\n https?://\n |\n # Avoid matching {@inline tags}; we match those below\n (?:\\[[^\\[\\]]*\\])? # Possible description [preceding]{@tag}\n {@(?:link|linkcode|linkplain|tutorial)\\b\n )\n # Matched namepath\n (?:[^@\\s*/]|\\*[^/])+\n )\n)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.link.underline.jsdoc" + }, + "4": { + "name": "entity.name.type.instance.jsdoc" + } + } + }, + { + "match": "(?x)\n((@)template)\n\\s+\n# One or more valid identifiers\n(\n [A-Za-z_$] # First character: non-numeric word character\n [\\w$.\\[\\]]* # Rest of identifier\n (?: # Possible list of additional identifiers\n \\s* , \\s*\n [A-Za-z_$]\n [\\w$.\\[\\]]*\n )*\n)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.jsdoc" + } + } + }, + { + "begin": "((@)typedef)\\s+(?={)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", + "patterns": [ + { + "include": "#jsdoctype" + }, + { + "name": "entity.name.type.instance.jsdoc", + "match": "(?:[^@\\s*/]|\\*[^/])+" + } + ] + }, + { + "begin": "((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\s+(?=[\\[{]|(?!\\d)\\w)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "end": "(?=\\s|\\*/|[^{}\\[\\]\\w])", + "patterns": [ + { + "include": "#jsdoctype" + }, + { + "name": "variable.other.jsdoc", + "match": "((?!\\d)\\w[\\w.\\[\\]]*)" + }, + { + "name": "variable.other.jsdoc", + "match": "(?x)\n(\\[)\\s*\n\\w+\n(?:\n (?:\\[\\])? # Foo[ ].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [\\w$]+\n)*\n(?:\n \\s*\n (=) # [foo=bar] Default parameter value\n \\s*\n (\n # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\n (?>\n \"(?:(?:\\*(?!/))|(?:\\\\(?!\"))|[^*\\\\])*?\" | # [foo=\"bar\"] Double-quoted\n '(?:(?:\\*(?!/))|(?:\\\\(?!'))|[^*\\\\])*?' | # [foo='bar'] Single-quoted\n \\[ (?:(?:\\*(?!/))|[^*])*? \\] | # [foo=[1,2]] Array literal\n (?:(?:\\*(?!/))|\\s(?!\\s*\\])|\\[.*?(?:\\]|(?=\\*/))|[^*\\s\\[\\]])* # Everything else\n )*\n )\n)?\n\\s*(?:(\\])((?:[^*\\s]|\\*[^\\s/])+)?|(?=\\*/))", + "captures": { + "1": { + "name": "punctuation.definition.optional-value.begin.bracket.square.jsdoc" + }, + "2": { + "name": "keyword.operator.assignment.jsdoc" + }, + "3": { + "name": "meta.embedded.ahk2" + }, + "4": { + "name": "punctuation.definition.optional-value.end.bracket.square.jsdoc" + }, + "5": { + "name": "invalid.illegal.syntax.jsdoc" + } + } + } + ] + }, + { + "begin": "(?x)\n(\n (@)\n (?:define|enum|exception|export|extends|lends|implements|modifies\n |namespace|private|protected|returns?|suppress|this|throws|type\n |yields?)\n)\n\\s+(?={)", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + }, + "end": "(?=\\s|\\*/|[^{}\\[\\]A-Za-z_$])", + "patterns": [ + { + "include": "#jsdoctype" + } + ] + }, + { + "match": "((@)method)\\b\\s*((\\w|[^\\x00-\\x7f])+)?", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.function.method.ahk2" + } + } + }, + { + "match": "(?x)\n(\n (@)\n (?:alias|augments|callback|constructs|emits|event|fires|exports?\n |extends|external|function|func|host|lends|listens|interface|memberof!?\n |module|mixes|mixin|name|requires|see|this|typedef|uses)\n)\n\\s+\n(\n (?:\n [^{}@\\s*] | \\*[^/]\n )+\n)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "entity.name.type.instance.jsdoc" + } + } + }, + { + "contentName": "variable.other.jsdoc", + "begin": "((@)(?:default(?:value)?|license|version))\\s+(([''\"]))", + "beginCaptures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.jsdoc" + }, + "4": { + "name": "punctuation.definition.string.begin.jsdoc" + } + }, + "end": "(\\3)|(?=$|\\*/)", + "endCaptures": { + "0": { + "name": "variable.other.jsdoc" + }, + "1": { + "name": "punctuation.definition.string.end.jsdoc" + } + } + }, + { + "match": "((@)(?:default(?:value)?|license|tutorial|variation|version))\\s+([^\\s*]+)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + }, + "3": { + "name": "variable.other.jsdoc" + } + } + }, + { + "name": "storage.type.class.jsdoc", + "match": "(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\b", + "captures": { + "1": { + "name": "punctuation.definition.block.tag.jsdoc" + } + } + }, + { + "include": "#inline-tags" + }, + { + "match": "((@)(?:[_$[:alpha:]][_$[:alnum:]]*))(?=\\s+)", + "captures": { + "1": { + "name": "storage.type.class.jsdoc" + }, + "2": { + "name": "punctuation.definition.block.tag.jsdoc" + } + } + } + ] + }, + "function_call": { + "match": "([_[:alpha:]][[:alnum:]_]*+)(?=\\()", + "captures": { + "1": { + "name": "entity.name.function.ahk2", + "patterns": [ + { + "match": "(?<=\\.).+", + "name": "entity.name.function.method.ahk2" + }, + { + "include": "#variables_language" + } + ] + } + } + }, + "function_call_notparens": { + "patterns": [ + { + "match": "(?<=^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\b(?>=|\\?|\\{))|$))", + "name": "entity.name.function.ahk2", + "captures": { + "0": { + "patterns": [ + { + "include": "#function_defaultLibrary" + } + ] + } + } + }, + { + "match": "(?<=(^[ \t]*(\\{[ \t]*)?|::[ \t]*|(?i:(try|else|finally)[ \t]+))([[:alpha:]_][[:alnum:]_]*\\.)+)([[:alpha:]_][[:alnum:]_]*\\b)(?=$|[ \t]((?!([ \t]*[+\\-*/^&:.|]?=|<<=|>>=|\\?|\\{))|$))", + "name": "entity.name.function.method.ahk2" + } + ] + }, + "function_defaultLibrary": { + "patterns": [ + { + "match": "(?$~*!+#^]*?)(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))|~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+)[ \t]+&[ \t]+~?(`;|(?<=[^ \t]);|[\\x21-\\x3A\\x3C-\\x7E]|[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x5e\\x60\\x7b-\\x7f]+))([ \t]+up)?)(::)", + "beginCaptures": { + "1": { + "name": "hotkey.ahk2", + "patterns": [ + { + "match": "(?<=[ \t])&(?=[ \t]+[^ \t]+(?i:[ \t]+up)?$)", + "name": "keyword.operator.ahk2" + }, + { + "match": "(?<=(&[ \t]+|^[ \t]*))([<>$~*!+#^]*?)(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|(0*[2-9]|0*1[0-6]?)?joy0*([1-9]|[12]\\d|3[012])|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+|`[;{]|[\\x21-\\x3A\\x3C-\\x7E]|(?<=[^ \t]);)(?=([ \t]|$))", + "name": "keyword.keys.ahk2" + } + ] + }, + "7": { + "name": "keyword.keys.up.ahk2" + }, + "8": { + "name": "punctuation.definition.colon" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "match": "(?<=\\G[ \t]*)((?i:alttab|alttabandmenu|alttabmenu|alttabmenudismiss|shiftalttab)\\b|([<>]?[!+#^]){0,4}(`[{;]|(?<=\\G);|[^{;]|(?i:shift|lshift|rshift|alt|lalt|ralt|control|lcontrol|rcontrol|ctrl|lctrl|rctrl|lwin|rwin|appskey|lbutton|rbutton|mbutton|wheeldown|wheelup|wheelleft|wheelright|xbutton[12]|space|tab|enter|escape|esc|backspace|bs|delete|del|insert|ins|pgdn|pgup|home|end|up|down|left|right|printscreen|ctrlbreak|pause|help|sleep|scrolllock|capslock|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadmult|numpadadd|numpadsub|numpaddiv|numpaddot|numpaddel|numpadins|numpadclear|numpadleft|numpadright|numpaddown|numpadup|numpadhome|numpadend|numpadpgdn|numpadpgup|numpadenter|f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|browser_back|browser_forward|browser_refresh|browser_stop|browser_search|browser_favorites|browser_home|volume_mute|volume_down|volume_up|media_next|media_prev|media_stop|media_play_pause|launch_mail|launch_media|launch_app1|launch_app2|vk[a-f\\d]{1,2}(sc[a-f\\d]+)?|sc[a-f\\d]+))(?=([ \t]+;.*|[ \t]*)\\n))", + "name": "keyword.keys.ahk2" + }, + { + "include": "$base" + } + ] + }, + { + "match": "(?<=^[ \t]*\\{?[ \t]*)(\\w+)(:)(?=[ \t]*([ \t];.*)?$)", + "captures": { + "1": { + "name": "entity.name.label.ahk2" + }, + "2": { + "name": "punctuation.definition.colon" + } + } + } + ] + }, + "hotstring_execute": { + "match": "^[ \t]*(:)([^:]*)(:)((`.|[^`])*?)(::)", + "captures": { + "1": { + "name": "punctuation.definition.colon" + }, + "2": { + "patterns": [ + { + "match": "(?i:(s[ipe]|[*?borstz]0?|c[01]?|k-1|[kp]\\d+|x1?))", + "name": "string.options.ahk2 markup.italic" + }, + { + "match": "[^ \t]", + "name": "invalid.options.ahk2 markup.strikethrough" + } + ] + }, + "3": { + "name": "punctuation.definition.colon" + }, + "4": { + "name": "keyword.keys.ahk2 markup.underline" + }, + "6": { + "name": "punctuation.definition.colon" + } + }, + "name": "hotstring.ahk2" + }, + "inline-tags": { + "patterns": [ + { + "name": "constant.other.description.jsdoc", + "match": "(\\[)[^\\]]+(\\])(?={@(?:link|linkcode|linkplain|tutorial))", + "captures": { + "1": { + "name": "punctuation.definition.bracket.square.begin.jsdoc" + }, + "2": { + "name": "punctuation.definition.bracket.square.end.jsdoc" + } + } + }, + { + "name": "entity.name.type.instance.jsdoc", + "begin": "({)((@)(?:link(?:code|plain)?|tutorial))\\s*", + "beginCaptures": { + "1": { + "name": "punctuation.definition.bracket.curly.begin.jsdoc" + }, + "2": { + "name": "storage.type.class.jsdoc" + }, + "3": { + "name": "punctuation.definition.inline.tag.jsdoc" + } + }, + "end": "}|(?=\\*/)", + "endCaptures": { + "0": { + "name": "punctuation.definition.bracket.curly.end.jsdoc" + } + }, + "patterns": [ + { + "match": "\\G((?=https?://)(?:[^|}\\s*]|\\*[/])+)(\\|)?", + "captures": { + "1": { + "name": "variable.other.link.underline.jsdoc" + }, + "2": { + "name": "punctuation.separator.pipe.jsdoc" + } + } + }, + { + "match": "\\G((?:[^{}@\\s|*]|\\*[^/])+)(\\|)?", + "captures": { + "1": { + "name": "variable.other.description.jsdoc" + }, + "2": { + "name": "punctuation.separator.pipe.jsdoc" + } + } + } + ] + } + ] + }, + "brackets": { + "patterns": [ + { + "match": "^\\s*\\*\\s+", + "name": "comment.block.ahk2" + }, + { + "match": "(['\"])(`\\1|.(??:=.&|^]+|[~+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or)))[ \t]*([ \t];.*)?\\n", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#operators" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "=>", + "name": "storage.type.function.arrow.ahk2" + } + ] + }, + "3": { + "name": "comment.line.ahk2" + } + }, + "end": "(?!([*/<>?:=.]+|[+\\-]=?|!==?|,|\\b(?i:(and|contain|not|in|is|or))))[ \t]*([ \t];.*)?(?=\\n)|(?<=^[ \t]*(?i:class|static|if|try|loop|while)[ \t]+\\w+)", + "endCaptures": { + "3": { + "name": "comment.line.ahk2" + } + }, + "patterns": [ + { + "match": "(?<=^[ \t]*)\\w+(?=(\\n|[ \t]))", + "captures": { + "0": { + "patterns": [ + { + "include": "#variables" + } + ] + } + } + }, + { + "include": "#line_continue" + }, + { + "include": "$base" + } + ] + }, + "numbers": { + "match": "(?", + "name": "storage.type.function.arrow.ahk2" + }, + { + "match": "\\.=|\\+=|-=|\\*=|/?/=", + "name": "keyword.operator.assignment.compound.ahk2" + }, + { + "match": "&=|\\^=|<<=|>>>=|>>=|\\|=", + "name": "keyword.operator.assignment.compound.bitwise.ahk2" + }, + { + "match": "<<|>>>|>>", + "name": "keyword.operator.bitwise.shift.ahk2" + }, + { + "match": "!=|<=|>=|=?=|<|>", + "name": "keyword.operator.comparison.ahk2" + }, + { + "match": "~=", + "name": "keyword.operator.regexp.ahk2" + }, + { + "match": "\\?\\?|&&|!|\\|\\|", + "name": "keyword.operator.logical.ahk2" + }, + { + "match": "&|\\||\\^|~", + "name": "keyword.operator.ahk2" + }, + { + "match": ":=", + "name": "keyword.operator.assignment.ahk2" + }, + { + "match": "\\.(?=\\w)", + "name": "punctuation.accessor.ahk2" + }, + { + "match": "\\*|/|-|\\+|\\.", + "name": "keyword.operator.ahk2" + }, + { + "match": "%", + "name": "punctuation.parens.percent.ahk2" + }, + { + "match": "\\[", + "name": "punctuation.square.begin.ahk2" + }, + { + "match": "\\]", + "name": "punctuation.square.end.ahk2" + }, + { + "match": "\\?(?=[ \t]*[,)\\]}])", + "name": "keyword.operator.optional.ahk2" + }, + { + "match": "\\?|:(?!\\:)", + "name": "keyword.operator.ternary.ahk2" + }, + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + } + ] + }, + "parens": { + "name": "meta.parens.ahk2", + "begin": "\\(", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.ahk2" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.section.parens.end.bracket.round.ahk2" + } + }, + "patterns": [ + { + "include": "$base" + } + ] + }, + "property": { + "patterns": [ + { + "name": "variable.other.property.ahk2", + "match": "\\b(?<=\\.)[_[:alnum:]]+\\b" + } + ] + }, + "pre_definition": { + "patterns": [ + { + "begin": "^[ \t]*((#)(?i:dllload|hotstring|include(again)?|mapcasesense|requires|errorstdout|definedefault(array|map|object)value|windowclass(gui|main)|singleinstance|targetcontrolerror|targetwindowerror))\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + }, + "end": "\\n", + "name": "meta.preprocessor.ahk2", + "patterns": [ + { + "match": "[^ \t;].*?(?=([ \t]+;|[ \t]*\\n))", + "name": "string.literal.ahk2" + }, + { + "match": "(?<=[ \t]);.*", + "name": "comment.line.ahk2" + } + ] + }, + { + "begin": "^[ \t]*((#)(?i:warn))\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + }, + "end": "\\n", + "name": "meta.preprocessor.ahk2", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "\\w+", + "name": "string.literal.ahk2" + }, + { + "match": "(?<=[ \t]);.*", + "name": "comment.line.ahk2" + } + ] + }, + { + "match": "^[ \t]*((#)(?i:clipboardtimeout|criticalobject(sleeptime|timeout)|hotif|hotiftimeout|inputlevel|initexec|maxthreads|maxthreadsbuffer|maxthreadsperhotkey|notrayicon|suspendexempt|usehook|usestdlib|warn|warncontinuableexception|winactivateforce))\\b", + "captures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + } + } + }, + { + "begin": "^[ \t]*((#)(?i:dllimport))([ \t]+(\\w+)[ \t]*(,?))?", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.ahk2" + }, + "2": { + "name": "punctuation.definition.directive.ahk2" + }, + "4": { + "name": "entity.name.function.ahk2" + }, + "5": { + "name": "punctuation.separator.comma.ahk2" + } + }, + "end": "\\n", + "name": "meta.preprocessor.ahk2", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.comma.ahk2" + }, + { + "match": "[^,\\n\\r]+", + "name": "string.literal.ahk2" + } + ] + } + ] + }, + "reserved": { + "patterns": [ + { + "match": "(?(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))(\\()", + "beginCaptures": { + "1": { + "patterns": [ + { + "include": "#compiler_directive" + }, + { + "include": "#comments" + } + ] + }, + "2": { + "name": "comment.block.ahk2 punctuation.definition.comment.begin.ahk2" + }, + "3": { + "name": "comment.block.ahk2" + }, + "4": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.ahk2 punctuation.definition.comment.end.ahk2" + }, + { + "match": "\\*", + "name": "comment.block.ahk2" + } + ] + }, + "5": { + "name": "punctuation.section.parens.begin.bracket.round.conditional.switch.ahk2" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.conditional.switch.ahk2" + } + }, + "patterns": [ + { + "include": "#conditional_context" + } + ] + }, + "switch_statement": { + "name": "meta.block.switch.ahk2", + "begin": "(((?>(?:(?:(?>(?(?:[^\\*]|(?>\\*+)[^\\/])*)((?>\\*+)\\/)))+|(?:(?:(?:(?:\\b|(?<=\\W))|(?=\\W))|\\A)|\\Z))))((?\\[\\]=]))", + "patterns": [ + { + "name": "meta.head.switch.ahk2", + "begin": "\\G ?", + "end": "(? { + test('top-level property', () => { + const cfg: AHKLSConfig = newConfig(); + + setCfg(CfgKey.LibrarySuggestions, LibIncludeType.Disabled, cfg); + + assert.strictEqual( + LibIncludeType.Disabled, + getCfg(CfgKey.LibrarySuggestions, cfg), + ); + + setCfg(CfgKey.LibrarySuggestions, LibIncludeType.All, cfg); + + assert.strictEqual( + LibIncludeType.All, + getCfg(CfgKey.LibrarySuggestions, cfg), + ); + }); + + test('nested property', () => { + const cfg: AHKLSConfig = newConfig(); + + setCfg(CfgKey.CallWithoutParentheses, CallWithoutParentheses.Off, cfg); + + assert.strictEqual( + CallWithoutParentheses.Off, + getCfg(CfgKey.CallWithoutParentheses, cfg), + ); + + setCfg(CfgKey.CallWithoutParentheses, CallWithoutParentheses.On, cfg); + + assert.strictEqual( + CallWithoutParentheses.On, + getCfg(CfgKey.CallWithoutParentheses, cfg), + ); + }); + + test('nested object property', () => { + const cfg: AHKLSConfig = newConfig(); + + setCfg(CfgKey.ArrayStyle, 1, cfg); + setCfg(CfgKey.BraceStyle, 0, cfg); + + assert.strictEqual(0, getCfg(CfgKey.BraceStyle, cfg)); + + setCfg(CfgKey.ArrayStyle, 2, cfg); + + // Check for updated value and other value not deleted + assert.strictEqual(2, getCfg(CfgKey.ArrayStyle, cfg)); + assert.strictEqual(0, getCfg(CfgKey.BraceStyle, cfg)); + }); + + test('invalid property', () => { + // no assertion necessary, just needs not to throw + setCfg('potato' as CfgKey, 1); + }); +}); + +suite('getCfg', () => { + test('invalid nested property', () => { + const cfg: AHKLSConfig = newConfig(); + + // no assertion necessary, just needs not to throw + getCfg(`${CfgKey.Formatter}.superDuperInvalid` as CfgKey, cfg); + }); +}); diff --git a/util/src/config.ts b/util/src/config.ts new file mode 100644 index 00000000..621a5309 --- /dev/null +++ b/util/src/config.ts @@ -0,0 +1,311 @@ +//* Utility functions to access the config variable from either client or server +//* All exported values here match contributed settings/configurations in package.json +export enum CfgKey { + ActionWhenV1Detected = 'v2.general.actionWhenV1Detected', + ArrayStyle = 'v2.formatter.arrayStyle', + BraceStyle = 'v2.formatter.braceStyle', + BreakChainedMethods = 'v2.formatter.breakChainedMethods', + CallWithoutParentheses = 'v2.warn.callWithoutParentheses', + ClassNonDynamicMemberCheck = 'v2.diagnostics.classNonDynamicMemberCheck', + Commands = 'commands', + CommentTagRegex = 'v2.general.commentTagRegex', + CompleteFunctionCalls = 'v2.general.completeFunctionCalls', + CompletionCommitCharacters = 'v2.completionCommitCharacters', + DebugConfiguration = 'DebugConfiguration', + Exclude = 'v2.exclude', + ExtensionUri = 'extensionUri', + Formatter = 'v2.formatter', + IgnoreComment = 'v2.formatter.ignoreComment', + IndentBetweenHotIfDirective = 'v2.formatter.indentBetweenHotIfDirectives', + IndentString = 'v2.formatter.indent_string', + InterpreterPath = 'v2.file.interpreterPath', + InterpreterPathV1 = 'v1.file.interpreterPath', // unique to AHK++ + KeywordStartWithUppercase = 'v2.formatter.keywordStartWithUppercase', + LibrarySuggestions = 'v2.general.librarySuggestions', + LocalSameAsGlobal = 'v2.warn.localSameAsGlobal', + Locale = 'locale', + MaxPreserveNewlines = 'v2.formatter.maxPreserveNewlines', + MaxScanDepth = 'v2.file.maxScanDepth', + ObjectStyle = 'v2.formatter.objectStyle', + OneTrueBrace = 'v2.formatter.one_true_brace', // deprecated, not used + ParamsCheck = 'v2.diagnostics.paramsCheck', + PreserveNewlines = 'v2.formatter.preserveNewlines', + ShowOutput = 'general.showOutput', // unique to AHK++ + SpaceAfterDoubleColon = 'v2.formatter.spaceAfterDoubleColon', + SpaceBeforeConditional = 'v2.formatter.spaceBeforeConditional', + SpaceInEmptyParen = 'v2.formatter.spaceInEmptyParen', + SpaceInOther = 'v2.formatter.spaceInOther', + SpaceInParen = 'v2.formatter.spaceInParen', + SwitchCaseAlignment = 'v2.formatter.switchCaseAlignment', + SymbolFoldingFromOpenBrace = 'v2.general.symbolFoldingFromOpenBrace', + SymbolWithSameCase = 'v2.formatter.symbolWithSameCase', + Syntaxes = 'v2.general.syntaxes', + VarUnset = 'v2.warn.varUnset', + WhiteSpaceBeforeInlineComment = 'v2.formatter.whitespaceBeforeInlineComment', + WorkingDirectories = 'v2.workingDirectories', + WrapLineLength = 'v2.formatter.wrapLineLength', +} + +export type ActionType = + | 'Continue' + | 'Warn' + | 'SkipLine' + | 'SwitchToV1' + | 'Stop'; + +export enum LibIncludeType { + Disabled = 'Off', + Local = 'Local', + UserAndStandard = 'User and Standard', + All = 'All', +} + +export enum CallWithoutParentheses { + Off = 'Off', + Parentheses = 'Parentheses', + On = 'On', +} + +/** Possible values for `array_style` and `object_style` */ +export type BlockStyle = 'collapse' | 'expand' | 'none'; + +export type BraceStyle = + | 'One True Brace' + | 'Allman' + | 'One True Brace Variant' + | 'Preserve'; + +export interface FormatOptions { + arrayStyle: BlockStyle; + braceStyle: BraceStyle; + breakChainedMethods: boolean; + ignoreComment: boolean; + indentString: string; + indentBetweenHotIfDirectives: boolean; + keywordStartWithUppercase: boolean; + maxPreserveNewlines: number; + objectStyle: BlockStyle; + preserveNewlines: boolean; + spaceBeforeConditional: boolean; + spaceAfterDoubleColon: boolean; + spaceInEmptyParen: boolean; + spaceInOther: boolean; + spaceInParen: boolean; + switchCaseAlignment: boolean; + symbolWithSameCase: boolean; + whitespaceBeforeInlineComment: string; + wrapLineLength: number; +} + +export interface CompletionCommitCharacters { + Class: string; + Function: string; +} + +/** Matches the contributed extension configuration in package.json */ +export interface AHKLSConfig { + v2: { + general: { + actionWhenV1Detected: ActionType; + /** The regex denoting a custom symbol. Defaults to `;;` */ + commentTagRegex?: string; + /** Automatically insert parentheses on function call */ + completeFunctionCalls: boolean; + /** Suggest library functions */ + librarySuggestions: LibIncludeType; + symbolFoldingFromOpenBrace: boolean; + syntaxes: string; + }; + completionCommitCharacters: CompletionCommitCharacters; + diagnostics: { + classNonDynamicMemberCheck: boolean; + paramsCheck: boolean; + }; + /** Glob pattern of files to ignore */ + exclude: string[]; + file: { + /** Path to the AHK v2 intepreter */ + interpreterPath: string; + /** Depth of folders to scan for IntelliSense */ + maxScanDepth: number; + }; + /** Config of the v2 formatter */ + formatter: FormatOptions; + warn: { + /** Ref to a potentially-unset variable */ + varUnset: boolean; + /** Undeclared local has same name as global */ + localSameAsGlobal: boolean; + /** Function call without parentheses */ + callWithoutParentheses: CallWithoutParentheses; + }; + /** Directories containing AHK files that can be #included */ + workingDirectories: string[]; + }; + locale?: string; + commands?: string[]; + extensionUri?: string; + GlobalStorage?: string; +} + +/** + * Returns a formatter config built from the given config and defaults. + * Defaults defined in package.json + */ +export const newFormatOptions = ( + config: Partial = {}, +): FormatOptions => ({ + arrayStyle: 'none', + braceStyle: 'One True Brace', + breakChainedMethods: false, + ignoreComment: false, + indentString: ' ', + indentBetweenHotIfDirectives: false, + keywordStartWithUppercase: false, + maxPreserveNewlines: 2, + objectStyle: 'none', + preserveNewlines: true, + spaceBeforeConditional: true, + spaceAfterDoubleColon: true, + spaceInEmptyParen: false, + spaceInOther: true, + spaceInParen: false, + switchCaseAlignment: false, + symbolWithSameCase: false, + whitespaceBeforeInlineComment: '', + wrapLineLength: 120, + ...config, +}); + +/** Defaults according to package.json */ +export const newConfig = (config: Partial = {}): AHKLSConfig => ({ + v2: { + general: { + actionWhenV1Detected: 'SwitchToV1', + commentTagRegex: '^;;\\s*(.*)', + completeFunctionCalls: false, + librarySuggestions: LibIncludeType.Disabled, + symbolFoldingFromOpenBrace: false, + syntaxes: '', + }, + completionCommitCharacters: { + Class: '.(', + Function: '(', + }, + diagnostics: { + classNonDynamicMemberCheck: true, + paramsCheck: true, + }, + exclude: [], + file: { + interpreterPath: 'C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey.exe', + maxScanDepth: 2, + }, + formatter: newFormatOptions(), + warn: { + varUnset: true, + localSameAsGlobal: false, + callWithoutParentheses: CallWithoutParentheses.Off, + }, + workingDirectories: [], + }, + ...config, +}); + +/** + * The global object shared across the server. + * The client fetches the config from VS Code directly. + * Updated when the user changes their settings. + */ +const ahklsConfig: AHKLSConfig = newConfig(); + +/** The start of each config value in package.json */ +export const configPrefix = 'AHK++'; + +/** + * Gets a single config value from the provided config. + * If no config provided, uses the global config. + */ +export const getCfg = ( + key?: CfgKey, + /** + * AHKLSConfig for server, { readonly ... } for client. + * Since this func just reads values, both are acceptable. + */ + config: AHKLSConfig | { readonly [key: string]: unknown } = ahklsConfig, +): T => { + if (!key) return config as T; + const keyPath = key.split('.'); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let value: any = config; + for (const k of keyPath) { + if (!value) { + if (config === ahklsConfig) { + console.warn(`Failed to get config`, key); + } + return undefined as T; + } + value = value?.[k]; + } + return value; +}; + +/** + * Sets the value of the key in the provided config. + * If no config provided, updates the global config. + * Does not update IDE settings. + */ +export const setCfg = ( + key: CfgKey, + value: T, + config: AHKLSConfig = ahklsConfig, +): void => { + const keyPath = key.split('.'); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let obj: any = config; + for (const k of keyPath.slice(0, -1)) { + obj = obj?.[k]; + } + if (!obj) { + if (config === ahklsConfig) { + console.warn(`(Global) Failed to set config`, key, value); + } + return; + } + obj[keyPath[keyPath.length - 1]] = value; +}; + +/** + * Assign the provided config to the root config. + * Assumes the provided config is valid. + */ +export const setConfigRoot = (config: AHKLSConfig): void => { + Object.assign(ahklsConfig, config); +}; + +export const shouldIncludeUserStdLib = ( + config: AHKLSConfig = ahklsConfig, +): boolean => { + const result = + getCfg(CfgKey.LibrarySuggestions, config) === + LibIncludeType.UserAndStandard || + getCfg(CfgKey.LibrarySuggestions, config) === + LibIncludeType.All; + return result; +}; + +export const shouldIncludeLocalLib = ( + config: AHKLSConfig = ahklsConfig, +): boolean => { + const result = + getCfg(CfgKey.LibrarySuggestions, config) === + LibIncludeType.Local || + getCfg(CfgKey.LibrarySuggestions, config) === + LibIncludeType.All; + return result; +}; + +//* Unique to AHK++ + +/** Defined in package.json */ +export type ShowOutput = 'always' | 'never'; diff --git a/util/src/env.ts b/util/src/env.ts new file mode 100644 index 00000000..fdfcb9e5 --- /dev/null +++ b/util/src/env.ts @@ -0,0 +1,106 @@ +//* General global variables that may be changed by forks +// For config-specific values, see `config.ts` + +/** ID of the language client, used for internal reference */ +export const languageClientId = 'AHK++'; + +/** Name of the language client, displayed to users? */ +export const languageClientName = 'AHK++'; + +/** Name of the output channel for debugging information, displayed to users */ +export const outputChannelName = 'AHK++'; + +//* Internal commands - Client-side + +/** Prefix for commands handled by the client. These are not registered in package.json */ +const clientCommandPrefix = 'ahk++.'; +export type ClientCommand = `${typeof clientCommandPrefix}${string}`; + +/** + * Ask the server to execute the provided command. + * See `executeCommandProvider` in `server/src/commandProvider.ts` for details. + */ +export const clientExecuteCommand = `${clientCommandPrefix}executeCommand`; + +/** Get the active text editor URI and position */ +export const clientGetActiveEditorInfo: ClientCommand = `${clientCommandPrefix}getActiveTextEditorUriAndPosition`; + +/** Insert a snippet */ +export const clientInsertSnippet: ClientCommand = `${clientCommandPrefix}insertSnippet`; + +/** Set the language of the text document */ +export const clientSetTextDocumentLanguage: ClientCommand = `${clientCommandPrefix}setTextDocumentLanguage`; + +/** Update the status bar with the new interpreter info */ +export const clientUpdateStatusBar: ClientCommand = `${clientCommandPrefix}updateStatusBar`; + +/** Get matching AHK files */ +export const clientGetWorkspaceFiles: ClientCommand = `${clientCommandPrefix}getWorkspaceFiles`; + +/** Get the text content of the provided file */ +export const clientGetWorkspaceFileContent: ClientCommand = `${clientCommandPrefix}getWorkspaceFileContent`; + +//* Internal commands - Server-side + +/** Prefix for commands handled by the server. These are not registered in package.json */ +const serverCommandPrefix = 'ahk++.lsp.'; +export type ServerCommand = `${typeof serverCommandPrefix}${string}`; + +export const serverExportSymbols = `${serverCommandPrefix}exportSymbols`; + +export const serverGetAHKVersion = `${serverCommandPrefix}getAHKversion`; + +export const serverGetContent = `${serverCommandPrefix}getContent`; + +export const serverGetVersionInfo = `${serverCommandPrefix}getVersionInfo`; + +/** Set the path to the AHK v2 interpreter to match the provided value */ +export const serverResetInterpreterPath = `${serverCommandPrefix}setV2Interpreter`; + +//* External commands (contributed by package.json) +//* These should not change unless package.json changes + +const extCommandPrefix = 'ahk++.'; +export type ExtensionCommand = `${typeof extCommandPrefix}${string}`; + +/** Diagnose all files */ +export const extDiagnoseAll = `${extCommandPrefix}diagnostic.full`; + +/** Generate a method header comment */ +export const extGenerateComment = `${extCommandPrefix}addDocComment`; + +/** Set the script directory */ +export const extSetScriptDir = `${extCommandPrefix}setAScriptDir`; + +/** Run the script in the active text editor */ +export const extRun = `${extCommandPrefix}run`; + +/** Run the selected text */ +export const extRunSelection = `${extCommandPrefix}runSelection`; + +/** Stop an AHK script started by this process */ +export const extStop = `${extCommandPrefix}stop`; + +/** Set the interpreter */ +export const extSetInterpreter = `${extCommandPrefix}setV2Interpreter`; + +/** Debug from a selected config */ +export const extDebugConfig = `${extCommandPrefix}debugConfigs`; + +/** Debug with params */ +export const extDebugParams = `${extCommandPrefix}debugParams`; + +/** Debug and attach */ +export const extDebugAttach = `${extCommandPrefix}debugAttach`; + +/** Select syntaxes */ +export const extSelectSyntaxes = `${extCommandPrefix}select.syntaxes`; + +/** Update version info file header comment */ +export const extUpdateVersionInfo = `${extCommandPrefix}updateVersionInfo`; + +/** Extract the symbols from the active editor */ +export const extExtractSymbols = `${extCommandPrefix}exportSymbols`; + +/** Switch the current editor from AHK v1 to AHK v2 and vice versa */ +export const extSwitchAHKVersion = `${extCommandPrefix}switchAhkVersion`; From e3851c2d5d0362cbeb4f811ef95933f1d2b0d868 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:46:54 -0700 Subject: [PATCH 45/60] Fixup selectSyntaxes command (#59) --- util/src/env.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/env.ts b/util/src/env.ts index fdfcb9e5..b9a644b2 100644 --- a/util/src/env.ts +++ b/util/src/env.ts @@ -94,7 +94,7 @@ export const extDebugParams = `${extCommandPrefix}debugParams`; export const extDebugAttach = `${extCommandPrefix}debugAttach`; /** Select syntaxes */ -export const extSelectSyntaxes = `${extCommandPrefix}select.syntaxes`; +export const extSelectSyntaxes = `${extCommandPrefix}selectSyntaxes`; /** Update version info file header comment */ export const extUpdateVersionInfo = `${extCommandPrefix}updateVersionInfo`; From 456dfc3b6d66ab5953fba9a20f0dc23e94e8008b Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:25:12 -0700 Subject: [PATCH 46/60] Format directives are snake_case for compatibility with thqby (#60) --- syntaxes/ahk2_common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syntaxes/ahk2_common.json b/syntaxes/ahk2_common.json index 2a1739f5..31d3438c 100644 --- a/syntaxes/ahk2_common.json +++ b/syntaxes/ahk2_common.json @@ -32,7 +32,7 @@ "description": "Enables or disables class non-dynamic member checking for the current file/class" }, { - "body": ";@format ${1|arrayStyle,objectStyle|}: ${2|collapse,expand,none|}", + "body": ";@format ${1|array_style,object_style|}: ${2|collapse,expand,none|}", "prefix": "@format", "description": "Sets the object or array style of the current block for formatting" }, From 4ebf94290b3734add118a922805545c3ec2036da Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:16:29 -0700 Subject: [PATCH 47/60] Update and pin some dependencies (#61) --- package-lock.json | 1058 ++++++++++++++++++++------------------------- package.json | 4 +- 2 files changed, 463 insertions(+), 599 deletions(-) diff --git a/package-lock.json b/package-lock.json index a59df277..561c1712 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,8 +23,8 @@ "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/vsce": "^3.1.1", - "del-cli": "^5.1.0", - "esbuild": "^0.24.0", + "del-cli": "^6.0.0", + "esbuild": "0.24.0", "eslint": "^9.11.0", "mocha": "^10.7.3", "prettier": "3.3.3", @@ -245,51 +245,402 @@ "node": ">=16" } }, - "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.25.7", - "picocolors": "^1.0.0" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "node_modules/@esbuild/android-arm": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "node_modules/@esbuild/android-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "node_modules/@esbuild/android-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } }, "node_modules/@esbuild/win32-x64": { "version": "0.24.0", @@ -624,6 +975,19 @@ "node": ">=14" } }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz", @@ -642,13 +1006,6 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/mocha": { "version": "10.0.8", "resolved": "https://registry.npmmirror.com/@types/mocha/-/mocha-10.0.8.tgz", @@ -665,13 +1022,6 @@ "undici-types": "~6.19.2" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/vscode": { "version": "1.93.0", "resolved": "https://registry.npmmirror.com/@types/vscode/-/vscode-1.93.0.tgz", @@ -1124,23 +1474,6 @@ "node": ">= 14" } }, - "node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", @@ -1206,16 +1539,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", @@ -1436,25 +1759,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", @@ -1554,35 +1858,6 @@ "dev": true, "optional": true }, - "node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clean-stack/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cli-cursor": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", @@ -1831,43 +2106,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz", @@ -1927,80 +2165,66 @@ } }, "node_modules/del": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/del/-/del-7.1.0.tgz", - "integrity": "sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==", + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/del/-/del-8.0.0.tgz", + "integrity": "sha512-R6ep6JJ+eOBZsBr9esiNN1gxFbZE4Q2cULkUSFumGYecAiS6qodDvcPx/sFuWHMNul7DWmrtoEOpYSm7o6tbSA==", "dev": true, "license": "MIT", "dependencies": { - "globby": "^13.1.2", - "graceful-fs": "^4.2.10", + "globby": "^14.0.2", "is-glob": "^4.0.3", "is-path-cwd": "^3.0.0", "is-path-inside": "^4.0.0", - "p-map": "^5.5.0", - "rimraf": "^3.0.2", - "slash": "^4.0.0" + "p-map": "^7.0.2", + "slash": "^5.1.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/del-cli": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/del-cli/-/del-cli-5.1.0.tgz", - "integrity": "sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==", + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/del-cli/-/del-cli-6.0.0.tgz", + "integrity": "sha512-9nitGV2W6KLFyya4qYt4+9AKQFL+c0Ehj5K7V7IwlxTc6RMCfQUGY9E9pLG6e8TQjtwXpuiWIGGZb3mfVxyZkw==", "dev": true, "license": "MIT", "dependencies": { - "del": "^7.1.0", - "meow": "^10.1.3" + "del": "^8.0.0", + "meow": "^13.2.0" }, "bin": { "del": "cli.js", "del-cli": "cli.js" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/del/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/del/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmmirror.com/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/del/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": "*" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/del/node_modules/is-path-inside": { @@ -2016,34 +2240,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/del/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/del/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/del/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/del/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "license": "MIT", + "engines": { + "node": ">=14.16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/delayed-stream": { @@ -2234,16 +2454,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz", @@ -2294,6 +2504,7 @@ "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -2935,16 +3146,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", @@ -3146,19 +3347,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", @@ -3183,13 +3371,6 @@ "dev": true, "optional": true }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3202,22 +3383,6 @@ "node": ">=8" } }, - "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", @@ -3423,13 +3588,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3448,13 +3606,6 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3570,16 +3721,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/klona": { "version": "2.0.6", "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz", @@ -3620,13 +3761,6 @@ "immediate": "~3.0.5" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, "node_modules/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.0.tgz", @@ -3813,19 +3947,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.1.0.tgz", @@ -3852,55 +3973,18 @@ "license": "MIT" }, "node_modules/meow": { - "version": "10.1.5", - "resolved": "https://registry.npmmirror.com/meow/-/meow-10.1.5.tgz", - "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^7.0.0", - "decamelize": "^5.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.2", - "read-pkg-up": "^8.0.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^1.2.2", - "yargs-parser": "^20.2.9" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "version": "13.2.0", + "resolved": "https://registry.npmmirror.com/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/meow/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", @@ -3978,16 +4062,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", @@ -4013,31 +4087,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minimist-options/node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz", @@ -4310,22 +4359,6 @@ "dev": true, "optional": true }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", @@ -4561,15 +4594,13 @@ } }, "node_modules/p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmmirror.com/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "version": "7.0.2", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-7.0.2.tgz", + "integrity": "sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==", "dev": true, - "dependencies": { - "aggregate-error": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4599,25 +4630,6 @@ "node": ">=6" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parse-semver": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/parse-semver/-/parse-semver-1.1.1.tgz", @@ -4743,13 +4755,6 @@ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, - "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true, - "license": "ISC" - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", @@ -4890,19 +4895,6 @@ } ] }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", @@ -4950,42 +4942,6 @@ "node": ">=0.8" } }, - "node_modules/read-pkg": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-6.0.0.tgz", - "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-8.0.0.tgz", - "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^5.0.0", - "read-pkg": "^6.0.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", @@ -5019,23 +4975,6 @@ "node": ">=8.10.0" } }, - "node_modules/redent": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "license": "MIT", - "dependencies": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", @@ -5335,42 +5274,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", - "dev": true, - "license": "CC0-1.0" - }, "node_modules/stdin-discarder": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz", @@ -5501,21 +5404,6 @@ "node": ">=8" } }, - "node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -5715,19 +5603,6 @@ "node": ">=8.0" } }, - "node_modules/trim-newlines": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-4.1.1.tgz", - "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -5780,19 +5655,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typed-rest-client": { "version": "1.8.11", "resolved": "https://registry.npmmirror.com/typed-rest-client/-/typed-rest-client-1.8.11.tgz", @@ -5868,6 +5730,19 @@ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", @@ -5912,17 +5787,6 @@ "node": ">=10.12.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", diff --git a/package.json b/package.json index 0f948ed1..73635b21 100644 --- a/package.json +++ b/package.json @@ -966,8 +966,8 @@ "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.1", "@vscode/vsce": "^3.1.1", - "del-cli": "^5.1.0", - "esbuild": "^0.24.0", + "del-cli": "^6.0.0", + "esbuild": "0.24.0", "eslint": "^9.11.0", "mocha": "^10.7.3", "prettier": "3.3.3", From d7dfd3bf2eb3ceaf5deac6554957e6cf4f22f047 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:00:07 -0700 Subject: [PATCH 48/60] Wrap special chars in double quotes (#62) --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 73635b21..cb5cde43 100644 --- a/package.json +++ b/package.json @@ -34,9 +34,9 @@ "build:e2e": "npm run build -- --e2e", "check-types": "tsc", "clean": "npm run clean:dist && npm run clean:out && npm run clean:watch", - "clean:dist": "del-cli client/dist && del-cli server/dist/*.js(.map)?", + "clean:dist": "del-cli client/dist \"server/dist/*.js*\"", "clean:out": "del-cli out", - "clean:watch": "del-cli client/dist && del-cli server/out && del-cli util/src/*.js*", + "clean:watch": "del-cli client/dist server/out \"util/src/*.js*\"", "clean:watch//": "echo If watch is running, files will reappear instantly!", "precompile-ts": "npm run clean:out", "compile-ts": "tsc --noEmit false --outDir out", @@ -53,7 +53,7 @@ "test": "npm run test:grammar && npm run test:unit && npm run test:e2e", "pretest:e2e": "npm run build:e2e", "test:e2e": "vscode-test", - "test:grammar": "vscode-tmgrammar-snap tmgrammar-test/*.ahk", + "test:grammar": "vscode-tmgrammar-snap \"tmgrammar-test/*.ahk\"", "pretest:unit": "npm run compile-ts", "test:unit": "mocha", "prevalidate": "npm run clean", From 65ac012e61b7446503593f53091c4461a32abb6c Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 12 Oct 2024 04:11:04 -0700 Subject: [PATCH 49/60] Merge upstream-main (#66) Co-authored-by: thqby <294633707@qq.com> --- client/src/extension.ts | 11 +- esbuild.mjs | 2 +- server/src/common.ts | 3 +- server/src/lexer.ts | 24 +- tools/install.js | 1266 +++++++++++++++++++++++++++++++++++++++ util/src/env.ts | 2 + 6 files changed, 1286 insertions(+), 22 deletions(-) create mode 100644 tools/install.js diff --git a/client/src/extension.ts b/client/src/extension.ts index a431028c..9b487ded 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -55,6 +55,7 @@ import { extExtractSymbols, extSwitchAHKVersion, serverResetInterpreterPath, + ahkIsRunningContext, } from '../../util/src/env'; import { getConfigIDE, getConfigRoot } from './config'; @@ -86,9 +87,7 @@ const loadedCollection = { export function activate(context: ExtensionContext): Promise { /** Absolute path to `server.js` */ const extId = context.extension.id; - // todo should be able to run as part of AHK++ and standalone (external commands will not work standalone) - const defaultServerModule = context.asAbsolutePath(`${extId.startsWith('mark-wiemer') ? 'ahk2/' : ''}server/dist/server.js`); - const serverModule = process.env.VSCODE_AHK_SERVER_PATH ? context.asAbsolutePath(process.env.VSCODE_AHK_SERVER_PATH) : defaultServerModule; + const serverModule = context.asAbsolutePath(`${extId.startsWith('mark-wiemer') ? 'ahk2/' : ''}server/${process.env.DEBUG ? 'out' : 'dist'}/server.js`); // If the extension is launched in debug mode then the debug server options are used // Otherwise the run options are used @@ -229,7 +228,7 @@ export function activate(context: ExtensionContext): Promise { } update_extensions_info(); - commands.executeCommand('setContext', 'ahk:isRunning', false); + commands.executeCommand('setContext', ahkIsRunningContext, false); ahkStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 75); ahkStatusBarItem.command = extSetInterpreter; for (const it of [ @@ -405,7 +404,7 @@ async function runScript(textEditor: TextEditor, runSelection = false) { outputchannel.appendLine(`[Running] [pid:${process.pid}] ${command}`); ahkprocesses.set(process.pid, process); process.path = path; - commands.executeCommand('setContext', 'ahk:isRunning', true); + commands.executeCommand('setContext', ahkIsRunningContext, true); process.stderr?.on('data', (data) => { outputchannel.appendLine(decode(data)); }); @@ -420,7 +419,7 @@ async function runScript(textEditor: TextEditor, runSelection = false) { outputchannel.appendLine(`[Done] [pid:${process.pid}] exited with code=${code} in ${((new Date()).getTime() - startTime.getTime()) / 1000} seconds`); ahkprocesses.delete(process.pid!); if (!ahkprocesses.size) - commands.executeCommand('setContext', 'ahk:isRunning', false); + commands.executeCommand('setContext', ahkIsRunningContext, false); }); } else outputchannel.appendLine(`[Fail] ${command}`); diff --git a/esbuild.mjs b/esbuild.mjs index e74807d8..6e7cb380 100644 --- a/esbuild.mjs +++ b/esbuild.mjs @@ -122,7 +122,7 @@ function build_watch(web = false) { if (web) opts = browser_opts(false); else { server_opt.entryPoints = ['server/src/*.ts']; - server_opt.outdir = 'server/dist'; + server_opt.outdir = 'server/out'; opts = [client_opt, server_opt, util_opt]; } for (const opt of opts) { diff --git a/server/src/common.ts b/server/src/common.ts index 003e6513..59ffca51 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -190,8 +190,7 @@ export function initahk2cache() { /** Loads IntelliSense hover text */ export function loadAHK2(filename = 'ahk2', d = 3) { let path: string | undefined; - const syntaxesPath = process.env.SYNTAXES_PATH || 'syntaxes'; - const file = `${rootdir}/${syntaxesPath}/<>/${filename}`; + const file = `${rootdir}/syntaxes/<>/${filename}`; if (process.env.BROWSER) { const td = openFile(file + '.d.ahk'); if (td) { diff --git a/server/src/lexer.ts b/server/src/lexer.ts index 809c470f..0da31df7 100644 --- a/server/src/lexer.ts +++ b/server/src/lexer.ts @@ -5547,11 +5547,9 @@ export class Lexer { flags.indentation_level = level ??= flags.indentation_level; output_space_before_token ??= space_in_other; - const firstCondition = previous_flags.in_case_statement && last_type === 'TK_LABEL' && /^(default)?:$/.test(last_text); - const secondCondition = opt.brace_style === 'Allman' || input_wanted_newline && opt.preserve_newlines && opt.brace_style === 'Preserve'; - if (firstCondition) + if (previous_flags.in_case_statement && last_type === 'TK_LABEL' && /^(default)?:$/.test(last_text)) flags.case_body = null, print_newline(), flags.indentation_level--; - else if (secondCondition) + else if (opt.brace_style === 'Allman' || input_wanted_newline && opt.preserve_newlines && opt.brace_style === 'Preserve') if (ck.in_expr === undefined || flags.mode === MODE.Expression) print_newline(true); @@ -5573,7 +5571,6 @@ export class Lexer { restore_mode(); const is_obj = flags.mode === MODE.ObjectLiteral, is_exp = is_obj || (ck.in_expr !== undefined); - const secondCondition = opt.brace_style !== 'Preserve' || input_wanted_newline; if (is_obj) { const style = flags.object_style ?? opt.object_style; if (style === OBJECT_STYLE.collapse || last_text === '{') @@ -5581,7 +5578,7 @@ export class Lexer { else if (style || input_wanted_newline && opt.preserve_newlines) print_newline(true); output_space_before_token = space_in_other && last_text !== '{'; - } else if (secondCondition) + } else if (opt.brace_style !== 'Preserve' || input_wanted_newline) print_newline(true); restore_mode(); @@ -5702,13 +5699,14 @@ export class Lexer { } if (maybe_need_newline) { trim_newlines(); - const condition = flags.last_text !== '}' - || opt.brace_style === 'Allman' - || opt.brace_style === 'One True Brace Variant' - || input_wanted_newline - && opt.preserve_newlines - && opt.brace_style !== 'Preserve'; - if (condition) + if ( + flags.last_text !== '}' + || opt.brace_style === 'Allman' + || opt.brace_style === 'One True Brace Variant' + || input_wanted_newline + && opt.preserve_newlines + && opt.brace_style !== 'Preserve' + ) print_newline(true); else output_space_before_token = space_in_other; } else if (input_wanted_newline) diff --git a/tools/install.js b/tools/install.js new file mode 100644 index 00000000..c0d108e7 --- /dev/null +++ b/tools/install.js @@ -0,0 +1,1266 @@ +/** + * @license node-stream-zip | (c) 2020 Antelle | https://github.com/antelle/node-stream-zip/blob/master/LICENSE + * Portions copyright https://github.com/cthackers/adm-zip | https://raw.githubusercontent.com/cthackers/adm-zip/master/LICENSE + */ +/* eslint-disable */ +let fs = require('fs'); +const path = require('path'); +const events = require('events'); +const zlib = require('zlib'); +const stream = require('stream'); + +const consts = { + /* The local file header */ + LOCHDR: 30, // LOC header size + LOCSIG: 0x04034b50, // "PK\003\004" + LOCVER: 4, // version needed to extract + LOCFLG: 6, // general purpose bit flag + LOCHOW: 8, // compression method + LOCTIM: 10, // modification time (2 bytes time, 2 bytes date) + LOCCRC: 14, // uncompressed file crc-32 value + LOCSIZ: 18, // compressed size + LOCLEN: 22, // uncompressed size + LOCNAM: 26, // filename length + LOCEXT: 28, // extra field length + + /* The Data descriptor */ + EXTSIG: 0x08074b50, // "PK\007\008" + EXTHDR: 16, // EXT header size + EXTCRC: 4, // uncompressed file crc-32 value + EXTSIZ: 8, // compressed size + EXTLEN: 12, // uncompressed size + + /* The central directory file header */ + CENHDR: 46, // CEN header size + CENSIG: 0x02014b50, // "PK\001\002" + CENVEM: 4, // version made by + CENVER: 6, // version needed to extract + CENFLG: 8, // encrypt, decrypt flags + CENHOW: 10, // compression method + CENTIM: 12, // modification time (2 bytes time, 2 bytes date) + CENCRC: 16, // uncompressed file crc-32 value + CENSIZ: 20, // compressed size + CENLEN: 24, // uncompressed size + CENNAM: 28, // filename length + CENEXT: 30, // extra field length + CENCOM: 32, // file comment length + CENDSK: 34, // volume number start + CENATT: 36, // internal file attributes + CENATX: 38, // external file attributes (host system dependent) + CENOFF: 42, // LOC header offset + + /* The entries in the end of central directory */ + ENDHDR: 22, // END header size + ENDSIG: 0x06054b50, // "PK\005\006" + ENDSIGFIRST: 0x50, + ENDSUB: 8, // number of entries on this disk + ENDTOT: 10, // total number of entries + ENDSIZ: 12, // central directory size in bytes + ENDOFF: 16, // offset of first CEN header + ENDCOM: 20, // zip file comment length + MAXFILECOMMENT: 0xffff, + + /* The entries in the end of ZIP64 central directory locator */ + ENDL64HDR: 20, // ZIP64 end of central directory locator header size + ENDL64SIG: 0x07064b50, // ZIP64 end of central directory locator signature + ENDL64SIGFIRST: 0x50, + ENDL64OFS: 8, // ZIP64 end of central directory offset + + /* The entries in the end of ZIP64 central directory */ + END64HDR: 56, // ZIP64 end of central directory header size + END64SIG: 0x06064b50, // ZIP64 end of central directory signature + END64SIGFIRST: 0x50, + END64SUB: 24, // number of entries on this disk + END64TOT: 32, // total number of entries + END64SIZ: 40, + END64OFF: 48, + + /* Compression methods */ + STORED: 0, // no compression + SHRUNK: 1, // shrunk + REDUCED1: 2, // reduced with compression factor 1 + REDUCED2: 3, // reduced with compression factor 2 + REDUCED3: 4, // reduced with compression factor 3 + REDUCED4: 5, // reduced with compression factor 4 + IMPLODED: 6, // imploded + // 7 reserved + DEFLATED: 8, // deflated + ENHANCED_DEFLATED: 9, // deflate64 + PKWARE: 10, // PKWare DCL imploded + // 11 reserved + BZIP2: 12, // compressed using BZIP2 + // 13 reserved + LZMA: 14, // LZMA + // 15-17 reserved + IBM_TERSE: 18, // compressed using IBM TERSE + IBM_LZ77: 19, //IBM LZ77 z + + /* General purpose bit flag */ + FLG_ENC: 0, // encrypted file + FLG_COMP1: 1, // compression option + FLG_COMP2: 2, // compression option + FLG_DESC: 4, // data descriptor + FLG_ENH: 8, // enhanced deflation + FLG_STR: 16, // strong encryption + FLG_LNG: 1024, // language encoding + FLG_MSK: 4096, // mask header values + FLG_ENTRY_ENC: 1, + + /* 4.5 Extensible data fields */ + EF_ID: 0, + EF_SIZE: 2, + + /* Header IDs */ + ID_ZIP64: 0x0001, + ID_AVINFO: 0x0007, + ID_PFS: 0x0008, + ID_OS2: 0x0009, + ID_NTFS: 0x000a, + ID_OPENVMS: 0x000c, + ID_UNIX: 0x000d, + ID_FORK: 0x000e, + ID_PATCH: 0x000f, + ID_X509_PKCS7: 0x0014, + ID_X509_CERTID_F: 0x0015, + ID_X509_CERTID_C: 0x0016, + ID_STRONGENC: 0x0017, + ID_RECORD_MGT: 0x0018, + ID_X509_PKCS7_RL: 0x0019, + ID_IBM1: 0x0065, + ID_IBM2: 0x0066, + ID_POSZIP: 0x4690, + + EF_ZIP64_OR_32: 0xffffffff, + EF_ZIP64_OR_16: 0xffff, +}; + +class StreamZip extends events.EventEmitter { + constructor(config) { + super(); + let fd, fileSize, chunkSize, op, centralDirectory, closed; + const ready = false, + that = this, + entries = config.storeEntries !== false ? {} : null, + textDecoder = config.nameEncoding + ? new TextDecoder(config.nameEncoding) + : null; + + fd = config.buffer; + fileSize = fd.byteLength; + chunkSize = config.chunkSize || Math.round(fileSize / 1000); + chunkSize = Math.max( + Math.min(chunkSize, Math.min(128 * 1024, fileSize)), + Math.min(1024, fileSize), + ); + setImmediate(readCentralDirectory); + + function readUntilFoundCallback(err, bytesRead) { + if (err || !bytesRead) { + return that.emit('error', err || new Error('Archive read error')); + } + let pos = op.lastPos; + let bufferPosition = pos - op.win.position; + const buffer = op.win.buffer; + const minPos = op.minPos; + while (--pos >= minPos && --bufferPosition >= 0) { + if ( + buffer.length - bufferPosition >= 4 && + buffer[bufferPosition] === op.firstByte + ) { + // quick check first signature byte + if (buffer.readUInt32LE(bufferPosition) === op.sig) { + op.lastBufferPosition = bufferPosition; + op.lastBytesRead = bytesRead; + op.complete(); + return; + } + } + } + if (pos === minPos) { + return that.emit('error', new Error('Bad archive')); + } + op.lastPos = pos + 1; + op.chunkSize *= 2; + if (pos <= minPos) { + return that.emit('error', new Error('Bad archive')); + } + const expandLength = Math.min(op.chunkSize, pos - minPos); + op.win.expandLeft(expandLength, readUntilFoundCallback); + } + + function readCentralDirectory() { + const totalReadLength = Math.min( + consts.ENDHDR + consts.MAXFILECOMMENT, + fileSize, + ); + op = { + win: new FileWindowBuffer(fd), + totalReadLength, + minPos: fileSize - totalReadLength, + lastPos: fileSize, + chunkSize: Math.min(1024, chunkSize), + firstByte: consts.ENDSIGFIRST, + sig: consts.ENDSIG, + complete: readCentralDirectoryComplete, + }; + op.win.read( + fileSize - op.chunkSize, + op.chunkSize, + readUntilFoundCallback, + ); + } + + function readCentralDirectoryComplete() { + const buffer = op.win.buffer; + const pos = op.lastBufferPosition; + try { + centralDirectory = new CentralDirectoryHeader(); + centralDirectory.read(buffer.slice(pos, pos + consts.ENDHDR)); + centralDirectory.headerOffset = op.win.position + pos; + if (centralDirectory.commentLength) { + that.comment = buffer + .slice( + pos + consts.ENDHDR, + pos + consts.ENDHDR + centralDirectory.commentLength, + ) + .toString(); + } else { + that.comment = null; + } + that.entriesCount = centralDirectory.volumeEntries; + that.centralDirectory = centralDirectory; + if ( + (centralDirectory.volumeEntries === consts.EF_ZIP64_OR_16 && + centralDirectory.totalEntries === consts.EF_ZIP64_OR_16) || + centralDirectory.size === consts.EF_ZIP64_OR_32 || + centralDirectory.offset === consts.EF_ZIP64_OR_32 + ) { + readZip64CentralDirectoryLocator(); + } else { + op = {}; + readEntries(); + } + } catch (err) { + that.emit('error', err); + } + } + + function readZip64CentralDirectoryLocator() { + const length = consts.ENDL64HDR; + if (op.lastBufferPosition > length) { + op.lastBufferPosition -= length; + readZip64CentralDirectoryLocatorComplete(); + } else { + op = { + win: op.win, + totalReadLength: length, + minPos: op.win.position - length, + lastPos: op.win.position, + chunkSize: op.chunkSize, + firstByte: consts.ENDL64SIGFIRST, + sig: consts.ENDL64SIG, + complete: readZip64CentralDirectoryLocatorComplete, + }; + op.win.read( + op.lastPos - op.chunkSize, + op.chunkSize, + readUntilFoundCallback, + ); + } + } + + function readZip64CentralDirectoryLocatorComplete() { + const buffer = op.win.buffer; + const locHeader = new CentralDirectoryLoc64Header(); + locHeader.read( + buffer.slice( + op.lastBufferPosition, + op.lastBufferPosition + consts.ENDL64HDR, + ), + ); + const readLength = fileSize - locHeader.headerOffset; + op = { + win: op.win, + totalReadLength: readLength, + minPos: locHeader.headerOffset, + lastPos: op.lastPos, + chunkSize: op.chunkSize, + firstByte: consts.END64SIGFIRST, + sig: consts.END64SIG, + complete: readZip64CentralDirectoryComplete, + }; + op.win.read( + fileSize - op.chunkSize, + op.chunkSize, + readUntilFoundCallback, + ); + } + + function readZip64CentralDirectoryComplete() { + const buffer = op.win.buffer; + const zip64cd = new CentralDirectoryZip64Header(); + zip64cd.read( + buffer.slice( + op.lastBufferPosition, + op.lastBufferPosition + consts.END64HDR, + ), + ); + that.centralDirectory.volumeEntries = zip64cd.volumeEntries; + that.centralDirectory.totalEntries = zip64cd.totalEntries; + that.centralDirectory.size = zip64cd.size; + that.centralDirectory.offset = zip64cd.offset; + that.entriesCount = zip64cd.volumeEntries; + op = {}; + readEntries(); + } + + function readEntries() { + op = { + win: new FileWindowBuffer(fd), + pos: centralDirectory.offset, + chunkSize, + entriesLeft: centralDirectory.volumeEntries, + }; + op.win.read( + op.pos, + Math.min(chunkSize, fileSize - op.pos), + readEntriesCallback, + ); + } + + function readEntriesCallback(err, bytesRead) { + if (err || !bytesRead) { + return that.emit('error', err || new Error('Entries read error')); + } + let bufferPos = op.pos - op.win.position; + let entry = op.entry; + const buffer = op.win.buffer; + const bufferLength = buffer.length; + try { + while (op.entriesLeft > 0) { + if (!entry) { + entry = new ZipEntry(); + entry.readHeader(buffer, bufferPos); + entry.headerOffset = op.win.position + bufferPos; + op.entry = entry; + op.pos += consts.CENHDR; + bufferPos += consts.CENHDR; + } + const entryHeaderSize = + entry.fnameLen + entry.extraLen + entry.comLen; + const advanceBytes = + entryHeaderSize + (op.entriesLeft > 1 ? consts.CENHDR : 0); + if (bufferLength - bufferPos < advanceBytes) { + op.win.moveRight(chunkSize, readEntriesCallback, bufferPos); + op.move = true; + return; + } + entry.read(buffer, bufferPos, textDecoder); + if (!config.skipEntryNameValidation) { + entry.validateName(); + } + if (entries) { + entries[entry.name] = entry; + } + that.emit('entry', entry); + op.entry = entry = null; + op.entriesLeft--; + op.pos += entryHeaderSize; + bufferPos += entryHeaderSize; + } + that.emit('ready'); + } catch (err) { + that.emit('error', err); + } + } + + function checkEntriesExist() { + if (!entries) { + throw new Error('storeEntries disabled'); + } + } + + Object.defineProperty(this, 'ready', { + get() { + return ready; + }, + }); + + this.entry = function (name) { + checkEntriesExist(); + return entries[name]; + }; + + this.entries = function () { + checkEntriesExist(); + return entries; + }; + + this.stream = function (entry, callback) { + return this.openEntry( + entry, + (err, entry) => { + if (err) { + return callback(err); + } + const offset = dataOffset(entry); + let entryStream = new EntryDataReaderStream( + fd, + offset, + entry.compressedSize, + ); + if (entry.method === consts.STORED) { + // nothing to do + } else if (entry.method === consts.DEFLATED) { + entryStream = entryStream.pipe(zlib.createInflateRaw()); + } else { + return callback( + new Error('Unknown compression method: ' + entry.method), + ); + } + if (canVerifyCrc(entry)) { + entryStream = entryStream.pipe( + new EntryVerifyStream(entryStream, entry.crc, entry.size), + ); + } + callback(null, entryStream); + }, + false, + ); + }; + + this.entryDataSync = function (entry) { + let err = null; + this.openEntry( + entry, + (e, en) => { + err = e; + entry = en; + }, + true, + ); + if (err) { + throw err; + } + let data = Buffer.alloc(entry.compressedSize); + new BufRead(fd, data, 0, entry.compressedSize, dataOffset(entry), (e) => { + err = e; + }).read(true); + if (err) { + throw err; + } + if (entry.method === consts.STORED) { + // nothing to do + } else if ( + entry.method === consts.DEFLATED || + entry.method === consts.ENHANCED_DEFLATED + ) { + data = zlib.inflateRawSync(data); + } else { + throw new Error('Unknown compression method: ' + entry.method); + } + if (data.length !== entry.size) { + throw new Error('Invalid size'); + } + if (canVerifyCrc(entry)) { + const verify = new CrcVerify(entry.crc, entry.size); + verify.data(data); + } + return data; + }; + + this.openEntry = function (entry, callback, sync) { + if (typeof entry === 'string') { + checkEntriesExist(); + entry = entries[entry]; + if (!entry) { + return callback(new Error('Entry not found')); + } + } + if (!entry.isFile) { + return callback(new Error('Entry is not file')); + } + if (!fd) { + return callback(new Error('Archive closed')); + } + const buffer = Buffer.alloc(consts.LOCHDR); + new BufRead(fd, buffer, 0, buffer.length, entry.offset, (err) => { + if (err) { + return callback(err); + } + let readEx; + try { + entry.readDataHeader(buffer); + if (entry.encrypted) { + readEx = new Error('Entry encrypted'); + } + } catch (ex) { + readEx = ex; + } + callback(readEx, entry); + }).read(sync); + }; + + function dataOffset(entry) { + return entry.offset + consts.LOCHDR + entry.fnameLen + entry.extraLen; + } + + function canVerifyCrc(entry) { + // if bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written + return (entry.flags & 0x8) !== 0x8; + } + + function extract(entry, outPath, callback) { + that.stream(entry, (err, stm) => { + if (err) { + callback(err); + } else { + let fsStm, errThrown; + stm.on('error', (err) => { + errThrown = err; + if (fsStm) { + stm.unpipe(fsStm); + fsStm.close(() => { + callback(err); + }); + } + }); + fs.open(outPath, 'w', (err, fdFile) => { + if (err) { + return callback(err); + } + if (errThrown) { + fs.close(fd, () => { + callback(errThrown); + }); + return; + } + fsStm = fs.createWriteStream(outPath, { fd: fdFile }); + fsStm.on('finish', () => { + that.emit('extract', entry, outPath); + if (!errThrown) { + callback(); + } + }); + stm.pipe(fsStm); + }); + } + }); + } + + function createDirectories(baseDir, dirs, callback) { + if (!dirs.length) { + return callback(); + } + let dir = dirs.shift(); + dir = path.join(baseDir, path.join(...dir)); + fs.mkdir(dir, { recursive: true }, (err) => { + if (err && err.code !== 'EEXIST') { + return callback(err); + } + createDirectories(baseDir, dirs, callback); + }); + } + + function extractFiles( + baseDir, + baseRelPath, + files, + callback, + extractedCount, + ) { + if (!files.length) { + return callback(null, extractedCount); + } + const file = files.shift(); + const targetPath = path.join(baseDir, file.name.replace(baseRelPath, '')); + extract(file, targetPath, (err) => { + if (err) { + return callback(err, extractedCount); + } + extractFiles(baseDir, baseRelPath, files, callback, extractedCount + 1); + }); + } + + this.extract = function (entry, outPath, callback, filter) { + let entryName = entry || ''; + if (typeof entry === 'string') { + entry = this.entry(entry); + if (entry) { + entryName = entry.name; + } else { + if (entryName.length && entryName[entryName.length - 1] !== '/') { + entryName += '/'; + } + } + } + if (!entry || entry.isDirectory) { + const files = [], + dirs = [], + allDirs = {}; + for (const e in entries) { + if ( + Object.prototype.hasOwnProperty.call(entries, e) && + e.lastIndexOf(entryName, 0) === 0 + ) { + let relPath = e.replace(entryName, ''); + const childEntry = entries[e]; + if (filter && !filter(childEntry)) continue; + if (childEntry.isFile) { + files.push(childEntry); + relPath = path.dirname(relPath); + } + if (relPath && !allDirs[relPath] && relPath !== '.') { + allDirs[relPath] = true; + let parts = relPath.split('/').filter((f) => { + return f; + }); + if (parts.length) { + dirs.push(parts); + } + while (parts.length > 1) { + parts = parts.slice(0, parts.length - 1); + const partsPath = parts.join('/'); + if (allDirs[partsPath] || partsPath === '.') { + break; + } + allDirs[partsPath] = true; + dirs.push(parts); + } + } + } + } + dirs.sort((x, y) => { + return x.length - y.length; + }); + if (dirs.length) { + createDirectories(outPath, dirs, (err) => { + if (err) { + callback(err); + } else { + extractFiles(outPath, entryName, files, callback, 0); + } + }); + } else { + extractFiles(outPath, entryName, files, callback, 0); + } + } else { + fs.stat(outPath, (err, stat) => { + if (stat && stat.isDirectory()) { + extract( + entry, + path.join(outPath, path.basename(entry.name)), + callback, + ); + } else { + extract(entry, outPath, callback); + } + }); + } + }; + + this.close = function (callback) { + if (closed || !fd || (BufRead === BufRead && !(fd = null))) { + closed = true; + if (callback) { + callback(); + } + } else { + closed = true; + fs.close(fd, (err) => { + fd = null; + if (callback) { + callback(err); + } + }); + } + }; + + const originalEmit = events.EventEmitter.prototype.emit; + this.emit = function (...args) { + if (!closed) { + return originalEmit.call(this, ...args); + } + }; + } +} + +class CentralDirectoryHeader { + read(data) { + if ( + data.length !== consts.ENDHDR || + data.readUInt32LE(0) !== consts.ENDSIG + ) { + throw new Error('Invalid central directory'); + } + // number of entries on this volume + this.volumeEntries = data.readUInt16LE(consts.ENDSUB); + // total number of entries + this.totalEntries = data.readUInt16LE(consts.ENDTOT); + // central directory size in bytes + this.size = data.readUInt32LE(consts.ENDSIZ); + // offset of first CEN header + this.offset = data.readUInt32LE(consts.ENDOFF); + // zip file comment length + this.commentLength = data.readUInt16LE(consts.ENDCOM); + } +} + +class CentralDirectoryLoc64Header { + read(data) { + if ( + data.length !== consts.ENDL64HDR || + data.readUInt32LE(0) !== consts.ENDL64SIG + ) { + throw new Error('Invalid zip64 central directory locator'); + } + // ZIP64 EOCD header offset + this.headerOffset = readUInt64LE(data, consts.ENDSUB); + } +} + +class CentralDirectoryZip64Header { + read(data) { + if ( + data.length !== consts.END64HDR || + data.readUInt32LE(0) !== consts.END64SIG + ) { + throw new Error('Invalid central directory'); + } + // number of entries on this volume + this.volumeEntries = readUInt64LE(data, consts.END64SUB); + // total number of entries + this.totalEntries = readUInt64LE(data, consts.END64TOT); + // central directory size in bytes + this.size = readUInt64LE(data, consts.END64SIZ); + // offset of first CEN header + this.offset = readUInt64LE(data, consts.END64OFF); + } +} + +class ZipEntry { + readHeader(data, offset) { + // data should be 46 bytes and start with "PK 01 02" + if ( + data.length < offset + consts.CENHDR || + data.readUInt32LE(offset) !== consts.CENSIG + ) { + throw new Error('Invalid entry header'); + } + // version made by + this.verMade = data.readUInt16LE(offset + consts.CENVEM); + // version needed to extract + this.version = data.readUInt16LE(offset + consts.CENVER); + // encrypt, decrypt flags + this.flags = data.readUInt16LE(offset + consts.CENFLG); + // compression method + this.method = data.readUInt16LE(offset + consts.CENHOW); + // modification time (2 bytes time, 2 bytes date) + const timebytes = data.readUInt16LE(offset + consts.CENTIM); + const datebytes = data.readUInt16LE(offset + consts.CENTIM + 2); + this.time = parseZipTime(timebytes, datebytes); + + // uncompressed file crc-32 value + this.crc = data.readUInt32LE(offset + consts.CENCRC); + // compressed size + this.compressedSize = data.readUInt32LE(offset + consts.CENSIZ); + // uncompressed size + this.size = data.readUInt32LE(offset + consts.CENLEN); + // filename length + this.fnameLen = data.readUInt16LE(offset + consts.CENNAM); + // extra field length + this.extraLen = data.readUInt16LE(offset + consts.CENEXT); + // file comment length + this.comLen = data.readUInt16LE(offset + consts.CENCOM); + // volume number start + this.diskStart = data.readUInt16LE(offset + consts.CENDSK); + // internal file attributes + this.inattr = data.readUInt16LE(offset + consts.CENATT); + // external file attributes + this.attr = data.readUInt32LE(offset + consts.CENATX); + // LOC header offset + this.offset = data.readUInt32LE(offset + consts.CENOFF); + } + + readDataHeader(data) { + // 30 bytes and should start with "PK\003\004" + if (data.readUInt32LE(0) !== consts.LOCSIG) { + throw new Error('Invalid local header'); + } + // version needed to extract + this.version = data.readUInt16LE(consts.LOCVER); + // general purpose bit flag + this.flags = data.readUInt16LE(consts.LOCFLG); + // compression method + this.method = data.readUInt16LE(consts.LOCHOW); + // modification time (2 bytes time ; 2 bytes date) + const timebytes = data.readUInt16LE(consts.LOCTIM); + const datebytes = data.readUInt16LE(consts.LOCTIM + 2); + this.time = parseZipTime(timebytes, datebytes); + + // uncompressed file crc-32 value + this.crc = data.readUInt32LE(consts.LOCCRC) || this.crc; + // compressed size + const compressedSize = data.readUInt32LE(consts.LOCSIZ); + if (compressedSize && compressedSize !== consts.EF_ZIP64_OR_32) { + this.compressedSize = compressedSize; + } + // uncompressed size + const size = data.readUInt32LE(consts.LOCLEN); + if (size && size !== consts.EF_ZIP64_OR_32) { + this.size = size; + } + // filename length + this.fnameLen = data.readUInt16LE(consts.LOCNAM); + // extra field length + this.extraLen = data.readUInt16LE(consts.LOCEXT); + } + + read(data, offset, textDecoder) { + const nameData = data.slice(offset, (offset += this.fnameLen)); + this.name = textDecoder + ? textDecoder.decode(new Uint8Array(nameData)) + : nameData.toString('utf8'); + const lastChar = data[offset - 1]; + this.isDirectory = lastChar === 47 || lastChar === 92; + + if (this.extraLen) { + this.readExtra(data, offset); + offset += this.extraLen; + } + this.comment = this.comLen + ? data.slice(offset, offset + this.comLen).toString() + : null; + } + + validateName() { + if (/\\|^\w+:|^\/|(^|\/)\.\.(\/|$)/.test(this.name)) { + throw new Error('Malicious entry: ' + this.name); + } + } + + readExtra(data, offset) { + let signature, size; + const maxPos = offset + this.extraLen; + while (offset < maxPos) { + signature = data.readUInt16LE(offset); + offset += 2; + size = data.readUInt16LE(offset); + offset += 2; + if (consts.ID_ZIP64 === signature) { + this.parseZip64Extra(data, offset, size); + } + offset += size; + } + } + + parseZip64Extra(data, offset, length) { + if (length >= 8 && this.size === consts.EF_ZIP64_OR_32) { + this.size = readUInt64LE(data, offset); + offset += 8; + length -= 8; + } + if (length >= 8 && this.compressedSize === consts.EF_ZIP64_OR_32) { + this.compressedSize = readUInt64LE(data, offset); + offset += 8; + length -= 8; + } + if (length >= 8 && this.offset === consts.EF_ZIP64_OR_32) { + this.offset = readUInt64LE(data, offset); + offset += 8; + length -= 8; + } + if (length >= 4 && this.diskStart === consts.EF_ZIP64_OR_16) { + this.diskStart = data.readUInt32LE(offset); + // offset += 4; length -= 4; + } + } + + get encrypted() { + return (this.flags & consts.FLG_ENTRY_ENC) === consts.FLG_ENTRY_ENC; + } + + get isFile() { + return !this.isDirectory; + } +} + +class BufRead { + constructor(fd, buffer, offset, length, position, callback) { + /** @type Buffer */ + this.fd = fd; + this.buffer = buffer; + this.offset = offset; + this.length = length; + this.position = position; + this.callback = callback; + this.bytesRead = 0; + this.waiting = false; + } + + read(sync) { + this.waiting = true; + let err; + let bytesRead = this.fd.copy( + this.buffer, + this.offset + this.bytesRead, + this.position + this.bytesRead, + ); + this.readCallback(sync, err, !sync || err ? bytesRead : null); + } + + readCallback(sync, err, bytesRead) { + if (typeof bytesRead === 'number') { + this.bytesRead += bytesRead; + } + if (err || !bytesRead || this.bytesRead === this.length) { + this.waiting = false; + return this.callback(err, this.bytesRead); + } else { + this.read(sync); + } + } +} + +class FileWindowBuffer { + constructor(fd) { + this.position = 0; + this.buffer = Buffer.alloc(0); + this.fd = fd; + this.fsOp = null; + } + + checkOp() { + if (this.fsOp && this.fsOp.waiting) { + throw new Error('Operation in progress'); + } + } + + read(pos, length, callback) { + this.checkOp(); + if (this.buffer.length < length) { + this.buffer = Buffer.alloc(length); + } + this.position = pos; + this.fsOp = new BufRead( + this.fd, + this.buffer, + 0, + length, + this.position, + callback, + ).read(); + } + + expandLeft(length, callback) { + this.checkOp(); + this.buffer = Buffer.concat([Buffer.alloc(length), this.buffer]); + this.position -= length; + if (this.position < 0) { + this.position = 0; + } + this.fsOp = new BufRead( + this.fd, + this.buffer, + 0, + length, + this.position, + callback, + ).read(); + } + + expandRight(length, callback) { + this.checkOp(); + const offset = this.buffer.length; + this.buffer = Buffer.concat([this.buffer, Buffer.alloc(length)]); + this.fsOp = new BufRead( + this.fd, + this.buffer, + offset, + length, + this.position + offset, + callback, + ).read(); + } + + moveRight(length, callback, shift) { + this.checkOp(); + if (shift) { + this.buffer.copy(this.buffer, 0, shift); + } else { + shift = 0; + } + this.position += shift; + this.fsOp = new BufRead( + this.fd, + this.buffer, + this.buffer.length - shift, + shift, + this.position + this.buffer.length - shift, + callback, + ).read(); + } +} + +class EntryDataReaderStream extends stream.Readable { + constructor(fd, offset, length) { + super(); + this.fd = fd; + this.offset = offset; + this.length = length; + this.pos = 0; + } + + _read(n) { + const buffer = Buffer.alloc(Math.min(n, this.length - this.pos)); + if (buffer.length) { + this.readCallback( + undefined, + this.fd.copy(buffer, 0, this.offset + this.pos), + buffer, + ); + } else { + this.push(null); + } + } + + readCallback(err, bytesRead, buffer) { + this.pos += bytesRead; + if (err) { + this.emit('error', err); + this.push(null); + } else if (!bytesRead) { + this.push(null); + } else { + if (bytesRead !== buffer.length) { + buffer = buffer.slice(0, bytesRead); + } + this.push(buffer); + } + } +} + +class EntryVerifyStream extends stream.Transform { + constructor(baseStm, crc, size) { + super(); + this.verify = new CrcVerify(crc, size); + baseStm.on('error', (e) => { + this.emit('error', e); + }); + } + + _transform(data, encoding, callback) { + let err; + try { + this.verify.data(data); + } catch (e) { + err = e; + } + callback(err, data); + } +} + +class CrcVerify { + constructor(crc, size) { + this.crc = crc; + this.size = size; + this.state = { + crc: ~0, + size: 0, + }; + } + + data(data) { + const crcTable = CrcVerify.getCrcTable(); + let crc = this.state.crc; + let off = 0; + let len = data.length; + while (--len >= 0) { + crc = crcTable[(crc ^ data[off++]) & 0xff] ^ (crc >>> 8); + } + this.state.crc = crc; + this.state.size += data.length; + if (this.state.size >= this.size) { + const buf = Buffer.alloc(4); + buf.writeInt32LE(~this.state.crc & 0xffffffff, 0); + crc = buf.readUInt32LE(0); + if (crc !== this.crc) { + throw new Error('Invalid CRC'); + } + if (this.state.size !== this.size) { + throw new Error('Invalid size'); + } + } + } + + static getCrcTable() { + let crcTable = CrcVerify.crcTable; + if (!crcTable) { + CrcVerify.crcTable = crcTable = []; + const b = Buffer.alloc(4); + for (let n = 0; n < 256; n++) { + let c = n; + for (let k = 8; --k >= 0; ) { + if ((c & 1) !== 0) { + c = 0xedb88320 ^ (c >>> 1); + } else { + c = c >>> 1; + } + } + if (c < 0) { + b.writeInt32LE(c, 0); + c = b.readUInt32LE(0); + } + crcTable[n] = c; + } + } + return crcTable; + } +} + +function parseZipTime(timebytes, datebytes) { + const timebits = toBits(timebytes, 16); + const datebits = toBits(datebytes, 16); + + const mt = { + h: parseInt(timebits.slice(0, 5).join(''), 2), + m: parseInt(timebits.slice(5, 11).join(''), 2), + s: parseInt(timebits.slice(11, 16).join(''), 2) * 2, + Y: parseInt(datebits.slice(0, 7).join(''), 2) + 1980, + M: parseInt(datebits.slice(7, 11).join(''), 2), + D: parseInt(datebits.slice(11, 16).join(''), 2), + }; + const dt_str = + [mt.Y, mt.M, mt.D].join('-') + + ' ' + + [mt.h, mt.m, mt.s].join(':') + + ' GMT+0'; + return new Date(dt_str).getTime(); +} + +function toBits(dec, size) { + let b = (dec >>> 0).toString(2); + while (b.length < size) { + b = '0' + b; + } + return b.split(''); +} + +function readUInt64LE(buffer, offset) { + return ( + buffer.readUInt32LE(offset + 4) * 0x0000000100000000 + + buffer.readUInt32LE(offset) + ); +} + +const https = require('https'); +function https_request(url, data, headers) { + return new Promise((resolve, reject) => { + let req = https.request( + url, + { method: data ? 'POST' : 'GET', headers }, + (msg) => { + let body = Buffer.alloc(0); + let isgzip = msg.headers['content-encoding'] === 'gzip'; + msg.on('data', (chunk) => (body = Buffer.concat([body, chunk]))); + msg.on('end', () => { + if (isgzip) + zlib.gunzip(body, (err, buf) => resolve(err ? body : buf)); + else resolve(body); + }); + }, + ); + data && req.write(data); + req.end(); + req.on('error', (err) => reject(err)); + req.on('timeout', () => reject('timeout')); + }); +} + +function get_latest_ahk2lsp() { + https_request( + 'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery', + '{"assetTypes":null,"filters":[{"criteria":[{"filterType":7,"value":"thqby.vscode-autohotkey2-lsp"}],"direction":2,"pageSize":100,"pageNumber":1,"sortBy":0,"sortOrder":0,"pagingToken":null}],"flags":2151}', + { + 'content-type': 'application/json', + accept: 'application/json;api-version=7.1-preview.1;excludeUrls=true', + }, + ) + .catch((err) => console.error(err)) + .then((info) => { + let ext = JSON.parse(info).results[0].extensions[0].versions[0]; + let version = ext.version; + fs.readFile('./package.json', (err, buf) => { + let update = !buf; + if (buf) { + try { + let curver = JSON.parse(buf).version.split('.'), + ver = version.split('.'); + for (let n in curver) { + if (parseInt(curver[n]) < parseInt(ver[n])) { + update = true; + break; + } + } + } catch (e) { + update = true; + } + } + if (update) download_ahk2lsp(); + else + console.log( + `thqby.vscode-autohotkey2-lsp v${version} is the latest version.`, + ); + + function download_ahk2lsp(url) { + https_request( + url ?? + `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/thqby/vsextensions/vscode-autohotkey2-lsp/${version}/vspackage`, + ) + .then((buffer) => { + if (buffer[0] === 123) { + if (!url) { + for (let f of ext.files) + if (f.assetType.endsWith('.VSIXPackage')) + return download_ahk2lsp(f.source); + } + return console.error(buffer.toString()); + } + let zip = new StreamZip({ buffer }); + let extract_count = 0, + has_extract_count = 0; + zip.on('ready', () => + zip.extract( + 'extension/', + './', + (err) => err && console.error(err), + (entry) => { + let name = entry.name.toLowerCase(); + if (name.includes('/client/') || name.includes('/browser')) + return false; + if ( + name.endsWith('/ahk2.configuration.json') || + name.endsWith('.png') || + name.endsWith('.tmlanguage.json') + ) + return false; + extract_count++; + return true; + }, + ), + ); + zip.on('error', (err) => console.error(err)); + zip.on('extract', (entry, outPath) => { + if (++has_extract_count === extract_count) + console.log( + `thqby.vscode-autohotkey2-lsp v${version} has been installed.`, + ); + }); + }) + .catch((err) => console.error(err)); + } + }); + }); +} + +get_latest_ahk2lsp(); diff --git a/util/src/env.ts b/util/src/env.ts index b9a644b2..356dfc2b 100644 --- a/util/src/env.ts +++ b/util/src/env.ts @@ -11,6 +11,8 @@ export const languageClientName = 'AHK++'; export const outputChannelName = 'AHK++'; //* Internal commands - Client-side +/** IDE context variable to enable or disable the stop command */ +export const ahkIsRunningContext = 'ahk:isRunning'; /** Prefix for commands handled by the client. These are not registered in package.json */ const clientCommandPrefix = 'ahk++.'; From 086be1dd6a5f4628954bed074829ddf309fd3823 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 12 Oct 2024 04:17:14 -0700 Subject: [PATCH 50/60] (test) Cherry-pick thqby commit (#67) Co-authored-by: thqby <294633707@qq.com> From 9aa041f679dada6588d691201ae7006fdfd871a7 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 12 Oct 2024 04:43:52 -0700 Subject: [PATCH 51/60] Merge thqby's main branch directly (#68) Co-authored-by: thqby <294633707@qq.com> --- .../test/formatting/array_object_style.ahk | 26 +++++++++++++++++++ package-lock.json | 3 --- 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 client/src/test/formatting/array_object_style.ahk diff --git a/client/src/test/formatting/array_object_style.ahk b/client/src/test/formatting/array_object_style.ahk new file mode 100644 index 00000000..896273f9 --- /dev/null +++ b/client/src/test/formatting/array_object_style.ahk @@ -0,0 +1,26 @@ +;@format array_style: expand, object_style: expand +list := [ + { + name: 1, + age: 2 + }, + { + name: 2, + age: 3 + } +] +;@format array_style: collapse, object_style: expand +list := [{ + name: 1, + age: 2 +}, { + name: 2, + age: 3 +}] +;@format array_style: expand, object_style: collapse +list := [ + { name: 1, age: 2 }, + { name: 2, age: 3 } +] +;@format array_style: collapse, object_style: collapse +list := [{ name: 1, age: 2 }, { name: 2, age: 3 }] \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 561c1712..a50340dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1266,7 +1266,6 @@ "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-3.1.1.tgz", "integrity": "sha512-N62Ca9ElRPLUUzf7l9CeEBlLrYzFPRQq7huKk4pVW+LjIOSXfFIPudixn5QvZcz+yXDOh15IopI3K2o3y9666Q==", "dev": true, - "license": "MIT", "dependencies": { "@azure/identity": "^4.1.0", "@vscode/vsce-sign": "^2.0.0", @@ -3766,7 +3765,6 @@ "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, - "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" } @@ -3952,7 +3950,6 @@ "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", From 82b28afbadf0d052db550bb9854b3368db8e8271 Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Sat, 12 Oct 2024 04:57:57 -0700 Subject: [PATCH 52/60] Fixup package lock --- package-lock.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/package-lock.json b/package-lock.json index 195df1a9..a50340dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2316,6 +2316,19 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", From f75b53eb8b7b14e8bfd4a6ad299dd19caa8526c1 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sun, 13 Oct 2024 15:38:01 -0700 Subject: [PATCH 53/60] Exclude files even when opened (#70) --- .vscode-test.mjs | 3 +- .vscode/launch.json | 2 +- client/src/test/exclude.test.ts | 19 +++++ client/src/test/extension.test.ts | 5 +- client/src/test/utils.ts | 12 +++ e2e/.gitignore | 1 + e2e/lib.ahk | 6 ++ e2e/main.ahk | 2 + package.json | 135 +++++++++++------------------- package.nls.json | 67 +++++++-------- server/src/common.ts | 22 +++-- server/src/server.ts | 13 ++- util/src/config.ts | 8 +- util/src/env.ts | 2 +- 14 files changed, 157 insertions(+), 140 deletions(-) create mode 100644 client/src/test/exclude.test.ts create mode 100644 e2e/.gitignore create mode 100644 e2e/lib.ahk create mode 100644 e2e/main.ahk diff --git a/.vscode-test.mjs b/.vscode-test.mjs index 1fcfb459..b73f2a7d 100644 --- a/.vscode-test.mjs +++ b/.vscode-test.mjs @@ -16,9 +16,10 @@ else { export default defineConfig({ files: 'client/dist/test/**/*.test.js', + workspaceFolder: 'e2e', mocha: { failZero: true, - timeout, + timeout: 60_000, }, useInstallation: vscode_path && { fromPath: vscode_path, diff --git a/.vscode/launch.json b/.vscode/launch.json index 02b02aee..43137b6e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -46,7 +46,7 @@ "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", - "preLaunchTask": "npm: watch", + "preLaunchTask": "npm: build:e2e", "args": [ "--disable-extensions", "--extensionDevelopmentPath=${workspaceFolder}" diff --git a/client/src/test/exclude.test.ts b/client/src/test/exclude.test.ts new file mode 100644 index 00000000..d20e0606 --- /dev/null +++ b/client/src/test/exclude.test.ts @@ -0,0 +1,19 @@ +import * as assert from 'assert'; +import { LanguageClient } from 'vscode-languageclient/node'; +import { getClient } from './utils'; +import { before, test } from 'mocha'; + +let client: LanguageClient; +before(async () => { + client = (await getClient()) as LanguageClient; +}); + +// todo copy from ahkpp +test('should be running', () => { + assert.equal(client?.isRunning(), true); + // open a file + + // trigger a suggestion + + // ensure that the right files are excluded +}); diff --git a/client/src/test/extension.test.ts b/client/src/test/extension.test.ts index c0c86b41..faf8c326 100644 --- a/client/src/test/extension.test.ts +++ b/client/src/test/extension.test.ts @@ -45,12 +45,11 @@ import { readdirSync } from 'fs'; import { suite, before, test } from 'mocha'; import { serverGetContent } from '../../../util/src/env'; import { newConfig } from '../../../util/src/config'; +import { getClient } from './utils'; let client: LanguageClient; before(async () => { - client = await vscode.extensions - .getExtension('thqby.vscode-autohotkey2-lsp') - ?.activate(); + client = (await getClient()) as LanguageClient; await vscode.commands.executeCommand('workbench.action.closeAllEditors'); }); diff --git a/client/src/test/utils.ts b/client/src/test/utils.ts index d3318b63..d85db974 100644 --- a/client/src/test/utils.ts +++ b/client/src/test/utils.ts @@ -1,4 +1,5 @@ import * as vscode from 'vscode'; +import { LanguageClient } from 'vscode-languageclient/node'; /** * Shortcut for `vscode.workspace.openTextDocument(Uri.file(fileName))` @@ -11,3 +12,14 @@ export const getDocument = async (path: string): Promise => export async function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } + +let client: LanguageClient | undefined = undefined; +/** Singleton exported client to be used across test files */ +export const getClient = async () => { + if (client) return client; + client = (await vscode.extensions + .getExtension('thqby.vscode-autohotkey2-lsp') + ?.activate()) as LanguageClient; + if (!client) throw new Error('Failed to activate language client'); + return client; +} \ No newline at end of file diff --git a/e2e/.gitignore b/e2e/.gitignore new file mode 100644 index 00000000..54133502 --- /dev/null +++ b/e2e/.gitignore @@ -0,0 +1 @@ +# Keep \ No newline at end of file diff --git a/e2e/lib.ahk b/e2e/lib.ahk new file mode 100644 index 00000000..f2fd3537 --- /dev/null +++ b/e2e/lib.ahk @@ -0,0 +1,6 @@ +#Include +#Requires AutoHotkey v2.0 + +LibMsgBox() { + MsgBox("Hello from lib.ahk") +} \ No newline at end of file diff --git a/e2e/main.ahk b/e2e/main.ahk new file mode 100644 index 00000000..5bea0b35 --- /dev/null +++ b/e2e/main.ahk @@ -0,0 +1,2 @@ +#Requires AutoHotkey v2.0 + diff --git a/package.json b/package.json index cb5cde43..2b4121f3 100644 --- a/package.json +++ b/package.json @@ -217,6 +217,16 @@ }, "markdownDescription": "Learn more about [MPRESS](https://www.autohotkey.com/mpress/mpress_web.htm)" }, + "AHK++.exclude": { + "scope": "window", + "type": "array", + "default": [], + "items": { + "type": "string" + }, + "uniqueItems": true, + "markdownDescription": "%ahk++.config.exclude%" + }, "AHK++.general": { "type": "object", "properties": { @@ -432,16 +442,6 @@ "type": "string" } }, - "AHK++.v2.exclude": { - "scope": "window", - "type": "array", - "default": [], - "items": { - "type": "string" - }, - "uniqueItems": true, - "markdownDescription": "%ahk++.config.v2.file.exclude%" - }, "AHK++.v2.file": { "type": "object", "properties": { @@ -817,112 +817,79 @@ "menus": { "editor/context": [ { - "submenu": "ahk2.context", + "submenu": "ahk++.context", "group": "navigation@0" } ], - "editor/title/run": [ + "ahk++.context": [ { - "command": "ahk2.run", - "group": "navigation@0", - "when": "resourceLangId == ahk2 && shellExecutionSupported" + "command": "ahk++.runSelection", + "when": "(editorLangId == ahk || editorLangId == ahk2) && editorHasSelection" }, { - "command": "ahk2.stop", - "group": "navigation@1", - "when": "resourceLangId == ahk2 && ahk2:isRunning && shellExecutionSupported" + "command": "ahk++.run", + "key": "ctrl+f9", + "when": "editorLangId == ahk || editorLangId == ahk2" }, { - "command": "ahk2.debug.file", - "group": "navigation@2", - "when": "resourceLangId == ahk2 && shellExecutionSupported" + "command": "ahk++.stop", + "when": "ahk:isRunning" }, { - "command": "ahk2.debug.configs", - "group": "navigation@3", - "when": "resourceLangId == ahk2 && shellExecutionSupported" + "command": "ahk++.compile", + "when": "editorLangId == ahk || editorLangId == ahk2" }, { - "command": "ahk2.debug.params", - "group": "navigation@4", - "when": "resourceLangId == ahk2 && shellExecutionSupported" + "command": "ahk++.compilerGui", + "when": "editorLangId == ahk || editorLangId == ahk2" }, { - "command": "ahk2.debug.attach", - "group": "navigation@5", - "when": "resourceLangId == ahk2 && shellExecutionSupported" - } - ], - "ahk2.context": [ - { - "when": "editorLangId == ahk2 && !isWeb && editorHasSelection", - "command": "ahk2.run.selection", - "group": "navigation@0" - }, - { - "when": "editorLangId == ahk2 && !isWeb && !editorHasSelection", - "command": "ahk2.run", - "group": "navigation@0" - }, - { - "when": "editorLangId == ahk2 && !isWeb && ahk2:isRunning", - "command": "ahk2.stop", - "group": "navigation@1" - }, - { - "command": "ahk2.debug.file", - "when": "resourceLangId == ahk2 && shellExecutionSupported", - "group": "navigation@2" + "command": "ahk++.debugAttach", + "when": "editorLangId == ahk || editorLangId == ahk2" }, { - "command": "ahk2.debug.configs", - "when": "resourceLangId == ahk2 && shellExecutionSupported", - "group": "navigation@3" + "command": "ahk++.debugConfigs", + "when": "editorLangId == ahk || editorLangId == ahk2" }, { - "command": "ahk2.debug.params", - "when": "resourceLangId == ahk2 && shellExecutionSupported", - "group": "navigation@4" + "command": "ahk++.debugParams", + "when": "editorLangId == ahk || editorLangId == ahk2" }, { - "command": "ahk2.debug.attach", - "when": "resourceLangId == ahk2 && shellExecutionSupported", - "group": "navigation@5" + "when": "editorLangId == ahk2", + "command": "ahk++.addDocComment" }, { - "when": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.help", - "group": "other@0" - }, + "when": "editorLangId == ahk2", + "command": "ahk++.updateVersionInfo" + } + ], + "editor/title/run": [ { - "when": "editorLangId == ahk2 && !isWeb", - "command": "ahk2.compile", - "group": "other@1" + "command": "ahk++.run", + "group": "navigation@0", + "when": "(editorLangId == ahk || editorLangId == ahk2) && shellExecutionSupported" }, { - "when": "editorLangId == ahk2", - "command": "ahk2.generate.comment", - "group": "other@2" + "command": "ahk++.stop", + "group": "navigation@0", + "when": "ahk:isRunning" }, { - "when": "editorLangId == ahk2", - "command": "ahk2.update.versioninfo", - "group": "other@3" + "command": "ahk++.debug", + "when": "(editorLangId == ahk || editorLangId == ahk2) && config.AHK++.menu.showDebugButton" }, { - "when": "editorLangId == ahk2", - "command": "ahk2.diagnose.all", - "group": "other@4" + "command": "ahk++.debugConfigs", + "when": "(editorLangId == ahk || editorLangId == ahk2) && config.AHK++.menu.showDebugButton" }, { - "when": "editorLangId == ahk2", - "command": "ahk2.extract.symbols", - "group": "other@5" + "command": "ahk++.debugParams", + "when": "(editorLangId == ahk || editorLangId == ahk2) && config.AHK++.menu.showDebugButton" }, { - "when": "editorLangId == ahk2 && resourceScheme == file", - "command": "ahk2.set.scriptdir", - "group": "other@6" + "command": "ahk++.debugAttach", + "when": "(editorLangId == ahk || editorLangId == ahk2) && config.AHK++.menu.showDebugButton" } ] }, @@ -938,7 +905,7 @@ ], "submenus": [ { - "id": "ahk2.context", + "id": "ahk++.context", "label": "AutoHotkey v2" } ] diff --git a/package.nls.json b/package.nls.json index c9049eeb..04a9e328 100644 --- a/package.nls.json +++ b/package.nls.json @@ -1,37 +1,34 @@ { - "ahk2.actionwhenv1isdetected": "Action when v1 script is detected", - "ahk2.autolibinclude": "Provide completion and automatic include from User and Standard library, Local library", - "ahk2.commenttags": "A regular expression used to extract named tags from comments and generate module symbols", - "ahk2.compile": "Compile Script", - "ahk2.compilercmd": "Compiler command line options. If ahk2exe.exe is not specified, the default path will be used. `${execPath}` is equal to the currently selected AutoHotkey.exe", - "ahk2.completefunctionparens": "Parentheses are added to function completion when there is no `(` or `[` on the right; otherwise move the cursor to the right", - "ahk2.completioncommitcharacters": "Characters which commit auto completion, such as `.(`", - "ahk2.debug.attach": "Attach to ahk process", - "ahk2.debug.configs": "Debug ahk File using launch.json", - "ahk2.debug.file": "Debug ahk File", - "ahk2.debug.params": "Debug ahk File with Params", - "ahk2.debugconfiguration": "Append debugging configuration to the currently started debugger, same as launch.json configuration", - "ahk2.description": "Autohotkey2 Language Support using vscode-lsp", - "ahk2.diagnose.all": "Diagnostic All", - "ahk2.diagnostics.class-non-dynamic-member-check": "Check whether non-dynamic members of class exist", - "ahk2.diagnostics.paramscheck": "Check that the function call has the correct number of arguments", - "ahk2.warn.varunset": "Display warnings for each variable that has never been directly assigned or used with the reference operator", - "ahk2.warn.localsameasglobal": "Display warnings for each undeclared local variable which has the same name as a global variable", - "ahk2.warn.callwithoutparentheses": "Display warnings for each function or method call without parentheses", - "ahk2.extract.symbols": "Extract Symbol Information", - "ahk2.files.exclude": "Configure glob patterns for excluding files and folders when scanning ahk files.", - "ahk2.files.scanmaxdepth": "Controls the depth when scanning ahk files.", - "ahk2.generate.comment": "Generate Comment Template", - "ahk2.help": "Quick Help", - "ahk2.interpreterpath": "The path of the `AutoHotkey.exe` executable file. If `AutoHotkeyUX.exe` is selected, the script will be launched using UX Launcher.", - "ahk2.run": "Run ahk File", - "ahk2.run.selection": "Run Selected Script", - "ahk2.select.syntaxes": "Select Language Definition Folder", - "ahk2.set.interpreter": "Select AutoHotkey2 Interpreter", - "ahk2.set.scriptdir": "Set Here as A_ScriptDir", - "ahk2.stop": "Stop Running Script", - "ahk2.symbolfoldingfromopenbrace": "Forced symbol folding starts at open brace", - "ahk2.syntaxes": "Specifies the folder path to the `ahk2.json`, `*.snippet.json` and `ahk2.d.ahk` files used for IntelliSense.", - "ahk2.update.versioninfo": "Update File Version Info", - "ahk2.workingdirs": "Sets the working directory for the script" + "ahk++.command.addDocComment": "Add Doc Comment", + "ahk++.command.debugAttach": "Debug AHK and Attach", + "ahk++.command.debugConfigs": "Debug Configurations", + "ahk++.command.debugParams": "Debug AHK with Params", + "ahk++.command.diagnostic.full": "Run AHK++ Diagnostic", + "ahk++.command.exportSymbols": "Export AHK Symbols", + "ahk++.command.run": "Run AHK Script", + "ahk++.command.runSelection": "Run Selection", + "ahk++.command.setAScriptDir": "Set A_ScriptDir Here", + "ahk++.command.setV2Interpreter": "Set AHK v2 Interpreter", + "ahk++.command.stop": "Stop AHK Script", + "ahk++.command.updateVersionInfo": "Update File Version Info", + "ahk++.config.general.showOutput": "Automatically show output view when running a script. View can always be toggled with F1 > 'View: Toggle Output' (`Ctrl+Shift+U`)", + "ahk++.config.general.showOutput.always": "Always open the output view when running a script", + "ahk++.config.general.showOutput.never": "Never automatically show the output view", + "ahk++.config.v2.actionWhenV1Detected": "Action when v1 script is detected", + "ahk++.config.v2.commentTagRegex": "The regular expression for custom symbols to appear in the breadcrumb and elsewhere. Default matches any line that starts with `;;`. Changes take effect after restart.", + "ahk++.config.v2.completionCommitCharacters": "Characters which commit auto-completion", + "ahk++.config.v2.completeFunctionCalls": "Whether to automatically add parenetheses when calling a function", + "ahk++.config.v2.debugConfiguration": "The [launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) to use when debugging", + "ahk++.config.v2.diagnostics.classNonDynamicMemberCheck": "Check whether non-dynamic members of a class exist", + "ahk++.config.v2.diagnostics.paramsCheck": "Check that the function call has the correct number of arguments", + "ahk++.config.v2.file.interpreterPath": "Path to the `AutoHotkey.exe` executable file for AHK v2.", + "ahk++.config.exclude": "⚠️ Not yet supported, ref [issue #488](https://github.com/mark-wiemer-org/ahkpp/issues/488).\n\nGlob patterns for excluding files and folders when scanning AHK files.", + "ahk++.config.v2.file.maxScanDepth": "Depth of folders to scan for IntelliSense. Negative values mean infinite depth.", + "ahk++.config.v2.librarySuggestions": "Which libraries to suggest functions from, if any. In case of issues, restart your IDE.", + "ahk++.config.v2.symbolFoldingFromOpenBrace": "Fold parameter lists separately from definitions.", + "ahk++.config.v2.syntaxes": "Path to the ahk2.json, ahk2.d.ahk, and *.snippet.json files used by IntelliSense.", + "ahk++.config.v2.warn.callWithoutParentheses": "Display warnings for each function or method call without parentheses. Changes take effect after restart.", + "ahk++.config.v2.warn.localSameAsGlobal": "Display warnings for each undeclared local variable that has the same name as a global variable. Changes take effect after restart.", + "ahk++.config.v2.warn.varUnset": "Display a warning when referencing an unassigned variable. Changes take effect after restart.", + "ahk++.config.v2.workingDirectories": "The directories containing referenced AHK files" } diff --git a/server/src/common.ts b/server/src/common.ts index 59ffca51..aed558ee 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -339,11 +339,11 @@ export function loadAHK2(filename = 'ahk2', d = 3) { } } - -let scanExclude: { file?: RegExp[], folder?: RegExp[] } = {}; -export function enum_ahkfiles(dirpath: string) { +interface ScanExclude { file?: RegExp[], folder?: RegExp[] }; +export let globalScanExclude: ScanExclude = {}; +export function enum_ahkfiles(dirpath: string, localScanExclude: ScanExclude = globalScanExclude): AsyncGenerator { const maxScanDepth = getCfg(CfgKey.MaxScanDepth); - const { file: fileExclude, folder: folderExclude } = scanExclude; + const { file: fileExclude, folder: folderExclude } = localScanExclude; return enumfile(restorePath(dirpath), 0); async function* enumfile(dirpath: string, depth: number): AsyncGenerator { try { @@ -386,7 +386,7 @@ export function updateConfig(newConfig: AHKLSConfig): void { (dir = URI.file(dir.includes(':') ? dir : resolve(dir)).toString().toLowerCase()) .endsWith('/') ? dir : dir + '/'), newConfig); else setCfg(CfgKey.WorkingDirectories, [], newConfig); - scanExclude = {}; + globalScanExclude = {}; if (getCfg(CfgKey.Exclude, newConfig)) { const file: RegExp[] = [], folder: RegExp[] = []; for (const s of getCfg(CfgKey.Exclude, newConfig)) @@ -395,10 +395,14 @@ export function updateConfig(newConfig: AHKLSConfig): void { } catch (e) { console.log(`[Error] Invalid glob pattern: ${s}`); } - if (file.length) - scanExclude.file = file; - if (folder.length) - scanExclude.folder = folder; + if (file.length) { + globalScanExclude.file = file; + } + if (folder.length) { + globalScanExclude.folder = folder; + } + console.log(`Excluded files: ${globalScanExclude.file?.map(re => re.source).join('\n') ?? '(none)'}`); + console.log(`Excluded folders: ${globalScanExclude.folder?.map(re => re.source).join('\n') ?? '(none)'}`); let maxScanDepth = getCfg(CfgKey.MaxScanDepth, newConfig); if (maxScanDepth === undefined) { maxScanDepth = 2; diff --git a/server/src/server.ts b/server/src/server.ts index 9c4dd5c2..076a807b 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -19,7 +19,8 @@ import { parse_include, prepareRename, rangeFormatting, read_ahk_file, referenceProvider, renameProvider, SemanticTokenModifiers, semanticTokensOnFull, semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, setInterpreterPath, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, setting, signatureProvider, sleep, symbolProvider, - traverse_include, typeFormatting, updateConfig, utils, winapis, workspaceSymbolProvider + traverse_include, typeFormatting, updateConfig, utils, winapis, workspaceSymbolProvider, + globalScanExclude } from './common'; import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; import { resolvePath, runscript } from './scriptrunner'; @@ -198,11 +199,19 @@ connection.onDidChangeWatchedFiles((change) => { }); documents.onDidOpen(e => { + console.log(`Document opened: ${e.document.uri}`); const to_ahk2 = uri_switch_to_ahk2 === e.document.uri; const uri = e.document.uri.toLowerCase(); let lexer = lexers[uri]; + // don't add excluded documents + if (globalScanExclude.file?.some(re => re.test(e.document.uri))) { + console.log(`Skipping: ${e.document.uri}`); + return; + } if (lexer) lexer.document = e.document; - else lexers[uri] = lexer = new Lexer(e.document); + else { + lexers[uri] = lexer = new Lexer(e.document); + } Object.defineProperty(lexer.include, '', { value: '', enumerable: false }); lexer.actived = true; if (to_ahk2) diff --git a/util/src/config.ts b/util/src/config.ts index 621a5309..e9144d75 100644 --- a/util/src/config.ts +++ b/util/src/config.ts @@ -12,7 +12,7 @@ export enum CfgKey { CompleteFunctionCalls = 'v2.general.completeFunctionCalls', CompletionCommitCharacters = 'v2.completionCommitCharacters', DebugConfiguration = 'DebugConfiguration', - Exclude = 'v2.exclude', + Exclude = 'exclude', ExtensionUri = 'extensionUri', Formatter = 'v2.formatter', IgnoreComment = 'v2.formatter.ignoreComment', @@ -104,6 +104,8 @@ export interface CompletionCommitCharacters { /** Matches the contributed extension configuration in package.json */ export interface AHKLSConfig { + /** Glob pattern of files to ignore */ + exclude: string[]; v2: { general: { actionWhenV1Detected: ActionType; @@ -121,8 +123,6 @@ export interface AHKLSConfig { classNonDynamicMemberCheck: boolean; paramsCheck: boolean; }; - /** Glob pattern of files to ignore */ - exclude: string[]; file: { /** Path to the AHK v2 intepreter */ interpreterPath: string; @@ -179,6 +179,7 @@ export const newFormatOptions = ( /** Defaults according to package.json */ export const newConfig = (config: Partial = {}): AHKLSConfig => ({ + exclude: [], v2: { general: { actionWhenV1Detected: 'SwitchToV1', @@ -196,7 +197,6 @@ export const newConfig = (config: Partial = {}): AHKLSConfig => ({ classNonDynamicMemberCheck: true, paramsCheck: true, }, - exclude: [], file: { interpreterPath: 'C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey.exe', maxScanDepth: 2, diff --git a/util/src/env.ts b/util/src/env.ts index 356dfc2b..b5d03dcb 100644 --- a/util/src/env.ts +++ b/util/src/env.ts @@ -8,7 +8,7 @@ export const languageClientId = 'AHK++'; export const languageClientName = 'AHK++'; /** Name of the output channel for debugging information, displayed to users */ -export const outputChannelName = 'AHK++'; +export const outputChannelName = 'AHK++ (v2)'; //* Internal commands - Client-side /** IDE context variable to enable or disable the stop command */ From d5a3f83e88d624eb2cd0ec06cc99b36e8855cd8a Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Tue, 15 Oct 2024 22:39:55 -0700 Subject: [PATCH 54/60] Respect exclude without requiring restart (#71) --- .vscode/dev.code-snippets | 38 ++++++++++++++++++ package.json | 2 +- package.nls.json | 2 +- server/src/common.ts | 29 +++++++------- server/src/completionProvider.ts | 67 +++++++++++++++++++++----------- server/src/lexer.ts | 2 + server/src/server.ts | 18 +++++---- util/src/config.ts | 1 + util/src/exclude.spec.ts | 33 ++++++++++++++++ util/src/exclude.ts | 27 +++++++++++++ 10 files changed, 173 insertions(+), 46 deletions(-) create mode 100644 .vscode/dev.code-snippets create mode 100644 util/src/exclude.spec.ts create mode 100644 util/src/exclude.ts diff --git a/.vscode/dev.code-snippets b/.vscode/dev.code-snippets new file mode 100644 index 00000000..fba3904a --- /dev/null +++ b/.vscode/dev.code-snippets @@ -0,0 +1,38 @@ +{ + // Place ahk2-lsp workspace snippets here. + // Each snippet is defined under a snippet name and has a scope, prefix, body and description. + // Add comma-separated IDs of the languages where the snippet is applicable in the scope field. + // If scope is left empty or omitted, the snippet gets applied to all languages. + // The prefix is what is used to trigger the snippet and the body will be expanded and inserted. + // Possible variables are: $1, $2 for tab stops, $0 for the final cursor position, + // and ${1:label}, ${2:another} for placeholders. + // Placeholders with the same IDs are connected. + // Example: + // "Print to console": { + // "scope": "javascript,typescript", + // "prefix": "log", + // "body": [ + // "console.log('$1');", + // "$2" + // ], + // "description": "Log output to console" + // } + "Mocha tuple tests": { + "scope": "javascript,typescript", + "prefix": "suite", + "body": [ + "suite('$1', () => {", + " const tests: [", + " name: string,", + " args: Parameters,", + " expected: ReturnType,", + " ][] = [$0];", + + " tests.forEach(([name, args, expected]) =>", + " test(name, () => assert.strictEqual($1(...args), expected)),", + " );", + "});", + ], + "description": "Generate tests for Mocha.", + }, +} diff --git a/package.json b/package.json index 2b4121f3..25e98ace 100644 --- a/package.json +++ b/package.json @@ -186,7 +186,7 @@ ], "configuration": { "type": "object", - "title": "AHK++ (AutoHotkey Plus Plus)", + "title": "AHK++ v2 support", "properties": { "AHK++.compiler": { "type": "object", diff --git a/package.nls.json b/package.nls.json index 04a9e328..35ec2722 100644 --- a/package.nls.json +++ b/package.nls.json @@ -22,7 +22,7 @@ "ahk++.config.v2.diagnostics.classNonDynamicMemberCheck": "Check whether non-dynamic members of a class exist", "ahk++.config.v2.diagnostics.paramsCheck": "Check that the function call has the correct number of arguments", "ahk++.config.v2.file.interpreterPath": "Path to the `AutoHotkey.exe` executable file for AHK v2.", - "ahk++.config.exclude": "⚠️ Not yet supported, ref [issue #488](https://github.com/mark-wiemer-org/ahkpp/issues/488).\n\nGlob patterns for excluding files and folders when scanning AHK files.", + "ahk++.config.exclude": "[Glob patterns]() for excluding files and folders from completion suggestions. Applies even when files are opened.", "ahk++.config.v2.file.maxScanDepth": "Depth of folders to scan for IntelliSense. Negative values mean infinite depth.", "ahk++.config.v2.librarySuggestions": "Which libraries to suggest functions from, if any. In case of issues, restart your IDE.", "ahk++.config.v2.symbolFoldingFromOpenBrace": "Fold parameter lists separately from definitions.", diff --git a/server/src/common.ts b/server/src/common.ts index aed558ee..abff61f7 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -8,6 +8,7 @@ import { AhkSymbol, Lexer, fixupFormatConfig, updateCommentTagRegex } from './le import { diagnostic } from './localize'; import { jsDocTagNames } from './constants'; import { AHKLSConfig, CfgKey, getCfg, LibIncludeType, setCfg, setConfigRoot } from '../../util/src/config'; +import { globalScanExclude, ScanExclude, shouldExclude } from '../../util/src/exclude'; export * from './codeActionProvider'; export * from './colorProvider'; export * from './commandProvider'; @@ -95,7 +96,8 @@ export function openFile(path: string, showError = true): TextDocument | undefin } } -export function openAndParse(path: string, showError = true, cache = true) { +export function openAndParse(path: string, showError = true, cache = true): Lexer | undefined { + if (shouldExclude(path)) return undefined; const td = openFile(path, showError); if (td) { const lex = new Lexer(td); @@ -190,6 +192,7 @@ export function initahk2cache() { /** Loads IntelliSense hover text */ export function loadAHK2(filename = 'ahk2', d = 3) { let path: string | undefined; + /** Path to included syntax files, with `<>` replacing the locale */ const file = `${rootdir}/syntaxes/<>/${filename}`; if (process.env.BROWSER) { const td = openFile(file + '.d.ahk'); @@ -206,7 +209,12 @@ export function loadAHK2(filename = 'ahk2', d = 3) { } else { const syntaxConfig = getCfg(CfgKey.Syntaxes); const syntaxes = syntaxConfig && existsSync(syntaxConfig) ? syntaxConfig : ''; - const file2 = syntaxes ? `${syntaxes}/<>/${filename}` : file; + /** + * Path to syntax files to load, + * either chosen by user or included with extension, + * with `<>` replacing the locale + */ + const syntaxFilesToLoad = syntaxes ? `${syntaxes}/<>/${filename}` : file; let td: TextDocument | undefined; if ((path = getfilepath('.d.ahk')) && (td = openFile(restorePath(path)))) { const doc = new Lexer(td, undefined, d); @@ -224,7 +232,7 @@ export function loadAHK2(filename = 'ahk2', d = 3) { } } function getfilepath(ext: string) { - return getlocalefilepath(file2 + ext) || (file2 !== file ? getlocalefilepath(file + ext) : undefined); + return getlocalefilepath(syntaxFilesToLoad + ext) || (syntaxFilesToLoad !== file ? getlocalefilepath(file + ext) : undefined); } } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -339,8 +347,6 @@ export function loadAHK2(filename = 'ahk2', d = 3) { } } -interface ScanExclude { file?: RegExp[], folder?: RegExp[] }; -export let globalScanExclude: ScanExclude = {}; export function enum_ahkfiles(dirpath: string, localScanExclude: ScanExclude = globalScanExclude): AsyncGenerator { const maxScanDepth = getCfg(CfgKey.MaxScanDepth); const { file: fileExclude, folder: folderExclude } = localScanExclude; @@ -386,7 +392,6 @@ export function updateConfig(newConfig: AHKLSConfig): void { (dir = URI.file(dir.includes(':') ? dir : resolve(dir)).toString().toLowerCase()) .endsWith('/') ? dir : dir + '/'), newConfig); else setCfg(CfgKey.WorkingDirectories, [], newConfig); - globalScanExclude = {}; if (getCfg(CfgKey.Exclude, newConfig)) { const file: RegExp[] = [], folder: RegExp[] = []; for (const s of getCfg(CfgKey.Exclude, newConfig)) @@ -395,14 +400,10 @@ export function updateConfig(newConfig: AHKLSConfig): void { } catch (e) { console.log(`[Error] Invalid glob pattern: ${s}`); } - if (file.length) { - globalScanExclude.file = file; - } - if (folder.length) { - globalScanExclude.folder = folder; - } - console.log(`Excluded files: ${globalScanExclude.file?.map(re => re.source).join('\n') ?? '(none)'}`); - console.log(`Excluded folders: ${globalScanExclude.folder?.map(re => re.source).join('\n') ?? '(none)'}`); + globalScanExclude.file = file; + globalScanExclude.folder = folder; + console.log(`Excluded files:\n\t${globalScanExclude.file.map(re => re.source).join('\n\t') || '(none)'}`); + console.log(`Excluded folders\n\t ${globalScanExclude.folder.map(re => re.source).join('\n\t') || '(none)'}`); let maxScanDepth = getCfg(CfgKey.MaxScanDepth, newConfig); if (maxScanDepth === undefined) { maxScanDepth = 2; diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index 910eddae..2199e457 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -13,7 +13,10 @@ import { lexers, libfuncs, make_search_re, sendAhkRequest, utils, winapis } from './common'; import { BraceStyle, CfgKey, getCfg, shouldIncludeLocalLib, shouldIncludeUserStdLib } from '../../util/src/config'; +import { shouldExclude } from '../../util/src/exclude'; +import { klona } from 'klona'; +//* comments including the pipe char | indicate where the cursor is export async function completionProvider(params: CompletionParams, _token: CancellationToken): Promise> { let { position, textDocument: { uri } } = params; const doc = lexers[uri = uri.toLowerCase()], vars: Record = {}; @@ -83,7 +86,15 @@ export async function completionProvider(params: CompletionParams, _token: Cance .map((v: any) => (v[1] = (v[1] || undefined)?.split(''), v))); // eslint-disable-next-line prefer-const let { text, word, token, range, linetext, kind, symbol } = doc.getContext(position, true); - const list = doc.relevance, { line, character } = position; + const relevantUriMaps = klona(doc.relevance), { line, character } = position; + // Exclude files according to current user settings (may have changed since extension was activated) + for (const uri in relevantUriMaps) { + if (shouldExclude(uri)) { + console.log('Excluding ' + uri + ' from completion suggestions'); + delete relevantUriMaps[uri]; + } + } + let isexpr = false, expg = make_search_re(word), offset: number; switch (token.type) { @@ -311,8 +322,8 @@ export async function completionProvider(params: CompletionParams, _token: Cance } } if (!scope) { - for (const u in list) { - for (const n in labels = lexers[u]?.labels) { + for (const uri in relevantUriMaps) { + for (const n in labels = lexers[uri]?.labels) { if (!expg.test(n)) continue; for (const it of labels[n]) { @@ -584,7 +595,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance const objs = new Set([doc.object, lexers[ahkuris.ahk2]?.object, lexers[ahkuris.ahk2_h]?.object]); // eslint-disable-next-line @typescript-eslint/no-explicit-any objs.delete(undefined as any); - for (const uri in list) + for (const uri in relevantUriMaps) objs.add(lexers[uri].object); for (const k in (temp = doc.object.property)) { const v = temp[k]; @@ -665,8 +676,8 @@ export async function completionProvider(params: CompletionParams, _token: Cance if (expg.test(l = it.name.toUpperCase()) && !at_edit_pos(it) && (!vars[l] || it.kind !== SymbolKind.Variable)) vars[l] = convertNodeCompletion(it); } - const list_arr = Object.keys(list).reverse(); - for (const uri of new Set([doc.d_uri, ...list_arr.map(p => lexers[p]?.d_uri), ...list_arr])) { + const reversedRelevantUris = Object.keys(relevantUriMaps).reverse(); + for (const uri of new Set([doc.d_uri, ...reversedRelevantUris.map(p => lexers[p]?.d_uri), ...reversedRelevantUris])) { if (!(temp = lexers[uri])) continue; const d = temp.d; @@ -696,16 +707,21 @@ export async function completionProvider(params: CompletionParams, _token: Cance let dir = doc.workspaceFolder; dir = (dir ? URI.parse(dir).fsPath : doc.scriptdir).toLowerCase(); doc.includedir.forEach((v, k) => line = k); - for (const u in libfuncs) { - if (!list[u] && (path = libfuncs[u].fsPath) && ((includeUserStdLib && libfuncs[u].islib) || + for (const uri in libfuncs) { + if (shouldExclude(uri)) { + console.log('Excluding', uri); + continue; + } + if (!relevantUriMaps[uri] && (path = libfuncs[uri].fsPath) && ((includeUserStdLib && libfuncs[uri].islib) || (includeLocalLib && path.toLowerCase().startsWith(dir)))) { - for (const it of libfuncs[u]) { - expg.test(l = it.name) && (vars[l.toUpperCase()] ??= ( - cpitem = convertNodeCompletion(it), exportnum++, - cpitem.additionalTextEdits = caches[path] ??= autoinclude(path), - cpitem.detail = `${completionitem.include(path)}\n\n${cpitem.detail ?? ''}`, - cpitem - )); + for (const it of libfuncs[uri]) { + if (expg.test(l = it.name) && !vars[l.toUpperCase()]) { + cpitem = convertNodeCompletion(it), exportnum++; + cpitem.additionalTextEdits = caches[path] ??= autoinclude(path); + cpitem.detail = `${completionitem.include(path)}\n\n${cpitem.detail ?? ''}`; + console.log(`Adding ${cpitem.label} to vars`); + vars[l.toUpperCase()] = cpitem; + }; } if (exportnum > 300) break; @@ -750,9 +766,12 @@ export async function completionProvider(params: CompletionParams, _token: Cance } } - if ((list_arr.unshift(doc.uri), !list_arr.includes(ahkuris.winapi)) && list_arr.some(u => lexers[u]?.include[ahkuris.winapi])) + if ((reversedRelevantUris.unshift(doc.uri), !reversedRelevantUris.includes(ahkuris.winapi)) && reversedRelevantUris.some(u => lexers[u]?.include[ahkuris.winapi])) for (const n in temp = lexers[ahkuris.winapi]?.declaration) - expg.test(n) && (vars[n] ??= convertNodeCompletion(temp[n])); + if (expg.test(n) && !vars[n]) { + const newValue = convertNodeCompletion(temp[n]); + vars[n] = newValue; + } // constant if (!isexpr && kind !== SymbolKind.Event) { @@ -760,7 +779,9 @@ export async function completionProvider(params: CompletionParams, _token: Cance for (const it of completionItemCache.constant) expg.test(it.label) && items.push(it); } - return items.concat(Object.values(vars) as CompletionItem[]); + const result = items.concat(Object.values(vars) as CompletionItem[]); + console.log('Vars:', (Object.values(vars) as CompletionItem[]).map(i => i.label).join('\n')); + return result; //#endregion //#region utils @@ -775,7 +796,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance function add_classes() { let t; const decls = [ahkvars, doc.declaration]; - for (const uri in list) + for (const uri in relevantUriMaps) (t = lexers[uri]) && decls.push(t.declaration); for (const decl of decls) for (const cl in decl) @@ -835,8 +856,8 @@ export async function completionProvider(params: CompletionParams, _token: Cance offset ??= doc.document.offsetAt(position); let pre = token.content.substring(1, offset - token.offset), suf = '', t; const docs = [doc], ls: Record = {}; - for (const u in list) - (t = lexers[u]) && docs.push(t); + for (const uri in relevantUriMaps) + (t = lexers[uri]) && docs.push(t); pre = pre.replace(/`(.)/g, '$1').replace(/[^\\/]+$/, m => (suf = m, '')); const expg = make_search_re(suf), kind = CompletionItemKind.Function; const range = !allIdentifierChar.test(suf) ? { @@ -898,8 +919,8 @@ export async function completionProvider(params: CompletionParams, _token: Cance } for (const t in (temp = doc.texts)) expg.test(t) && add_item(temp[t], CompletionItemKind.Text); - for (const u in list) - for (const t in (temp = lexers[u]?.texts)) + for (const uri in relevantUriMaps) + for (const t in (temp = lexers[uri]?.texts)) expg.test(t) && add_item(temp[t], CompletionItemKind.Text); } function add_item(label: string, kind: CompletionItemKind) { diff --git a/server/src/lexer.ts b/server/src/lexer.ts index 0da31df7..36bd7440 100644 --- a/server/src/lexer.ts +++ b/server/src/lexer.ts @@ -26,6 +26,7 @@ import { restorePath, rootdir, setTextDocumentLanguage, symbolProvider, utils, workspaceFolders } from './common'; import { ActionType, BlockStyle, BraceStyle, CallWithoutParentheses, CfgKey, FormatOptions, getCfg } from '../../util/src/config'; +import { shouldExclude } from '../../util/src/exclude'; export interface ParamInfo { offset: number @@ -6623,6 +6624,7 @@ export function parse_include(lex: Lexer, dir: string, _set = new Set()) { _set.add(lex); for (const uri in include) { const path = include[uri]; + if (shouldExclude(path)) continue; let lex, t; if (!(lex = lexers[uri])) { if (!existsSync(path) || !(t = openFile(restorePath(path)))) diff --git a/server/src/server.ts b/server/src/server.ts index 076a807b..5a9e2f66 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -20,13 +20,13 @@ import { semanticTokensOnFull, semanticTokensOnRange, SemanticTokenTypes, set_ahk_h, setInterpreterPath, set_Connection, set_dirname, set_locale, set_version, set_WorkspaceFolders, setting, signatureProvider, sleep, symbolProvider, traverse_include, typeFormatting, updateConfig, utils, winapis, workspaceSymbolProvider, - globalScanExclude } from './common'; import { PEFile, RESOURCE_TYPE, searchAndOpenPEFile } from './PEFile'; import { resolvePath, runscript } from './scriptrunner'; import { AHKLSConfig, CfgKey, configPrefix, getCfg, shouldIncludeUserStdLib, shouldIncludeLocalLib, setCfg } from '../../util/src/config'; import { klona } from 'klona/json'; import { clientExecuteCommand, clientUpdateStatusBar, extSetInterpreter, serverExportSymbols, serverGetAHKVersion, serverGetContent, serverGetVersionInfo, serverResetInterpreterPath } from '../../util/src/env'; +import { shouldExclude } from '../../util/src/exclude'; const languageServer = 'ahk2-language-server'; const documents = new TextDocuments(TextDocument); @@ -164,16 +164,17 @@ connection.onDidChangeConfiguration(async change => { // clone the old config to compare const oldConfig = klona(getCfg()); updateConfig(newConfig); // this updates the object in-place, hence the clone above + const excludeChanged = getCfg(CfgKey.Exclude) !== getCfg(CfgKey.Exclude, oldConfig); set_WorkspaceFolders(workspaceFolders); const newInterpreterPath = getCfg(CfgKey.InterpreterPath); if (newInterpreterPath !== getCfg(CfgKey.InterpreterPath, oldConfig)) { if (await setInterpreter(resolvePath(newInterpreterPath))) connection.sendRequest(clientUpdateStatusBar, [newInterpreterPath]); } - if (getCfg(CfgKey.LibrarySuggestions) !== getCfg(CfgKey.LibrarySuggestions, oldConfig)) { - if (shouldIncludeUserStdLib() && !shouldIncludeUserStdLib(oldConfig)) + if (excludeChanged || getCfg(CfgKey.LibrarySuggestions) !== getCfg(CfgKey.LibrarySuggestions, oldConfig)) { + if (shouldIncludeUserStdLib() && (excludeChanged || !shouldIncludeUserStdLib(oldConfig))) parseuserlibs(); - if (shouldIncludeLocalLib() && !shouldIncludeLocalLib(oldConfig)) + if (shouldIncludeLocalLib() && (excludeChanged || !shouldIncludeLocalLib(oldConfig))) documents.all().forEach(e => parseproject(e.uri.toLowerCase())); } if (getCfg(CfgKey.Syntaxes) !== getCfg(CfgKey.Syntaxes, oldConfig)) { @@ -199,15 +200,18 @@ connection.onDidChangeWatchedFiles((change) => { }); documents.onDidOpen(e => { - console.log(`Document opened: ${e.document.uri}`); const to_ahk2 = uri_switch_to_ahk2 === e.document.uri; const uri = e.document.uri.toLowerCase(); let lexer = lexers[uri]; + console.log(`Document opened: ${uri}`); + // don't add excluded documents - if (globalScanExclude.file?.some(re => re.test(e.document.uri))) { - console.log(`Skipping: ${e.document.uri}`); + if (shouldExclude(uri)) + { + console.log(`Skipping: ${uri}`); return; } + if (lexer) lexer.document = e.document; else { lexers[uri] = lexer = new Lexer(e.document); diff --git a/util/src/config.ts b/util/src/config.ts index e9144d75..422a0b97 100644 --- a/util/src/config.ts +++ b/util/src/config.ts @@ -225,6 +225,7 @@ export const configPrefix = 'AHK++'; /** * Gets a single config value from the provided config. * If no config provided, uses the global config. + * If no key provided, returns the entire config. */ export const getCfg = ( key?: CfgKey, diff --git a/util/src/exclude.spec.ts b/util/src/exclude.spec.ts new file mode 100644 index 00000000..5667c037 --- /dev/null +++ b/util/src/exclude.spec.ts @@ -0,0 +1,33 @@ +import assert from 'assert'; +import { suite, test } from 'mocha'; +import { shouldExclude } from './exclude'; + +suite('shouldExclude', () => { + const tests: [ + name: string, + args: Parameters, + expected: ReturnType, + ][] = [ + ['include file', ['file', 'all', { file: [], folder: [] }], false], + ['include folder', ['folder', 'all', { file: [], folder: [] }], false], + [ + 'exclude folder', + ['folder', 'folderOnly', { file: [], folder: [/folder/i] }], + true, + ], + ['exclude file', ['file', 'all', { file: [/file/i], folder: [] }], true], + [ + `include folder that matches file pattern`, + ['folder', 'folderOnly', { file: [/file/i], folder: [] }], + false, + ], + [ + `exclude file that matches folder pattern`, + ['folder/file', 'all', { file: [], folder: [/folder/i] }], + true, + ], + ]; + tests.forEach(([name, args, expected]) => + test(name, () => assert.strictEqual(shouldExclude(...args), expected)), + ); +}); diff --git a/util/src/exclude.ts b/util/src/exclude.ts new file mode 100644 index 00000000..2b274d25 --- /dev/null +++ b/util/src/exclude.ts @@ -0,0 +1,27 @@ +/** The regular expressions to check for exclusion */ +export interface ScanExclude { + file: RegExp[]; + folder: RegExp[]; +} + +export const globalScanExclude: ScanExclude = { file: [], folder: [] }; + +/** + * Returns whether the provided path should be excluded from scanning based on its name. + * Assumes the path is already resolved. + */ +export const shouldExclude = ( + path: string, + /** Folder only will check only the folder patterns in the provided exclude object */ + options: 'folderOnly' | 'all' = 'all', + /** The patterns to use for exclusion testing. Defaults to global patterns, matching user settings */ + exclude: ScanExclude = globalScanExclude, +): boolean => { + if (exclude.folder.some((re) => re.test(path))) { + return true; + } + if (options === 'all' && exclude.file.some((re) => re.test(path))) { + return true; + } + return false; +}; From 297742ef9d2db65985007b19603c2a0d28b3c173 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Thu, 17 Oct 2024 05:23:01 -0700 Subject: [PATCH 55/60] Improve logs, fix LibIncludeType.Disabled (#72) --- server/src/common.ts | 2 +- server/src/completionProvider.ts | 1 + server/src/server.ts | 8 ++++++++ util/src/config.ts | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/server/src/common.ts b/server/src/common.ts index abff61f7..d500f60c 100644 --- a/server/src/common.ts +++ b/server/src/common.ts @@ -403,7 +403,7 @@ export function updateConfig(newConfig: AHKLSConfig): void { globalScanExclude.file = file; globalScanExclude.folder = folder; console.log(`Excluded files:\n\t${globalScanExclude.file.map(re => re.source).join('\n\t') || '(none)'}`); - console.log(`Excluded folders\n\t ${globalScanExclude.folder.map(re => re.source).join('\n\t') || '(none)'}`); + console.log(`Excluded folders:\n\t${globalScanExclude.folder.map(re => re.source).join('\n\t') || '(none)'}`); let maxScanDepth = getCfg(CfgKey.MaxScanDepth, newConfig); if (maxScanDepth === undefined) { maxScanDepth = 2; diff --git a/server/src/completionProvider.ts b/server/src/completionProvider.ts index 2199e457..dc5fdbdc 100644 --- a/server/src/completionProvider.ts +++ b/server/src/completionProvider.ts @@ -701,6 +701,7 @@ export async function completionProvider(params: CompletionParams, _token: Cance // auto-include const includeUserStdLib = shouldIncludeUserStdLib(); const includeLocalLib = shouldIncludeLocalLib(); + console.log('includeUserStdLib:', includeUserStdLib, ', includeLocalLib:', includeLocalLib); if (includeUserStdLib || includeLocalLib) { const libdirs = doc.libdirs, caches: Record = {}; let exportnum = 0, line = -1, first_is_comment: boolean | undefined, cm: Token; diff --git a/server/src/server.ts b/server/src/server.ts index 5a9e2f66..84ffa7ca 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -155,12 +155,14 @@ connection.onInitialized(() => { connection.onDidChangeConfiguration(async change => { let newConfig: AHKLSConfig | undefined = change?.settings; + console.log('Configuration changed'); if (hasConfigurationCapability && !newConfig) newConfig = await connection.workspace.getConfiguration(configPrefix); if (!newConfig) { connection.window.showWarningMessage('Failed to obtain the configuration'); return; } + console.log('New configuration:', newConfig); // clone the old config to compare const oldConfig = klona(getCfg()); updateConfig(newConfig); // this updates the object in-place, hence the clone above @@ -175,7 +177,10 @@ connection.onDidChangeConfiguration(async change => { if (shouldIncludeUserStdLib() && (excludeChanged || !shouldIncludeUserStdLib(oldConfig))) parseuserlibs(); if (shouldIncludeLocalLib() && (excludeChanged || !shouldIncludeLocalLib(oldConfig))) + { + console.log('Parsing local libraries'); documents.all().forEach(e => parseproject(e.uri.toLowerCase())); + } } if (getCfg(CfgKey.Syntaxes) !== getCfg(CfgKey.Syntaxes, oldConfig)) { initahk2cache(), loadAHK2(); @@ -388,6 +393,8 @@ async function parseuserlibs() { uri: string, d: Lexer, t: TextDocument | undefined; + console.log('Parsing user libraries'); + console.log('Libraries:\n\t', libdirs.join('\n\t')); for (dir of libdirs) for await (path of enum_ahkfiles(dir)) { if (!libfuncs[(uri = URI.file(path).toString().toLowerCase())]) { @@ -440,6 +447,7 @@ async function setInterpreter(path: string) { } async function parseproject(uri: string) { + console.log(`Parsing project: ${uri}`); let lex = lexers[uri]; if (!lex || !uri.startsWith('file:')) return; if (!lex.d) { diff --git a/util/src/config.ts b/util/src/config.ts index 422a0b97..4f08ab64 100644 --- a/util/src/config.ts +++ b/util/src/config.ts @@ -54,7 +54,7 @@ export type ActionType = | 'Stop'; export enum LibIncludeType { - Disabled = 'Off', + Disabled = 'Disabled', Local = 'Local', UserAndStandard = 'User and Standard', All = 'All', From 234ebd1c804cd83de7462a7b6fe46015ffcb984c Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Thu, 17 Oct 2024 07:13:18 -0700 Subject: [PATCH 56/60] Add GroggyOtter syntax (#73) --- syntaxes/ahk2.d.ahk | 32408 ++++++++++++++++++++++++++++++++++++------ syntaxes/ahk2.json | 233 +- 2 files changed, 28197 insertions(+), 4444 deletions(-) diff --git a/syntaxes/ahk2.d.ahk b/syntaxes/ahk2.d.ahk index 54368c06..c8bbe94f 100644 --- a/syntaxes/ahk2.d.ahk +++ b/syntaxes/ahk2.d.ahk @@ -1,4833 +1,28585 @@ -;@region vars -; For uncompiled scripts: the full path and name of the EXE file that actually runs the current script. -; For compiled scripts: except for obtaining the AutoHotkey directory through the registry entry HKLM\SOFTWARE\AutoHotkey\InstallDir. -A_AhkPath: String - -; Contains the version number of the AutoHotkey main program running the current script, for example `1.0.22`. -; In the compiled script, it contains the version number of the main program used in the original compilation. -A_AhkVersion: String - -; It can be used to get or set whether to allow the main window of the script to be opened through the tray icon. -; For compiled scripts, this variable defaults to 0, but it can be overridden by assigning a value to this variable. Set it to 1 will activate the items under the View menu of the main window (such as'Lines most recently executed'), which allows you to view the source code and other information of the script. -; If the script is not compiled, then the value of this variable is always 1. Its attempts to make changes will be ignored. -A_AllowMainWindow: Integer - -; The full path and name of the current user's application data folder. For example: `C:\Users\\AppData\Roaming` -A_AppData: String - -; The full path and name of the application data folder for all users. For example: `C:\ProgramData` -A_AppDataCommon: String - -; Contains an array of command line parameters. -A_Args: Array - -; Can be used to get or set the contents of the system clipboard. -A_Clipboard: String - -; Contains the same string as the ComSpec variable of the environment. For example: `C:\Windows\system32\cmd.exe` -A_ComSpec: String - -; The computer name seen on the network. -A_ComputerName: String - -; It can be used to get or set the delay of the control modification function, in milliseconds. -A_ControlDelay: Integer - -; The area that can be used to get or set relative coordinates. -A_CoordModeCaret: 'Window' | 'Client' | 'Screen' - -; The area that can be used to get or set relative coordinates. -A_CoordModeMenu: 'Window' | 'Client' | 'Screen' - -; The area that can be used to get or set relative coordinates. -A_CoordModeMouse: 'Window' | 'Client' | 'Screen' - -; The area that can be used to get or set relative coordinates. -A_CoordModePixel: 'Window' | 'Client' | 'Screen' - -; The area that can be used to get or set relative coordinates. -A_CoordModeToolTip: 'Window' | 'Client' | 'Screen' - -; The currently displayed mouse cursor type. Its value is one of the following words: -; - AppStarting (program start, background running--arrow+wait) -; - Arrow(arrow, normal selection--standard cursor) -; - Cross( Cross, precise selection) -; - Help(Help, help selection--arrow+question mark) -; - IBeam(I-cursor, text selection--input) -; - Icon -; - No(No, not available--circle plus backslash) -; - Size , SizeAll (all sizes, move-four-way arrow) -; - SizeNESW (southeast and northwest size, diagonal adjustment 2-double arrows point to southeast and northwest) -; - SizeNS (north-south size, vertical adjustment-double arrows point to north and south ) -; - SizeNWSE (the size of northwest and southeast, adjust 1 along the diagonal-double arrows point to northwest and southeast) -; - SizeWE (size of east and west, adjust horizontally-double arrows point to east) -; - UpArrow (up arrow, candidates-point up Arrow) -; - Wait(Waiting, busy--hourglass or circle) -; - Unknown. The hand pointer (click and grab) belongs to the Unknown category. -A_Cursor: String - -; The day of the current month represented by 2 digits (01-31). It has the same meaning as A_MDay. -A_DD: String - -; The abbreviation of the current day of the week in the language of the current user, such as Sun -A_DDD: String - -; Use the full name of the current day of the week in the current user's language, for example, Sunday -A_DDDD: String - -; Can be used to get or set the default mouse speed, an integer from 0 (fastest) to 100 (slowest). -A_DefaultMouseSpeed: Integer - -; The full path and name of the desktop folder of the current user. For example: `C:\Users\\Desktop` -A_Desktop: String - -; The full path and name of the desktop folder of all users. For example: `C:\Users\Public\Desktop` -A_DesktopCommon: String - -; Can be used to get or set whether to detect hidden text in the window. -A_DetectHiddenText: Integer - -; Can be used to get or set whether to detect hidden windows. -A_DetectHiddenWindows: Integer - -; The user recently pressed the termination character that triggered the non-auto-replacement hotstring. -A_EndChar: String - -; Each thread retains its own A_EventInfo value. It contains additional information about the following events: -; Mouse wheel hotkey (WheelDown/Up/Left/Right) -; OnMessage -; Regular Expression Callouts -A_EventInfo: Integer - -; Can be used to get or set the default encoding of various built-in functions. -A_FileEncoding: String - -; Defines how long after pressing the hotkey it is assumed that (Alt/Ctrl/Win/Shift) is still pressed. -A_HotkeyModifierTimeout: Integer - -; The A_MaxHotkeysPerInterval and A_HotkeyInterval variables control the rate of hotkey activation, beyond which a warning dialog will be displayed. -A_HotkeyInterval: Integer - -; The current hour (00-23) represented by 2 digits in the 24-hour clock (for example, 17 for 5pm). -; To get the time in the 12-hour clock with AM/PM prompts, please refer to this example: FormatTime(,'h:mm:ss tt') -A_Hour: String - -; If a custom tray icon is specified by TraySetIcon, the value of the variable is the full path and name of the icon file, otherwise it is empty. -A_IconFile: String - -; Can be used to get or set whether to hide the tray icon. -A_IconHidden: Integer - -; If A_IconFile is empty, the value is empty. Otherwise, its value is the number of the icon in A_IconFile (usually 1). -A_IconNumber: Integer | "" - -; It can be used to get or set the tooltip text of the tray icon, which will be displayed when the mouse hovers over it. -; If it is empty, the name of the script is used. -; To create a multi-line tooltip, please click Use a newline character (`n) between each line, such as'Line1`nLine2'. -; Only the first 127 characters are displayed, and the text is truncated at the first tab (if it exists). -A_IconTip: String - -; Contains the number of current loop iterations, which can be assigned to any integer value by the script. -A_Index: Integer - -; The initial working directory of the script, determined by how it was started. -A_InitialWorkingDir: String - -; The value is 1 (true) when the operating system is 64-bit, and 0 (false) when it is 32-bit. -A_Is64bitOS: Integer - -; If the current user has administrator rights, the value of this variable is 1. Otherwise, it is 0. -A_IsAdmin: Integer - -; If the currently running script is a compiled EXE, the value of this variable is 1, -; otherwise it is an empty string (this will be regarded as false). -A_IsCompiled: Integer - -; If the Critical of the current thread is closed, the value is 0. Otherwise, -; the value is an integer greater than zero, which is the message check frequency used by Critical. -A_IsCritical: Integer - -; If the thread after the current thread is suspended, the value is 1, otherwise it is 0. -A_IsPaused: Integer - -; If the script is suspended, the value is 1, otherwise it is 0. -A_IsSuspended: Integer - -; It can be used to get or set the delay time of the button, in milliseconds. -A_KeyDelay: Integer - -; It can be used to get or set the delay time of keys sent through SendPlay mode, in milliseconds. -A_KeyDelayPlay: Integer - -; It can be used to get or set the duration of the button, in milliseconds. -A_KeyDuration: Integer - -; It can be used to get or set the duration of the button sent through SendPlay mode, in milliseconds. -A_KeyDurationPlay: Integer - -; The default language of the current system, the value is one of these 4-digit codes. -; For example, if the value of A_Language is 0436, the default language of the system is Afrikaans. -A_Language: String - -; This is usually the result of the system's GetLastError() function after the script calls certain functions (such as DllCall or Run/RunWait), or the HRESULT of the last COM object call. -A_LastError: Integer - -; The full path and name of the file that A_LineNumber belongs to. Unless the current line belongs to a #Include file of an uncompiled script, it will be the same as A_ScriptFullPath. -A_LineFile: String - -; The line number of the line being executed in the script (or its #Include file). This line number is consistent with that displayed by ListLines; it is very useful for error reporting, such as this example: MsgBox'Could not write to log file (line number 'A_LineNumber')'. -; Because the compiled script has merged all its #Include files into one large script, its line number may be different from when it is run in uncompiled mode. -A_LineNumber: Integer - -; Can be used to get or set whether to record a row. -A_ListLines: Integer - -; Exists in any parsing loop, it contains the contents of the current substring (field). -A_LoopField: String - -; The attributes of the currently retrieved file. -A_LoopFileAttrib: String - -; The path of the directory where A_LoopFileName is located. If FilePattern contains a relative path instead of an absolute path, then the path here will also be a relative path. The root directory will not contain a backslash. For example: C: -A_LoopFileDir: String - -; The extension of the file (such as TXT, DOC or EXE). Do not include the period (.). -A_LoopFileExt: String - -; This is different from A_LoopFilePath as follows: 1) It always contains the absolute/full path of the file, even if the FilePattern contains a relative path; 2) Any short (8.3) folder name in the FilePattern itself will be converted to a long file Name; 3) The characters in the FilePattern will be converted to uppercase or lowercase to match the case stored in the file system. This is for the file name - for example, the file name passed into the script as a command line parameter - is converted to the resource manager The exact path name displayed is useful. -A_LoopFileFullPath: String - -; The name of the file or folder currently retrieved (not including the path). -A_LoopFileName: String - -; The path and name of the file/folder currently retrieved. If FilePattern contains a relative path instead of an absolute path, the path here will also be a relative path. -A_LoopFilePath: String - -; The 8.3 short name of the file, or alternative name. If the file does not have a short file name (because the long file is shorter than 8.3, or perhaps because the NTFS file system disables the generation of short file names), A_LoopFileName will be retrieved. -A_LoopFileShortName: String - -; The 8.3 short path and name of the currently retrieved file/folder. For example: C:\MYDOCU~1\ADDRES~1.txt. If FilePattern contains a relative path instead of an absolute path, the path here will also be Is a relative path. -A_LoopFileShortPath: String - -; The size of the currently retrieved file, in KB, rounded down to the nearest integer. -A_LoopFileSize: Integer - -; The size of the currently retrieved file, in KB, rounded down to the nearest integer. -A_LoopFileSizeKB: Integer - -; The size of the currently retrieved file, in Mb, rounded down to the nearest integer. -A_LoopFileSizeMB: Integer - -; The last time the file was accessed. The format is YYYYMMDDHH24MISS. -A_LoopFileTimeAccessed: String - -; The time when the file was created. The format is YYYYMMDDHH24MISS. -A_LoopFileTimeCreated: String - -; The time when the file was last modified. The format is YYYYMMDDHH24MISS. -A_LoopFileTimeModified: String - -; Exists in any file reading loop, it contains the content of the current line, excluding the carriage return and the newline (`r`n) marking the end of the line. -A_LoopReadLine: String - -; Contains the full name of the key of the current loop item. For remote registry access, this value will not include the computer name. -A_LoopRegKey: String - -; The name of the item currently retrieved. It can be a value name or the name of a sub-item. -A_LoopRegName: String - -; The time when the current item or any value was last modified. The format is YYYYMMDDHH24MISS. -A_LoopRegTimeModified: String - -; The type of item currently retrieved. -A_LoopRegType: String - -; The A_MaxHotkeysPerInterval and A_HotkeyInterval variables control the rate of hotkey activation, beyond which a warning dialog will be displayed. -A_MaxHotkeysPerInterval: Integer - -; The day of the current month represented by 2 digits (01-31). -A_MDay: String - -; Control which key is used to mask Win or Alt key events. -A_MenuMaskKey: String - -; The current month represented by 2 digits (01-12). It has the same meaning as A_Mon. -A_MM: String - -; The abbreviation of the current month in the language of the current user, such as Jul -A_MMM: String - -; The full name of the current month in the language of the current user, for example July -A_MMMM: String - -; The current three-digit number of milliseconds (000-999). -A_MSec: String - -; The current minute in 2 digits (00-59). -A_Min: String - -; The current month represented by 2 digits (01-12). -A_Mon: String - -; Can be used to get or set the mouse delay, in milliseconds. -A_MouseDelay: Integer - -; It can be used to get or set the mouse delay of SendPlay, in milliseconds. -A_MouseDelayPlay: Integer - -; The full path and name of the current user's'My Documents' folder. -A_MyDocuments: String - -; The current local time in YYYYMMDDHH24MISS format. -A_Now: String - -; The current Coordinated Universal Time (UTC) in YYYYMMDDHH24MISS format. UTC is essentially the same as Greenwich Mean Time (GMT). -A_NowUTC: String - -; The version number of the operating system, in the format of'major.minor.build'. For example, Windows 7 SP1 is `6.1.7601`. -; Applying compatibility settings in the properties of the AutoHotkey executable file or compiled script will Cause the system to report a different version number, which will be reflected in A_OSVersion. -A_OSVersion: String - -; Except for saving the name of the previous hotkey, everything else is the same as above. It will be empty if there is no one. -A_PriorHotkey: String - -; The name of the last key pressed before the most recent key-press or key-release. If no suitable key is found in the key history-it will be empty. Does not include generated by AutoHotkey script To use this variable, you must first install a keyboard or mouse hook and enable key history. -A_PriorKey: String - -; Program Files directory (e.g. `C:\Program Files` or `C:\Program Files (x86)`). This is usually the same as the ProgramFiles environment variable. -A_ProgramFiles: String - -; The full path and name of the program folder in the start menu of the current user. For example: `C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs` -A_Programs: String - -; The full path and name of the program folder in the start menu of all users. For example: `C:\ProgramData\Microsoft\Windows\Start Menu\Programs` -A_ProgramsCommon: String - -; Contains the size value of the pointer, in bytes. The value is 4 (32-bit) or 8 (64-bit), depending on the type of executor running the current script. -A_PtrSize: 4 | 8 - -; Can be used to get or set the registry view. -A_RegView: '32' | '64' | 'Default' - -; The number of pixels per logical inch of screen width. In a system with multiple display monitors, this value is the same for all monitors. -A_ScreenDPI: Integer - -; The height of the main monitor, in pixels -A_ScreenHeight: Integer - -; The width of the main monitor, in pixels -A_ScreenWidth: Integer - -; The full path of the directory where the current script is located. Does not include the final backslash (the same is true for the root directory). -; If the script text is read from standard input instead of from a file, variable The value is the initial working directory. -A_ScriptDir: String - -; The full path of the current script, for example C:\My Documents\My Script.ahk -; If the script text is read from standard input instead of from the file, the value is'* '. -A_ScriptFullPath: String - -; The unique ID (HWND/handle) of the script's main window (hidden). -A_ScriptHwnd: Integer - -; It can be used to get or set the default title of MsgBox, InputBox, FileSelect, DirSelect and Gui.New. If the script is not set, it defaults to the file name of the current script, excluding the path, such as MyScript.ahk. -A_ScriptName: String - -; The current second in 2 digits (00-59). -A_Sec: String - -; Can be used to get or set the sending level, an integer between 0 and 100, including 0 and 100. -A_SendLevel: Integer - -; Can be used to get or set the sending mode. -A_SendMode: 'Event' | 'Input' | 'Play' | 'InputThenPlay' - -; Contains a single space character. -A_Space: ' ' - -; The full path and name of the start menu folder of the current user. For example: `C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu` -A_StartMenu: String - -; The full path and name of the start menu folder for all users. For example: `C:\ProgramData\Microsoft\Windows\Start Menu` -A_StartMenuCommon: String - -; The full path and name of the startup folder in the start menu of the current user. For example: `C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup` -A_Startup: String - -; The full path and name of the startup folder in the start menu of all users. For example: `C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup` -A_StartupCommon: String - -; Can be used to get or set whether to restore the state of CapsLock after Send. -A_StoreCapsLockMode: Integer - -; Contains a single tab character. -A_Tab: '`t' - -; The full path and name of the folder where temporary files are stored. Its value is retrieved from one of the following locations (in order): 1) Environment variable TMP, TEMP or USERPROFILE; 2) Windows directory. For example: `C:\Users\\AppData\Local\Temp` -A_Temp: String - -; The name of the custom function currently being executed (empty if none); For example: MyFunction. -A_ThisFunc: String - -; The most recently executed hotkey or non-auto-replacement hotstring (empty if there is none), such as #z. If the current thread is interrupted by other hotkeys or hotstrings, then the value of this variable will change, So in general, it is best to use the ThisHotkey parameter. -A_ThisHotkey: String - -; The number of milliseconds that have elapsed since the computer was started, up to 49.7 days. By saving A_TickCount to a variable, and after a period of time, subtracting that variable from the latest A_TickCount value, the elapsed time can be calculated. -A_TickCount: Integer - -; The number of milliseconds since the last time the system received keyboard, mouse or other input. This can be used to determine whether the user has left. The user's physical input and analog input generated by any program or script (such as Send Or MouseMove function) will reset this variable to zero. -A_TimeIdle: Integer - -; If the keyboard hook is installed, this is the number of milliseconds that have passed since the system last received physical keyboard input. Otherwise, this variable is equal to A_TimeIdle. -A_TimeIdleKeyboard: Integer - -; If the mouse hook is installed, this is the number of milliseconds that have passed since the system last received physical mouse input. Otherwise, this variable is equal to A_TimeIdle. -A_TimeIdleMouse: Integer - -; Similar to the above, but after installing the corresponding hook (keyboard or mouse), the simulated keystrokes and/or mouse clicks will be ignored; that is, this variable only responds to physical events. (This avoids Simulate keystrokes and mouse clicks and mistakenly believe that the user exists.) If both hooks are not installed, this variable is equivalent to A_TimeIdle. If only one hook is installed, then only this type of physical input will work on A_TimeIdlePhysical ( Another input/no hook installed, both physical and simulated, will be ignored). -A_TimeIdlePhysical: Integer - -; The number of milliseconds that have elapsed since A_PriorHotkey was pressed. It will be blank whenever A_PriorHotkey is blank. -A_TimeSincePriorHotkey: Integer | '' - -; The number of milliseconds that have elapsed since A_ThisHotkey was pressed. It will be blank whenever A_ThisHotkey is blank. -A_TimeSinceThisHotkey: Integer | '' - -; Can be used to get or set the title matching mode. -A_TitleMatchMode: 1 | 2 | 3 | 'RegEx' - -; Can be used to get or set the title matching speed. -A_TitleMatchModeSpeed: 'Fast' | 'Slow' - -; Returns the menu object that can be used to modify or display the tray menu. -A_TrayMenu: Menu - -; The login name of the user running the current script. -A_UserName: String - -; One digit represents the elapsed days of the current week (1-7). In all locales, 1 means Sunday. -A_WDay: String - -; Can be used to get or set the delay of the window function, in milliseconds. -A_WinDelay: Integer - -; Windows directory. For example: C:\Windows -A_WinDir: String - -; Can be used to get or set the current working directory of the script, which is the default path for accessing files. Unless it is the root directory, the path does not contain a backslash at the end. Two examples: C:\ and C:\My Documents. Use SetWorkingDir or assign a path to A_WorkingDir to change the current working directory. -; No matter how the script is started, the script's working directory defaults to A_ScriptDir. -A_WorkingDir: String - -; The number of days elapsed in the current year (1-366). The value of the variable will not be filled with zeros, for example, 9, instead of 009. -A_YDay: String - -; The current year and week according to the ISO 8601 standard (e.g. 200453). -A_YWeek: String - -; The current year represented by 4 digits (for example, 2004). It has the same meaning as A_Year. -A_YYYY: String - -; The current year represented by 4 digits (e.g. 2004). -A_Year: String - -; Boolean value'true', same as value 1. -true: 1 - -; Boolean value'false', same as value 0. -false: 0 - -; Within a function call, array literal or object literal, the keyword unset can be used to explicitly omit the parameter or value. -unset: unset -;@endregion - -;@region functions -/** - * Returns the absolute value of Number. - */ -Abs(Number) => Float | Integer - -/** - * Returns the arc cosine value expressed in radians (the cosine value is Number). - */ -ACos(Number) => Float - -/** - * Returns the arc sine value expressed in radians (its sine value is Number). - */ -ASin(Number) => Float - -/** - * Returns the arctangent value expressed in radians (its tangent value is Number). - */ -ATan(Number) => Float - -/** - * Returns the inverse tangent of y/x in radians. - * @since v2.1-alpha.1 - */ -ATan2(Y, X) => Float - -/** - * Disable or enable the user's ability to interact with the computer through the keyboard and mouse. - * @param {'On'|'Off'|'Send'|'Mouse'|'SendAndMouse'|'Default'|'MouseMove'|'MouseMoveOff'} Option - */ -BlockInput(Option) => void - -/** - * Create a machine code address, when it is called, it will be redirected to the function in the script. - * @param Function function object. This function object is automatically called whenever Address is called. This function also receives the parameters passed to Address. - * Closure or binding function can be used to distinguish multiple callback functions from calling the same script function. - * The callback function retains a reference to the function object and releases it when the script calls CallbackFree. - * @param Options Specify zero or more of the following words or strings. Use spaces to separate the options (for example, "C Fast"). - * Fast or F: Avoid starting a new thread every time Function is called. Although this performs better, it is necessary to avoid changes in the thread that calls Address (for example, when the callback function is triggered by an incoming message). This is because Function It is possible to change the global settings of the thread that was running when it was called (such as A_LastError and the last window found). For details, see the remarks. - * - * CDecl or C: Let Address follow the "C" calling convention. This option is usually omitted because it is more common to use the standard calling convention in the callback function. The 64-bit version of AutoHotkey ignores this option, which uses the x64 calling convention. - * - * &: The address of the parameter list (a single integer) is passed to the Function instead of each parameter. You can use Numget to retrieve the parameter value. When using the standard 32-bit calling convention, ParamCount must specify the size of the parameter list in DWORDs ( Divide the number of bytes by 4). - * @param ParamCount Address The number of parameters that the caller will pass to it. If omitted, it defaults to Function.MinParams, which is usually the number of mandatory parameters in the Function definition. In both cases, you must ensure that the caller is accurate Pass this number of parameters. - */ -CallbackCreate(Function [, Options, ParamCount]) => Integer - -/** - * Release the reference of the callback to the script function object. - */ -CallbackFree(Address) => void - -/** - * Retrieve the current position of the caret (text insertion point). - */ -CaretGetPos([&OutputVarX: VarRef, &OutputVarY: VarRef]) => Integer - -/** - * Return Number rounded up to integer (without any .00 suffix). - */ -Ceil(Number) => Integer - -/** - * Returns the string (usually a single character) corresponding to the code represented by the specified number. - */ -Chr(Number) => String - -/** - * Specify zero or more of the following items: Coords, WhichButton, Clickount, DownOrUp and/or Relative. Each item must be separated by at least one space, tab and/or comma. The items can appear in any order, Except that Clickcount must appear to the right of coords (if it exists). - * - Coords: The X and Y coordinates that the mouse cursor will move to before clicking. For example, click "100 200" to click the left mouse button at a specific position. The coordinates are relative to the active window, unless you have used coordMode to change this setting. If omitted , The current position of the cursor is used. - * - WhichButton: Left (default), Right, Middle (or just the first letter of these names); or the fourth or fifth mouse button (X1 or X2). For example, click "Right" at the current position of the mouse cursor click the right mouse button. Left and Right correspond to the primary and secondary buttons of the mouse. If the user swaps the buttons through the system settings, the physical location of the buttons will be replaced, but the effect remains the same. - * - WhichButton can also be WheelUp or WU to turn the wheel up (away from you), or WheelDown or WD to turn the wheel down (toward you). You can also specify WheelLeft (or WL) or WheelRight (or WR). For clickcount, specify The number of grids that the scroll wheel should rotate. However, some programs do not accept the case where clickcount is greater than 1. For these programs, the click function can be used multiple times through Loop and other methods. - * - ClickCount: the number of mouse clicks. For example, Click 2 double-click at the mouse cursor position. If omitted, click the mouse once. If coords is specified, then clickcount must be placed after the coordinates. specify zero (0) to move the mouse without Make a click; for example, click "100 200 0". - * - DownOrUp: This part is usually omitted. At this time, each click includes the press event and the subsequent pop-up event. Otherwise, specify the word Down (or letter D) to hold down the mouse button. after that, use the word Up (or letter U) to release the mouse button. For example, click "Down" to hold down the left mouse button. - * - Relative: The word Rel or Relative will treat the specified X and Y coordinates as an offset from the current mouse position. In other words, it will move the cursor X pixels to the right from the current position (negative value is to the left) and down Move Y pixels (negative values go up). - */ -Click(Options*) => void - -/** - * Wait until the clipboard contains data. - * @param Timeout If omitted, this command will wait indefinitely. Otherwise, it will wait no more than this number of seconds (can include a decimal point). - * @param WaitForAnyData If this parameter is omitted or 0 (false), this command will be more selective, explicitly waiting for the text or file to appear in the clipboard ("text" includes anything that will produce text when you paste it into Notepad content). - * If this parameter is 1 (true), the function waits for any type of data to appear on the clipboard. - */ -ClipWait([Timeout, WaitForAnyData]) => Integer - -/** - * Call native COM interface methods by index. - * @param Index The index of the method in the virtual function table (zero-based). - * Index corresponds to the position of the method in the original interface definition. Microsoft documentation usually lists methods in alphabetical order, which is irrelevant. - * To determine the correct index, please find the original interface definition. This may be in the header file or type library. - * - * It is important to consider the parent interface that the method inherits from. The first three methods are always QueryInterface (0), AddRef (1) and Release (2). - * @param ComObject The target COM object; that is, a COM interface pointer. - * The pointer value can be passed directly or encapsulated in an object with Ptr attribute, such as ComObj with VT_UNKNOWN variable type. - */ -ComCall(Index, ComObject [, Type1, arg1, *, ReturnType]) => Float | Integer | String - -/** - * Retrieve running objects that have been registered using OLE (Object Connection and Embedding). - * @param CLSID The CLSID or readable Prog ID of the COM object to be retrieved. - */ -ComObjActive(CLSID) => ComObjct - -/** - * Connect the event source of the object to the function with the given prefix. - */ -ComObjConnect(ComObject [, Prefix]) => void - -/** - * Wrap the original IDispatch pointer. - * IDispatch or non-null interface pointer of derived interface. - */ -ComObjFromPtr(DispPtr) => ComObject - -/** - * Get or change the flags that control the behavior of the COM wrapper object. - * @param ComObject COM object wrapper. - * @param NewFlags The new value of flags identified by Mask, or the flags to be added or deleted. - * @param Mask changes the bit mask of flags. - * @returns This function returns the current flags of the specified COM object (if specified, after applying NewFlags). - */ -ComObjFlags(ComObject [, NewFlags, Mask]) => Integer - -/** - * Returns a reference to the object provided by the COM component. - * @param Name The display name of the object to be retrieved. For details, please refer to MkParseDisplayName (MSDN) - */ -ComObjGet(Name) => ComObject - -/** - * Query the interface or service of the COM object. - * @param ComObject COM wrapper object, interface pointer or an object with Ptr attribute, which returns an interface pointer. - * @param SID format is "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" interface identifier (GUID). - * @param IID A service identifier with the same format as IID. When omitting this parameter, also omit the comma. - * @returns returns a COM package object of type VT_UNKNOWN(13). - */ -ComObjQuery(ComObject [, SID], IID) => ComObject - -/** - * Retrieve type information from COM objects. - * @param ComObject contains a COM object or a wrapper object for typed values. - * @param Type The second parameter is a string indicating the type information returned. - * Name, IID, Class, CLSID - */ -ComObjType(ComObject [, Type]) => Integer | String - -/** - * Retrieve the value or pointer stored in the COM wrapper object. - * @param ComObject contains a COM object or a wrapper object for typed values. - * @returns returns a 64-bit signed integer. - */ -ComObjValue(ComObject) => Integer - -/** - * Add the specified string as a new entry at the bottom of the ListBox or ComboBox. - */ -ControlAddItem(String, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Set the selection in the list box, combo box or tab page control to the specified item or tab number. - * @param N Index of entry or tab page, where 1 is the first item or tab, 2 is the second item, and so on. - * To select all items in ListBox or ComboBox, specify 0. - */ -ControlChooseIndex(N, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Set the selection in ListBox or ComboBox to the first entry whose leading part matches the specified string. - * @param String The string to select. The search is not case sensitive. For example, if a ListBox/ComboBox contains the item "UNIX Text", specifying the word "unix" (lower case) is sufficient to select it. - */ -ControlChooseString(String, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Send mouse button or mouse wheel events to the control. - * @param ControlOrPos If this parameter is omitted, the target window itself will be clicked. Otherwise, one of the following two modes will be used. - * Mode 1 (Position): Specify the X and Y coordinates relative to the upper left corner of the client area of the target window. The X coordinate must be before the Y coordinate, and there must be at least one space or tab between them. For example: X55 Y33. If there is a control at the specified coordinates, it will send a click event at these exact coordinates. If there is no control, the target window itself will be sent an event (depending on the nature of the window, it may have no effect). - * - * Mode 2 (Control): Specify the ClassNN, text or HWND of the control, or an object with Hwnd property. For details, please refer to the parameters of the control. - * - * By default, Mode 2 takes precedence over Mode 1. For example, in an unlikely situation where the text or ClassNN format of a control is "Xnnn Ynnn", then Mode 2 will be used. To override this behavior To use mode 1 unconditionally, please add the word Pos to Options, as shown in the following example: ControlClick "x255 y152", WinTitle,,,, "Pos". - * @param WhichButton The button to click: LEFT, RIGHT, MIDDLE (or the first letter of these words). If omitted or empty, use the LEFT button. - * Supports X1 (XButton1, the fourth mouse button) and X2 (XButton2, the fifth mouse button). - * Supports WheelUp (or WU), WheelDown (or WD), WheelLeft (or WL) and WheelRight (or WR). At this time, ClickCount is the number of wheel grids that need to be turned. - * @param Options A series of zero or more of the following option letters. For example: d x50 y25 - * NA: May improve reliability. Please refer to reliability below. - * - * D: Press and hold the mouse button (that is, a press event is generated). If there are no D and U options, a complete click event (press event and pop-up event) will be sent. - * - * U: Release the mouse button (i.e. generate a pop-up event). This option cannot be used at the same time as the D option. - * - * Pos: Specify the word Pos at any position in Options, so that the X/Y position mode described in the Control-or-Pos parameter will be used unconditionally. - * - * Xn: Specify n as the X coordinate to be clicked relative to the upper left corner of the control. If not specified, click at the horizontal center of the control. - * - * Yn: Specify n as the Y coordinate to be clicked relative to the upper left corner of the control. If not specified, click at the vertical center of the control. - * - * Decimal (not hexadecimal) numbers are used in the X and Y options. - */ -ControlClick([ControlOrPos, WinTitle, WinText, WhichButton, ClickCount, Options, ExcludeTitle, ExcludeText]) => void - -/** - * Delete the specified item from ListBox or ComboBox. - */ -ControlDeleteItem(N, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Returns the entry number of the ListBox or ComboBox that exactly matches the specified string. - * @param String The string to find. The search is not case sensitive. Unlike ControlChooseString, the entire text of the entry must match, not just the beginning. - */ -ControlFindItem(String, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Set the input focus to the specified control of the window. - */ -ControlFocus(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * If the check box or radio button is selected, a non-zero value is returned. - */ -ControlGetChecked(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Returns the name of the currently selected item in the ListBox or ComboBox. - */ -ControlGetChoice(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => String - -/** - * Return the ClassNN (class name and number) of the specified control. - */ -ControlGetClassNN(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => String - -/** - * If the specified control is enabled, it returns a non-zero value. - */ -ControlGetEnabled(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Returns an integer representing the specified control style or extended style. - */ -ControlGetExStyle(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * If there is, get the control that has the input focus in the target window. - */ -ControlGetFocus([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Returns the unique ID of the specified control. - */ -ControlGetHwnd(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Returns the index of the currently selected item or label in the ListBox, ComboBox or Tab control. - */ -ControlGetIndex(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Return an array of items/rows from a list box, combo box or drop-down list. - */ -ControlGetItems(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Array - -/** - * Get the position and size of the control. - */ -ControlGetPos([&X: VarRef, &Y: VarRef, &Width: VarRef, &Height: VarRef, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Returns an integer representing the specified control style or extended style. - */ -ControlGetStyle(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Retrieve the text of the control. - */ -ControlGetText(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => String - -/** - * If the specified control is visible, it returns a non-zero value. - */ -ControlGetVisible(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Hide designated controls. - */ -ControlHide(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Hide the drop-down list of the ComboBox control. - */ -ControlHideDropDown(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Move or resize the control. - */ -ControlMove([X, Y, Width, Height, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Send simulated keyboard input to the window or control. - * @param Keys The sequence of keys to be sent (for details, please refer to the Send function). The rate of sending characters is determined by SetKeyDelay. - * Unlike the Send function, ControlSend cannot send mouse clicks. Please use ControlClick to send. - */ -ControlSend(Keys [, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Send text input to a window or control. - * @param Keys ControlSendText sends a single character in the Keys parameter without converting (Enter) to Enter, ^c to Ctrl+C, etc. - * For details, see Text mode. You can also use (Raw) or (Text) in ControlSend. - */ -ControlSendText(Keys [, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Turn on (check) or turn off (uncheck) check boxes or radio buttons. - * @param Value 1 or True to open the settings - * - * 0 or False close the setting - * - * -1 Set it to the opposite state of the current state - */ -ControlSetChecked(Value, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Enable or disable the specified control. - * @param Value 1 or True to open the settings - * - * 0 or False close the setting - * - * -1 Set it to the opposite state of the current state - */ -ControlSetEnabled(Value, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Change the style or extended style of the specified control respectively. - * @param Value Pass a positive integer to completely cover the style of the window; that is, set its value to Value. - * To add, delete or switch styles, please pass a number string prefixed with plus sign (+), minus sign (-) or caret (^) respectively. - * The calculation of the new style value is shown below (where CurrentStyle can be retrieved through ControlGetStyle/ControlGetExStyle or WinGetStyle/WinGetExStyle) - * If Value is a negative integer, it will be treated as the same as the corresponding numeric string. - * To use the + or ^ prefix literally in the expression, the prefix or value must be enclosed in quotation marks. - */ -ControlSetExStyle(Value, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Change the style or extended style of the specified control respectively. - * @param Value Pass a positive integer to completely cover the style of the window; that is, set its value to Value. - * To add, delete or switch styles, please pass a number string prefixed with plus sign (+), minus sign (-) or caret (^) respectively. - * The calculation of the new style value is shown below (where CurrentStyle can be retrieved through ControlGetStyle/ControlGetExStyle or WinGetStyle/WinGetExStyle) - * If Value is a negative integer, it will be treated as the same as the corresponding numeric string. - * To use the + or ^ prefix literally in the expression, the prefix or value must be enclosed in quotation marks. - */ -ControlSetStyle(Value, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Change the text of the control. - */ -ControlSetText(NewText, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * If the specified control was previously hidden, the control will be displayed. - */ -ControlShow(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Display the drop-down list of the ComboBox control. - */ -ControlShowDropDown(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Set the coordinate mode for multiple built-in functions, relative to the active window or the screen. - * @param {'ToolTip'|'Pixel'|'Mouse'|'Caret'|'Menu'} TargetType - * @param {'Screen'|'Window'|'Client'} RelativeTo - */ -CoordMode(TargetType, RelativeTo := 'Screen') => String - -/** - * Returns the cosine value of Number. - */ -Cos(Number) => Float - -/** - * Prevent the current thread from being interrupted by other threads, or enable it to be interrupted. - * @param OnOffNumeric - */ -Critical(OnOffNumeric := 'On') => Integer - -/** - * Add or subtract time from the date-time value. - * @param DateTime YYYYMMDDHH24MISS format date-time stamp. - * @param Time The time to be added, expressed as an integer or floating point number. Specify a negative number to perform the subtraction. - * @param TimeUnits The unit of the Time parameter. TimeUnits can be one of the following strings (or the first letter): Seconds, Minutes, Hours or Days. - */ -DateAdd(DateTime, Time, TimeUnits: 'Seconds' | 'Minutes' | 'Hours' | 'Days') => String - -/** - * Compare two date-times and return their difference value. - * @param TimeUnits The unit of the Time parameter. TimeUnits can be one of the following strings (or the first letter): Seconds, Minutes, Hours or Days. - */ -DateDiff(DateTime1, DateTime2, TimeUnits: 'Seconds' | 'Minutes' | 'Hours' | 'Days') => Integer - -/** - * Set whether to'see' hidden text when searching for windows. This will affect built-in functions such as WinExist and Winactivate. - */ -DetectHiddenText(Mode) => Integer - -/** - * Set whether the script can'see' the hidden window. - */ -DetectHiddenWindows(Mode) => Integer - -/** - * Copy the folder, and all its subfolders and files (similar to xcopy). - * @param Overwrite This parameter determines whether to overwrite existing files. If omitted, it defaults to 0 (false). Specify one of the following values: - * - * 0(false): Do not overwrite the existing file. If a file or directory named Dest already exists, the operation will fail without any effect. - * - * 1(true): Overwrite the current file. However, other subdirectories or files in Dest that are not overwritten by the files in the Source directory will not be deleted. - */ -DirCopy(Source: $DirPath, Dest: $DirPath, Overwrite := false) => void - -/** - * Create directories/folders. - */ -DirCreate(DirName: $DirPath) => void - -/** - * Delete the folder. - * @param Recurse This parameter determines whether to recurse to subdirectories. If omitted, it defaults to 0 (false). Specify one of the following values: - * - * 0(false): Do not remove the files and subdirectories contained in DirName. At this time, if DirName is not empty, no operation is performed and an exception is thrown. - * - * 1(true): Remove all files and subdirectories (similar to the Windows command "rmdir /S"). - */ -DirDelete(DirName: $DirPath, Recurse := false) => void - -/** - * Check if the folder exists and return its attributes. - * @returns returns the attributes of the first folder that meets the criteria. This string is a subset of ASHDOC, where each letter means the following: - * - * A = ARCHIVE - * - * S = SYSTEM (system) - * - * H = HIDDEN (hidden) - * - * D = DIRECTORY (directory) - * - * O = OFFLINE (offline) - * - * C = COMPRESSED (compressed) - */ -DirExist(FilePattern: $DirPath) => String - -/** - * Move a folder, and all its subfolders and files. It can also rename a folder. - * @param Source The name of the source directory (without the trailing backslash). - * @param Dest The name of the target directory (without the trailing backslash). - * @param Flag specifies one of the following single characters: - * - * 0 (default): Do not overwrite existing files. If Dest already exists as a file or directory, the operation will fail. - * - * 1: Overwrite the current file. However, any file or subfolder in Dest will not be deleted if there is no corresponding file in Source. - * `Known limitation:` If Dest already exists as a folder and is on the same volume as Source, move Source into it instead of overwriting it. To avoid this, see the next option. - * - * 2: Same as Mode 1 above, but there are no restrictions. - * - * R: Rename the directory without moving it. Although ordinary renaming and moving have the same effect, it will be useful if you want the result of "complete success or complete failure"; that is, you don't want it due to Source or One of the files is locked (in use) and only partially moved successfully. - * Although this method cannot move Source to another volume, it can be moved to any other directory in the same volume. If Dest already exists as a file or directory, the operation fails. - */ -DirMove(Source: $DirPath, Dest: $DirPath, Flag := 0) => void - -/** - * A standard dialog box that allows the user to select a folder is displayed. - * @param StartingFolder If it is empty or omitted, the initial selection of the dialog box is the user's My Documents folder (or possibly My Computer). You can specify the CLSID folder, such as "::{20d04fe0-3aea-1069- a2d8-08002b30309d}" (ie My Computer) to start navigation from a specific dedicated folder. - * - * Otherwise, the most common usage of this parameter is an asterisk followed by the absolute path of the initially selected drive or folder. For example, "*C:\" will initially select the C drive. Similarly, "*C:\My "Folder" will initially select this special folder. - * - * The asterisk indicates that the user is allowed to navigate upwards from the starting folder (close to the root directory). If there is no asterisk, the user is forced to select a folder in StartingFolder (or StartingFolder itself). One advantage of omitting the asterisk is that the StartingFolder will initially be displayed It is a tree expanded state, which can save the user time to click the plus sign in front. - * - * If there is an asterisk, the upward navigation can also be restricted to folders other than the desktop. This is achieved by adding the absolute path of the topmost folder in front of the asterisk, followed by a space or tab. For example, "C:\My Folder *C:\My Folder\Projects" will not allow users to navigate to a folder higher than C:\My Folder (but the initial selection can be C:\My Folder\Projects): - * @param Options One of the following numbers: - * - * 0: Disable all the following options. - * - * 1 (default): Provide a button that allows users to create a new folder. - * - * Add 2 to the number above to provide an editing area that allows the user to enter the folder name. For example, the parameter value 3 means that the editing area and the "New Folder" button are provided at the same time. - * - * Add 4 to the number above to ignore the BIF_NEWDIALOGSTYLE attribute. Adding 4 ensures that DirSelect will work even in a pre-installed environment like WinPE or BartPE. However, this prevents the "New Folder" button from appearing. - * - * If the user enters an invalid folder name in the editing area, SelectedFolder will be set to the folder selected in the navigation tree instead of the content entered by the user. - * @param Prompt The text displayed in the window to prompt the user to operate. If omitted or empty, it defaults to "Select Folder-"A_ScriptName (namely the name of the current script). - */ -DirSelect(StartingFolder?: $DirPath, Options := 1, Prompt?) => String - -/** - * Call functions in DLL files, such as standard Windows API functions. - */ -DllCall(DllFile_Function: $DllFunc | $FilePath<'dll|ocx|cpl'> [, Type1, Arg1, *, Cdecl_ReturnType]) => Float | Integer | String - -/** - * Download files from the Internet. - */ -Download(URL, FileName: $FilePath) => void - -/** - * Eject the designated CD/DVD drive or removable drive. - * @param Drive The drive letter is followed by a colon and optional backslash (can also be used for UNC paths and mapped drives). If omitted, the default CD/DVD drive will be used. If the drive is not found, an exception will be raised. - */ -DriveEject(Drive?) => void - -/** - * Returns the total capacity of the drive containing the specified path, in mb (megabytes). - */ -DriveGetCapacity(Path) => Integer - -/** - * Returns the type of the file system of the specified drive. - * @param Drive Drive letter followed by a colon and optional backslash, or UNC name, such as \server1\share1. - */ -DriveGetFileSystem(Drive) => String - -/** - * Return the volume label of the specified drive. - */ -DriveGetLabel(Drive) => String - -/** - * Return a string of letters, each drive letter in the system corresponds to a character. - * @param Type If omitted, all types of drives are retrieved. Otherwise, specify one of the following words to obtain the specific type of drive: CDROM, REMOVABLE, FIXED, NETWORK, RAMDISK, UNKNOWN. - */ -DriveGetList(Type?) => String - -/** - * Returns the volume serial number of the specified drive. - */ -DriveGetSerial(Drive) => Integer - -/** - * The free disk space of the drive containing the specified path, in mb (megabytes). - */ -DriveGetSpaceFree(Path) => Integer - -/** - * Returns the status of the drive containing the specified path. - */ -DriveGetStatus(Path) => String - -/** - * Returns the media status of the specified CD/DVD drive. - * @param Drive Drive letter followed by a colon. If omitted, the default CD/DVD drive will be used. - * @returns not ready The drive is not ready to be accessed, possibly because it is busy writing operations. Known limitations: When the drive is a DVD instead of a CD, the "not ready" situation may also occur. - * - * There is no disc in the open drive, or the tray has been ejected. - * - * playing The drive is playing the disc. - * - * paused The previously played audio or video is now paused. - * - * seeking The drive is seeking. - * - * There is a CD in the stopped drive but it is not currently being accessed. - */ -DriveGetStatusCD(Drive?) => String - -/** - * Returns the drive type containing the specified path. - * @returns returns the drive type that contains the specified path: Unknown, Removable, Fixed, Network, CDROM or RAMDisk. If the path is invalid (for example, because the drive does not exist), the return value is an empty string. - */ -DriveGetType(Path) => String - -/** - * Prevent the eject function of the specified drive from working properly. - */ -DriveLock(Drive) => void - -/** - * Recover designated CD/DVD drives. - */ -DriveRetract([Drive]) => void - -/** - * Change the volume label of the specified drive. - */ -DriveSetLabel(Drive, NewLabel?) => void - -/** - * Restore the eject function of the specified drive. - */ -DriveUnlock(Drive) => void - -/** - * Opens the current script for editing in the associated editor. - * @param FileName [@since v2.1-alpha.1] The path and name of the file to open for editing. If omitted, it defaults to the main file of the current script (A_ScriptFullPath). Relative paths are relative to the script directory (A_ScriptDir). - */ -Edit(FileName?: $FilePath) => void - -/** - * Returns the column number of the caret (text insertion point) in the Edit control. - */ -EditGetCurrentCol(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Returns the line number of the caret (insertion point) in the Edit control. - */ -EditGetCurrentLine(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Returns the text of the specified line in the Edit control. - */ -EditGetLine(N, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => String - -/** - * Returns the number of rows of the Edit control. - */ -EditGetLineCount(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer - -/** - * Return the selected text in the Edit control. - */ -EditGetSelectedText(Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => String - -/** - * Paste the specified string to the caret (text insertion point) in the Edit control. - */ -EditPaste(String, Control [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * Retrieve environment variables. - */ -EnvGet(EnvVarName) => String - -/** - * Write the value to the variable contained in the environment variable. - */ -EnvSet(EnvVar [, Value]) => void - -/** - * Exit the current thread. When the script exits, it returns an integer between -2147483648 and 2147483647 to its caller. - */ -Exit(ExitCode := 0) => void - -/** - * Exit the current thread. When the script exits, it returns an integer between -2147483648 and 2147483647 to its caller. - */ -ExitApp(ExitCode := 0) => void - -/** - * Returns e (approximately 2.71828182845905) raised to the power of N. - */ -Exp(N) => Float - -/** - * Append (write) text or binary data at the end of the file (if necessary, create the file first). - * @param FileName The name of the file to be appended. If the absolute path is not specified, it is assumed to be in A_WorkingDir. The target directory must already exist. - * Standard output (stdout): Specify an asterisk (*) in FileName to send Text to standard output (stdout). - * Specify two asterisks (**) in FileName to send Text to standard error output (stderr). - * @param Options zero or more of the following strings. Use a single space or tab to separate each option from the next. For example: "`n UTF-8" - * - * Encoding: If the file lacks UTF-8 or UTF-16 byte order mark, specify any encoding name accepted by FileEncoding (excluding the empty string) to use that encoding. If omitted, the default is A_FileEncoding (unless Text is an object, In this case, the byte order mark is not written). - * - * RAW: Specify the word RAW (not case sensitive) to write the exact bytes contained in Text to the file as-is, without any conversion. This option overwrites any encoding previously specified, and vice versa. If Text is not an object, due to use UTF-16 string, the data size is always a multiple of 2 bytes. - * - * `n (newline character): If the carriage return character does not exist, insert the carriage return character (`r) before each newline character (`n). In other words, it will convert `n to `r`n. This This conversion usually does not affect performance. If this option is not used, the end of the line in the Text will not be changed. - */ -FileAppend(Text, FileName?: $FilePath, Options?) => void - -/** - * Copy one or more files. - * @param SourcePattern The name of a single file or folder, or wildcard pattern (e.g. C:\Temp\*.tmp). - * @param DestPattern The name or pattern of the target, if the asterisk exists, replace the first asterisk (*) in the file name with the source file name without its extension, - * Replace the first asterisk after the last period (.) with the extension of the source file. If there is an asterisk but the extension is omitted, the extension of the source file is used. - * @param Overwrite This parameter determines whether to overwrite an existing file. If this parameter is 1 (true), the function will overwrite the existing file. If it is omitted or 0 (false), the function will not overwrite the existing file . - */ -FileCopy(SourcePattern: $FilePath, DestPattern: $FilePath, Overwrite := false) => void - -/** - * Create a shortcut (.lnk) file. - * @param Target The name of the file referenced by the shortcut, unless the file is integrated into the system (such as Notepad.exe), it should contain the absolute path. The file it points to does not necessarily need to exist when the shortcut is created - * @param LinkFile The name of the shortcut file to be created, if the absolute path is not specified, it is assumed to be in A_WorkingDir. You must ensure that the extension is .lnk. The target directory must already exist. If the file already exists, it will be overwritten. - * @param WorkingDir The current working directory of the Target when the shortcut is launched. If it is empty or omitted, the "Starting Position" field of the shortcut is empty, and the system will provide the default working directory when the shortcut is launched. - * @param Args The parameters passed to Target when the shortcut is launched. The parameters are separated by spaces. If a parameter contains spaces, enclose it in double quotes. - * @param Description A comment describing the shortcut (used by the operating system to be displayed in ToolTip, etc.) - * @param IconFile displays the full path and name of the icon in LinkFile. It must be the first icon in an ico file or an EXE or DLL. - * @param ShortcutKey A single letter, number or name of a single key in the key list (mouse buttons or other non-standard keys may not be supported). Do not include modifiers. Currently, all created shortcut keys use Ctrl+Alt as Modifier keys. For example, if you specify the letter B in this parameter, the shortcut key will be Ctrl+Alt+B. - * @param IconNumber To use the icons in IconFile (except the first icon), please specify the number here. For example, 2 means the second icon. - * @param RunState To minimize or maximize the run Target. If it is empty or omitted, the default is 1 (normal). Otherwise, specify one of the following numbers: - * - * 1 = normal - * - * 3 = maximize - * - * 7 = minimize - */ -FileCreateShortcut(Target: $FilePath, LinkFile: $FilePath<'.link'> [, WorkingDir, Args, Description, IconFile, ShortcutKey, IconNumber, RunState]) => void - -/** - * Delete one or more files. - * @param FilePattern The name of a single file, or a wildcard pattern (such as "C:\Temp\*.tmp"). If an absolute path is not specified, it is assumed that FilePattern is in A_WorkingDir. - * To delete the entire folder and all its subfolders and files, use DirDelete - */ -FileDelete(FilePattern: $FilePath) => void - -/** - * Set the default encoding for FileRead, Loop Read, FileAppend and FileOpen. - * @param Encoding One of the following values (if omitted, it defaults to CP0): - * UTF-8: Unicode UTF-8, equivalent to CP65001. - * - * UTF-8-RAW: Same as above, but the byte order mark is not written when creating a new file. - * - * UTF-16: Unicode UTF-16 with little-endian byte order identifier, equivalent to CP1200. - * - * UTF-16-RAW: Same as above, but the byte order mark is not written when creating a new file. - * - * CPnnn: Code page with numeric identifier nnn. Please refer to code page identifier ¬. - * - * nnn: Number code page identifier. - */ -FileEncoding(Encoding := 'CP0') => String - -/** - * Check if the file or directory exists and return its attributes. - * @returns returns the attributes of the first matching file or folder. This string is a subset of RASHNDOCT, where each letter means the following: - * - * R = READONLY (read only) - * - * A = ARCHIVE - * - * S = SYSTEM (system) - * - * H = HIDDEN (hidden) - * - * N = NORMAL (normal) - * - * D = DIRECTORY (directory) - * - * O = OFFLINE (offline) - * - * C = COMPRESSED (compressed) - * - * T = TEMPORARY (temporary) - */ -FileExist(FilePattern: $FilePath) => String - -/** - * Report whether the file or folder is read-only, hidden, etc. - * @returns returns the attributes of the file or folder. This string is a subset of RASHNDOCT, where each letter means the following: - * - * R = READONLY (read only) - * - * A = ARCHIVE - * - * S = SYSTEM (system) - * - * H = HIDDEN (hidden) - * - * N = NORMAL (normal) - * - * D = DIRECTORY (directory) - * - * O = OFFLINE (offline) - * - * C = COMPRESSED (compressed) - * - * T = TEMPORARY (temporary) - */ -FileGetAttrib(FileName?: $FilePath) => String - -/** - * Get the information of the shortcut (.lnk) file, such as its target file. - */ -FileGetShortcut(LinkFile: $FilePath<'lnk'> [, &OutTarget: VarRef, &OutDir: VarRef, &OutArgs: VarRef, &OutDescription: VarRef, &OutIcon: VarRef, &OutIconNum: VarRef, &OutRunState: VarRef]) => String - -/** - * Get the size of the file. - */ -FileGetSize(FileName?: $FilePath, Units?) => Integer - -/** - * Get the timestamp of a file or folder. - */ -FileGetTime(FileName?: $FilePath, WhichTime: 'M' | 'C' | 'A' := 'M') => String - -/** - * Retrieve the version of the file. - */ -FileGetVersion(FileName?: $FilePath) => String - -/** - * Include the specified file in the compiled script. - */ -FileInstall(Source: $FilePath, Dest: $FilePath, Overwrite := false) => void - -/** - * Move or rename one or more files. - */ -FileMove(SourcePattern: $FilePath, DestPattern: $FilePath, Overwrite := false) => void -/** - * Open the file, read specific content from it and/or write new content into it. - * @param Flags `Access Mode (mutually exclusive)` - * - * r 0x0 Read: Fail when the file does not exist. - * - * w 0x1 write: create a new file, overwrite any existing file. - * - * a 0x2 Append: If the file does not exist, create a new file, otherwise move the file pointer to the end of the file. - * - * rw 0x3 Read/write: Create a new file when the file does not exist. - * - * h means FileName is the file handle wrapped in the object. Ignore the sharing mode flag, and do not check the byte order mark of the file or stream represented by the handle. When the file object is destroyed, when the file object is destroyed, the file handle will not be automatically Close and calling Close has no effect. Note that when FileName is a handle to a non-search device (such as a pipe or communication device), Seek, Pos, and Length should not be used. - * - * `Sharing mode flag` - * - * -rwd is file locking for read, write and/or delete access. Any combination of r, w and d can be used. Specifying-is equivalent to specifying -rwd. If omitted completely, all accesses are shared by default. - * - * 0x0 If Flags is numeric, the lack of sharing mode flags will cause the file to be locked. - * - * 0x100 Shared read access. - * - * 0x200 Shared write access. - * - * 0x400 Shared delete access. - * - * `End of Line (EOL) option` - * - * `n 0x4 Replace `r`n with `n when reading, and replace `n with `r`n when writing. - * - * `r 0x8 Replace the single `r with `n when reading. - * @param Encoding If the file does not have UTF-8 or UTF-16 byte order mark, or the h (handle) flag is used, the code page used when reading and writing the file (AutoHotkey automatically recognizes the file with byte order mark, specified Encoding is invalid). If this parameter is omitted, the current value of A_FileEncoding will be used. - */ -FileOpen(FileName: $FilePath, Flags [, Encoding]) => File - -/** - * Retrieve the contents of the file. - * @param Options Zero or more of the following strings, use a single space or tab to separate each option from the next option. For example: "`n m5000 UTF-8" - * - * Encoding: If the file lacks UTF-8 or UTF-16 byte order mark, specify any encoding name accepted by FileEncoding (excluding the empty string) to use that encoding. If omitted, the default is A_FileEncoding. - * - * RAW: Specify the word RAW (not case sensitive) to read the contents of the file as raw binary data and return the buffer object instead of a string. This option overwrites any previously specified encoding, and vice versa. - * - * m1024: If this option is omitted, the entire file will be read, but if the memory is insufficient, an error message will be displayed and the thread will exit (Use Try to avoid this situation). Otherwise, please replace 1024 with decimal or hexadecimal representation The number of bytes in the file. If the file is larger than this number of bytes, only the first part of it will be read. - * - * `n (newline character): Replace all carriage return and newline characters (`r`n) with newline characters (`n). However, this conversion reduces performance and is often unnecessary. For example, include `r`n The text has been added to the Gui Edit control in the correct format. The following parsing loop will work correctly, regardless of whether the end of each line is `r`n or `n: Loop Parse, MyFileContents, "`n", "`r" . - */ -FileRead(FileName: $FilePath [, Options]) => Buffer | String - -/** - * If possible, send the file or directory to the recycle bin, or delete the file permanently. - * @param FilePattern The name or wildcard pattern of a single file (such as C:\Temp\*.tmp). If FilePattern does not specify an absolute path, it is assumed to be in A_WorkingDir. - * To recycle the entire directory, please specify the directory name without the trailing backslash. - */ -FileRecycle(FilePattern: $FilePath) => void - -/** - * Empty the recycle bin. - * @param DriveLetter If omitted, the recycle bin of all drives will be cleared. Otherwise, please specify the drive letter, such as C:\ - */ -FileRecycleEmpty(DriveLetter?) => void - -/** - * Display a standard dialog box that allows users to open or save files. - * @param Options can be a number or one of the letters listed below, optionally followed by a number. For example, "M", 1 and "M1" are all valid (but not the same). - * - * D: Select a folder (directory). Specify the letter D to allow the user to select a folder instead of a file. This dialog box has most of the same functions as when selecting a file, but does not support filters (Filter must be omitted or left blank) . - * - * M: Multiple selection. Specifying the letter M allows users to use Shift+click, Control+click or other methods to select multiple files. In this case, the return value is an array not a string. To extract a single file, please refer to Example at the bottom of this page. - * - * S: Save dialog box. Specify the letter S to make the dialog box display a save button instead of an open button. - * - * The following numbers can be used. To make more than one of them effective, add them together. For example, to use 1 and 2, specify the number 3. - * - * 1: The file must exist - * - * 2: The path must exist - * - * 8: Prompt to create a new file - * - * 16: Prompt to overwrite files - * - * 32: Select the shortcut itself (.lnk file) without being resolved as their target. This option also avoids the situation of jumping to that folder through a folder shortcut. - * - * Because the "Prompt Overwrite" option is only supported by the save dialog, specifying this option without the "Prompt to Create" option will also make the "S" option effective. Similarly, when the "S" option exists, "Prompt to create" The option has no effect. Specify the number 24 to enable any prompt type supported by the dialog box. - */ -FileSelect(Options := 0, RootDir_FileName?: $FilePath, Title?, Filter?) => String | Array - -/** - * Change the attributes of one or more files or folders. Wildcards are supported. - * @param Attributes The attribute to be changed. For example, +HA-R. To conveniently open, close or switch attributes, please add plus sign (+) and minus sign (-) before one or more of the following attribute letters respectively Or caret (^): - * - * R = read only - * - * A = archive - * - * S = system - * - * H = hidden - * - * N = Normal (only valid when this attribute is used alone) - * - * O = offline - * - * T = temporary - * @param FilePattern The name of a single file or folder, or a wildcard pattern, such as "C:\Temp\*.tmp". If the absolute path is not specified, it is assumed that FilePattern is in A_WorkingDir. - * If omitted, the current file in the innermost file loop will be used. - * @param Mode If it is empty or omitted, it will only operate on files by default, and subdirectories will not be recursive. Otherwise, please specify zero or more of the following letters: - * - * D = Contains the directory (folder). - * - * F = Include files. If both F and D are omitted, only files are included and not directories. - * - * R = Subfolders are recursively into it, so if the files and folders contained in it match FilePattern, they will be operated on. All subfolders will be recursively into it, not just those whose names match FilePattern Subfolders. If R is omitted, files and directories in subdirectories are not included. - */ -FileSetAttrib(Attributes, FilePattern?: $FilePath, Mode?) => void - -/** - * Change the timestamp of one or more files or folders. Wildcards are supported. - * @param YYYYMMDDHH24MISS If it is blank or omitted, it will default to the current time. - * @param FilePattern The name or wildcard pattern of a single file or folder, such as C:\Temp\*.tmp. If the absolute path is not specified, the FilePattern is assumed to be in A_WorkingDir. If omitted, the innermost file-loop is used Current file. - * @param WhichTime If it is empty or omitted, the default is M (modification time). Otherwise, specify one of the following letters to set the timestamp that should be changed: - * - * M = modification time - * - * C = creation time - * - * A = last access time - * @param Mode If it is empty or omitted, only the file will be operated, and the subdirectories will not be recursive. Otherwise, please specify zero or more of the following letters: - * - * D = Contains the directory (folder). - * - * F = Include files. If both F and D are omitted, only files are included and not directories. - * - * R = Subfolders are recursively into it, so if the files and folders contained in it match FilePattern, they will be operated on. All subfolders will be recursively into it, not just those whose names match FilePattern Subfolders. If R is omitted, files and directories in subdirectories are not included. - */ -FileSetTime(YYYYMMDDHH24MISS?, FilePattern?: $FilePath, WhichTime: 'M' | 'C' | 'A' := 'M', Mode?) => void - -/** - * Return Number rounded down to integer (without any .00 suffix). - */ -Floor(Number) => Integer - -/** - * Format a variable number of input values according to the format string. - * @param FormatStr format string consists of literal text and placeholders, and its form is {Index:Format}. Omit the index to use the next input value in the sequence (even if it has been used before). - * Use (() and ()) to include literal brackets in the string. Any other invalid placeholders will be included in the result. * Space characters in the braces are not allowed (unless as a sign). - * Each format specifier can contain the following parts in order (without spaces): `Flags Width .Precision ULT Type` - * `Flags` Select zero or more flags from the flag table below to affect the alignment and prefix of the output. - * - * -Align the result to the left under the given positioning width (padded the right part of the bit width with a space). For example, Format("{:-10}", 1) returns `1`. If omitted, the result will be given Right-justified within a fixed bit width. - * - * + If the output value is a signed type, use the sign (+ or -) as the prefix. For example, Format("{:+d}", 1) returns `+1`. - * - * 0 If width is prefixed with 0, leading 0 will be added up to the minimum width. For example, Format("{:010}", 1) returns `0000000001`. If both 0 and-are used, the former will be ignored. If 0 is specified as an integer format (i, u, x, X, o, d) with precision indication-for example, (:04.d)-at this time 0 will be ignored. - * - * (Space) When the output value is a signed number and a positive number, it is decorated with a space as a prefix. If a space and + appear at the same time, the space will be ignored. For example, Format("{: 10}", 1) Returns `1`. - * - * \# When # is used with o, x or X format, this flag uses the form of 0, 0x or 0X to modify any non-zero output value respectively. For example, Format("{:#x}", 1) returns 0x1. - * When # is used with e, E, f, a, A format, this flag forces the output value to include a decimal point. For example, Format("{:#.0f}", 1) returns 1.. - * When # is used with g or G, this flag forces the output value to include a decimal point and retain the trailing 0. - * When # is used with c, d, i, u or s format, it will be ignored. - * - * `Width` Decimal integer, controls the minimum width of the formatted value, in characters. By default, the value is right-aligned and filled with spaces. This can be done by using-(left-aligned) and 0 (prefix 0) Sign to cover. - * - * `.Precision` decimal integer, control the string to be output, the maximum number of decimal places or significant digits, depending on the output type. - * - * f, e, E: Precision specifies the number of digits after the decimal point. The default value is 6. - * - * g, G: Precision specifies the largest number of significant digits. The default value is 6. - * - * s: Precision specifies the maximum number of characters to be printed. Characters exceeding this number will not be printed. - * - * For integer types (d, i, u, x, X, o), Precision acts like Width with a prefix of 0 and a default value of 1. - * - * `ULT` specifies the case conversion applied to string values - U (uppercase), L (lowercase) or T (title). Only valid for s type. For example {:U} or {:.20Ts}. Also Lowercase letters l and t are supported, but u is reserved for unsigned integers. - * - * `Type` A character in the type table below that indicates how the input value will be parsed. If omitted, the default is s. - * - * d or i is a signed integer. - * - * u Unsigned integer. - * - * x or X is an unsigned hexadecimal integer; the case of x determines whether the output value is in the form of "abcdef" or "ABCDEF". Only when the # sign is used, the 0x prefix will be included in the output value - * - * o Unsigned octal integer. - * - * f Floating point number The number of digits before the decimal point depends on the size of the integer part, and the number of digits after the decimal point depends on the required precision. For example, Format("{:.2f}", 1) returns 1.00. - * - * e Floating point number For example, Format("{:e}", 255) returns 2.550000e+002. - * - * E floating point number is equivalent to e format, but the exponent part of the result shows E instead of e. - * - * g floating-point numbers display signed values in f or e format, subject to the given value and more compact precision. e format is only used when the exponent of the value is less than -4 or greater than or equal to the precision parameter. The trailing zero is Truncation, the decimal point only appears when there are one or more digits behind. - * - * G floating point number is equivalent to g format, but e when introducing exponent will be replaced by E (where appropriate). - * - * a floating-point number is a signed hexadecimal double-precision floating-point value in the form of [?]0xh.hhhh p±dd, where the decimal part of h.hhhh is a hexadecimal value (using lowercase letters), and dd is One or more numbers representing the exponent, and the precision specifies the number of digits after the decimal point. - * - * A floating point number is equivalent to a format, but when introducing exponents, use P instead of p. - * - * p integer Display the parameter as a hexadecimal memory address. For example, Format("{:p}", 255) returns 000000FF. - * - * s string Output string. If the input value is a numeric value, the input value will be automatically converted to a string before Width and Precision take effect. - * - * c character encoding output a single character in encoding order, similar to Chr(n). If the input value is not within the expected range, it will be reversed. For example, Format("{:c}", 116) returns t. - */ -Format(FormatStr, Values*) => String - -/** - * Convert YYYYMMDDHH24MISS timestamp to the specified date/time format. - */ -FormatTime([YYYYMMDDHH24MISS, Format]) => String - -/** - * Retrieve the name of the button. - */ -GetKeyName(KeyName) => String - -/** - * Retrieve the scan code of the button. - */ -GetKeySC(KeyName) => Integer - -/** - * Check whether the keyboard button or mouse/joystick button is pressed or released. The state of the joystick can also be obtained. - * @param KeyName `Known limitation:` This function cannot distinguish two keys that share the same virtual key code, such as Left and NumpadLeft. - * @param Mode When obtaining the joystick state, this parameter is ignored. If omitted, the mode defaults to obtaining the logical state of the button. This is the state of the button considered by the operating system and the active window, but it may be related to the physical state of the button The status is inconsistent. - * - * Alternatively, one of these letters can be specified: - * - * P: Get the physical state (that is, whether the user actually pressed the button). The physical state of the button or mouse button is usually the same as the logical state, unless a keyboard and/or mouse hook is installed, in which case it will accurately reflect Check whether the user has pressed a button or mouse button (as long as the button is being held down when the script is executed). You can use the KeyHistory function or menu item to determine whether the hook is used in the script. You can add #InstallKeybdHook and/or # InstallMouseHook command to the script to force the hook to be installed. - * - * T: Get the switching status. For keys other than CapsLock, NumLock and ScrollLock, when the script is started, the switching status is generally 0, and they are not synchronized between processes. - * @returns For keyboard keys and mouse buttons, if the key is down (or the switch is on), the function returns 1 (true) If the key is up (or the switch is off), the function returns 0 (false). - * - * When KeyName is the axis of the joystick, such as JoyX, the function returns a floating point number between 0 and 100, which is used to indicate that the position of the joystick is the percentage of the axis's motion range. - * - * When the KeyName is JoyPOV, the function returns an integer between 0 and 35900. Many joysticks use POV values similar to the following: - * - * -1: no angle - * - * 0: Forward POV - * - * 9000 (i.e. 90 degrees): POV to the right - * - * 27000 (i.e. 270 degrees): POV to the left - * - * 18000 (i.e. 180 degrees): backward POV - */ -GetKeyState(KeyName, Mode?) => String - -/** - * Retrieve the virtual key code of the button. - */ -GetKeyVK(KeyName) => Integer - -/** - * The implementation function of the retrieval method. - */ -GetMethod(Value [, Name, ParamCount]) => Func - -/** - * Activate the next window in the window group defined by GroupAdd. - * @param Mode If omitted, the oldest window in the group is activated. To change this behavior, please specify the following letters: - * - * R: The most recent window (the most recently activated window) is activated, but only when there are no active members in the group when the function is running. "R" is very useful when temporarily switching to handling irrelevant tasks. When When you use GroupActivate, GroupDeactivate or GroupClose to return to the target group, the most recently worked window will be activated instead of the oldest window. - */ -GroupActivate(GroupName, Mode?) => Integer - -/** - * Add the window specification to the window group, if necessary, create the group. - */ -GroupAdd(GroupName [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void - -/** - * If the active window has just been activated by GroupActivate or GroupDeactivate, close the window. Then, it will activate the next window in the series. It can also close all windows in the group. - * @param Mode If omitted, the function closes the active window and activates the oldest window in the group. To change this behavior, specify one of the following letters: - * - * R: The most recent window (the most recently activated window) is activated, but only when there are no active members in the group when the function is running. "R" is very useful when temporarily switching to handling irrelevant tasks. When When you use GroupActivate, GroupDeactivate, or GroupClose to return to the group, the most recently worked window will be activated instead of the oldest window. - * - * A: Close all members of the group. This is equivalent to WinClose "ahk_group GroupName". - */ -GroupClose(GroupName, Mode?) => void - -/** - * Similar to GroupActivate, except that the next window that is not in the group is activated. - * @param Mode If omitted, the function will activate the oldest non-member window. To change this behavior, specify the following letters: - * - * R: The latest non-member window (the most recently activated window) is activated, but only when the members of the group are active when the function is running. "R" is very useful when temporarily switching to handling irrelevant tasks Useful. When you use GroupActivate, GroupDeactivate or GroupClose to return to the group, the most recently worked window will be activated instead of the oldest window. - */ -GroupDeactivate(GroupName, Mode?) => void - -/** - * Retrieve the GuiControl object of the GUI control associated with the specified HWND. - */ -GuiCtrlFromHwnd(Hwnd) => Gui.List | Gui.ListView | Gui.StatusBar | Gui.Tab | Gui.TreeView - -/** - * Retrieve the Gui object of the Gui window associated with the specified HWND. - * @param RecurseParent If this parameter is 1 (true), it will automatically search and retrieve the parent (i.e. GUI) closest to the specified HWND. - */ -GuiFromHwnd(Hwnd, RecurseParent := false) => Gui - -/** - * If the specified value is derived from the specified base object, a non-zero number is returned. - */ -HasBase(Value, BaseObj) => Integer - -/** - * If the specified value has a method with the specified name, a non-zero number is returned. - */ -HasMethod(Value [, Name, ParamCount]) => Integer - -/** - * If the specified value has an attribute with the specified name, a non-zero number is returned. - */ -HasProp(Value, Name) => Integer - -/** - * Specify the conditions for subsequent creation or modification of hotkey variants. - */ -HotIf([FuncOrExpr]) => void - -/** - * Specify the conditions for the hotkey variants to be subsequently created or modified. - */ -HotIfWinActive([WinTitle, WinText]) => void - -/** - * Specify the conditions for the hotkey variants to be subsequently created or modified. - */ -HotIfWinExist([WinTitle, WinText]) => void - -/** - * Specify the conditions for the hotkey variants to be subsequently created or modified. - */ -HotIfWinNotActive([WinTitle, WinText]) => void - -/** - * Specify the conditions for the hotkey variants to be subsequently created or modified. - */ -HotIfWinNotExist([WinTitle, WinText]) => void - -/** - * Create, modify, enable or disable hotkeys while the script is running. - * @param Callback This parameter can also be one of the following specific values: - * - * On: Enable the hotkey. If the hotkey is already enabled, no operation will be performed. - * - * Off: Disable the hotkey. If the hotkey is already in the disabled state, no operation is performed. - * - * Toggle: Set the hotkey to the opposite state (enable or disable). - * - * AltTab (and others): The special Alt-Tab hotkey action described here. - * @param Options A string consisting of zero or more of the following letters, which can be separated by spaces. For example: On B0. - * - * On: If the hotkey is currently disabled, enable it. - * - * Off: If the hotkey is currently enabled, disable it. This option is often used to create a hotkey whose initial state is disabled. - * - * B or B0: Specifying the letter B will buffer the hotkey as described in #MaxThreadsBuffer. Specify B0 (B followed by the number 0) to disable this type of buffering. - * - * Pn: Specify the thread priority of the hotkey followed by the letter P. If the P option is omitted when creating the hotkey, the priority will be set to 0. - * - * Tn: Specify the letter T followed by a number indicating the number of threads allowed by this hotkey, as described in #MaxThreadsPerHotkey. For example: T5. - * - * In(InputLevel): Specify the input level of the letter I (or i) followed by the hot key. For example: I1. - */ -Hotkey(KeyName [, Callback, Options]) => void - -/** - * Create, modify, enable or disable hot strings while the script is running. - */ -Hotstring(StringOrOptions [, Replacement, OnOffToggle]) => String - -/** - * Add the icon or picture to the specified ImageListID and return the index of the new icon (1 is the first icon, 2 is the second icon, and so on). - * @param ImageListID IL_Create The ID of the image list created. - * @param FileName icon (.ICO), cursor (.CUR) or animated cursor (.ANI) file name (dynamic cursor will not actually move when displayed in ListView), or bitmap or icon handle, such as "HBITMAP :" handle. Other sources of icons include the following types of files: EXE, DLL, CPL, SCR, and other types that contain icon resources. - * @param IconNumber To use an icon group other than the first one in the file, please specify its number in IconNumber. If IconNumber is a negative number, it is assumed that its absolute value represents the resource ID of the icon in the executable file. In the following example, The default icon in the second icon group will be used: IL_Add(ImageListID, "C:\My Application.exe", 2). - * @param ResizeNonIcon can also load non-icon images, such as BMP, GIF and JPG. However, the last two parameters should be specified at this time to ensure correct execution: IconNumber should be a masked/transparent color code (for most images 0xFFFFFF [ White) may be the best); and ResizeNonIcon should be a non-zero value to scale the image into a single icon, or zero to divide the image into multiple icons that can match the actual width. - * - * Supported image types include ANI, BMP, CUR, EMF, Exif, GIF, ICO, JPG, PNG, TIF and WMF. - */ -IL_Add(ImageListID, FileName: $FilePath<'bmp|jpg|png|gif|ico'> [, IconNumber, ResizeNonIcon]) => Integer - -/** - * Create a new ImageList, initially empty, and return the unique ID of the ImageList (return 0 on failure). - * @param InitialCount The number of icons you want to put in the list immediately (if omitted, the default is 2). - * @param GrowCount The number of icons in the list, each time it exceeds the capacity of the current list, the number of icons in the list will increase (if omitted, the default is 5). - * @param LargeIcons If this parameter is 1 (true), the image list will contain large icons. If it is 0 (false), then it will contain small icons (this is the default when omitted). Will be added to the list proportionally The icons in are automatically scaled to fit the size of the large and small icons in the system. - */ -IL_Create(InitialCount := 2, GrowCount := 5, LargeIcons := false) => Integer - -/** - * Delete the specified ImageList, return 1 if it succeeds, and return 0 if it fails. - */ -IL_Destroy(ImageListID) => Integer - -/** - * Search for images in the screen area. - * @param OutputVarX [@since v2.1-alpha.3] Can be omitted. - * @param OutputVarY [@since v2.1-alpha.3] Can be omitted. - * @param ImageFile image file name, if the absolute path is not specified, it is assumed to be in A_WorkingDir. Supported image formats include ANI, BMP, CUR, EMF, Exif, GIF, ICO, JPG, PNG, TIF and WMF (BMP images must 16-bit or higher). Other sources of icons include the following types of files: EXE, DLL, CPL, SCR and other types that contain icon resources. - * - * Option: You can directly add zero or more of the following strings in front of the file name. Use a single space or tab to separate the options. For example: "*2 *w100 *h-1 C:\Main Logo.bmp". - * - * IconN: To use an icon group other than the first icon in the file, please specify *Icon followed by the icon group number. For example, *Icon2 will load the default icon in the second icon group. - * - * n (gradient value): Specify n as a number between 0 and 255 (inclusive), which is used to indicate the permissible gradient value of the red/green/blue channel intensity of each pixel in any direction. For example, if specified *2, and the color of the pixel is 0x444444, then any color from 0x424242 to 0x464646 will be regarded as a match. This parameter can be used for slight changes in the color of the image or the format used by ImageFile (such as GIF or JPG) cannot be accurately displayed on the screen The upper represents the image. If you specify 255 as the gradient value, all colors are matched. The default gradient value is 0. - * - * TransN: This option can match any color on the screen by specifying a certain color in the image, making it easier to find a match. It is often used to find PNG, GIF and TIF files with transparent areas (however, this is not required for icons Option, because their transparency is automatically supported). For GIF files, *TransWhite is likely to be useful. For PNG and TIF files, *TransBlack may be the best. Otherwise, specify N as other color names or RGB values (related For details, please refer to the color chart, or use the RGB mode of PixelGetColor). For example: *TransBlack, *TransFFFFAA, *Trans0xFFFFAA. - * - * wn and *hn: the width and height used to scale the image size (the width and height also determine which icon is loaded from the .ICO file with multiple icons). If both options are omitted, the ICO, DLL Or the icon loaded in the EXE file is adjusted to the system default small icon size, usually 16X16 (by specifying *w0 *h0 you can force the actual/internal size). Other images outside the icon are loaded at their actual size. To scale the image while maintaining the aspect ratio, specify -1 in one of the dimensions and a positive number in the other. For example, specifying *w200 *h-1 will scale the image to a width of 200 pixels and automatically set its height. - * - * Bitmap or icon handles can be used to replace file names. For example, "HBITMAP:*" handle. - */ -ImageSearch(&OutputVarX?: VarRef, &OutputVarY?: VarRef, X1, Y1, X2, Y2, ImageFile: $FilePath<'bmp|jpg|png|gif|ico'>) => Integer - -/** - * Delete the value in the standard format .ini file. - */ -IniDelete(FileName: $FilePath, Section [, Key]) => void - -/** - * Read a list of values, sections or section names from a standard format .ini file. - */ -IniRead(FileName: $FilePath [, Section, Key, Default]) => String - -/** - * Write values or sections into a standard format .ini file. - */ -IniWrite(Value, FileName: $FilePath, Section [, Key]) => void - -/** - * Display an input box, asking the user to enter a string. - * @param Options is a case-insensitive string option, and each option is separated from the last option with a space or tab. - * - * Xn Yn: The X and Y coordinates of the dialog box. For example, X0 Y0 places the window in the upper left corner of the desktop. If any of the coordinates is omitted, the dialog box will be centered in that dimension. Any coordinate can be a negative number to make The dialog box is partially or completely off the desktop (or on a secondary monitor in a multi-monitor setup). - * - * Wn Hn: The width and height of the client area of the dialog box, excluding the title bar and border. For example, W200 H100. - * - * T: Specify the timeout time in seconds. For example, T10.0 is 10 seconds. If this value exceeds 2147483 (24.8 days), then it will be set to 2147483. After the timeout period is reached, the input box window will be closed automatically at the same time Set Result to the word "Timeout". Value will still contain what the user entered. - * - * Password: shield the user's input. To specify which character to use, as shown in this example: Password - */ -InputBox([Prompt, Title, Options, Default]) => { - ; One of the following words indicating how the input box was closed: "OK", "Cancel", "Timeout". - Result: String, - ; The text entered by the user. - Value: String -} - -/** - * Install mouse hook - */ -InstallMouseHook(Install := true, Force := false) => void - -/** - * Install keyboard hook - */ -InstallKeybdHook(Install := true, Force := false) => void - -/** - * Search the specified content to the right or left in a character string. - * @param CaseSense One of the following values (if omitted, the default is 0): - * - * "On" or 1(True): Search is case sensitive. - * - * "Off" or 0(False): The letters A-Z are considered the same as their lowercase letters. - * - * "Locale": According to the current user's locale rules, the search is not case sensitive. For example, in most English and Western European regions, not only treats AZ as equivalent to their lowercase form, but also treats non-ASCII letters (Such as Ä and Ü) are considered equivalent. Depending on the nature of the string being compared, Locale is 1 to 8 times slower than Off. - * @param StartingPos If StartingPos is a negative number, perform the opposite search (from right to left), starting from the position on the right. For example, -1 starts from the last character. If StartingPos is 0 or exceeds the length of Haystack, it returns 0. - * - * Regardless of the value of StartingPos, the return value is always relative to the first character in Haystack. For example, the position of "abc" in "123abc789" is always 4. - * @param Occurrence If Occurrence is omitted, it defaults to 1, and the function returns the first matching position of Needle in Haystack. Specifying Occurrence as 2, returns the second matching position, 3 returns the third matching position, and so on. - */ -InStr(Haystack, Needle, CaseSense := false, StartingPos := 1, Occurrence := 1) => Integer - -/** - * Except that numbers from 0 to 9 are allowed, the others are the same as IsAlpha. - */ -IsAlnum(Value, Mode?) => Integer - -/** - * If Value is a string, it can be an empty string or only contain alphabetic characters. If there are any digits, spaces, tabs, punctuation or other non-letter characters anywhere in the string, it will be False. For example, if Value If it contains a space followed by a letter, it is not considered as an alpha. - * By default, only ASCII letters are considered. If you want to perform the check according to the current user's regional rules, please use IsAlpha(Value,'Locale'). - */ -IsAlpha(Value, Mode?) => Integer - -/** - * If Value is a valid date and time stamp, it can be all or the beginning of the YYYYMMDDHH24MISS format, then it is True. For example, a 4-digit string like 2004 is considered valid. Use StrLen to determine whether there are other time components. - * Years less than 1601 will be considered invalid because the operating system usually does not support them. The maximum year that is considered valid is 9999. - */ -IsDate(Value) => Integer - -/** - * If Value is a positive integer, an empty string, or a string containing only characters 0 to 9, then it is True. Other characters are not allowed, such as the following characters: space, tab, plus, minus, Decimal point, hexadecimal number, and 0x prefix. - */ -IsDigit(Value) => Integer - -/** - * True if Value is a floating-point number or a pure numeric string containing a decimal point. Leading and trailing spaces and tabs are allowed. The string can start with a plus sign, a minus sign or a decimal point, and it cannot be empty. - */ -IsFloat(Value) => Integer - -/** - * If Value is an integer or a pure numeric string (decimal or hexadecimal) without a decimal point, it is True. Leading and trailing spaces and tabs are allowed. The string can start with a plus or minus sign, and Can not be empty. - */ -IsInteger(Value) => Integer - -/** - * If Value is the name of a label defined in the current scope, IsLabel is True. - */ -IsLabel(Value) => Integer - -/** - * If Value is a string, it can be an empty string or only contains lowercase alphabetic characters, then it is True. If there are any digits, spaces, tabs, punctuation or other non-lowercase alphabetic characters anywhere in the string, it is False. - * By default, only ASCII letters are considered. If you want to perform the check according to the current user's regional rules, please use IsLower(Value,'Locale'). - */ -IsLower(Value, Mode?) => Integer - -/** - * If IsInteger(Value) or IsFloat(Value) is true, then it is True. - */ -IsNumber(Value) => Integer - -/** - * If Value is an object. This includes objects derived from Object, prototype objects (such as 0.base) and COM objects, but does not include numbers or strings. - */ -IsObject(Value) => Integer - -/** - * If the variable Value has been assigned, then IsSet is True. - * - * @param Var A variable. For example: `IsSet(MyVar)`. - */ -IsSet(Var) => Integer - -/** - * If the variable Value has been assigned, then IsSet is True. - * - * @param Ref An indirect reference to a variable. Usually it is not passed directly as in `IsSetRef(&MyVar)`, but indirectly, such as checking a parameter containing VarRef before dereferencing it. - */ -IsSetRef(Ref) => Integer - -/** - * If Value is a string, it can be an empty string or only contain the following blank characters: space (A_Space or `s), tab (A_Tab or `t), line feed (`n), carriage return (`r ), vertical tab character (`v) and paper feed character (`f), then True. - */ -IsSpace(Value) => Integer - -/** - * If Value is a valid date and time stamp, it can be all or the beginning of the YYYYMMDDHH24MISS format, then it is True. For example, a 4-digit string like 2004 is considered valid. Use StrLen to determine whether there are other time components. - * Years less than 1601 will be considered invalid because the operating system usually does not support them. The maximum year that is considered valid is 9999. - * You can use the word DATE instead of TIME, the effect is the same. - */ -IsTime(Value) => Integer - -/** - * If Value is a string, it can be an empty string or only contains uppercase alphabetic characters, then it is True. If there are any digits, spaces, tabs, punctuations or other non-uppercase alphabetic characters anywhere in the string, it is False. - * By default, only ASCII letters are considered. If you want to perform the check according to the current user's regional rules, please use IsUpper(Value,'Locale'). - */ -IsUpper(Value, Mode?) => Integer - -/** - * Hexadecimal digits: Same as digit, but the characters A to F (uppercase or lowercase) are also allowed. If the prefix 0x is present, it is acceptable. - */ -IsXDigit(Value) => Integer - -/** - * Display script information and the history of recent keystrokes and mouse clicks. - * @param MaxEvents Ignore this parameter to display the main window of the script, which is equivalent to selecting the "View -> Key History" menu item. - * Otherwise, this parameter setting can record the maximum number of keyboard and mouse events displayed in the window (the default is 40, the limit is 500). The key history is also reset, but the main window is not displayed or refreshed. Specify 0 to complete Disable key history. - */ -KeyHistory([MaxEvents]) => void - -/** - * Wait for the key or mouse/joystick button to be released or pressed. - * @param Options If this parameter is empty, the function will wait indefinitely for the user to release the specified key or mouse/joystick button. However, if the keyboard hook is not installed and the KeyName is a keyboard key similar to the Send function to simulate the release, then This button will be regarded as physically released. When the mouse hook is not installed, the same is true for the mouse button. - * Options: A string consisting of one or more of the following letters (in any order, the letters can be separated by spaces): - * - * D: Wait for the button to be pressed. - * - * L: Detect the logical state of the button, which is the state of the button considered by the operating system and the active window (may be inconsistent with its physical state). This option is ignored for the joystick button. - * - * T: Timeout (e.g. T3). The number of seconds to wait before the timeout, and return to 0 after the timeout. If the key or button reaches the specified state, the function does not wait for the timeout period to expire. On the contrary, it will immediately return 1. - * - * This timeout value can be a floating point number (e.g. 2.5), but cannot be a hexadecimal value (e.g. 0x03). - */ -KeyWait(KeyName, Options?) => Integer - -/** - * Displays the hotkeys in use by the current script, whether their subroutines are currently running, and whether or not they use the keyboard or mouse hook. - */ -ListHotkeys() => void - -/** - * Enable or disable line logging or display the most recently executed script line. - */ -ListLines([Mode]) => Integer - -/** - * Displays the script's variables: their names and current contents. - */ -ListVars() => void - -/** - * Return to the list of items/rows in the list view. - * @param Options specify what to retrieve. If it is empty or omitted, all text in the ListView will be retrieved. Otherwise, specify zero or more of the following words, separated by spaces or tabs: - * - * Selected: Only return selected (highlighted) rows, not all rows. If not, the return value is empty. - * - * Focused: Only return the focused row. If not, the return value is empty. - * - * Col4: Get only the fourth column (field) instead of all columns (replace 4 with the number you choose). - * - * Count: Returns the total number of rows in the ListView. - * - * Count Selected: Returns the number of selected (highlighted) rows. - * - * Count Focused: Returns the line number (position) of the focused line (if not, it returns 0). - * - * Count Col: Returns the number of columns in the control (if the number of columns cannot be determined, returns -1). - */ -ListViewGetContent([Options, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]) => String - -/** - * Returns the natural logarithm of Number (base e). - */ -Ln(Number) => Float - -/** - * Load the image file and return the bitmap or icon handle. - * @param FileName - * @param Options Zero or more strings in the following options, each option is separated by spaces or tabs:: - * - * Wn and Hn: the width and height of the image to be loaded, n is an integer. If a certain size is omitted or specified as -1, the size will be calculated based on the other size while maintaining the aspect ratio. If two All sizes are omitted, and the original size of the image will be used. If any size is specified as 0, the original size will still be used for that size. For example: "w80 h50", "w48 h-1" or "w48" (keep the width Height ratio), "h0 w100" (use the original height but cover the width). - * - * Iconn: Refers to the serial number of the icon to be loaded in a multi-icon file (usually an EXE or DLL file). For example, "Icon2" loads the second icon of the file. Any supported image format can be specified by "Icon1" To convert to an icon. However, if the ImageType parameter is omitted, the icon will be converted back to a bitmap. - * - * GDI+: Try to use GDI+ to load the image. For example, "GDI+ w100". - * @param ImageType variable reference, in this variable is stored a number representing the type of return handle: 0 (IMAGE_BITMAP), 1 (IMAGE_ICON) or 2 (IMAGE_CURSOR). - * If this parameter is omitted, the return value is always a bitmap handle (icon/cursor type will be converted as needed). This is because reliable use or deletion of bitmap/icon/cursor handle requires knowing which type it is. - * The @returns function returns the bitmap or icon handle according to the specified image or icon. - */ -LoadPicture(FileName: $FilePath<'bmp|jpg|png|gif|ico'> [, Options, &ImageType: VarRef]) => Integer - -/** - * Returns the logarithm of Number (base 10). - */ -Log(Number) => Float - -/** - * Trim characters from the beginning of the string. - */ -LTrim(String, OmitChars := ' `t') => String - -/** - * Returns the maximum value of one or more numbers. - */ -Max(Numbers*) => Float | Integer - -/** - * Retrieve the menu or menu bar object corresponding to the Win32 menu handle. - */ -MenuFromHandle(Handle) => Menu - -/** - * Call the menu item from the menu bar of the specified window. - * @param Menu The name (or name prefix) of the top-level menu item, such as File, Edit, View. This parameter can also use the position of the desired menu item, by using 1& to indicate the first menu, 2& to indicate the second, and so on analogy. - * - * According to the rules of the current user locale, the search is case-insensitive and stops at the first match. The ampersand (&) is used to represent the underlined letter in the menu item, which is usually unnecessary (e.g. &File is equivalent to File). - * - * `Known limitations:` If the parameter contains an ampersand (&), then it must exactly match the item name, including all non-literal ampersands (hidden or displayed as underscores). If the parameter does not contain ampersands, then Ignore all ampersands, including literal ones. For example, items shown as "a & b" may match the parameter value a && b or a b. - * - * Specify 0& to use the system menu of the window. - */ -MenuSelect(WinTitle, WinText?, Menu [, SubMenu1, SubMenu2, SubMenu3, SubMenu4, SubMenu5, SubMenu6, ExcludeTitle, ExcludeText]) => void - -/** - * Returns the minimum value of one or more numbers. - */ -Min(Numbers*) => Float | Integer - -/** - * Returns the remainder of Dividend divided by Divisor. - */ -Mod(Dividend, Divisor) => Float | Integer - -/** - * Check whether the specified monitor exists, and optionally retrieve its boundary coordinates. - */ -MonitorGet([N, &Left: VarRef, &Top: VarRef, &Right: VarRef, &Bottom: VarRef]) => Integer - -/** - * Returns the number of monitors. - */ -MonitorGetCount() => Integer - -/** - * Returns the operating system name of the specified monitor. - */ -MonitorGetName([N]) => String - -/** - * Returns the number of the main monitor. - */ -MonitorGetPrimary() => Integer - -/** - * Check whether the specified monitor exists, and optionally retrieve the boundary coordinates of its working area. - */ -MonitorGetWorkArea([N, &Left: VarRef, &Top: VarRef, &Right: VarRef, &Bottom: VarRef]) => Integer - -/** - * Click or hold the mouse button, or turn the mouse wheel. Note: The click function is usually more flexible and easier to use. - * @param {'Left'|'Right'|'Middle'|'X1'|'X2'|'WheelUp'|'WheelDown'|'WheelLeft'|'WheelRight'} WhichButton The button to click: Left (default), Right, Middle (or just the first letter of these names); or the fourth or fifth button of the mouse (X1 or X2). For example: MouseClick "X1" . This parameter can be omitted, at this time it defaults to Left. - * - * Left and Right correspond to the main button and the secondary button. If the user changes the button through the system settings, the physical position of the button is changed, but the effect remains unchanged. - * - * Mouse wheel to rotate: Specify WheelUp or WU to rotate the wheel upward (away from you); Specify WheelDown or WD to rotate the wheel downward (close to you). Specify WheelLeft (or WL) or WheelRight (or WR) Scroll the wheel to the left or right respectively. ClickCount is the number of grids of the wheel to be turned. - * @param Speed The speed of moving the mouse, between 0 (fastest) and 100 (slowest). - * If omitted, the default speed is used (set by SetDefaultMouseSpeed, otherwise it is 2). - * - * Speed is ignored for SendInput/Play mode; they will move the mouse to the target position instantaneously (but SetMouseDelay has a mode suitable for SendPlay). To display the mouse movement track (for example, when using a script to demonstrate to the audience) - please use SendEvent " {Click 100 200}" or SendMode "Event" (can be used in conjunction with BlockInput). - * @param DownOrUp If omitted, each click will consist of a "press" event followed by a "up" event. To change this behavior, please specify one of the following letters: - * - * D: Press the mouse button, but don't release it (i.e. generate a press event). - * - * U: Release the mouse button (i.e. generate a pop-up event). - * @param Relative If omitted, X and Y coordinates will be treated as absolute values. To change this behavior, specify the following letters: - * - * R: The X and Y coordinates are regarded as the offset from the current mouse position. In other words, the cursor will be moved X pixels to the right from the current position (a negative value will move to the left) and Y pixels will be moved down (a negative value will be Up). - */ -MouseClick([WhichButton, X, Y, ClickCount, Speed, DownOrUp, Relative]) => void - -/** - * Click and hold the designated mouse button, then move the mouse to the target coordinates, and then release the button. - * @param WhichButton Button to click: Left, Right, Middle (or the first letter of these words). For the fourth button, use X1, for the fifth button, use X2. For example: MouseClickDrag "X1", ... . - * - * Left and Right correspond to the main button and the secondary button respectively. If the user changes the button through the system settings, the physical position of the button will be changed, but the effect will not change. - * @param Relative If omitted, X and Y coordinates will be treated as absolute values. To change this behavior, specify the following letters: - * - * R: The X1 and Y1 coordinates are regarded as the offset from the current mouse position. In other words, the cursor will be moved X1 pixels to the right from the current position (negative value to the left) and down Y1 pixels (negative value is to the left) Up). Similarly, the X2 and Y2 coordinates will be regarded as the offset from the X1 and Y1 coordinates. For example, in the following example, the mouse will first move 5 pixels down and to the right from the starting position, and then from Drag 10 pixels down and to the right from this position: MouseClickDrag "Left", 5, 5, 10, 10,, "R". - */ -MouseClickDrag(WhichButton, X1?, Y1?, X2, Y2 [, Speed, Relative]) => void +;* Copyright 2023-2024 [GroggyOtter](https://github.com/GroggyOtter/ahkv2_definition_rewrite/issues/8), used with permission -/** - * Get the current position of the mouse cursor and which window and control it is hovering over. - * @param Flag If omitted or 0, the function uses the default method to determine OutputVarControl and stores the ClassNN of the control. To change this behavior, add one or two of the following numbers: - * - * 1: Use a simpler method to obtain OutputVarControl. This method can correctly obtain the information of the active/top-level child window of a multi-document interface (MDI) application (such as SysEdit or TextPad). However, for other cases (such as obtaining The control in the GroupBox control) is not so accurate. - * - * 2: Save the HWND of the control to OutputVarControl instead of the ClassNN of the control. - * - * For example, to make the above two options effective, the Flag parameter must be set to 3 (1+2). - */ -MouseGetPos([&OutputVarX: VarRef, &OutputVarY: VarRef, &OutputVarWin: VarRef, &OutputVarControl: VarRef, Flag]) => void +;@region v1.5 +;@endregion +;@region classes /** - * Move the mouse cursor. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Any.htm|`Any`} + * The root (topmost) class of AutoHotkey's type hierarchy. + * Every item in AHK v2 is derived from this base class. + * Primitives, objects, VarRefs, and everything else. + * @property {(Prototype)} Base - Retrieves the value's {@link https://www.autohotkey.com/docs/v2/Objects.htm#delegation|base object}. */ -MouseMove(X, Y [, Speed, Relative]) => void +class Any { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#Base|`Base`} + * Retrieve the value's {@link https://www.autohotkey.com/docs/v2/Objects.htm#delegation|base object}: `value.base` + * All items in AHK have this property and their value can be retrieved. + * However, only objects derived from the Object class can have their `Base` property altered. + * @type Prototype + * @see {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#GetBase|ObjGetBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#SetBase|ObjSetBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#Base|Object.Base} + * @throws Error - Assigning a new base that would change the native type of the object. + * @example Confirming an object came from the Array class. + * my_arr := Array() + * ; The base of a created object is normally derived + * ; from the prototype of the class that created it. + * if (my_arr.base = Array.Prototype) + * MsgBox('The base of my_arr is the Array class prototype.' + * '`nMeaning this item is an Array instance and it was created by the Array class.') + * + * ; Define a string + * str := 'AutoHotkey' + * if (str.base = Primitive.Prototype) + * MsgBox('Yes, all Strings are derived from the Primitive class') + */ + Base { + get => Prototype + set => EmptyString + } + + /** + * @description __Class + * Contains the name of the class the item was derived from. + * @type String + * @example __Class examples: + * obj := {a:1} + * MsgBox(obj.__Class) ; Shows Object + * + * str := 'Hi' + * MsgBox(str.__Class) ; Shows String + * + * cls := Test_Class() + * MsgBox(cls.__Class) ; Shows Test_Class + * + * class Test_Class { + * + * } + */ + __Class: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/Objects.htm#static__New|`__Init()`} + * A method that is called the first time an object is referenced. + * This method is defined automatically and handles initialization of any type of AHK object. + * Generally, this method should not be used directly. + * Class objects should use the {@link https://www.autohotkey.com/docs/v2/Objects.htm#Custom_NewDelete|`__New()`} method instead. + * @returns {(String)} + * An empty string is always returned. + */ + __Init() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/Objects.htm#Custom_NewDelete|`__Delete()`} + * A method that is automatically called whenever an object is released. + * This method does not exist by default and must be added to an object. + * @returns {(Any)} + * Return value implementation is determined by the user. + */ + __Delete() => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#GetMethod|`GetMethod()`} + * Retrieves the implementation function of a method. + * @param {(String)} [Name] + * The name of the method to retrieve. + * If omitted, the value that owns GetMethod() will attempt to self-validate, returning the value itself if successful: `value.GetMethod()` + * @param {(Number)} [ParamCount] + * The number of parameters that would be passed to the method or function. + * This number should not include a method's implicit `this` parameter. + * If omitted or if the parameter count cannot be verified, a check is made to see if a Call() method exists. + * @returns {(FuncObject|Object)} + * A reference to the specified method. + * If no method Name was provided, the value that owns GetMethod() is returned if validation is successful. + * @throws MethodError - Method is not found or cannot be retrieved without invoking a property getter. + * @throws ValueError - Validation attempted and failed. + * @throws MethodError - Validation attempted and failed. + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm|Objects} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasBase.htm|HasBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasMethod.htm|HasMethod()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasProp.htm|HasProp()} + * @example Getting a reference to the HasBase() method and using it. + * ; Get reference to the 'HasBase' method. + * ; All objects have this method. + * has_base := Any.GetMethod('HasBase') + * ; The method can now be used as a function to check if array is of "object" type + * if has_base(array, object) + * MsgBox('True. Array is derived from object') + */ + GetMethod([Name:=unset, ParamCount:=unset]) => Func + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#HasBase|`HasBase()`} + * Returns a 1 if the current object belongs to the provided BaseObj, otherwise returns a 0. + * Meaning BaseObj exists somewhere in the inheritance chain of this object. + * @param {(Object | Primitive)} BaseObj + * The base object to test against. + * @returns {(Boolean)} + * - `1` = BaseObj exists in this object's chain of inheritance. + * - `0` = BaseObj and this object do not share inheritance. + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm|Objects} | + * {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#Base|Object.Base} | + * {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#GetBase|ObjGetBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasMethod.htm|HasMethod()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasProp.htm|HasProp()} + * @example Confirming that Arrays are derived from Objects. + * if array.HasBase(object) + * MsgBox('Yes. Object is the base class of array.' + * '`nMeaning Array is derived from Object.') + */ + HasBase(BaseObj) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#HasMethod|`HasMethod()`} + * Returns a non-zero number if this object has a method by the specified Name. + * @param {(String)} [Name] + * The method name to check for. + * If omitted, the value that owns HasMethod() is checked to see if it's callable. + * @param {(Integer)} [ParamCount] + * The number of parameters that would be passed to the method or function. + * If omitted, or if the parameter count was not verified, a check is made to see if the object is callable. + * ParamCount should not include a method's implicit `this` parameter. + * @returns {(Boolean)} + * Name provided: + * - `1` = Method exists and ParamCount passed validation. + * - `0` = Method does not exist or ParamCount failed validation. + * + * Name omitted: + * - `1` = Object is callable. + * - `0` = Object is not callable. + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm|Objects} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasBase.htm|HasBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasProp.htm|HasProp()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetMethod.htm|GetMethod()} + * @example Verifying that an array has a push method + * ; Create an array and check for a push method + * arr := Array() + * if arr.HasMethod('Push') + * MsgBox('Yes. All Array objects have a Push() method.') + * + * ; Make a fat arrow function called fn + * fn(*) => MsgBox('Hello, world.') + * ; Create a call descriptor using fn + * descriptor := {call:fn} + * ; Use the descriptor to make a method + * obj := {my_method:descriptor} + * ; Check if object has a my_method method + * if obj.HasMethod('my_method') + * MsgBox('Yes, obj has a method calls "my_method()".') + * + * ; Omit the Name param and check the descriptor object to see if it's callable + * if descriptor.HasMethod() + * MsgBox('Yes, the descriptor object is callable.') + * + * ; Object lacking the specified method + * if descriptor.HasMethod('puppy') + * MsgBox('Yes, a puppy() method exists.') + * else MsgBox('No, a puppy() method does not exist.') + */ + HasMethod([Name:=unset, ParamCount:=unset]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#HasProp|`HasProp()`} + * Returns true if object has a property of the specified name. + * The property does not have to be assigned a value. It only needs to exist in the object. + * To remove a property, use the object's {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#DeleteProp|DeleteProp()} method. + * @param {(String)} Name + * The property name to check for. + * @returns {(Boolean)} + * - `1` = Object has specified property. + * - `0` = Object property not found. + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm|Objects} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasBase.htm|HasBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasMethod.htm|HasMethod()} + * @example Checking an object for a specific property. + * obj := {ahk:'AutoHotkey'} + * + * ; Check for a default property: + * if obj.HasProp('base') + * MsgBox('Yes, a base property exists.') + * else MsgBox('No, a base property does not exist.') + * + * ; Check for an own property: + * if obj.HasProp('ahk') + * MsgBox('Yes, an ahk property exists.') + * else MsgBox('No, an ahk property does not exist.') + * + * ; Check for a nonexistent property: + * if obj.HasProp('java') + * MsgBox('Yes, a java property exists.') + * else MsgBox('No, a java property does not exist.') + */ + HasProp(Name) => Integer +} /** - * Display the specified text in a small window containing one or more buttons (such as'Yes' and'No'). - * @param Options indicates the type of message box and possible button combinations. If it is empty or omitted, the default is 0. Please refer to the table below for the allowed values. In addition, you can specify zero or more of the following options: - * - * Owner: To specify the owner window for the message box, use the word Owner followed by HWND (window ID). - * - * T: Timeout. If the user does not close the message box within the specified time, to make the message box close automatically, please use the letter T followed by the timeout seconds, which can include a decimal point. If the value exceeds 2147483 (24.8 days), it will be Set to 2147483. If the message box times out, the return value is the word Timeout. - * - * 0x0 confirm - * - * 0x1 Confirm/Cancel - * - * 0x2 abort/retry/ignore + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object} + * Object is the basic class from which all AHK objects are derived. + * Each new object inherits properties and methods from the base object it is created from. + * All properties added after object creation are considered the object's "own properties". + * Objects can be iterated through using a {@link https://www.autohotkey.com/docs/v2/lib/For.htm|for-loop} and the {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#OwnProps|OwnProps()} method. + * @property {(Prototype)} Base - Retrieves or sets an object's base object. + * @example Different ways to create an object, adding a property, and looping through an object. + * ; Using the object class. + * obj1 := Object() + * obj1.prop := 'value' * - * 0x3 Yes/No/Cancel + * ; Specifically using the Call() method. + * ; This works identically to Object() + * obj2 := Object.Call() + * obj2.prop := 'value' * - * 0x4 yes/no + * ; Using object syntax (curly braces). + * obj3 := {prop: 'Value'} * - * 0x5 Retry/Cancel - * - * 0x6 cancel/retry/continue - * - * 0x10 Stop/error icon. - * - * 0x20 question mark icon. - * - * 0x30 exclamation point icon. - * - * 0x40 star icon (information). - * - * 0x100 makes the second button the default button. - * - * 0x200 makes the third button the default button. - * - * 0x300 Make the fourth button the default. A Help button is required - * - * 0x1000 system mode (always on top) - * - * 0x2000 mission mode - * - * 0x40000 to the top (WS_EX_TOPMOST style) (similar to the system mode, but the title bar icon is omitted) - * - * 0x4000 Add a help button (please refer to the remarks below) - * - * 0x80000 Let the text be displayed right-aligned. - * - * 0x100000 is used for Hebrew/Arabic right-to-left reading order. - * @returns When called from an expression, MsgBox returns one of the following strings to indicate which button the user pressed: - * OK, Cancel, Yes, No, Abort, Retry, Ignore, TryAgain, Continue, Timeout + * ; Use the .OwnProps() method to iterate, + * ; or loop through, an object. + * obj := {a:'auto', h:'hot', k:'key'} + * for key, value in obj.OwnProps() + * MsgBox('key: ' key '`nvalue: ' value) */ -MsgBox([Text, Title, Options]) => String +class Object extends Any { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#Call|`Object()`} + * Creates a new Object. + * @returns {Object} + * A reference to the newly created object. + * @example Different ways to create a new object. + * ; Calling object. + * my_obj1 := Object() + * my_obj1.prop := 'Value A' + * + * ; The same as using Object(). + * my_obj2 := Object.Call() + * my_obj2.prop := 'Value B' + * + * ; Using object syntax. + * my_obj3 := {prop: 'Value C'} + * + * ; View each object's property. + * loop 3 + * MsgBox(my_obj%A_Index%.prop) + */ + static Call() => Object + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#Clone|`Clone()`} + * Returns a shallow copy of the object. + * Each property and method owned by the object is copied into the clone. + * The clone uses the same base object as the original. + * Shallow copy means: + * - Primitive values (strings/numbers) are copied + * - Object **references** are copied. The objects referenced will not be duplicated. + * Meaning the original and the clone will both references the same object. See example. + * - {@link https://www.autohotkey.com/docs/v2/Objects.htm#Dynamic_Properties|Dynamic properties} are copied but not invoked. + * @returns {(Object)} + * Shallow copy of the object. + * @example Clone() example showing objects aren't duplicated. + * ; Create an object and make a clone + * obj := {string:'test', array:[1,2,3]} + * clone := obj.Clone() + * + * ; Change a primitive and an object value. + * obj.string := 'changed!' + * obj.array[1] := 'changed!' + * + * ; Showing the data of the shallow copy + * ; compared to the original object. + * MsgBox('clone.string = ' clone.string + * '`nobj.string = ' obj.string + * '`nPrimitive values are copied. Each is unique.' + * '`nChanging one does not change the other.' + * '`n`nobj.array[1] = ' obj.array[1] + * '`nclone.array[1] = ' clone.array[1] + * '`nObject reference are cloned, not the array itself.' + * '`nMeaning all clones point to the same objects.') + */ + Clone() => Object + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#DefineProp|`DefineProp()`} + * Defines a new own property for the object. + * This includes methods, which are callable properties. + * @param {(String)} Name + * A defining name for the property or method. + * @param {(Object)} DescriptorObject + * A descriptor object controls what happens when a property is used in different ways. + * There are 4 different keywords, each pertaining to a different action: `Call`, `Get`, `Set`, `Value` + * - `Call` = An object with a "call" property can be called like a function and will execute a function object: `obj.prop()` + * This allows you to pass in parameters and is how {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Methods} are created. + * - `Get` = An object with a "get" property will activate a function object whenever that property is accessed: `var := obj.prop` + * - `Set` = An object with a "set" property will activate a function object whenever that property is assigned: `obj.prop := 'some value'` + * - `Value` = Assigns a specific value to that property: `obj.prop := {value:'hi'}` + * This is identical to assigning the value with dot notation: `obj.prop := 'hi'` + * Descriptors that use function objects (get, set, call) will ALWAYS receive a reference to the object as the first parameter. + * The first parameter is generally names `this` to mean "this object". + * @returns {(Object)} + * A reference to the object that received the new property. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#GetOwnPropDesc|Object.GetOwnPropDesc()} + * @example Examples of all descriptor types: + * ; Adding a value descriptor. Create an object + * ; and give it a number property with a value of 100. + * obj := {} + * descriptor := {value:100} + * obj.DefineProp('number', descriptor) + * MsgBox('obj.number: ' obj.number) + * obj.number := 7 + * MsgBox('obj.number: ' obj.number) + * ; Value descriptors are automatically created + * ; when assigning a value using dot notation. + * obj.number2 := 50 + * MsgBox('obj.number2: ' obj.number2) + * + * ;============================== + * ; Adding a call descriptor. This creates a method. + * ; In AHK, a method is a "callable property". + * ; Create a mouse object and give it a call descriptor + * ; to get the current mouse coords when called: + * mouse := {} + * mouse.DefineProp('get_coords', {Call:mouse_get_coords}) + * mouse.get_coords('Screen') + * MsgBox('mouse x: ' mouse.x + * '`nmouse y: ' mouse.y) + * + * ; The function to run when get_coords is called + * ; CoordMode() is set using an optional parameter. + * ; Notice the first parameter is 'this' + * ; 'this' references the object that called the function + * ; 'this' will always be passed by call, get, and set. + * ; In this code, 'this' will be a reference to mouse + * mouse_get_coords(this, coord_type:='Client') { + * CoordMode('Mouse', coord_type) + * MouseGetPos(&mx, &my) + * this.x := mx + * this.y := my + * } + * + * ;============================== + * ; Adding a setter and getter to an object. + * ; Known as "accessors" and "mutators". + * ; Create an object with a number that will always be an integer. + * obj := {num:0} + * ; Add a setter and getter descriptor to the object. + * ; This ensures numbers saved to the property are always integer. + * ; This example also uses fat arrow functions instead of normal ones. + * descriptor := { + * Set:(this, value) => this.num := Integer(value), + * Get:(this) => this.num + * } + * ; Add the descriptor to obj and name it integer. + * obj.DefineProp('integer', descriptor) + * MsgBox('Default value of obj.integer = ' obj.integer) + * ; Assign a non-integer to the property + * obj.integer := 3.99 + * MsgBox('Assigning 3.99 converts the number to an integer, ' + * '`ntruncating the fractional part:' + * '`nobj.integer = ' obj.integer) + */ + DefineProp(Name, DescriptorObject) => Object + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#DeleteProp|`DeleteProp()`} + * Removes an own property from an object. + * Using `obj.prop := ''` only releases the data. It does not delete the property. + * @param {(String)} Name + * Name of the property to delete. + * @returns {(Any)} + * The value of the removed property is always returned. + * @see {@link } | + * {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#DefineProp|Object.DefineProp()} | + * @example Removing a property from an object. + * ; Make an object and give it a property + * obj := {delete_me:'Property Text'} + * ; Remove that property and save the value + * removed := obj.DeleteProp('delete_me') + * MsgBox('Value of the removed property:`n' removed) + * + * ; Check for property existence + * if obj.Has('delete_me') + * MsgBox('delete_me: ' obj.delete_me) + * else Msgbox('obj does not have a delete_me prop.') + */ + DeleteProp(Name) => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#GetOwnPropDesc|`GetOwnPropDesc()`} + * Returns the {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#DefineProp|descriptor object} of an own property. + * A descriptor is the function or func object associated with the property. + * @param {(String)} Name + * The name of the own property to get the descriptor of. + * @returns {(Object)} + * A reference to the specified {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#DefineProp|descriptor object}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#DefineProp|Object.DefineProp()} + * @example Getting a descriptor object from an object property. + * ; Create a math object and give it an add method. + * math := {} + * math.DefineProp('add', {call:add_fn}) + * + * ; Get a reference to the object's add descriptor. + * ; descriptor now contains a reference to the add_fn function. + * ; It'd be the same as writing: descriptor := add_fn + * descriptor := math.GetOwnPropDesc('add') + * + * ; Show that they work identically. + * MsgBox('Both add up to 7 b/c it`'s the same function:' + * '`nmath.add(3, 4): ' math.add(3, 4) + * '`nadd_desc(4, 3): ' descriptor(3, 4)) + * + * ; The function that the method and descriptor reference. + * add_fn(this, n1, n2) { + * return (n1 + n2) + * } + */ + GetOwnPropDesc(Name) => {Get?: Func, Set?: Func, Call?: Func, Value?: Any} + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#HasOwnProp|`HasOwnProp()`} + * Returns true if the object has a property by the specified Name. + * @param {(String)} Name + * The name of a property. + * @returns {(Integer)} + * - `1` = Object has the specified property. + * - `0` = Object property not found. + * @example Test if an object has a specific property. + * obj := {test: 'data'} + * if (obj.HasOwnProp('test')) + * MsgBox('obj has a property named test.') + * else MsgBox('obj does not have a test property.') + */ + HasOwnProp(Name) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#OwnProps|`OwnProps()`} + * Returns an enumerator object containing all the object's own properties. + * Enumerators are normally used with a {@link https://www.autohotkey.com/docs/v2/lib/For.htm|for-loop} to iterate through each object property. + * @returns {(Enumerator)} + * An {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|enumerator object}. + * @example Using OwnProps() to iterate through an object's properties. + * ; Create an object. + * obj := {p1:'apple', p2:'banana', p3:'cherry'} + * + * ; Get enumerator object from obj + * enum := obj.OwnProps() + * ; Use enumerator to iterate through each property. + * for key, value in enum + * MsgBox('Key: ' key '`nvalue: ' value) + * + * ; It's better to use the function call directly + * ; instead of making and referencing a 1-time-use object. + * for key, value in obj.OwnProps() + * MsgBox('Key: ' key '`nvalue: ' value) + * + * ; To get only the key names, specify only one for-loop var name + * for key in obj.OwnProps() + * MsgBox('Key: ' key) + */ + OwnProps() => Enumerator | Enumerator +} /** - * Returns the binary number stored at the specified address + offset. - */ -NumGet(Source [, Offset], Type) => Float | Integer + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm|`Array`} + * A type of object dedicated to storing values in sequential order. + * Each individual piece of data is called an element and is referenced by an index number. + * All AHK indexes start at 1. This is contrary to most other languages which start at 0. + * Arrays are also referred to as lists, vectors, or tuples. + * Arrays can contain arrays, allowing for the creation of a 2 dimensional (2D) array/table/matrix. + * This can be extended into further nesting, creating 3D arrays/4D arrays/etc called tensors. + * @property {(Integer)} Length - Retrieves or sets the length of an array. + * @property {(Integer)} Capacity - Retrieves or sets the current capacity of an array. + * @property {(Any)} Default - Defines the default value to return when an index has no value or does not exist. + * @property {(Any)} __Item - Used to retrieve or set the value of array element. + * The use of the word __Item is normally omitted and bracket syntax is used. + * `arr[2]` infers `arr.__Item[2]` and will yield the same results. + * @example Array basics: + * ; New array + * arr := [] + * ; New array initialized with data + * animals := ['bird', 'cat', 'dog'] + * MsgBox(animals[1]) + * ; Add item to end of array + * animals.Push('eel') + * ; Add multiple items to end of array + * animals.Push('fox', 'goat') + * ; Insert value into the array, pushing other values right. + * animals.InsertAt(1, 'ape') + * MsgBox(animals[1]) + * ; Remove last item from array + * last_animal := animals.Pop() + * ; Retrieve element value using index + * MsgBox(animals[5]) + * ; Check if array has a valid index number + * MsgBox('Index 6 has value: ' animals.Has(6)) + * ; Delete element value but leave the element in the array + * removed := animals.Delete(6) + * MsgBox(removed) + * ; Remove one or more elements + * animals.RemoveAt(4, 3) + */ +class Array extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Length|`Length`} + * Get or set the length of the array. + * Length is the total number of elements in the array, including any unset elements. + * Increasing Length will create new elements, each with an {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset} value. + * Setting Length to a lower number will truncate all elements past that number. + * @type Integer + * @example Setting an array's length. + * ; Create an array with 2 elements + * arr := ['A', 'B'] + * MsgBox("New array:`narr := ['A', 'B']" view_array(arr)) + * + * ; Increase its length to 4 + * ; New element values are unset (not initialized) + * arr.Length := 4 + * MsgBox('Increase array length to 4.' + * '`narr.Length := 4' view_array(arr)) + * + * ; Create an array with 6 elements + * arr := ['A', 'B', 'C', unset, [], {}] + * MsgBox('New array with 5 elements:' + * "`narr := ['A', 'B', 'C', unset, [], {}]" view_array(arr)) + * + * ; Now decrease its length to 2. + * ; This will truncate the last 3 elements. + * arr.Length := 2 + * MsgBox('Reduce array length to 2.' + * '`narr.length := 2' view_array(arr)) + * + * ; A function to view the primitives in an array. + * view_array(arr) { + * ; String to build and return. + * str := '`n' + * ; Loop through each item of the array. + * for index, val in arr { + * ; Create new line and add index number. + * str .= '`nIndex ' index ': ' + * ; Using switch to check data type + * switch { + * ; Check if unset first + * case !IsSet(val): str .= '' + * ; Check for primitive value + * case (val is Primitive): str .= val + * ; Otherwise, include the type + * default: str .= '<' StrUpper(Type(val)) '>' + * } + * } + * ; Return string + * return str + * } + */ + Length { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Capacity|`Capacity`} + * Get or set the capacity of the array. + * Capacity is the total amount of elements the array can hold before the script needs to expand the array's memory. + * This is not the same as array `Length`, which is the total amount of elements in use. + * If Capacity is set lower than `Length`, all elements greater than the new length are truncated. + * @type Integer + * @example Showing that Capacity differs from Length. + * arr := ['a', 'b', 'c', 'd'] + * MsgBox('Array Length: ' arr.Length + * '`nArray Capacity: ' arr.Capacity + * '`n' view_array(arr)) + * arr.RemoveAt(2, 2) + * MsgBox('After arr.RemoveAt(2, 2)' + * '`n`nRemoving values does not change capacity.' + * '`nLength: ' arr.Length + * '`nCapacity: ' arr.Capacity + * '`n' view_array(arr)) + * + * view_array(arr) { + * str := '`nArray contents:' + * for index, value in arr + * str .= '`nIndex ' index ':' value + * return str + * } + */ + Capacity { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Default|`Default`} + * Defines the default value returned when an unset element is accessed. + * This property does not exist until the user defines it. + * Default values are not used when the index is out of range. An error is thrown. + * To remove a Default value from an array, the property must be removed using {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#|DeleteProp()}. + * @type Any + * @throws UnsetItemError - An attempt was made to read an unset value. + * @example Assigning a default array property and removing it. + * ; Create an array with an unset value. + * arr := ['a', 'b', unset] + * ; Set the default property. + * arr.Default := 'Not found' + * ; Reference a set and unset property. + * MsgBox('Index 2: ' arr[2] '`nIndex 3: ' arr[3]) + * + * ; The Default property does not affect + * ; an invalid or out of range index. + * try + * MsgBox(arr[7]) + * ; Catch the error that's thrown + * ; This prevents the script from closing. + * catch as err + * ; And show the error message. + * MsgBox('Error:`n' err.Message) + * + * ; Finally, we can remove the array's default property. + * arr.DeleteProp('Default') + * ; And if an unset value is accessed, an error is thrown + * try MsgBox(arr[3]) + * ; Catch error and show it + * catch as err + * MsgBox('Error:`n' err.Message) + */ + Default?: Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#__Item|`__Item[]`} + * Get or set the value of an array element. + * The use of the word `__Item` is normally omitted and bracket syntax is used. + * `arr[2]` is the same as `arr.__Item[2]`. + * @param {(Integer)} Index + * The number if the element to get or set. + * A negative number can be used to go count backward through the array: `-1` last element, `-2` second from last, etc. + * @throws IndexError - Using an out-of-bounds index. + * @example Using the __item property. + * arr := ['a','b','c'] + * MsgBox('Accessing array elements:' + * '`narr.__Item[2] = ' arr.__Item[2] + * '`n`nNormally, __Item is omitted and only brackets are used: ' + * '`narr[2] = ' arr[2] + * '`n`nA negative index starts at the end and counts backwards: ' + * '`narr[-1] = ' arr[-1] + * '`narr[3] = ' arr[3] + * ) + */ + __Item[Index] { + get => Any + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Call|`Call()`} + * Creates a new Array. + * @param {(Any)} [ValueN] + * Include zero or more values to add to the array. + * Values are assigned to the array in the order they're listed. + * Parameter 1 is element 1, parameter 3 is element 3, etc. + * Skipping a parameter will still create the element but its value will be {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * @example 3 different ways to create an array. + * my_arr1 := Array(1, 2, 3) + * my_arr2 := Array.Call(1, 2, 3) + * my_arr3 := [1, 2, 3] + * + * ; The 2nd element will be unset + * my_arr4 := Array('a', , 'c') + * ; This is the same as my_arr4 + * my_arr5 := ['a', unset , 'c'] + */ + static Call([ValueN*]) => Array + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Clone|`Clone()`} + * Returns a shallow copy of the array. + * A shallow copy is not a true duplicate. It means: + * - Primitive values (strings/numbers) are copied. + * - Object *references* are copied. The objects they reference are not duplicated. + * This means the original and the clone will reference the same object. + * @returns {(Array)} + * Shallow copy of the array. + * @example Clone() shallow copy example. + * abc_arr := ['A', 'B', 'C'] + * ; Make an array. First element is a primitive. + * ; Second and third are both array references + * ; regardless of where the array is declared. + * arr := ['OriginalText', abc_arr, [1, 2, 3]] + * ; Create a clone to inspect + * clone := arr.Clone() + * + * ; Change the original array string + * arr[1] := 'Changed!' + * ; Change the original array references + * arr[2][1] := 'Changed!' + * arr[3][1] := 'Changed!' + * + * MsgBox('Primitive values are copied when cloning.' + * '`nEach is unique.' + * '`nChanging one does not change the other.' + * '`n`n`tarr[1] string = ' arr[1] + * '`n`tclone[1] string = ' clone[1] + * '`n`nObject references get copied.' + * '`nThis is not the same as cloning the entire object.' + * '`nRemember, these are references.' + * '`nBoth the original and clone point to the same object.' + * '`n`n`tarr[2][1] reference = ' arr[2][1] + * '`n`tarr[2][1] reference = ' clone[2][1] + * '`n`n`tarr[3][1] subarray = ' arr[3][1] + * '`n`tarr[3][1] subarray = ' clone[3][1]) + */ + Clone() => Array + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Delete|`Delete()`} + * Removes the value of an array element, leaving that element value as {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * Deleting a value does not affect the array's {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Length|Length}. + * Use {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#RemoveAt|RemoveAt()} to completely remove an element. + * @param {(Integer)} Index + * The index number of the element to delete. + * A negative index can be used to count from the end to the start. + * -1 = last element, -2 = second from last element, etc. + * @returns {(Any)} + * The removed value is always returned. + * @throws ValueError - Index is out of range. + * @example Removing an element from an array. + * ; Create an array and assign a default + * arr := ['a', 'b', 'c', 'd'] + * arr.Default := 'No value set' + * ; Show array and length + * MsgBox('Array length: ' arr.Length + * '`n' view_array(arr)) + * + * ; Remove and save the 2nd element + * removed1 := arr.Delete(2) + * ; Remove and save the last element + * removed2 := arr.Delete(-1) + * + * ; Show removed values and array again + * MsgBox('Array length Unchanged: ' arr.Length + * '`nIndex 2 Removed value: ' removed1 + * '`nIndex -1 Removed value: ' removed2 + * '`n' view_array(arr)) + * + * view_array(arr) { + * str := '`nArray contents:' + * for index, value in arr { + * str .= '`nIndex ' index ': ' + * if IsSet(value) + * str .= value + * else str .= 'UNSET VALUE' + * } + * return str + * } + * + */ + Delete(Index) => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Get|`Get()`} + * Returns the value of the specified array element, or a default value if one is set. + * @param {(Integer)} Index + * The number of the element to get from the array. + * A negative index can be used to count from the end to the start. + * -1 = last element, -2 = second from last element, etc. + * @param {(Any)} [Default] + * A value to return if the specified index contains an unset value. + * The Default parameter has precedence over an array's {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Default|Default property}. + * @returns {(Any)} + * The value at the specified index. + * If no value is found, the Default parameter is used. + * If no Default parameter was provided, the array's {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Default|Default property} is used. + * If no Default property exists, an {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|UnsetItemError} is thrown. + * @throws UnsetItemError - Value not set, no default parameter provided, and no default property defined. + * @throws IndexError - Index is zero or out of range. + * @example Demonstrating the multiple ways Get() works. + * arr := ['a', 'b', 'c', unset] + * arr.Default := 'Default Property Value' + * MsgBox('index 2: ' arr.Get(2, 'Default Parameter Value') + * '`nindex -2: ' arr.Get(-2, 'Default Parameter Value') + * '`nindex 4: ' arr.Get(4, 'Default Parameter Value') + * '`nindex 4: ' arr.Get(4) + * '`nThe "Default parameter" takes precedence over a "Default property".') + */ + Get(Index [,Default:=unset]) => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Has|`Has()`} + * Returns true if the specified array element has a set value. + * Unlike {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Get|Get()}, Has() does not throw an error if the Index is out of range. + * @param {(Integer)} Index + * The number of the element to check for a value. + * A negative index can be used to count from the end to the start. + * -1 = last element, -2 = second from last element, etc. + * @returns {(Boolean)} + * - `1` = The element has a set value. + * - `0` = The element is unset or does not exist. + * @example Using Has() to check array elements for a value. + * arr := ['a', 'b', 'c', unset] + * MsgBox('Has(2) - String: ' arr.Has(2) + * '`nHas(4) - Unset value: ' arr.Has(4) + * '`nHas(7) - Out of range index: ' arr.Has(7)) + */ + Has(Index) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#InsertAt|`InsertAt()`} + * Inserts one or more values at a given position in the array. + * All the elements after that position are shifted to the right. + * @param {(Integer)} Index + * The array position to receive the first value. + * An index of 0 will append value(s) to the end of the array, similar to {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Push|Push()}. + * `arr.InsertAt(arr.length+1, value)` is the same as `arr.Push(value)`. + * A negative index can be used to count from the end to the start. + * -1 = last element, -2 = second from last element, etc. + * @param {(Any)} Value + * The value to insert at `Index`. + * An array of values can be used if it is marked {@link https://www.autohotkey.com/docs/v2/Functions.htm#VariadicCall|variadic*} and is the last parameter. + * This causes each element of that array to be added instead of adding a reference to the array. See example code. + * @param {(Any)} [AdditionalValues] + * Any number of additional values, each being inserted after the other. + * All other array elements are shifted right each time another value is added to the array. + * An array of values can be used if it is marked {@link https://www.autohotkey.com/docs/v2/Functions.htm#VariadicCall|variadic*} and is the last parameter. + * This causes each element of that array to be added instead of adding a reference to the array. See example code. + * @returns {(String)} + * An empty string is always returned. + * @throws ValueError - Index is out of range + * @example Multiple ways to insert values into an Array. + * ; Using a 0 index. + * arr := [1, 2, 3] + * arr.InsertAt(0, 4) + * MsgBox('Add 4 to the end using 0 as the index.' + * '`nThis works the same as arr.Push(4)' + * '`n' view_array(arr)) + * arr.InsertAt(1, 0) + * MsgBox('Insert a zero at the beginning (Index 1):' + * '`n' view_array(arr)) + * + * ; Inserting multiple values. + * arr := ['A', 'B', 'E', 'F'] + * arr.InsertAt(3, 'C', 'D') + * MsgBox('Inserting multiple values:' + * '`n' view_array(arr)) + * + * ; Inserting multiple values using + * ; an array of values. + * arr := ['A', 'B', 'E'] + * arr_of_values := ['C', 'D'] + * arr.InsertAt(3, arr_of_values*) + * MsgBox('Inserting multiple values using ' + * 'an array of values:' + * '`n' view_array(arr)) + * + * view_array(arr) { + * str := '`nArray contents:' + * for index, value in arr { + * str .= '`nIndex ' index ': ' + * if IsSet(value) + * str .= value + * else str .= 'UNSET VALUE' + * } + * return str + * } + */ + InsertAt(Index, Value [,AdditionalValues*]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Pop|`Pop()`} + * Removes and returns the last element of the array. + * Pop() removes the element, unlike {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Delete|Delete()}, which sets the element to {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * This is reflected by the array's {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Length|Length}. + * `arr.Pop() is the same as `arr.RemoveAt(-1)` and `arr.RemoveAt(arr.Length)`. + * @returns {(Any)} + * The removed element is always returned. + * @throws Error - Cannot remove an element from an empty array. + * @example How Pop() + * arr := ['a', 'b', 'c'] + * MsgBox('Array size: ' arr.Length) + * removed_item := arr.Pop() + * MsgBox('Array size post-Pop(): ' arr.Length + * '`nRemoved value: ' removed_item) + */ + Pop() => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Push|`Push()`} + * Adds one or more values to the end of an array. + * `arr.Push(value) is the same as `arr.InsertAt(0, value)` and `arr.InsertAt(arr.length+1, value)`. + * @param {(Any)} Value + * A value to add to the end of the array. + * An array of values can be used if it is marked {@link https://www.autohotkey.com/docs/v2/Functions.htm#VariadicCall|variadic*} and is the last parameter. + * This causes each element of the passed array to be added individually instead of adding an array reference. See example code. + * @param {(Any)} [AdditionalValues] + * Any number of additional values can be included, each declared in its own parameter. + * An array of values can be used if it is marked {@link https://www.autohotkey.com/docs/v2/Functions.htm#VariadicCall|variadic*} and is the last parameter. + * This causes each element of that array to be added instead of adding a reference to the array. See example code. + * @returns {(String)} + * An empty string is always returned. + * @example Add an element to the end of an array. + * ; Adding a single value + * arr := ['a', 'b', 'c'] + * arr.Push('d') + * view_array(arr) + * + * ; Adding an array of values + * arr := ['a', 'b', 'c'] + * arr_of_values := ['d', 'e'] + * arr.Push(arr_of_values*) + * view_array(arr) + * + * ; Adding a reference to an array + * arr := ['a', 'b', 'c'] + * arr_of_values := ['d', 'e'] + * arr.Push(arr_of_values) + * MsgBox('This time, the 4th array element is a reference to another array.' + * '`narr[4][1] = ' arr[4][1] + * '`narr[4][2] = ' arr[4][2]) + * + * view_array(arr) { + * str := '`nArray contents:' + * for index, value in arr { + * str .= '`nIndex ' index ': ' + * if IsSet(value) + * str .= value + * else str .= 'UNSET VALUE' + * } + * return str + * } + */ + Push(Value*) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#RemoveAt|`RemoveAt()`} + * Removes one or more elements from the array at the specified index. + * Unlike {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Delete|Delete()}, this affects the array's {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Length|Length}. + * @param {(Integer)} Index + * The array element number to be removed. + * All remaining elements are shifted to the left, filling in the removed element slots. + * A negative index can be used to count from the end to the start. + * -1 = last element, -2 = second from last element, etc. + * @param {(Integer)} [Length] + * The number of elements to remove, starting at the provided `Index`. + * If omitted, this defaults to 1. + * @returns {(Any)} + * If only one element is removed, that element's value is returned. + * Otherwise, an empty string is returned. + * @throws ValueError - Index is out of range. + * @example Remove a value from a specific element. + * ; Remove a single value + * arr := ['a', 'b', 'c', 'd'] + * removed := arr.RemoveAt(2) + * MsgBox('arr.RemoveAt(2):' + * '`n`n' view_array(arr) + * '`nRemoved value: ' removed) + * + * ; Remove multiple values + * arr := ['a', 'b', 'c', 'd'] + * removed := arr.RemoveAt(2, 2) + * MsgBox('arr.RemoveAt(2, 2)' + * '`n`n' view_array(arr) + * '`n`nNo value was returned because multiple values were removed.' + * '`nRemoved value: ' removed) + * + * ; Clear array of all elements + * arr := ['a', 'b', 'c', 'd'] + * removed := arr.RemoveAt(1, arr.Length) + * MsgBox('Empty array by removing all elements.' + * '`narr.RemoveAt(1, arr.Length)' + * '`nArray Length: ' arr.Length) + * + * view_array(arr) { + * str := '`nArray contents:' + * for index, value in arr { + * str .= '`nIndex ' index ': ' + * if IsSet(value) + * str .= value + * else str .= 'UNSET VALUE' + * } + * return str + * } + */ + RemoveAt(Index [,Length:=1]) => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#__New|`__New()`} + * This method exists to support {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Call|Array's Call()}, and is not intended to be called directly. + * {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Push|Push()} should be used to add values to an array. + * An array of values can be used if it is marked {@link https://www.autohotkey.com/docs/v2/Functions.htm#VariadicCall|variadic*} and is the last parameter. + * This causes each element of that array to be added, in order, to the current array. + * @param {(Any)} [ValueN] + * A value to add to the array. + * Any number of values can be added. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm#Custom_NewDelete|Construction and Destruction} | + * {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Push|Push()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#Call|Call()} + */ + __New([ValueN*]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Array.htm#__Enum|`__Enum()`} + * Creates an {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|Enumerator} object that allows iteration of the array's elements. + * This method is typically not called directly but instead is used by a {@link https://www.autohotkey.com/docs/v2/lib/For.htm|for-loop} to loop through each element. + * @returns {(Enumerator)} + * Enumerable function object. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|Enumerator Object} + * @example Manually using an enumerator. + * arr := ['a', 'b', 'c'] + * + * ; Normal use: Passing the array to the for-loop + * ; The for-loop always checks the object for an __Enum() method. + * For index, value in arr + * MsgBox('index: ' index '`nvalue: ' value) + * + * ; Or create an enumerator object + * enum := arr.__Enum() + * ; And pass it the for-loop. + * For index, value in enum + * MsgBox('index: ' index '`nvalue: ' value) + * + * ; Example of setting up a for-loop using + * ; an enumerator and a while-loop. + * enum := arr.__Enum() + * While enum(&index, &value) + * MsgBox('Index: ' index '`nValue: ' value) + */ + __Enum() => Enumerator | Enumerator +} /** - * Store one or more numbers in binary format to the specified address + offset location. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|`Buffer`} + * Encapsulates a block of memory for use with memory sensitive actions such as {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()}, {@link https://learn.microsoft.com/en-us/cpp/cpp/struct-cpp?view=msvc-170|structures}, {@link https://www.autohotkey.com/docs/v2/lib/StrPut.htm|StrPut()}, and raw file I/O. + * Buffer objects are typically created by calling Buffer(), but can also be returned by {@link https://www.autohotkey.com/docs/v2/lib/FileRead.htm|FileRead} with the "RAW" option. + * It helps to understand the basics of "binary" and "data types" when working with buffers. + * @property {(Integer)} Ptr - Retrieves the buffer's current memory address. + * @property {(Integer)} Size - Retrieves or sets the buffer's size, in bytes. + * @see {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/NumPut.htm|NumPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/NumGet.htm|NumGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrPut.htm|StrPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrGet.htm|StrGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/File.htm#RawRead|File.RawRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/File.htm#RawWrite|File.RawWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ClipboardAll.htm|ClipboardAll} */ -NumPut(Type1, Number1, *, Target [, Offset]) => Integer +class Buffer extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Ptr|`Ptr`} + * Retrieves the buffer's current memory address. + * This property is read-only and cannot be assigned a new value. + * @type Integer + * @example Showing and using a buffer pointer. + * buff := Buffer(4) + * NumPut('Int', 420, buff.Ptr) + * MsgBox('Pointer address of this buffer:`n' buff.ptr + * '`nNumber stored in buffer: ' NumGet(buff.ptr, 0, 'Int')) + */ + Ptr { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Size|`Size`} + * Retrieves or sets the buffer's size, in bytes. + * @type Integer + * @throws MemoryError - Memory could not be allocated. + * @example Getting the size of a buffer. + * buff := Buffer(16) + * MsgBox('Size of buffer: ' buff.Size ' bytes') + */ + Size { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|`Buffer()`} + * Creates a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer} object. + * @param {(Integer)} [ByteCount] + * Number of bytes to allocate. + * If omitted, the Buffer is created with a null (zero) `Ptr` and `Size` is 0. + * @param {(Integer)} [FillByte] + * Number between 0-255. Each byte will be filled with that number. + * If omitted, the buffer's memory is allocated but the bytes of the buffer will contain whatever previous data was there before. + * If the buffer will be written to before being read, it is best to omit `FillByte`. + * This saves time by avoiding having to write data to every single bit. + * If the buffer will be read first, FillByte must be used. + * @returns {(Buffer)} + * A buffer object. + * @throws MemoryError - If the memory could not be allocated. + * @example Creating a new 8-byte buffer and writing 2 integers to it. + * buff := Buffer(8) + * NumPut('Int', 100, 'Float', 3.14, buff) + * MsgBox('The buffer object "buff" has been created.' + * '`nIt is ' buff.size ' bytes in size.' + * '`nThe first number is an integer: ' NumGet(buff, 'Int') + * '`nThe second number is a float: ' Round(NumGet(buff, '4', 'Float'), 2)) + */ + static Call([ByteCount:=0, FillByte:=unset]) => Buffer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#__New|`__New()`} + * Allocates or reallocates the buffer and optionally fills it. + * This method exists to support buffer's {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Call|Call()} method and is not intended to be called directly. + * @param {(Integer)} [ByteCount] + * Number of bytes to allocate or reallocate or using zero to free the buffer. + * This is equivalent to setting the {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Size|Size} property. + * If omitted, 0 is used. + * @param {(Integer)} [FillByte] + * Number between 0-255. Each byte will be filled with that number. + * If omitted, the buffer's memory retains whatever prior data was already there. + * If the buffer will be written to before being read, it is better to omit `FillByte` as this saves having to write to memory. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm#Custom_NewDelete|Construction and Destruction} + * @example Expanding, storing, and retrieving a number from a buffer. + * ; A buffer that can hold 2 bytes + * ; 2 bytes can hold a number between 0 and 65,535. + * buff := Buffer(2) + * + * ; This number is too large and needs at least 3 bytes. + * num := 70001 + * + * ; Expand buffer to 4 bytes. + * ; It can now hold a number between 0 and 4,294,967,295. + * buff.__New(4) + * ; Assign number to buffer + * NumPut('uInt', num, buff) + * ; Show buffer contains the number + * MsgBox('Value stored in buff: ' NumGet(buff, 'Int')) + */ + __New([ByteCount:=0, FillByte:=unset]) => EmptyString +} /** - * Increase the reference count of the object. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|`ClipboardAll`} + * Creates an object containing all the data on the clipboard. This includes binary data, like pictures or an exe. + * ClipboardAll is derived from the Buffer class. + * @property {(Integer)} Ptr - The address of the data contained by the object. This address is valid until the object is freed. + * @property {(Integer)} Size - The size, in bytes, of the raw binary data. + * @see {@link https://www.autohotkey.com/docs/v2/lib/A_Clipboard.htm|A_Clipboard} | + * {@link https://www.autohotkey.com/docs/v2/lib/ClipWait.htm|ClipWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnClipboardChange.htm|OnClipboardChange()} | + * {@link https://www.autohotkey.com/docs/v2/lib/_ClipboardTimeout.htm|#ClipboardTimeout} | + * {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer} + * @example A paste function that backs up and restores the clipboard. + * *F1::paste('Hello, world!') + * + * paste(data) { + * ; Backup clipboard + * clipbackup := ClipboardAll() + * ; Set new data to clipboard + * A_Clipboard := data + * ; Send the default paste command + * Send('^v') + * ; Check repeatedly to see if the clipboard is still open + * Loop + * ; If more than 20 tries, notify of failure + * if (A_Index > 20) + * return TrayTip(A_ThisFunc ' failed to restore clipboard contents.') + * ; Otherwise, wait another 100ms + * else Sleep(100) + * Until !DllCall('GetOpenClipboardWindow', 'Ptr') + * ; Finally, restore original clipboard contents + * A_Clipboard := clipbackup + * } */ -ObjAddRef(Ptr) => Integer +class ClipboardAll extends Buffer { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Ptr|`Ptr`} + * Retrieves the memory address of the buffer's data. + * This address is valid until the object is freed. + * This property is read-only and cannot be assigned a new value. + * @type Integer + * @throw Error - This is a read-only property and cannot be written to. + * @example Showing a ClipboardAll buffer address. + * clip_backup := ClipboardAll() + * MsgBox('The memory address of the backup is: ' clip_backup.Ptr) + */ + Ptr { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Size|`Size`} + * Retrieves the size, in bytes, of the raw binary data. + * @type Integer + * @example Showing size of a buffer. + * clip_backup := ClipboardAll() + * MsgBox('Size of the clipboard data is ' clip_backup.Size ' bytes.') + */ + Size { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ClipboardAll.htm|`ClipboardAll()`} + * Save the contents of the clipboard to a clipboard buffer object or create a clipboard object using the provided binary data. + * This object can be assigned to {@link https://www.autohotkey.com/docs/v2/lib/A_Clipboard.htm|A_Clipboard} to restore the data to the clipboard. + * @param {(Object|Integer)} [Data] + * A memory address or a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|buffer-like} object (any object with a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Ptr|Ptr} and {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Size|Size} property). + * The data must be in a {@link https://www.autohotkey.com/docs/v2/lib/ClipboardAll.htm#Remarks|specific format}, so typically it originates from a previous call to {@link https://www.autohotkey.com/docs/v2/lib/ClipboardAll.htm|ClipboardAll()}. + * Omitting this parameter and the `Size` parameter will retrieve the contents of the clipboard. + * @param {(Integer)} [Size] + * The number of bytes of data to use. + * This is not necessary with buffer objects. + * Omitting this parameter and the `Data` parameter will retrieve the contents of the clipboard. + * @returns {(ClipboardAll)} + * A buffer object + * @throws MemoryError - Memory could not be allocated. + * @see {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/NumPut.htm|NumPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/NumGet.htm|NumGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrPut.htm|StrPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrGet.htm|StrGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/File.htm#RawRead|File.RawRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/File.htm#RawWrite|File.RawWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ClipboardAll.htm|ClipboardAll} + * @example A paste function that backs up and restores the clipboard. + * *F1::paste('Hello, world!') + * + * paste(data) { + * ; Backup clipboard + * clipbackup := ClipboardAll() + * ; Set new data to clipboard + * A_Clipboard := data + * ; Send the default paste command + * Send('^v') + * ; Check repeatedly to see if the clipboard is still open + * Loop + * ; If more than 20 tries + * if (A_Index > 20) + * ; Stop trying and notify of failure + * return TrayTip(A_ThisFunc ' failed to restore clipboard contents.') + * ; Otherwise, wait another 100ms + * else Sleep(100) + * ; Stop when clipboard window isn't in use + * Until !DllCall('GetOpenClipboardWindow', 'Ptr') + * ; Restore original clipboard contents + * A_Clipboard := clipbackup + * } + */ + static Call([ByteCount:=0, FillByte:=0]) => ClipboardAll +} /** - * Create a binding function object, which can call methods of the specified object. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Class.htm|`Class`} + * Represents a class definition. A class can contain static methods and static properties as well as instance methods and instance properties. + * Static methods and static properties belong to the main class itself. Instances do not get these. + * Methods and properties that aren't static are what instances receive. An instance is an object created by the Class. + * Creating instance object is a feature of classes, but does not have to be the purpose of the class. + * A class can contain only static methods and variables and be used as a standalone unique class object. + * @property {(Object)} Prototype - Retrieves or sets the object on which all instances of the class are based. + * The Prototype contains all properties and methods that new instances will inherit. + * @see {@link https://www.autohotkey.com/docs/v2/lib/A_Clipboard.htm|A_Clipboard} | + * {@link https://www.autohotkey.com/docs/v2/lib/ClipWait.htm|ClipWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnClipboardChange.htm|OnClipboardChange()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer} | + * {@link https://www.autohotkey.com/docs/v2/lib/_ClipboardTimeout.htm|#ClipboardTimeout} + * @example A Class template showing all parts it can include. */ -ObjBindMethod(Obj, Method := 'Call', Params*) => Func +class Class extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Class.htm#Call|`Class()`} + * Constructs a new instance of the class. + * @param Params - Any amount of predetermined parameters. + * @returns {(Class)} A class object is returned. + * @example A template of + * obj1 := {} + * obj2 := Object() + * obj3 := Object.Call() + */ + Call(Params*) => Class + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Class.htm#Prototype|`Prototype`} + * Retrieves or sets the prototype object on which all instances of that class are based. + * The Prototype of a class is defined by all methods and properties within the base class that are not static. + * The Prototype is what all instances of the class will inherit. + * @type Prototype + * @example prototype example: + * ; Create and instance of test to use + * instance := test() + * try { + * MsgBox('instance.y: ' instance.y) ; Shows 2 + * MsgBox('test.x: ' test.x) ; Shows 1 + * MsgBox('instance.x: ' instance.x) ; Error! + * MsgBox('test.y: ' test.y) ; Error! + * } + * catch Error as err { + * ; x only exists in the test class, not in instances of test + * ; y only exists in instances of test, not in the text class + * MsgBox('Error.`n' err.message '`n' err.extra) + * } + * + * class test { + * ; Belongs to the test class + * static x := 1 + * ; Belongs to test.prototype + * y := 2 + * } + * + * ;============================== + * ; A class Prototype base is usually the same + * ; as the Prototype of its base class: + * if (Array.Prototype.Base == Array.Base.Prototype) + * MsgBox('yes') + * else MsgBox('no') * Prototype is automatically defined as an own property of any class object created by a class definition. + */ + Prototype: Prototype +} /** - * Convert the address to a suitable reference. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm|`Error`} + * An object containing information about an error that can be {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|thrown} when a runtime error occurs. + * Errors can be thrown by AHK or programmed to be thrown by the user. + * There are multiple types of specific error objects that can also be used: + * - `MemoryError` = A memory allocation failed. + * - `OSError` = An internal function call to a Win32 function failed. + * - `TargetError` = A function failed because its target could not be found. + * - `TimeoutError` = {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage} time out error. + * - `TypeError` = An unexpected value type was used as input for a function, property assignment, or some other operation. + * In other words, it expected a string and got a number, expected a number and got an object, etc. + * - `UnsetError` = An attempt was made to reference or use something that is current unset or not defined. + * - `MemberError` = An attempt was made to reference an unset or undefined property or method. + * - `PropertyError` = An attempt was made to reference an unset or undefined property. + * - `MethodError` = An attempt was made to reference an unset or undefined method. + * - `UnsetItemError` = An attempt was made to reference an unset or undefined item. + * - `ValueError` = An unexpected value was used as input for a function, property assignment, or some other operation. + * - `IndexError` = The index parameter of an object's {@link https://www.autohotkey.com/docs/v2/Objects.htm#__Item|__Item property} was an invalid type or out of range. + * - `ZeroDivisionError` = Division by zero is always an error. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function or method name. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjFromPtr(Address) => Object +class Error extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Message|`Message`} + * A description of the error that occurred. + * @type String + */ + Message: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#What|`What`} + * The identifier of the thing that threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @type String + */ + What: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Extra|`Extra`} + * Any additional information to include about the error. + * If extra information is passed, the error message will include a separate line that says: + * `Specifically: `. + * @type String + */ + Extra: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#File|`File`} + * The full path of the script file that contains the line at which the error occurred or where the Error object was constructed. + * @type String + */ + File: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Line|`Line`} + * The Line number at which the error occurred or where the Error object was constructed. + * @type Integer + */ + Line: Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Stack|`Stack`} + * The full call stack at the time of error or error object construction. + * Each line should be shown in one of the following formats: + * - ``err.File (err.Line): [err.What] SourceCode`r`n`` + * *What* is the thing that errored out. + * *File* is the file name and *Line* is the line number of the current stack entry depth. + * *SourceCode* is an approximation of the source code at that line, as it would be shown in {@link https://www.autohotkey.com/docs/v2/lib/ListLines.htm|ListLines()}. + * - ``> err.What`r`n`` + * Represents the launching of a thread, typically the direct cause of the function call above it. + * - `... N more` + * If this is displayed, the stack trace was truncated, and there are *N* more stack entries not being shown. + * The Stack property cannot exceed 2047 characters. + * @type String + */ + Stack: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|`Error()`} + * Creates an Error object that can be {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|thrown}. + * @param {(String)} [Message] + * A description of the error that occurred. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(Error)} + * Error object. + * @example Example of error-checking the division of 2 numbers. + * dividend := InputBox('Enter number to divide.') + * if (dividend.Result != 'OK') + * return + * + * divisor := InputBox('Enter number to divide by.`nTry using 0.') + * if (divisor.Result != 'OK') + * return + * + * switch { + * case !IsNumber(dividend.Value): + * throw(TypeError('Dividend must be a number.' + * , A_ThisFunc + * , 'A ' Type(dividend.Value) ' was supplied.')) + * case !IsNumber(divisor.Value): + * throw(TypeError('Divisor must be a number.' + * , A_ThisFunc + * , 'A ' Type(dividend.Value) ' was supplied.')) + * case (divisor.Value = 0): + * throw ZeroDivisionError('Dividing by zero is a no-no.' + * , A_ThisFunc + * , 'This is a math thing, not a computer thing.') + * default: + * quo := dividend.value / divisor.value + * msg := dividend.value ' / ' divisor.value ' = ' quo + * MsgBox(msg) + * } + */ + static Call([Message:='Error', What:=A_ThisFunc, Extra:=unset]) => Error +} /** - * Convert the address to a suitable reference and increase the reference count. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#MemoryError|`MemoryError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when a memory allocation has failed. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjFromPtrAddRef(Address) => Object +class MemoryError extends Error { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#MemoryError|`MemoryError()`} + * A memory allocation failed. + * @param {(String)} [Message] + * A description of the error that occurred. + * If omitted, "MemoryError" is used. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(MemoryError)} + * MemoryError object. + */ + static Call([Message:='MemoryError', What:=A_ThisFunc, Extra:=unset]) => MemoryError +} /** - * The Base object of the return value. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#OSError|`OSError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when an internal function call to a Win32 function fails. + * @property {(String)} Message - The error code number and a description generated by the operating system. + * @property {(Integer)} Number - The error code number. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjGetBase(Value) => Object +class OSError extends Error { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#OSError|`Number`} + * The number of the {@link https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-|OS Error}. + * @type Integer + */ + Number: Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#OSError|`OSError()`} + * An internal function call to a Win32 function failed. + * Message includes an {@link https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-|error code and description} generated by the operating system. + * OSErrors have an additional `Number` property which contains the error code number. + * Calling `OSError(CodeNumber)` sets `Number` to the code number and `Message` to an OS-Defined error message. + * Example: `OSError(1)` sets `Number` to 1 and `Message` to "(1) Incorrect Function". + * If the code number is omitted, it defaults to {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError}. + * @param {(String)} [ErrorNumber] + * A {@link https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-|Windows error code} number. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(OSError)} + * OSError object. + */ + static Call([ErrorNumber:=A_LastError, What:=A_ThisFunc, Extra:=unset]) => OSError +} /** - * The current capacity of the internal attribute array of the object. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TargetError|`TargetError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when a function fails because its target could not be found. + * @property {(String)} Message - Indicates the type of target expected, such as 'window', 'control', 'menu', or 'status bar'. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjGetCapacity(Obj) => Integer +class TargetError extends Error { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TargetError|`Message`} + * Indicates the type of target expected, such as 'window', 'control', 'menu', or 'status bar'. + * @type String + */ + Message: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TargetError|`TargetError()`} + * A function failed because its target could not be found. + * @param {(String)} [Message] + * Indicates the type of target expected, such as 'window', 'control', 'menu', or 'status bar'. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(TargetError)} + * TargetError object. + */ + static Call([Message:='TargetError', What:=A_ThisFunc, Extra:=unset]) => TargetError +} /** - * Returns the address of the object's structured data (typed properties). - * @since v2.1-alpha.3 + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TimeoutError|`TimeoutError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when the {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage()} function experiences a {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm#Error_Handling|timeout}. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjGetDataPtr(Obj) => Integer +class TimeoutError extends Error { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TimeoutError|`TimeoutError()`} + * {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage()} timed out. + * @param {(String)} [Message] + * A message describing the error. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(TimeoutError)} + * TimeoutError object. + */ + static Call([Message:='TimeoutError', What:=A_ThisFunc, Extra:=unset]) => TimeoutError +} /** - * Returns the size of the object's structure (typed properties), in bytes. - * @since v2.1-alpha.3 + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TypeError|`TypeError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when an unexpected {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#cat-type|value type} is used. + * Examples would include using a string where a number is expected or using an object when a primitive is expected. + * @property {(String)} Message - Normally, this indicates the type expected and the type provided. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Normally, this will contain a string representing the errant value. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjGetDataSize(Obj) => Integer +class TypeError extends Error { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TypeError|`Message`} + * Normally, this indicates the {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#cat-type|value type} expected and the type provided. + * @type String + */ + Message: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TypeError|`Extra`} + * Normally, this will contain a string representing the errant value. + * @type String + */ + Extra: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TypeError|`TypeError()`} + * An unexpected {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#cat-type|value type} was used as input for a function, property assignment, or some other operation. + * Usually, Message indicates the expected and actual type, and Extra contains a string representing the errant value. + * @param {(String)} [Message] + * Normally, this indicates the type expected and the type provided. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Normally, this will contain a string representing the errant value. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(TypeError)} + * TypeError object. + */ + static Call([Message:='TypeError', What:=A_ThisFunc, Extra:=unset]) => TypeError +} /** - * If the object has the attribute of this name, it returns true, otherwise it returns false. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#UnsetError|`UnsetError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when an attempt is made to read or use a variable, property, or item that doesn't exist or is currently {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjHasOwnProp(Obj, Name) => Integer +class UnsetError extends Error { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#UnsetError|`UnsetError()`} + * An attempt was made to read or use a variable, property, or item that doesn't exist or is currently {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * @param {(String)} [Message] + * A message describing the error. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(UnsetError)} + * UnsetError object. + */ + static Call([Message:='UnsetError', What:=A_ThisFunc, Extra:=unset]) => UnsetError +} /** - * Returns the number of attributes owned by the object. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#MemberError|`MemberError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when an attempt is made to read or use a property or method that doesn't exist or is currently {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjOwnPropCount(Obj) => Integer +class MemberError extends UnsetError { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#MemberError|`MemberError()`} + * An attempt was made to read or use a property or method that doesn't exist or is currently {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * @param {(String)} [Message] + * A message describing the error. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(MemberError)} + * MemberError object. + */ + static Call([Message:='MemberError', What:=A_ThisFunc, Extra:=unset]) => MemberError +} /** - * Return the attributes owned by the object. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#PropertyError|`PropertyError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when an attempt is made to read or use a property that doesn't exist or is currently {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjOwnProps(Obj) => Enumerator +class PropertyError extends MemberError { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#PropertyError|`PropertyError()`} + * An attempt was made to read or use a property that doesn't exist or is currently {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * @param {(String)} [Message] + * A message describing the error. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(PropertyError)} + * PropertyError object. + */ + static Call([Message:='PropertyError', What:=A_ThisFunc, Extra:=unset]) => PropertyError +} /** - * Retrieve the address of the object. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#MethodError|`MethodError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when an attempt is made to use or access a method that doesn't exist. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjPtr(Obj) => Integer +class MethodError extends MemberError { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#MethodError|`MethodError()`} + * An attempt was made to use or access a method that doesn't exist. + * @param {(String)} [Message] + * A message describing the error. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(MethodError)} + * MethodError object. + */ + static Call([Message:='MethodError', What:=A_ThisFunc, Extra:=unset]) => MethodError +} /** - * Retrieve the address of the object and increase the reference count. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#UnsetItemError|`UnsetItemError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when an attempt is made to read or use an {@link https://www.autohotkey.com/docs/v2/Objects.htm#__Item|object __item} that doesn't exist or is currently {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjPtrAddRef(Obj) => Integer +class UnsetItemError extends UnsetError { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#UnsetItemError|`UnsetItemError()`} + * An attempt was made to read or use an {@link https://www.autohotkey.com/docs/v2/Objects.htm#__Item|object __item} that doesn't exist or is currently {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset}. + * @param {(String)} [Message] + * A message describing the error. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(UnsetItemError)} + * UnsetItemError object. + */ + static Call([Message:='UnsetItemError', What:=A_ThisFunc, Extra:=unset]) => UnsetItemError +} /** - * Reduce the reference count of the object. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#ValueError|`ValueError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when an unexpected value is used for a function parameter, property assignment, or some other operation. + * @property {(String)} Message - Normally, this indicates what expectation was broken. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Normally, this will contain a string representing the errant value. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjRelease(Ptr) => Integer +class ValueError extends Error { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TypeError|`Message`} + * Normally, this indicates what expectation was broken. + * @type String + */ + Message: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TypeError|`Extra`} + * Normally, this will contain a string representing the errant value. + * @type String + */ + Extra: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#ValueError|`ValueError()`} + * An unexpected value was used for a function parameter, property assignment, or some other operation. + * @param {(String)} [Message] + * Normally, this indicates what expectation was broken. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Normally, this will contain a string representing the errant value. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(ValueError)} + * ValueError object. + */ + static Call([Message:='ValueError', What:=A_ThisFunc, Extra:=unset]) => ValueError +} /** - * Set the Base object of the object. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#IndexError|`IndexError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when the index of an {@link https://www.autohotkey.com/docs/v2/Objects.htm#__Item|__Item property} is invalid or out of range. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Normally, this indicates what invalid index was used. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjSetBase(Obj, BaseObj) => void +class IndexError extends ValueError { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#TypeError|`Extra`} + * Normally, this indicates what invalid index was used. + * @type String + */ + Extra: String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#IndexError|`IndexError()`} + * Used when the index of an {@link https://www.autohotkey.com/docs/v2/Objects.htm#__Item|__Item property} is invalid or out of range. + * @param {(String)} [Message] + * A message describing the error. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Normally, this indicates what invalid index was used. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(IndexError)} + * IndexError object. + */ + static Call([Message:='IndexError', What:=A_ThisFunc, Extra:=unset]) => IndexError +} /** - * Set the current capacity of the internal array of the object's own properties. - * @param MaxProps new capacity. If it is less than the current number of own properties, use that number and release all unused space. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#ZeroDivisionError|`ZeroDivisionError`} + * A predefined {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error} class for when when any math operation tries to divide by zero. + * @property {(String)} Message - The general error message. + * @property {(String)} What - What threw the error. Usually a function. Blank for expressions and global space errors. + * @property {(String)} Extra - Extra information to be included about the error. + * @property {(String)} File - The full path of the script file containing the line of code that caused the error. + * @property {(Integer)} Line - The number of the line of code that caused the error. + * @property {(String)} Stack - A string representing the call stack at the time of error. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Finally.htm|Finally} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#error-types|Error Types} */ -ObjSetCapacity(Obj, MaxProps) => Integer +class ZeroDivisionError extends Error { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#ZeroDivisionError|`ZeroDivisionError()`} + * A math operation tried to divide by zero. + * @param {(String)} [Message] + * A message describing the error. + * @param {(String)} [What] + * The identifier of what threw the error. This is usually a function or method name. + * If an expression or something in global space throws the error, this property will be blank. Example: `('a' / 1)` + * @param {(String|Number)} [Extra] + * Any additional information to include about the error. + * If `Extra` is provided, the error message will include a separate line that says: + * `Specifically: ` + * @returns {(ZeroDivisionError)} + * ZeroDivisionError object. + */ + static Call([Message:='ZeroDivisionError', What:=A_ThisFunc, Extra:=unset]) => ZeroDivisionError +} /** - * Sets the address of the object's structured data (typed properties). - * ObjSetDataPtr does not affect nested objects, as they each have their own data pointer (which points into the outer object's original data). - * @since v2.1-alpha.3 + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm|`File Object`} + * Provides an interface for file input and output, such as reading/writing tex, length, encoding, and more. + * This object is created using {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm|FileOpen()}. + * @property {(Integer)} Pos - Retrieves or sets the position of the file pointer. + * @property {(Integer)} Length - Retrieves or sets the size of the file. + * @property {(Integer)} AtEOF - (At End Of File) Retrieves a non-zero number if the file pointer has reached the end of the file. + * @property {(String)} Encoding - Retrieves or sets the text encoding used by this file object. + * @property {(Integer)} Handle - Retrieves a system file handle, intended for use with {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall}. */ -ObjSetDataPtr(Obj, Ptr) => void +class File extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#AtEOF|`AtEOF`} + * Retrieves a non-zero value if the file pointer has reached the end of the file. + * This property should only be used with actual files. + * @type Integer + * @example Count total lines in a file. + * ; Open a file as a file object + * fileObj := FileOpen(A_ScriptFullPath, 'r') + * ; Track how many lines there are + * lineTotal := 0 + * ; While not At End Of File + * While !fileObj.AtEOF + * ; Read the line + * fileObj.ReadLine() + * ; And add 1 to total + * ,lineTotal++ + * ; Always close a file when you're finished with it + * fileObj.Close() + * MsgBox('There are ' lineTotal ' line(s) in this file.') + */ + AtEOF { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#Encoding|`Encoding`} + * Retrieves or sets the text encoding used by this file object. + * NewEncoding may be a numeric code page identifier (see {@link https://learn.microsoft.com/windows/win32/intl/code-page-identifiers|Microsoft Docs}) or one of the following strings. + * - `UTF-8` = Unicode UTF-8, equivalent to CP65001. + * - `UTF-16` = Unicode UTF-16 with little endian byte order, equivalent to CP1200. + * - `CP#` = A code page where `#` is a numeric identifier, such as CP437 or CP65001. + * Setting a new encoding will never cause a {@link https://www.w3.org/International/questions/qa-byte-order-mark#bomwhat|BOM (Byte Order Mark)} to be added or removed, as the BOM is normally written to the file when it is first created. + * @type Primitive + * @example Showing a file's encoding type. + * := FileOpen(A_ScriptFullPath, 'r') + * MsgBox("This script's file encoding is: " fileObj.Encoding) + * fileObj.Close() + */ + Encoding { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#Handle|`Handle`} + * Retrieves a system file handle, intended for use with {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCalls}. See {@link https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-createfilea|CreateFile}. + * A file object internally buffers its reads and writes and if data has been written into the object's internal buffer, it is committed to disk before the handle is returned. + * @type Integer + * @example Getting the handle of . + * fileObj := FileOpen(A_ScriptFullPath, 'r') + * MsgBox('The handle to this file object is: ' fileObj.Handle) + * fileObj.Close() + */ + Handle { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#Length|`Length`} + * Retrieves or sets the size of the file. + * Length is represented in bytes. + * This property should only be used with actual files. + * @type Integer + * @example Checking the size of the current script file. + * fileObj := FileOpen(A_ScriptFullPath, 'r') + * MsgBox('Size of this script: ' fileObj.Length ' bytes') + * fileObj.Close() + */ + Length { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#Pos|`Pos`} + * Retrieves or sets the position of the file pointer. + * The position is a byte-offset from the beginning of the file, where 0 is the first byte. + * When data is written to or read from the file, the file pointer automatically moves to the next byte of the file. + * A file containing a UTF-8 or UTF-16 BOM (byte order mark) with read access may skip the BOM. + * This may cause the position to start at 2 or 3 after opening the file. + * @type Integer + * @example Get start position of the script 3rd line. + * fileObj := FileOpen(A_ScriptFullPath, 'r') + * loop 2 + * fileObj.ReadLine() + * MsgBox('The pointer position at the start of line 3 is: ' fileObj.pos) + * fileObj.Close() + */ + Pos { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#Close|`Close()`} + * Closes the file, flushes any data in the cache to disk, and releases the share locks. + * As a good practice, it is recommended to close the file as soon as possible. + * The file is closed automatically when the object is freed. + * @returns {(String)} + * An empty string is always returned. + * @example Closing an open file to access it. + * ; Path to the test file. + * path := A_ScriptDir '\testfile.txt' + * ; Open as a new file, even if the file already exists. + * fileObj := FileOpen(path, 'w') + * ; File can be written to because it's opened. + * fileObj.Write('Hello, world!') + * ; Trying to write to it while it's opened causes an error. + * try FileAppend('`nline 2', path) + * ; Catch the error and show it. + * catch as err + * MsgBox(err.What '`n' err.Extra + * '`nFailed to write line 2.') + * ; Instead, close the file object. + * ; Always close a file object when finished. + * fileObj.Close() + * ; Then append to it. + * try FileAppend('`nline 2', path) + * ; Catch the error and show it. + * catch as err + * MsgBox(err.What '`n' err.Extra + * '`nFailed to write line 2.') + * Run(path) + * ; Cleanup example file. + * if (MsgBox('Delete test file?', , 'YesNo') = 'Yes') + * FileDelete(path) + */ + Close() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#RawRead|`RawRead()`} + * Reads raw binary data from the file into memory and advances the file pointer. + * @param {(Integer)} Buffer + * Either a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer-like} object or the memory address which will receive the data. + * @param {(Integer)} [Bytes] + * The maximum number of bytes to read. + * This parameter is optional if Buffer is a Buffer object. + * @returns {(Integer)} + * Number of bytes that were read. + * @throws Error - If bytes exceed the size of the buffer. + * @example Writing and reading binary data from file. + * ; Create a path to where the binary data will be stored + * path := A_ScriptDir '\testfile.bin' + * ; Make a buffer that can hold 4 integers in binary form. + * ; An integer is 4 bytes so 4x4 is 16. + * buff := Buffer(16) + * ; Add 4 integers to the buffer. + * NumPut('Int', 200 + * , 'Int', 400 + * , 'Int', 800 + * , 'Int', 1600 + * , buff) + * ; Open file as write, creating a new file. + * fileObj := FileOpen(path, 'w') + * ; Write binary data to file and notify user. + * fileObj.RawWrite(buff) + * fileObj.Close() + * MsgBox('Data has been written to the file.' + * '`nThe file is saved and closed.' + * '`n`nClick OK to reopen file and get 3rd ' + * '`nnumber from the binary file just written.') + * + * ; Reopen the file as read. + * fileObj := FileOpen(path, 'r') + * ; Create a buffer to put the binary data into + * bin := Buffer(16) + * ; Move the file's pointer 8 bytes in + * ; This starts it at the 3rd Int + * fileObj.pos := 8 + * ; Get next 4 bytes and store in bin buffer. + * fileObj.RawRead(bin, 4) + * ; Get number from binary data. + * num := NumGet(bin, 'Int') + * ; Show the that the 3rd integer was retrieved. + * MsgBox('The 3rd integer should be 800.' + * '`nNumber gotten from fileObj: ' num) + * ; Don't forget to close your files! + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(path) + */ + RawRead(Buffer [,Bytes]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#RawWrite|`RawWrite()`} + * Writes raw binary data to the file and advances the file pointer. + * @param {(Buffer|String|Integer)} Buffer + * Either a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer-like} object, a string containing binary data, or a memory address containing the data. + * @param {(Integer)} [Bytes] + * The number of bytes to write. + * This parameter is optional if Buffer is an object or a string. + * @returns {(Integer)} + * Number of bytes that were read. + * @throws Error - If bytes exceed the size of the buffer. + * @example Writing and reading binary data from file. + * ; Create a path to where the binary data will be stored + * path := A_ScriptDir '\testfile.bin' + * ; Make a buffer that can hold 4 integers in binary form. + * ; An integer is 4 bytes so 4x4 is 16. + * buff := Buffer(16) + * ; Add 4 integers to the buffer. + * NumPut('Int', 200 + * , 'Int', 400 + * , 'Int', 800 + * , 'Int', 1600 + * , buff) + * ; Open file as write, creating a new file. + * fileObj := FileOpen(path, 'w') + * ; Write binary data to file and notify user. + * fileObj.RawWrite(buff) + * fileObj.Close() + * MsgBox('Data has been written to the file.' + * '`nThe file is saved and closed.' + * '`n`nClick OK to reopen file and get 3rd ' + * '`nnumber from the binary file just written.') + * + * ; Reopen the file as read. + * fileObj := FileOpen(path, 'r') + * ; Create a buffer to put the binary data into + * bin := Buffer(16) + * ; Move the file's pointer 8 bytes in + * ; This starts it at the 3rd Int + * fileObj.pos := 8 + * ; Get next 4 bytes and store in bin buffer. + * fileObj.RawRead(bin, 4) + * ; Get number from binary data. + * num := NumGet(bin, 'Int') + * ; Show the that the 3rd integer was retrieved. + * MsgBox('The 3rd integer should be 800.' + * '`nNumber gotten from fileObj: ' num) + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(path) + */ + RawWrite(Data [,Bytes]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#Read|`Read()`} + * Reads a string of characters from the file and advances the file pointer. + * @param {(Integer)} [NumberOfCharacters] + * The maximum number of characters to read. + * If omitted or unset, the remaining characters of the file are returned as one string. + * If the File object was created from a handle to a non-seeking device such as a console buffer or pipe, omitting this parameter may cause the method to fail or return only what data is currently available. + * @returns {(String)} + * One or more characters from the file. + * @example Reading characters from the script's file. + * ; Use the current script as the file to read. + * fileObj := FileOpen(A_ScriptFullPath, 'r') + * ; Get the first 89 characters. + * MsgBox(fileObj.read(89)) + * ; Calling with no parameters gets all + * ; remaining characters from the file + * MsgBox(fileObj.read()) + * ; Reset the file pointer to the beginning. + * fileObj.pos := 0 + * ; Passing unset as the parameter also + * ; retrieves all characters. + * MsgBox(fileObj.read(unset)) + * ; When finished with a file, always close it. + * fileObj.Close() + */ + Read([NumberOfCharacters:=unset]) => String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadNum|`ReadChar()`} + * Reads an 8-bit (1-byte) char from the file and advances the file pointer. + * Signed char range: `0` - `255` + * @returns {(Primitive)} + * On success, returns number, otherwise returns an empty string. + * If the number of bytes read is non-zero but less than the size of Char, the missing bytes are assumed to be zero. + * @example Getting an 8-bit signed integer from the start of a file. + * ; A Char value to save. + * orig_num := 100 + * ; Create a buffer and put a number in it. + * buff := Buffer(1) + * NumPut('Char', orig_num, buff) + * ; Path to write binary data to. + * file_path := A_ScriptDir '\FileObjectExample.bin' + * ; Delete old file if it exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Now create a file and write the binary number to it. + * FileAppend(buff, file_path, 'Raw') + * ; Now open the file up as a File object. + * fileObj := FileOpen(file_path, 'r') + * ; And get the first char of the file. + * num := fileObj.ReadChar() + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(file_path) + * ; Show original and retrieved numbers. + * MsgBox('original number: ' orig_num + * '`nnumber from file: ' num) + */ + ReadChar() => Primitive + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadNum|`ReadDouble()`} + * Reads a 64-bit (8-byte) floating point number from the file and advances the file pointer. + * Double range: `1.7E-308` to `1.7E+308` + * @returns {(Primitive)} + * On success, returns number, otherwise returns an empty string. + * If the number of bytes read is non-zero but less than the size of Double, the missing bytes are assumed to be zero. + * @example Getting a 64-bit floating point number from the start of a file. + * ; A Double value to save. + * orig_num := 1.1234567890123456789 + * ; Create a buffer and put a number in it. + * buff := Buffer(8) + * NumPut('Double', orig_num, buff) + * ; Path to write binary data to. + * file_path := A_ScriptDir '\FileObjectExample.bin' + * ; Delete old file if it exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Now create a file and write the binary number to it. + * FileAppend(buff, file_path, 'Raw') + * ; Now open the file up as a File object. + * fileObj := FileOpen(file_path, 'r') + * ; And get the first double of the file. + * num := fileObj.ReadDouble() + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(file_path) + * ; Show original and retrieved numbers. + * MsgBox('original number: ' orig_num + * '`nnumber from file: ' num) + */ + ReadDouble() => Primitive + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadNum|`ReadFloat()`} + * Reads a 32-bit (4-byte) floating point number from the file and advances the file pointer. + * Float range: `1.2E-38` to `3.4E+38` + * @returns {(Primitive)} + * On success, returns number, otherwise returns an empty string. + * If the number of bytes read is non-zero but less than the size of Float, the missing bytes are assumed to be zero. + * @example Getting a 32-bit floating point number from the start of a file. + * ; A float value to save. + * orig_num := 5.1234567890123 + * ; Create a buffer and put a number in it. + * buff := Buffer(4) + * NumPut('Float', orig_num, buff) + * ; Path to write binary data to. + * file_path := A_ScriptDir '\FileObjectExample.bin' + * ; Delete old file if it exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Now create a file and write the binary number to it. + * FileAppend(buff, file_path, 'Raw') + * ; Now open the file up as a File object. + * fileObj := FileOpen(file_path, 'r') + * ; And get the first float of the file. + * num := fileObj.ReadFloat() + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(file_path) + * ; Show original and retrieved numbers. + * MsgBox('original number: ' orig_num + * '`nnumber from file: ' num) + */ + ReadFloat() => Primitive + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadNum|`ReadInt()`} + * Reads a 32-bit (4-byte) integer from the file and advances the file pointer. + * Integer range: `0` to `4,294,967,295` + * @returns {(Primitive)} + * On success, returns number, otherwise returns an empty string. + * If the number of bytes read is non-zero but less than the size of Int, the missing bytes are assumed to be zero. + * @example Getting a 32-bit signed integer from the start of a file. + * ; A signed integer to save. + * orig_num := -9999 + * ; Create a buffer and put a number in it. + * buff := Buffer(4) + * NumPut('Int', orig_num, buff) + * ; Path to write binary data to. + * file_path := A_ScriptDir '\FileObjectExample.bin' + * ; Delete old file if it exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Now create a file and write the binary number to it. + * FileAppend(buff, file_path, 'Raw') + * ; Now open the file up as a File object. + * fileObj := FileOpen(file_path, 'r') + * ; And get the first signed integer of the file. + * num := fileObj.ReadInt() + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(file_path) + * ; Show original and retrieved numbers. + * MsgBox('original number: ' orig_num + * '`nnumber from file: ' num) + */ + ReadInt() => Primitive + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadNum|`ReadInt64()`} + * Reads a 64-bit (8-byte) integer from the file and advances the file pointer. + * Signed integer 64 range: `-9,223,372,036,854,775,808` to `9,223,372,036,854,775,807` + * @returns {(Primitive)} + * On success, returns number, otherwise returns an empty string. + * If the number of bytes read is non-zero but less than the size of Int64, the missing bytes are assumed to be zero. + * @example Getting a 64-bit integer from the start of a file. + * ; Pick a 64-bit integer to save. + * ; This is 1.2 quintillion. + * orig_num := 1234567890123456789 + * ; Create a buffer and put a number in it. + * buff := Buffer(8) + * NumPut('Int64', orig_num, buff) + * ; Path to write binary data to. + * file_path := A_ScriptDir '\FileObjectExample.bin' + * ; Delete old file if it exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Now create a file and write the binary number to it. + * FileAppend(buff, file_path, 'Raw') + * ; Now open the file up as a File object. + * fileObj := FileOpen(file_path, 'r') + * ; And get the first signed 64 bit integer of the file. + * num := fileObj.ReadInt64() + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(file_path) + * ; Show original and retrieved numbers. + * MsgBox('original number: ' orig_num + * '`nnumber from file: ' num + * '`n`nIf that was dollars and you wanted to spend ' + * 'it all, you would need to spend $391,000,000 ' + * 'every second for 100 years straight.') + */ + ReadInt64() => Primitive + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadLine|`ReadLine()`} + * Reads a line of text from the file and advances the file pointer. + * A max of 65,534 characters per line can be read in at a time and subsequent calls to ReadLine() will get the remaining characters. + * @returns {(String)} + * Next line of text from the file excluding the end character. + * @example Reading individual lines of script. + * ; Open the current running script as a file + * fileObj := FileOpen(A_ScriptFullPath, 'r') + * ; Show each individual line until end of file is reached. + * while !fileObj.AtEOF + * MsgBox(fileObj.ReadLine()) + * ; When finished with a file, always close it. + * fileObj.Close() + */ + ReadLine() => String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadNum|`ReadShort()`} + * Reads a 16-bit (2-byte) short integer from the file and advances the file pointer. + * Signed short range: `-32,768` to `32,767` + * @returns {(Primitive)} + * On success, returns number, otherwise returns an empty string. + * If the number of bytes read is non-zero but less than the size of Short, the missing bytes are assumed to be zero. + * @example Getting a 16-bit signed integer from the start of a file. + * ; A signed Short value to save. + * orig_num := 32000 + * ; Create a buffer and put a number in it. + * buff := Buffer(2) + * NumPut('Short', orig_num, buff) + * ; Path to write binary data to. + * file_path := A_ScriptDir '\FileObjectExample.bin' + * ; Delete old file if it exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Now create a file and write the binary number to it. + * FileAppend(buff, file_path, 'Raw') + * ; Now open the file up as a File object. + * fileObj := FileOpen(file_path, 'r') + * ; And get the first signed Short of the file. + * num := fileObj.ReadShort() + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(file_path) + * ; Show original and retrieved numbers. + * MsgBox('original number: ' orig_num + * '`nnumber from file: ' num) + */ + ReadShort() => Primitive + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadNum|`ReadUChar()`} + * Reads an 8-bit (1-byte) unsigned char from the file and advances the file pointer. + * Unsigned char range: `-128` - `127` + * @returns {(Primitive)} + * On success, returns number, otherwise returns an empty string. + * If the number of bytes read is non-zero but less than the size of UChar, the missing bytes are assumed to be zero. + * @example Getting an 8-bit unsigned integer from the start of a file. + * ; A Char value to save. + * orig_num := 255 + * ; Create a buffer and put a number in it. + * buff := Buffer(1) + * NumPut('UChar', orig_num, buff) + * ; Path to write binary data to. + * file_path := A_ScriptDir '\FileObjectExample.bin' + * ; Delete old file if it exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Now create a file and write the binary number to it. + * FileAppend(buff, file_path, 'Raw') + * ; Now open the file up as a File object. + * fileObj := FileOpen(file_path, 'r') + * ; And get the first unsigned char of the file. + * num := fileObj.ReadUChar() + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(file_path) + * ; Show original and retrieved numbers. + * MsgBox('original number: ' orig_num + * '`nnumber from file: ' num) + */ + ReadUChar() => Primitive + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadNum|`ReadUInt()`} + * Reads a 32-bit (4-byte) unsigned integer from the file and advances the file pointer. + * Unsigned integer range: `-2,147,483,648` to `2,147,483,647` + * @returns {(Primitive)} + * On success, returns number, otherwise returns an empty string. + * If the number of bytes read is non-zero but less than the size of UInt, the missing bytes are assumed to be zero. + * @example Getting a 32-bit unsigned integer from the start of a file. + * ; An unsigned integer to save. + * orig_num := 420 + * ; Create a buffer and put a number in it. + * buff := Buffer(4) + * NumPut('UInt', orig_num, buff) + * ; Path to write binary data to. + * file_path := A_ScriptDir '\FileObjectExample.bin' + * ; Delete old file if it exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Now create a file and write the binary number to it. + * FileAppend(buff, file_path, 'Raw') + * ; Now open the file up as a File object. + * fileObj := FileOpen(file_path, 'r') + * ; And get the first UInt of the file. + * num := fileObj.ReadUInt() + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(file_path) + * ; Show original and retrieved numbers. + * MsgBox('original number: ' orig_num + * '`nnumber from file: ' num) + */ + ReadUInt() => Primitive + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#ReadNum|`ReadUShort()`} + * Reads a 16-bit (2-byte) unsigned short integer from the file and advances the file pointer. + * Unsigned short range: `0` to `65,535` + * @returns {(Primitive)} + * On success, returns number, otherwise returns an empty string. + * If the number of bytes read is non-zero but less than the size of UShort, the missing bytes are assumed to be zero. + * @example Getting a 16-bit unsigned integer from the start of a file. + * ; An unsigned Short value to save. + * orig_num := 64000 + * ; Create a buffer and put a number in it. + * buff := Buffer(2) + * NumPut('UShort', orig_num, buff) + * ; Path to write binary data to. + * file_path := A_ScriptDir '\FileObjectExample.bin' + * ; Delete old file if it exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Now create a file and write the binary number to it. + * FileAppend(buff, file_path, 'Raw') + * ; Now open the file up as a File object. + * fileObj := FileOpen(file_path, 'r') + * ; And get the first unsigned short of the file. + * num := fileObj.ReadUShort() + * ; When finished with a file, always close it. + * fileObj.Close() + * ; Clean up. No need to keep the test file. + * FileDelete(file_path) + * ; Show original and retrieved numbers. + * MsgBox('original number: ' orig_num + * '`nnumber from file: ' num) + */ + ReadUShort() => Primitive + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#Seek|`Seek()`} + * Moves the file pointer. + * @param {(Integer)} Distance + * Distance to move, in bytes. + * @param {(Integer)} [Origin] + * Starting point for the file pointer move. Must be one of the following: + * - `0` (SEEK_SET) = Beginning of the file. Distance must be zero or greater. + * - `1` (SEEK_CUR) = Current position of the file pointer. + * - `2` (SEEK_END) = End of the file. Distance should usually be negative. + * If omitted: + * `0` is used if `Distance` is positive. + * `2` is used if `Distance` is negative. + * @returns {(Boolean)} + * - `1` = Seek successful. + * - `0` = Seek failed. + * @example + * ; Open the current script's text. + * fileObj := FileOpen(A_ScriptFullPath, 'r') + * ; Move pointer 79 bytes into the file. + * fileObj.Seek(79, 1) + * ; Show the current line. + * MsgBox(fileObj.ReadLine()) + * ; Always close your files when done. + * fileObj.Close() + */ + Seek(Distance [,Origin:=0]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#Write|`Write()`} + * Writes a string of characters to the file and advances the file pointer. + * @param {(String)} String + * The string of characters to write. + * @returns {(Integer)} + * Number of bytes that were written to file. + * Not to be confused with number of characters. + * @example Create a text file and write to it. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.txt' + * ; Open as write to create new file. + * fileObj := FileOpen(file_path, 'w') + * ; Write text to file and record bytes written. + * bytes_written := fileObj.write('hello world') + * ; Always close your files when done. + * fileObj.Close() + * msg := bytes_written ' bytes were written to the file.' + * . '`nDo you want to open the file?' + * if (MsgBox(msg,, 0x4) = 'Yes') + * Run(file_path) + */ + Write(String) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteNum|`WriteChar()`} + * Writes an 8-bit (1-byte) char to the file and advances the file pointer. + * Signed char range: `0` - `255` + * @returns {(Integer)} + * Returns the number of bytes that were written. + * @example Reading and writing an 8-bit integer to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.bin' + * ; Remove file if it already exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Open file as read-write. + * fileObj := FileOpen(file_path, 'rw') + * ; Char to write + * orig_number := 42 + * ; Write number to the file and save + * ; how many bytes were written. + * bytes := fileObj.WriteChar(orig_number) + * ; Move file pointer back to start + * ; to read the value just written. + * fileObj.Seek(0, 0) + * MsgBox('Bytes written: ' bytes + * '`nOriginal number: ' orig_number + * '`nValue from file: ' fileObj.ReadChar()) + * ; Always close your files when done. + * fileObj.Close() + * ; Clean up/Delete example file. + * FileDelete(file_path) + */ + WriteChar(Number) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteNum|`WriteDouble()`} + * Writes a 64-bit (8-byte) floating point number to the file and advances the file pointer. + * Double range: `1.7E-308` to `1.7E+308` + * @returns {(Integer)} + * Returns the number of bytes that were written. + * @example Reading and writing a 64-bit floating point number to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.bin' + * ; Remove file if it already exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Open file as read-write. + * fileObj := FileOpen(file_path, 'rw') + * ; Double to write + * orig_number := 1.987659876598765 + * ; Write number to the file and save + * ; how many bytes were written. + * bytes := fileObj.WriteDouble(orig_number) + * ; Move file pointer back to start + * ; to read the value just written. + * fileObj.Seek(0, 0) + * MsgBox('Bytes written: ' bytes + * '`nOriginal number: ' orig_number + * '`nValue from file: ' fileObj.ReadDouble()) + * ; Always close your files when done. + * fileObj.Close() + * ; Clean up/Delete example file. + * FileDelete(file_path) + */ + WriteDouble(Float) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteNum|`WriteFloat()`} + * Writes a 32-bit (4-byte) floating point number to the file and advances the file pointer. + * Float range: `1.2E-38` to `3.4E+38` + * @returns {(Integer)} + * Returns the number of bytes that were written. + * @example Reading and writing a 32-bit floating point number to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.bin' + * ; Remove file if it already exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Open file as read-write. + * fileObj := FileOpen(file_path, 'rw') + * ; Float to write + * orig_number := 5.1234567890123 + * ; Write number to the file and save + * ; how many bytes were written. + * bytes := fileObj.WriteFloat(orig_number) + * ; Move file pointer back to start + * ; to read the value just written. + * fileObj.Seek(0, 0) + * MsgBox('Bytes written: ' bytes + * '`nOriginal number: ' orig_number + * '`nValue from file: ' fileObj.ReadFloat()) + * ; Always close your files when done. + * fileObj.Close() + * ; Clean up/Delete example file. + * FileDelete(file_path) + */ + WriteFloat(Float) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteNum|`WriteInt()`} + * Writes a 32-bit (4-byte) integer to the file and advances the file pointer. + * Integer range: `0` to `4,294,967,295` + * @returns {(Integer)} + * Returns the number of bytes that were written. + * @example Reading and writing a 32-bit integer to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.bin' + * ; Remove file if it already exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Open file as read-write. + * fileObj := FileOpen(file_path, 'rw') + * ; Integer to write + * orig_number := 9999 + * ; Write number to the file and save + * ; how many bytes were written. + * bytes := fileObj.WriteInt(orig_number) + * ; Move file pointer back to start + * ; to read the value just written. + * fileObj.Seek(0, 0) + * MsgBox('Bytes written: ' bytes + * '`nOriginal number: ' orig_number + * '`nValue from file: ' fileObj.ReadInt()) + * ; Always close your files when done. + * fileObj.Close() + * ; Clean up/Delete example file. + * FileDelete(file_path) + */ + WriteInt(Integer) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteNum|`WriteInt64()`} + * Writes a 64-bit (8-byte) integer to the file and advances the file pointer. + * Signed integer 64 range: `-9,223,372,036,854,775,808` to `9,223,372,036,854,775,807` + * @returns {(Integer)} + * Returns the number of bytes that were written. + * @example Reading and writing a 64-bit integer to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.bin' + * ; Remove file if it already exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Open file as read-write. + * fileObj := FileOpen(file_path, 'rw') + * ; Integer 64 to write + * orig_number := 1234567890123456789 + * ; Write number to the file and save + * ; how many bytes were written. + * bytes := fileObj.WriteInt(orig_number) + * ; Move file pointer back to start + * ; to read the value just written. + * fileObj.Seek(0, 0) + * MsgBox('Bytes written: ' bytes + * '`nOriginal number: ' orig_number + * '`nValue from file: ' fileObj.ReadInt64()) + * ; Always close your files when done. + * fileObj.Close() + * ; Clean up/Delete example file. + * FileDelete(file_path) + */ + WriteInt64(Integer) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteLine|`WriteLine()`} + * Writes a string of characters followed by a new line `` `n `` or carriage return+new line `` `r`n ``. + * The {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm#EOL_options|EOL FileOpen() option} determines the character used at the end of each line. + * The file pointer is advanced to the next byte after the text written. + * @param {(String)} [Text] + * The string to write. + * If no parameter is passed, an empty line is inserted. + * @returns {(Integer)} + * Number of **bytes** that were written to file. + * Note: This is not characters written. + * @example Writing individual lines to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.txt' + * ; Create a new file by opening as write + * fileObj := FileOpen(file_path, 'w') + * ; Write a few lines of text to the file + * fileObj.WriteLine('Hello, world!') + * fileObj.WriteLine('Line 2') + * fileObj.WriteLine('One last line.') + * ; Always close your files when done. + * fileObj.Close() + * ; Run the file to open it + * Run(file_path) + */ + WriteLine([Text:='']) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteNum|`WriteShort()`} + * Writes a 16-bit (2-byte) short integer to the file and advances the file pointer. + * Signed short range: `-32,768` to `32,767` + * @returns {(Integer)} + * Returns the number of bytes that were written. + * @example Reading and writing a 16-bit integer to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.bin' + * ; Remove file if it already exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Open file as read-write. + * fileObj := FileOpen(file_path, 'rw') + * ; Short number to write + * orig_number := 32000 + * ; Write number to the file and save + * ; how many bytes were written. + * bytes := fileObj.WriteShort(orig_number) + * ; Move file pointer back to start + * ; to read the value just written. + * fileObj.Seek(0, 0) + * MsgBox('Bytes written: ' bytes + * '`nOriginal number: ' orig_number + * '`nValue from file: ' fileObj.ReadShort()) + * ; Always close your files when done. + * fileObj.Close() + * ; Clean up/Delete example file. + * FileDelete(file_path) + */ + WriteShort(Number) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteNum|`WriteUChar()`} + * Writes an 8-bit (1-byte) unsigned char to the file and advances the file pointer. + * Unsigned char range: `-128` - `127` + * @returns {(Integer)} + * Returns the number of bytes that were written. + * @example Reading and writing an 8-bit unsigned integer to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.bin' + * ; Remove file if it already exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Open file as read-write. + * fileObj := FileOpen(file_path, 'rw') + * ; Unsigned char to write + * orig_num := 255 + * ; Write number to the file and save + * ; how many bytes were written. + * bytes := fileObj.WriteUChar(orig_number) + * ; Move file pointer back to start + * ; to read the value just written. + * fileObj.Seek(0, 0) + * MsgBox('Bytes written: ' bytes + * '`nOriginal number: ' orig_number + * '`nValue from file: ' fileObj.ReadUChar()) + * ; Always close your files when done. + * fileObj.Close() + * ; Clean up/Delete example file. + * FileDelete(file_path) + */ + WriteUChar(Number) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteNum|`WriteUInt()`} + * Writes a 32-bit (4-byte) unsigned integer to the file and advances the file pointer. + * Unsigned integer range: `-2,147,483,648` to `2,147,483,647` + * @returns {(Integer)} + * Returns the number of bytes that were written. + * @example Reading and writing a 32-bit unsigned integer to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.bin' + * ; Remove file if it already exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Open file as read-write. + * fileObj := FileOpen(file_path, 'rw') + * ; Unsigned integer to write + * orig_num := 420 + * ; Write number to the file and save + * ; how many bytes were written. + * bytes := fileObj.WriteUInt(orig_number) + * ; Move file pointer back to start + * ; to read the value just written. + * fileObj.Seek(0, 0) + * MsgBox('Bytes written: ' bytes + * '`nOriginal number: ' orig_number + * '`nValue from file: ' fileObj.ReadUInt()) + * ; Always close your files when done. + * fileObj.Close() + * ; Clean up/Delete example file. + * FileDelete(file_path) + */ + WriteUInt(Integer) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/File.htm#WriteNum|`WriteUShort()`} + * Writes a 16-bit (2-byte) unsigned short integer to the file and advances the file pointer. + * Unsigned short range: `0` to `65,535` + * @returns {(Integer)} + * Returns the number of bytes that were written. + * @example Reading and writing a 16-bit unsigned integer to file. + * ; Path for test file. + * file_path := A_ScriptDir '\testfile.bin' + * ; Remove file if it already exists. + * if FileExist(file_path) + * FileDelete(file_path) + * ; Open file as read-write. + * fileObj := FileOpen(file_path, 'rw') + * ; Unsigned integer to write + * orig_num := 420 + * ; Write number to the file and save + * ; how many bytes were written. + * bytes := fileObj.WriteUInt(orig_number) + * ; Move file pointer back to start + * ; to read the value just written. + * fileObj.Seek(0, 0) + * MsgBox('Bytes written: ' bytes + * '`nOriginal number: ' orig_number + * '`nValue from file: ' fileObj.ReadUInt()) + * ; Always close your files when done. + * fileObj.Close() + * ; Clean up/Delete example file. + * FileDelete(file_path) + */ + WriteUShort(Number) => Integer +} /** - * Register a function or function object that will run whenever the contents of the clipboard are changed. - * @param {(Type) => Integer} Func The function object to call. - * @param AddRemove If empty or omitted, it defaults to 1 (call this function after any previous registered function). Otherwise, specify one of the following numbers: - * - * 1 = This function is called after any previous registered function. - * - * -1 = Call this function before any previous registered function. - * - * 0 = Do not call this function. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Func.htm|`Func`} + * Represents a user-defined or built-in function. + * The Closure class extends Func but does not define any new properties. + * @property {(String)} Name - Returns the function's name. + * @property {(Integer)} IsBuiltIn - Returns 1 (true) if the function is a native AHK function, otherwise 0 (false). + * @property {(Integer)} IsVariadic - Returns 1 (true) if the function is variadic, otherwise 0 (false). + * @property {(Integer)} MinParams - Returns the number of required parameters. + * @property {(Integer)} MaxParams - Returns the number of formally-declared parameters for a user-defined function or maximum parameters for a built-in function. */ -OnClipboardChange(Func, AddRemove := 1) => void - -/** - * Specify a function to run automatically when an unhandled error occurs. - * @param {(Thrown, Mode) => Integer} Func The function object to call when an unhandled error occurs. +class Func extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#Name|`Name`} + * Returns the function's name. + * @type String + * @example Get a function's name from a reference. + * func_reference := MsgBox() + * MsgBox('Original function name of the reference:' + * '`n' func_reference.Name) + */ + Name { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#IsBuiltIn|`IsBuiltIn`} + * Is set to 1 if the function is a native, built-in AHK function. + * Otherwise it is set to 0. + * @type Integer + * @example How to check if a function is provided natively by AHK. + * MsgBox('Is MsgBox() built-in: ' MsgBox.IsBuiltIn + * '`nIs my_func() built-in: ' my_func.IsBuiltIn) + * + * my_func() { + * } + */ + IsBuiltIn { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#IsVariadic|`IsVariadic`} + * Set to `1` if the function is {@link https://www.autohotkey.com/docs/v2/Functions.htm#Variadic|variadic*}. + * Otherwise, it's set to `0`. + * Only the last parameter of a function can be marked as variadic. + * @type Integer + * @example Check if the last parameter is variadic. + * if my_func.IsVariadic + * MsgBox('The last parameter of this function is variadic.') + * + * my_func(mandatory, optional:='default', variadic*) { + * return + * } + */ + IsVariadic { + get => Number + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#MinParams|`MinParams`} + * Returns the number of required parameters. + * Optional and variadic parameters are not included. + * @type Number + * @example Checking all parameters of a function. + * MsgBox('The ' my_func.Name ' function has ' (my_func.MaxParams + my_func.IsVariadic) ' parameters.' + * '`nRequired parameters: ' my_func.MinParams + * '`nOptional parameters: ' (my_func.MaxParams - my_func.MinParams) + * '`nLast parameter is variadic: ' (my_func.IsVariadic ? 'True' : 'False') + * ) + * + * my_func(mandatory1, mandatory2, opt1:='default', opt2:=0, variadic*) { + * return + * } + */ + MinParams { + get => Number + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#MaxParams|`MaxParams`} + * Returns the number of formally-declared parameters for a user-defined function or maximum parameters for a built-in function. + * If the function is {@link https://www.autohotkey.com/docs/v2/Functions.htm#Variadic|variadic*}, the returned number indicates the maximum amount of parameters which can be accepted by the function without overflowing into the "variadic*" parameter. + * @type Integer + * @example Checking all parameters of a function. + * MsgBox('The ' my_func.Name ' function has ' (my_func.MaxParams + my_func.IsVariadic) ' parameters.' + * '`nRequired parameters: ' my_func.MinParams + * '`nOptional parameters: ' (my_func.MaxParams - my_func.MinParams) + * '`nLast parameter is variadic: ' (my_func.IsVariadic ? 'True' : 'False') + * ) + * + * my_func(mandatory1, mandatory2, opt1:='default', opt2:=0, variadic*) { + * return + * } + */ + MaxParams { + get => Integer + set => Error + } + + /** + * {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#Call|Call()} calls the function. + * @param {(Any)} [Params] + * Any amount of parameters. + * Each parameter must be separated by a comma. + * @returns {(Any)} + * Return values, if any, are defined within each function. + * An empty string is always returned if no return value is explicitly provided. + */ + Call([Params*]) => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#Bind|`Bind()`} + * Binds parameters to the function and returns a {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc object}. + * This and {@link https://www.autohotkey.com/docs/v2/lib/ObjBindMethod.htm|ObjBindMethod()} are the two ways to create boundfuncs. + * @param {(Any)} [ParamN] + * One or more parameters to bind to the function. + * Any parameter can be skipped, leaving that parameter empty and able to receive a parameter later. + * A value can be provided later during the boundfunc Call(). + * Parameter slots can be skipped to pass values onto other parameters. + * @returns {(BoundFunc object)} + * @example Examples of creating BoundFuncs using a function's .Bind() method. + * ; Binding a parameter and calling the boundfunc + * hello := MsgBox.Bind('Hello, world!', 'Oh, hi!') + * hello() + * + * ;==================== + * ; Creating a boundfunc to use as a callback. + * ; Things like SetTimer need boundfuncs if you want to + * ; call a function with predefined parameters: + * farewell := MsgBox.Bind('Goodbye, world.', 'Bye-bye!') + * SetTimer(farewell, -3000) + * + * ;==================== + * ; The title parameter is skipped here. + * again := MsgBox.Bind('Continue?',, 'YesNo') + * ; The first parameter applies to the title (param 2) + * ; This is because the first parameter has a value bound to it + * ; Parameter two is the first available (unbound) parameter + * again('Custom Titlez R Cool',) + * + * ;==================== + * ; Example of a spam clicker that uses a boundfunc + * ; Create a ctrl+space hotkey for the spam clicker + * *^Space::spam_click('Space') + * + * ; Function to handle spam clicking + * spam_click(hold_key) { + * ; If the hold key isn't being physically held + * if !GetKeyState(hold_key, 'P') + * ; Return from function/go no further + * ; This stops the spam click looping + * return + * ; Otherwise click mouse + * Click() + * ; Create a callback (boundfunc) + * callback := spam_click.Bind(hold_key) + * ; And set a timer to run the callback one time in 50ms + * SetTimer(callback, -50) + * } + */ + Bind([ParamN*]) => BoundFunc + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#IsByRef|`IsByRef()`} + * Determines whether a parameter is ByRef. + * ByRef means a {@link https://www.autohotkey.com/docs/v2/Concepts.htm#variable-references|VarRef (Variable Reference)} is expected. + * Normally, when a variable is passed to a function, a copy of the variable is sent, not the variable itself. + * When passed as a VarRef (or By Reference), the actual variable is passed in and can be permanent altered by the function. + * This only applies to variables. Objects are ALWAYS passed ByRef and do not need to be declared as such. + * @param {(Integer)} [ParamIndex] + * The index number of the parameter check. + * Parameters are numbered starting at 1. + * If ParamIndex is omitted, all parameters are checked for ByRef status. + * @returns {(Boolean)} + * `ParamIndex` omitted: + * - `1` = Function contains at least one ByRef parameter. + * - `0` = Function has no ByRef parameters. + * + * `ParamIndex` provided: + * - `1` = The specified parameter is ByRef. + * - `0` = The specified parameter is not ByRef. + * @throws IndexError - ParamIndex is out of range. + * @example Checking for parameters that are "By Reference" + * ; Create two vars. + * var1 := 'Original Data' + * var2 := 'Original Data' + * ; Pass them into the function. + * my_func(var1, &var2) + * + * ; Contents for the var2 was changed + * ; because it was sent by reference. + * MsgBox('Does my_func have any ByRef parameters: ' my_func.IsByRef() + * '`nIs param 1 ByRef: ' my_func.IsByRef(1) + * '`nIs param 2 ByRef: ' my_func.IsByRef(2) + * '`n`nVar contents after function run: ' + * '`nvar1 (normal): ' var1 + * '`nvar2 (ByRef): ' var2) + * + * ; A function that changes both parameters. + * ; v_copy is a normal parameter. + * ; It receives a reference to a copy of var1. + * ; v_reference is a VarRef parameter. + * ; It receives a direct reference to var2. + * my_func(v_copy, &v_reference) { + * ; Change both values + * v_copy := 'Changed by function!' + * v_reference := 'Changed by function!' + * } + */ + IsByRef([ParamIndex:=unset]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#IsOptional|`IsOptional()`} + * Determines whether a parameter is optional. + * Parameters with pre-assigned values and variadic parameters are both optional. + * @param {(Integer)} [ParamIndex] + * The index number of the parameter check. + * Parameters are numbered starting at 1. + * If ParamIndex is omitted, all parameters are checked for optional status. + * @returns {(Boolean)} + * `ParamIndex` omitted: + * - `1` = Function contains at least one optional parameter. + * - `0` = Function has no optional parameters. + * + * `ParamIndex` provided: + * - `1` = The specified parameter is optional and can be omitted. + * - `0` = The specified parameter is required. + + * 1 if parameter is Optional, otherwise 0. + * @throws IndexError - ParamIndex is out of range. + * @example Checking for optional parameters. + * MsgBox('Does my_func have any optional parameters: ' my_func.IsOptional() + * '`nIs param 1 optional: ' my_func.IsOptional(1) + * '`nIs param 2 (predefined) optional: ' my_func.IsOptional(2) + * '`nIs param 3 (variadic) optional: ' my_func.IsOptional(3)) + * + * my_func(required, predefined:=1, variadic*) { + * } + */ + IsOptional([ParamIndex:=unset]) => Integer +} + +/** + * @description {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|`BoundFunc Object`} + * Created a callable function with predefined parameters. + * It's a function with data that's already "bound" to some parameters. + * BoundFunc objects can be created in two ways: + * - Using a function's {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#Bind|Bind()} method. + * Creates a function boundfunc. + * - Using the {@link https://www.autohotkey.com/docs/v2/lib/ObjBindMethod.htm|ObjBindMethod()} function. + * Creates a method boundfunc. + * To skip a parameter, leave that bind slot (index) blank. See example. + * + * A list of functions/methods that can utilize boundfuncs: + * - {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm|CallbackCreate()} + * - {@link https://www.autohotkey.com/docs/v2/lib/HotIf.htm|HotIf()} + * - {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} + * - {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} + * - {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm|InputHook()} + * - {@link https://www.autohotkey.com/docs/v2/lib/OnClipboardChange.htm|OnClipboardChange()} + * - {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} + * - {@link https://www.autohotkey.com/docs/v2/lib/OnExit.htm|OnExit()} + * - {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm|OnMessage()} + * - {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm|SetTimer()} + * - {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Add|Menu.Add()} + * - {@link https://www.autohotkey.com/docs/v2/misc/RegExCallout.htm|RegEx callouts} + * - {@link https://www.autohotkey.com/docs/v2/lib/Sort.htm|Sort} + * - {@link https://www.autohotkey.com/docs/v2/lib/For.htm|For-loops} + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|Gui events} + * @example Function and method boundfunc examples. + * ; Example of a spam clicker that uses a function boundfunc + * ; Create a ctrl+space hotkey for the spam clicker + * *^Space::spam_click('Space') + * + * ; Function to handle spam clicking + * spam_click(hold_key) { + * ; If the hold key isn't being physically held + * if !GetKeyState(hold_key, 'P') + * ; Return from function/go no further + * ; This stops the spam click looping + * return + * ; Otherwise click mouse + * Click() + * ; Create a callback (boundfunc) + * callback := spam_click.Bind(hold_key) + * ; And set a timer to run the callback one time in 50ms + * SetTimer(callback, -50) + * } + * + * ;==================== + * ; Example of a spam clicker that uses a method boundfunc + * ; Create a ctrl+space hotkey for the spam clicker + * *^Space::spammer.run('Space') + * + * class spammer { + * static run(hold_key) { + * ; If the hold key isn't being physically held + * if !GetKeyState(hold_key, 'P') + * ; Return from function/go no further + * ; This stops the spam click looping + * return + * ; Otherwise click mouse + * Click() + * ; Create a boundfunc for this method. + * ; An object and the method name must be provided. + * ; Any parameters to bind can be included after. + * callback := ObjBindMethod(this, 'run', hold_key) + * ; And set a timer to run the callback one time in 50ms + * SetTimer(callback, -50) + * } + * } */ -OnError(Func, AddRemove := 1) => void +class BoundFunc extends Func { +} /** - * Specify a function to run automatically when the script exits. - * @param {(ExitReason, ExitCode) => Integer} Func The function object to call when the script is exiting. + * @description {@link https://www.autohotkey.com/docs/v2/Functions.htm#closures|`Closure`} + * Closures are nested functions that are bound to a set of free variables. + * Free variables are function variables outside the closure that the closure can still access. + * To create a closure, simply define a nested function and have the nested function reference a variable from the outer function. + * @example Demonstrating closure vs static nested functions. + * example() + * + * example() { + * ; This variable can be accessed by a + * ; closure but not by a static function. + * x := 'Outer function text' + * + * ; Test both. + * closure_fn() + * static_fn() + * not_a_closure() + * + * ; Showing each function's type as AHK sees it: + * MsgBox('closure_fn: ' Type(closure_fn) + * '`nstatic_fn: ' Type(static_fn) + * '`nnot_a_closure: ' Type(not_a_closure)) + * return + * + * ; This is a closure because it's not static and + * ; because it references a variable from example(). + * closure_fn() { + * MsgBox('A closure function has access to ' + * '`nthe outer function variables.' + * '`nx from example() is set to: ' x) + * } + * + * static static_fn() { + * MsgBox('Unlike a closure, static functions ' + * 'cannot access variables from the function ' + * 'they are nested in.' + * '`nTrying to access x throws an error.') + * + * try + * MsgBox(x) + * catch + * MsgBox('ERROR!!' + * '`nx cannot be accessed' + * '`n`nStatic functions cannot access variables ' + * 'outside of their body.') + * } + * + * not_a_closure() { + * MsgBox('Because not_a_closure() does not reference any variables from the outer function, it is not considered a closure function. ' + * '`nInstead, it is considered a static function even though it was not declared as static.') + * } + * } */ -OnExit(Func, AddRemove := 1) => void +class Closure extends Func { +} /** - * Specify the function or function object to be automatically called when the script receives the specified message. - * @param MsgNumber The number of the message that needs to be monitored or queried. It should be between 0 and 4294967295 (0xFFFFFFFF). If you don't want to monitor system messages (that is, those with a number less than 0x0400), then it is best to choose one greater than 4096 (0x1000) Number. This reduces possible interference with messages used internally by current and future versions of AutoHotkey. - * @param {(wParam, lParam, msg, hwnd) => Integer} Function The name of the function or function object. To pass the literal function name, it must be enclosed in quotation marks (""). The function must be able to accept four parameters, as described below. - * @param MaxThreads This integer is usually omitted. In this case, the monitoring function can only process one thread at a time. This is usually the best, because otherwise whenever the monitoring function is interrupted, the script will process the messages in chronological order. Therefore, as an alternative to MaxThreads, Critical can be considered, as shown below. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|`Enumerator`} + * A type of {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} called to enumerate through each value of an object. + * They are primarily used by {@link https://www.autohotkey.com/docs/v2/lib/For.htm|for-loops} and are not usually called directly. + * @example Different ways to use enumerators + * arr := ['a', 'b', 'c'] * - * Specify 0 to unregister the function previously identified by Function. - * - * By default, when multiple functions are registered for a MsgNumber, they will be called in the order of registration. To register a function before the previously registered function, specify a negative value for MaxThreads. For example, OnMessage Msg, Fn, -2 Register Fn to be called before any other functions registered for Msg, and allow Fn to have up to 2 threads. However, if the function has already been registered, the order will not change unless the registration is cancelled and then re-registered. - */ -OnMessage(MsgNumber, Function, MaxThreads := 1) => void - -/** - * Returns the serial number value (digital character code) of the first character in the specified string. - */ -Ord(String) => Integer - -/** - * Send the string to the debugger (if available) to display it. - */ -OutputDebug(Text) => void - -/** - * Pause the current thread of the script. - */ -Pause([Newstate]) => void - -/** - * Prevent the script from automatically exiting when its last thread finishes, thereby keeping it running in an idle state. - * @param Persist If true or omitted, even if the other conditions of the exit script are not met, the script will continue to run after all threads exit. - * If false, the default behavior will be restored. - */ -Persistent(Persist := true) => Integer - -/** - * Retrieve the color of the pixel at the specified x and y coordinates. - * @param Mode This parameter can contain zero or more of the following words. If it contains more than one word, use spaces to separate them (eg "Alt Slow"). + * ; Enumerator that only returns the value of each element + * enum := arr.__Enum(1) + * for value in enum + * MsgBox('for-loop`nvalue only: ' value) * - * Alt: Use another method to obtain colors. When the normal method obtains invalid or wrong colors in a special type of window, this method should be considered. This method is about 10% slower than the normal method. + * ; Enumerator that returns the index and value of each element + * enum := arr.__Enum(2) + * for index, value in enum + * MsgBox('for-loop`nindex: ' index '`nvalue: ' value) * - * Slow: Use a more sophisticated method to get the color. This method may be effective when other methods fail in some full-screen applications. This method is about three times slower than the normal method. Note: The Slow method takes precedence over Alt, so There is no need to specify Alt at this time. + * ; Using an enumerator with a while-loop + * enum := arr.__Enum() + * while enum(&index, &value) + * MsgBox('while-loop`nindex: ' index '`nvalue: ' value) */ -PixelGetColor(X, Y, Mode?: 'Alt' | 'Slow' | 'Alt Slow') => String +class Enumerator extends Func { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm#Call|`Enumerator()`} + * A type of {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} which is called repeatedly to enumerate a sequence of values. + * @param {(VarRef)} OutputVar1 + * Variable reference to receive a value dependent on the type of enumerator: + * - `__Enum(1)` = OutputVar1 receives the value of each element. + * - `__Enum(2)` = OutputVar1 receives the value identifier (key/index/etc) of each element. + * @param {(VarRef)} [OutputVar2] + * Variable reference to receive a value dependent on the type of enumerator: + * - `__Enum(1)` = OutputVar2 receives nothing and must be omitted. + * - `__Enum(2)` = OutputVar2 receives the value of each element. + * @param {(VarRef)} [OutputVar3to19] + * A custom enumerator can handle up to 19 OutputVars, as that's the max a for-loop can utilize. + * @returns {(Boolean)} + * - `1` = The next value was successfully gotten. + * - `0` = No more values to enumerate. + * @example Different ways to use enumerators + * arr := ['a', 'b', 'c'] + * + * ; Enumerator that only returns the value of each element + * enum := arr.__Enum(1) + * for value in enum + * MsgBox('for-loop`nvalue only: ' value) + * + * ; Enumerator that returns the index and value of each element + * enum := arr.__Enum(2) + * for index, value in enum + * MsgBox('for-loop`nindex: ' index '`nvalue: ' value) + * + * ; Using an enumerator with a while-loop + * enum := arr.__Enum() + * while enum(&index, &value) + * MsgBox('while-loop`nindex: ' index '`nvalue: ' value) + * + * ;======================= + * ; Creating a class with a customized enumerator. + * ; This will allow the class to be passed to a for-loop. + * ; Unlike normal enumerators, this one uses 3 parameters. + * ; See the for-loop example below the class. + * class test_class { + * ; Define some properties to iterate through. + * static Name := 'GroggyOtter' + * static Age := 100 + * static URL := 'www.reddit.com/r/AutoHotkey' + * static SSN := 123456789 + * + * ; A for-loop always looks for an __Enum() method. + * ; If it finds it + * static __Enum(num_of_vars) { + * ; Normally, AHK's built-in enumerators only + * ; use 1-2 parameters. + * ; However, we're going to enforce 3 parameters + * if (num_of_vars != 3) + * throw(Error('3 parameters must be provided.' + * , A_ThisFunc + * , 'for key, value, value_type in test_class')) + * + * ; Make a call descriptor object. The assigned + * ; function will be called by the for-loop. + * enum := {call:get_next_prop} + * + * ; Make a list of properties to include. + * ; We skip SSN because we don't want it to + * ; show up while iterating through test_class. + * ; If properties are listed in reverse order, + * ; .Pop() can be used, which is faster than .RemoveAt(1). + * enum.list := ['URL', 'Age', 'Name'] + * ; And we need a reference to the + * ; class so we can get the values + * enum.class := this + * + * ; Return the enumerator to the for-loop. + * ; It can use it to loop through each specified item. + * return enum + * + * ; The function that gets called each + * ; iteration of the for-loop + * ; Normally, only 1-2 parameters are used. + * ; A For-loop can handle up to 19 VarRefs + * ; This example shows how to use three. + * get_next_prop(this, &prop, &value, &v_type) { + * ; When there are no properties left + * if (this.list.Length < 1) + * ; Return false to indicate none left + * return 0 + * ; Get next property name + * prop := this.list.Pop() + * ; And its value + * value := this.class.%prop% + * ; And its type + * v_type := Type(value) + * } + * } + * } + * + * ; For-looping through test_class + * ; Notice it uses 3 parameter values + * ; key, value, and value type + * for key, value, value_type in test_class + * MsgBox('Property: ' key + * '`nValue: ' value + * '`nType: ' value_type) + */ + Call(&OutputVar1?: VarRef [,&OutputVar2?: VarRef, &OutputVar3to19]) => Integer +} /** - * Search for pixels of the specified color in the screen area. - * @param OutputVarX [@since v2.1-alpha.3] Can be omitted. - * @param OutputVarY [@since v2.1-alpha.3] Can be omitted. - * @param ColorID The color ID to be searched. It is usually represented by a hexadecimal number in red, green and blue (RGB) format. For example: 0x9d6346. The color ID can be determined by Window Spy (accessible from the tray menu) or PixelGetColor. - * @param Variation is a number between 0 and 255 (inclusive), used to indicate the permissible gradient value of the red/green/blue channel intensity of each pixel color in any direction. If the color you are looking for is not always exactly the same This parameter is very useful. If you specify 255 as the gradient value, all colors will be matched. The default gradient value is 0. - */ -PixelSearch(&OutputVarX?: VarRef, &OutputVarY?: VarRef, X1, Y1, X2, Y2, ColorID, Variation := 0) => Integer + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|`GUI`} + * A GUI is a Graphical User Interface. + * These provide the ability to create and manage custom windows and controls. + * Such windows can be used for a multitude of things, including data entry, hotkey creation, file trees, calenders, or any other imaginable custom user interface. + * Gui objects are created by calling the GUI class. + * @property {(Integer)} BackColor - Retrieves or sets the background color of the window. + * @property {(GuiCtrl)} FocusedCtrl - Retrieves the GuiControl object of the window's focused control. + * @property {(Integer)} Hwnd - Retrieves the window handle (HWND) of the window. + * @property {(Integer)} MarginX - Retrieves or sets the horizontal padding between controls or the sides of the GUI. + * @property {(Integer)} MarginY - Retrieves or sets the vertical padding between controls or the sides of the GUI. + * @property {(MenuBar)} MenuBar - Retrieves or sets the window's menu bar. + * @property {(String)} Name - Retrieves or sets a custom name for the window. + * @property {(String)} Title - Retrieves or sets the window's title. + * @property {(GuiCtrl)} __Item - Retrieves the GuiControl object associated with the specified name, text, ClassNN or HWND. + * @example Gui with many common controls added. + * make_gui() + * + * make_gui() { + * ; Create a new GUI. + * goo := Gui() + * ; Make the background color black. + * goo.BackColor := 0x0 + * ; Set a new title. + * goo.Title := "Custom GUI" + * ; Set the margins (spacing) between controls. + * ; This applies whenever an x or y position isn't provided. + * goo.MarginX := goo.MarginY := 15 + * ; Set the default font color be used. + * goo.SetFont('cWhite') + * ; Close script if GUI is closed. + * ; Fat-arrow functions can be used + * ; instead of function references. + * goo.OnEvent('Close', (*) => ExitApp()) + * + * ; Add ability to make GUI always on top. + * con := goo.AddCheckbox('xm', 'Always On Top') + * con.OnEvent('Click', toggle_aot) + * + * ; Make a dark/light mode toggle. + * goo.AddGroupBox('xm y+m h75 Section', 'Choose Scheme:') + * con := goo.AddRadio('xs+15 ys+20 vDark Checked', 'Dark Mode') + * con.OnEvent('Click', scheme_update) + * con := goo.AddRadio('xs+15 y+m vLight', 'Light Mode') + * con.OnEvent('Click', scheme_update) + * + * ; Create a transparency slider. + * con := goo.AddText('xm ys+85 vtrans_percent', 'Transparency: 100%') + * ; Identifier of opaque side. + * goo.AddText('xm y+5', 'Opaque') + * ; Slider for adjusting transparency. + * con := goo.AddSlider('x+5 h20 Range20-255 AltSubmit Invert vslider', 255) + * ; Set the function to call when the slider is changed. + * con.OnEvent('Change', adjust_transparency) + * ; Identifier of clear/transparent side. + * goo.AddText('x+5', 'Clear') + * + * ; Add a control for setting a hotkey + * ; that launches calculator. + * goo.AddText('xm y+m', 'Set hotkey to launch Calculator') + * con := goo.AddHotkey('xm y+0') + * con.OnEvent('Change', update_calc_hotkey) + * + * ; Create a button to exit script. + * con := goo.AddButton('xm y+m', 'Exit Script') + * con.OnEvent('Click', (*) => ExitApp()) + * + * ; Build a custom menubar for the gui + * ; Create a main bar to apply to the gui. + * bar := MenuBar() + * ; Create a menu to bring up. + * file_menu := Menu() + * ; We can use the AHK standard menu. + * file_menu.AddStandard() + * ; Apply the menu to the bar and give it a name. + * bar.Add('Main Menu', file_menu) + * ; Apply new menu bar to the gui. + * goo.MenuBar := bar + * + * goo.Show('w250') + * return + * + * toggle_aot(checkbox, Info) { + * ; If checked, apply AOT + * ; otherwise remove it. + * if checkbox.Value + * aot := '+AlwaysOnTop' + * else aot := '-AlwaysOnTop' + * ; Update AOT option. + * checkbox.Gui.Opt(aot) + * } + * + * scheme_update(radio, Info) { + * ; Set background and text color base + * ; on which radio button was pressed. + * switch radio.name { + * case 'Light': + * radio.Gui.BackColor := 0xE0E0E0 + * text_color := 'cBlack' + * case 'Dark': + * radio.Gui.backcolor := 0x0 + * text_color := 'cWhite' + * } + * ; Loop through each control. + * for con in radio.Gui + * ; Apply white text + * ; Try is to prevent errors + * try con.SetFont(text_color) + * ; Focus slider then focus radio button. + * ; This forces slider background to update. + * radio.Gui['slider'].Focus() + * radio.Focus() + * } + * + * adjust_transparency(slider, Info) { + * ; Get value from slider. + * value := slider.value + * ; Apply transparency using slider number. + * WinSetTransparent(value, goo) + * ; Calculate current trans percentage + * ; and apply to the trans_percent text control. + * value := Round(value/255*100) '%' + * slider.gui['trans_percent'].Text := 'Transparency: ' value + * } + * + * update_calc_hotkey(hk, Info) { + * static last_hk := '' + * ; Unregister the previous hotkey + * if (last_hk != '') + * Hotkey(last_hk, 'Off') + * last_hk := hk.Value + * Hotkey(hk.Value, run_calc) + * return + * + * run_calc() { + * exe := 'calc.exe' + * id := 'ahk_exe ' exe + * if WinExist(id) + * WinActivate() + * else Run(exe) + * } + * } + * } + */ +class Gui extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|Control} + * This is the base object that all control objects are derived. + * It provides core properties and methods that all controls. + * @property {(String)} ClassNN - Retrieve the class name and sequence number (ClassNN) of the control. + * @property {(Integer)} Enabled - Retrieve or set the interaction state of the control to enabled or disabled. + * @property {(Integer)} Focused - Retrieve the focus state of the control. + * @property {(Gui)} Gui - Retrieve a reference to the GUI that owns the control. + * @property {(Integer)} Hwnd - Retrieve the window handle (HWND) of the control. + * @property {(String)} Name - Retrieve or set an identifying name for the control. + * @property {(String)} Text - Retrieve or set the text, caption, other information of the control. + * This property varies depending on the control's type. + * @property {(String)} Type - Retrieve the type of the control. + * @property {(String)} Value - Retrieve or set the data of a value-capable control. + * This property varies depending on the control's type and not all controls utilize the value property. + * @property {(Integer)} Visible - Retrieve or set the visible state of the control. + */ + class Control extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#ClassNN|`ClassNN`} + * Retrieves the class name and sequence number (ClassNN) of the control. + * The `Class` is the type of control and the `NN` is the sequence number. + * `Edit2` would denote the second edit box that was added to a GUI. + * @type String + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlGetClassNN.htm|ControlGetClassNN} + * @example Labeling all controls with their ClassNN. + * ; Create a gui and add multiple controls. + * goo := Gui() + * goo.AddText() + * goo.AddButton() + * goo.AddEdit() + * goo.AddCheckbox() + * goo.AddText() + * goo.AddRadio() + * goo.AddRadio() + * ; Loop through all controls. + * for control in goo { + * ; Assign the ClassNN as the control's text. + * control.Text := control.ClassNN + * ; Increase width to accommodate new text. + * control.Move(,,100) + * } + * goo.Show('w200') + */ + ClassNN { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Enabled|`Enabled`} + * Retrieve or set the interaction state of the control. + * By setting this, you can disable or enable the ability to interact with that control. + * - `1` = Control enabled + * - `0` = Control disabled + * + * For Tab controls, this will also enable or disable all of the tab's sub-controls. + * @type Integer + * @example A checkbox that enables/disables another control. + * goo := Gui() + * ; Add a checkbox that toggles a button on/off + * con := goo.AddCheckbox('xm ym Checked', 'Disable Button') + * con.OnEvent('Click', toggle_disable) + * ; Add the button to enable/disable + * con := goo.AddButton('w100 vexit_btn +Disabled', 'Exit Script') + * con.OnEvent('Click', (*) => ExitApp()) + * goo.Show() + * + * ; Function that runs when checkbox is clicked + * toggle_disable(checkbox, info) { + * ; Using the checkbox's GUI property, we have access + * ; to all other controls, including the exit button. + * button := checkbox.Gui['exit_btn'] + * ; If checkbox is checked + * if checkbox.Value + * ; Enable button + * button.Enabled := 0 + * ; Otherwise, disable button + * else button.Enabled := 1 + * } + */ + Enabled { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Focused|`Focused`} + * Retrieves the focus state of the control. + * - `1` = Focused + * - `0` = Not focused + * + * To set focus on a control, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Focus|Focus()} method. + * @type Integer + */ + Focused { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Gui|`Gui`} + * Retrieves a reference to the control's parent {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|GUI object}. + * This gives every control direct access to the GUI that owns it as well as all other controls owned by the GUI. + * @type Gui + * @example A checkbox that enables/disables another control. + * goo := Gui() + * ; Add a checkbox that toggles a button on/off + * con := goo.AddCheckbox('xm ym Checked', 'Disable Button') + * con.OnEvent('Click', toggle_disable) + * ; Add the button to enable/disable + * con := goo.AddButton('w100 vexit_btn +Disabled', 'Exit Script') + * con.OnEvent('Click', (*) => ExitApp()) + * goo.Show() + * + * ; Function that runs when checkbox is clicked + * toggle_disable(checkbox, info) { + * ; Using the checkbox's GUI property, we have access + * ; to all other controls, including the exit button. + * button := checkbox.Gui['exit_btn'] + * ; If checkbox is checked + * if checkbox.Value + * ; Enable button + * button.Enabled := 0 + * ; Otherwise, disable button + * else button.Enabled := 1 + * } + */ + Gui { + get => Gui + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Hwnd|`Hwnd`} + * Retrieves the window handle (HWND) of the control. + * @see {@link https://www.autohotkey.com/docs/v2/lib/PostMessage.htm|PostMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control parameter} + * @type Integer + */ + Hwnd { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|`Name`} + * Retrieves or sets the control's Name. + * A control name can be used to retrieve the control's object from the Gui. + * Using the Name property allows you to name the control anything, including spaces. + * Using the `v` option has character restrictions, such as spaces. + * + * con.Name := 'Exit Btn' ; Set name using property + * con.Opt('vExitBtn') ; Set name using v with Opt() + * goo.AddButton('vExitBtn') ; Set name using v with AddTYPE() + * @type String + * @example + * goo := Gui() ; New gui + * con := goo.AddButton(, 'Quit') ; Add a button. + * con.Name := 'Exit Btn' ; Name it 'Exit Btn' + * control := goo['Exit Btn'] ; Use a name to get control reference + * control.OnEvent('Click', quit) ; Adding a click event + * goo.Show('w200 h200') ; Show the gui + * + * quit(*) { + * ExitApp() ; Close the script + * } + */ + Name { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * Retrieves or sets the text/caption of the control. + * - Button, CheckBox, Edit, GroupBox, Link, Radio, Text: + * The caption or display text of the control. + * - DateTime: + * Get the current formatted text display or assign a new {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS} date-time stamp date-time stamp. + * - DropDownList, ComboBox, ListBox: + * Text of the currently selected item. + * - Tab: + * Text of the currently selected Tab. + * - Edit: + * The text in the control. + * - StatusBar: + * The text of the first section. + * @type String + */ + Text { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Type|`Type`} + * Retrieves the {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|type} of the control: + * | | | | | + * | :--- | :--- | :--- | :--- | + * | `ActiveX` | `DateTime` | `ListView` | `Slider` | + * | `Button` | `Edit` | `MonthCal` | `StatusBar` | + * | `CheckBox` | `GroupBox` | `Pic` | `Tab` | + * | `ComboBox` | `Hotkey` | `Picture` | `Text` | + * | `Custom` | `Link` | `Progress` | `TreeView` | + * | `DDL` | `ListBox` | `Radio` | `UpDown` | + * @type String + */ + Type { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets the contents of a value-capable control. + * If not value-capable, returns an empty string or errors if set. + * - `ActiveX`: + * The ActiveX object of the control. + * Assigning a new value is an error. + * - `Checkbox`, `Radio`: + * Get/set current checked status: `1`, `0`, `-1`. + * - `ComboBox`, `DropDownList`, `ListBox`, `Tab`: + * Position number of selected item. + * - `DateTime`, `MonthCal`: + * Get or set a {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS} date-time stamp. + * - `Edit`: + * Text of control. Similar to the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|text} property. + * - `Hotkey`: + * Text representing a hotkey. + * - `Picture`: + * Filename of a picture. + * - `Progress`, `Slider`, `UpDown`: + * Current position of the control. + * - `Text`: + * The text of the control. + */ + Value { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|`Visible`} + * Retrieves the current visibility state of the control, or set the control invisible/visible. + * @type Integer + */ + Visible { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Focus|`Focus()`} + * Sets the keyboard focus to this control. + * To be effective, the window generally must not be minimized or hidden. + * To retrieve the focus state of the control, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Focused|Focused} property. + * @returns {(String)} + * An empty string is always returned. + * @example Focusing a specific control. + * goo := Gui() + * goo.btn_exit := goo.AddButton('xm ym w100', 'Exit Script') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * goo.btn_msg := goo.AddButton('xm w100', 'PopUp Msg') + * goo.btn_msg.OnEvent('Click', (*) => MsgBox('Pop Up!')) + * goo.btn_exit.Focus() + * txt := 'Even though "PopUp Msg" was added last, the ' + * . '`nFocused button was set to "' goo.FocusedCtrl.Text '"' + * goo.AddText('xm', txt) + * goo.Show('y200') + */ + Focus() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#GetPos|`GetPos()`} + * Retrieves the position and size of the control. + * Unlike {@link https://www.autohotkey.com/docs/v2/lib/ControlGetPos.htm|ControlGetPos()}, this method applies {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#DPIScale|DPI scaling} to the returned coordinates. + * @param {(VarRef)} [X] + * Variable reference to receive x coordinate of GUI control + * @param {(VarRef)} [Y] + * Variable reference to receive y coordinate of GUI control + * @param {(VarRef)} [Width] + * Variable reference to receive width of control + * @param {(VarRef)} [Height] + * Variable reference to receive height of control + * @returns {(String)} + * An empty string is always returned. + * @example Adjust button attributes using checkboxes. + * goo := Gui() + * goo.MarginX := goo.MarginY := 10 + * goo.AddText('xm ym', 'Check boxes to change button:') + * goo.cb_tall := goo.AddCheckbox('xm w100 h30 vTall', 'Make Tall') + * goo.cb_tall.OnEvent('Click', check_events) + * goo.cb_wide := goo.AddCheckbox('x+m w100 h30 vWide', 'Make Wide') + * goo.cb_wide.OnEvent('Click', check_events) + * goo.btn_exit := goo.AddButton('xm', 'ExitScript') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * goo.Show('h150') + * + * check_events(control, info) { + * control.gui.btn_exit.GetPos(,, &w, &h) + * switch control.name { + * case 'Tall': + * if (h > 30) + * h := 30 + * else h := 60 + * case 'Wide': + * if (w > 100) + * w := 100 + * else w := 200 + * } + * control.gui.btn_exit.Move(,, w, h) + * } + */ + GetPos([&X, &Y, &Width, &Height]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|`Move()`} + * Moves and/or resizes the control. + * Unlike {@link https://www.autohotkey.com/docs/v2/lib/ControlMove.htm|ControlMove()}, this method applies {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#DPIScale|DPI scaling} to the returned coordinates. + * @param {(Integer)} [X] + * New x coordinate. + * @param {(Integer)} [Y] + * New y coordinate. + * @param {(Integer)} [Width] + * New control width. + * @param {(Integer)} [Height] + * New control height. + * @returns {(String)} + * An empty string is always returned. + * @example Adjust button attributes using checkboxes. + * goo := Gui() + * goo.MarginX := goo.MarginY := 10 + * goo.AddText('xm ym', 'Check boxes to change button:') + * goo.cb_tall := goo.AddCheckbox('xm w100 h30 vTall', 'Make Tall') + * goo.cb_tall.OnEvent('Click', check_events) + * goo.cb_wide := goo.AddCheckbox('x+m w100 h30 vWide', 'Make Wide') + * goo.cb_wide.OnEvent('Click', check_events) + * goo.btn_exit := goo.AddButton('xm', 'ExitScript') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * goo.Show('h150') + * + * check_events(control, info) { + * control.gui.btn_exit.GetPos(,, &w, &h) + * switch control.name { + * case 'Tall': + * if (h > 30) + * h := 30 + * else h := 60 + * case 'Wide': + * if (w > 100) + * w := 100 + * else w := 200 + * } + * control.gui.btn_exit.Move(,, w, h) + * } + */ + Move([X, Y, Width, Height]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#OnCommand|`OnCommand()`} + * Registers a function or method to be called when a control notification is received via the {@link https://learn.microsoft.com/windows/win32/menurc/wm-command|WM_COMMAND message}. + * @param {(Integer)} NotifyCode + * The control-defined notification code to monitor. + * @param {(String|FuncObj)} Callback + * The function, method, boundfunc, or object to call when the event is raised. + * If GUI uses an event sink, this can be a string with a method's name. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. If omitted, parameter defaults to 1. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/misc/SendMessageList.htm|WM - Window Messages} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiOnCommand.htm|Gui.OnCommand()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|OnEvent()} + */ + OnCommand(NotifyCode, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {(String)} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The control's value changes. + * + * Ctrl_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The control is clicked. + * + * Ctrl_Click(GuiCtrl, Info) + * Link_Click(GuiCtrl, Info, Href) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The control is double-clicked. + * + * Ctrl_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ColClick|`ColClick`} - One of the ListView's column headers is clicked. + * + * Ctrl_ColClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the control + * or presses Menu or Shift+F10 while the control has the keyboard focus. + * + * Ctrl_ContextMenu(GuiCtrl, Item, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The control gains the keyboard focus. + * + * Ctrl_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The control loses the keyboard focus. + * + * Ctrl_LoseFocus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemCheck|`ItemCheck`} - A ListView or TreeView item is checked or unchecked. + * + * Ctrl_ItemCheck(GuiCtrl, Item, Checked) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemEdit|`ItemEdit`} - A ListView or TreeView item's label is edited by the user. + * + * Ctrl_ItemEdit(GuiCtrl, Item) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemExpand|`ItemExpand`} - A TreeView item is expanded or collapsed. + * + * Ctrl_ItemExpand(GuiCtrl, Item, Expanded) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemFocus|`ItemFocus`} - The focused item changes in a ListView. + * + * Ctrl_ItemFocus(GuiCtrl, Item) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemSelect|`ItemSelect`} - A ListView or TreeView item is selected, or a ListView item is deselected. + * + * ListView_ItemSelect(GuiCtrl, Item, Selected) + * TreeView_ItemSelect(GuiCtrl, Item) + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * If GUI uses an event sink, this can be a string with a method's name. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnNotify.htm|`OnNotify()`} + * Registers a function or method to be called when a control notification + * is received via the {@link https://learn.microsoft.com/windows/win32/controls/wm-notify|WM_NOTIFY} message. + * @param {(Integer)} NotifyCode + * The control-defined notification code to monitor. + * @param {(String|FuncObj)} Callback + * The function, method, boundfunc, or object to call when the event is raised. + * If GUI uses an event sink, this can be a string with a method's name. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * If omitted, parameter defaults to 1. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GuiOnNotify.htm|OnNotify()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|OnEvent()} + */ + OnNotify(NotifyCode, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control. + * @param {String|'AltSubmit'|'Background'|'BackgroundTrans'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.Opt('+vExitBtn') ; Set using v option. Can't include a space + * con.Name := 'Exit Btn' ; Set using Name property. Can including a space + * - `AltSubmit`: Use control's alternate submit method. + * DropDownList, ComboBox, ListBox, Tab: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} uses selected item's position instead of its text. + * ComboBox: If no item is selected, the text of the edit field is instead stored. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * This option does not affect {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Button|buttons} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#StatusBar|status bars}. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.Opt('cRed') + * con.Opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed immediately by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.Opt('+Disabled') ; Control disabled + * var := 0 + * con.Opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed immediately by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * Applies to: Button, Checkbox, DateTime, Edit, GroupBox, Radio, Slider, Tab, Tab2, Text, UpDown + * - `Right`: Right justify control text within its available width. + * Checkbox and Radio Buttons have their box moved to the right side of the control. + * Applies to: Button, Checkbox, DateTime, Edit, GroupBox, Link, Radio, Slider, Tab, Tab2, Text, UpDown + * - `Center`: Center justify control text within its available width. + * Applies to: Button, Checkbox, Edit, GroupBox, Radio, Slider, Text + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the Picture to show through. Use `+Background` to remove this option later. + * Applies to: Text, Picture, GroupBox + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('Button', 'BackgroundNavy') + * con.opt('Button', 'Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Hiding and showing all GUI controls. + * goo := Gui() + * goo.cb_hide := goo.AddCheckbox('xm ym vcb_hide', 'Hide All') + * goo['cb_hide'].OnEvent('click', test) + * loop 3 + * goo.AddButton('xm w100 h25', 'Button' A_Index) + * ,goo.AddCheckbox('x+m w100 h25 +Border +Right', 'Checkbox' A_Index) + * con := goo.AddButton('xm w210', 'Exit Script') + * con.OnEvent('Click', (*) => ExitApp()) + * goo.show() + * + * test(con, info) { + * if con.value + * option := '+Hidden' + * else option := '-Hidden' + * + * for hwnd, control in con.gui + * if (control.Name != 'cb_hide') + * control.Opt(option) + * } + */ + Opt(Options) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Redraw|`Redraw()`} + * Repaints the region of the GUI window occupied by the control. + * Redrawing solves problems such as groupbox artifacting. + * If called repeatedly, this may cause GUI flickering. + * @returns {(String)} + * An empty string is always returned. + * @example Call Redraw() if a control needs redrawn. + * control_obj.Redraw() + */ + Redraw() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#SetFont|`SetFont()`} + * Sets the font typeface, size, style, and/or color for the control. + * Omitting both parameters sets the control font to the current Gui.SetFont() values. + * If Gui.SetFont() has not been set, the system default values are used. + * @param {String|'bold'|'italic'|'strike'|'underline'|'norm'|'C'|'S'|'W'|'Q'} [Options] + * Zero or more options separated by spaces. + * Styling words are applied in order. + * `norm italic` would disable all options and apply only italics + * - `bold` - Adds a heavy weight/boldness to text. + * - `italic` - Italicizes text. + * - `strike` - Strikes out text by adding a horizontal line through it. + * - `underline` - Underlines text. + * - `norm`- Disables all aforementioned settings. + * + * Other options: + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * + * - Reset/Default: + * `CDefault` or `C` + * The color option does not affect {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Button|buttons} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#StatusBar|status bars}. + * - `S#`: Size in points where `#` is a decimal value. + * - `W#`: Weight/boldness where `#` is a decimal value between 1 and 1000. 400 is normal. 700 is bold. + * - `Q#`: {@link https://learn.microsoft.com/windows/win32/api/wingdi/nf-wingdi-createfonta|Text rendering quality} where `#` is an integer between 0 and 5. + * - `0` - Window Constant: `DEFAULT_QUALITY` - Appearance of the font does not matter. + * - `1` - Window Constant: `DRAFT_QUALITY` - Appearance of the font is less important than when the PROOF_QUALITY value is used. + * - `2` - Window Constant: `PROOF_QUALITY` - Character quality of the font is more important than exact matching of the logical-font attributes. + * - `3` - Window Constant: `NONANTIALIASED_QUALITY` - Font is never antialiased, that is, font smoothing is not done. + * - `4` - Window Constant: `ANTIALIASED_QUALITY` - Font is antialiased, or smoothed, if the font supports it and the size of the font is not too small or too large. + * - `5` - Window Constant: `CLEARTYPE_QUALITY` - If set, text is rendered (when possible) using ClearType antialiasing method. + * @param {(String)} [FontName] + * The name of any font, such as one from the {@link https://www.autohotkey.com/docs/v2/misc/FontsStandard.htm|font table}. + * If `FontName` is omitted or does not exist on the system, the previous font typeface will be used, otherwise the system's default Gui typeface is used. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#SetFont|Gui.SetFont()} + * @example Changing control font properties. + * goo := Gui() + * con := goo.AddText('xm ym w200 h30 Center Border', 'Big Header Text') + * con.SetFont('S16 Bold c00A080') + * con := goo.AddText('xm w200 h100 Left', 'Normal text goes down here.`nMore text.' + * '`nEven more text`n+1 more line.`nLine++`nEOL (End of lines!)') + * con.SetFont('s10 Italic') + * con.SetFont(, 'Courier New') + * con.SetFont(, 'Consolas') + * goo.Show() + */ + SetFont([Options:=GuiFontOptions, FontName:=GuiFontType]) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ActiveX|`ActiveX`} + * ActiveX components, such as the {@link https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/webbrowser-control-overview?view=netframeworkdesktop-4.8|MSIE browser control}, can be embedded into a GUI window. + */ + class ActiveX extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets the contents of a value-capable control. + * The Value is the ActiveX object of the ActiveX control. + * For details about the ActiveX component and its method used below, see: + * - {@link https://learn.microsoft.com/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752085(v=vs.85)|WebBrowser object (Microsoft Docs)} + * - {@link https://learn.microsoft.com/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752093(v=vs.85)|Navigate method (Microsoft Docs)} + * @example Adding an MSIE control to a GUI. + * goo := Gui() + * goo.MarginX := goo.MarginY := 0 + * goo.BackColor := 0xFFFF00 + * con := goo.AddText('xm ym w924 h30', 'Yes, this is inside a GUI.') + * con.SetFont('s18') + * con.SetFont('s18 Bold') + * con := goo.AddButton('x+0 w100 h30', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * goo.web := goo.AddActiveX("x0 y+0 w1024 h768", "Shell.Explorer") + * ; The ActiveX object is stored in the value property + * goo.Show() + * goo.web.value.Navigate("https://www.autohotkey.com/docs/v2/index.htm") + */ + value { + get => String + set => Error + } + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Button|`Button`} + * A pushbutton, which can be pressed to trigger an action. + */ + class Button extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The caption that displays on the button. + * If the text size of a button is increased, the button does not auto-adjust in size. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to adjust button width if needed. + * @type String + * @example Changing button caption. + * goo := Gui() + * control := goo.AddButton('w200 h100', 'change') + * control.lowercase := 1 + * control.OnEvent('Click', change_text) + * goo.Show('') + * + * change_text(con, info) { + * if (con.lowercase) + * con.Text := StrUpper(con.Text) + * ,con.lowercase := 0 + * else + * con.Text := StrLower(con.Text) + * ,con.lowercase := 1 + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'DoubleClick'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The Button is clicked. + * + * Button_Click(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The Button is double-clicked. + * + * Button_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Button or presses + * Menu or Shift+F10 while the Button has the keyboard focus. + * + * Button_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The Button gains the keyboard focus. + * + * Button_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The Button loses the keyboard focus. + * + * Button_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Button's object + * - `Info`: Not used with Button controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Multiple buttons and events + * goo := Gui() + * + * goo.btn_max := goo.AddButton('xm ym w100', 'Maximize Window') + * goo.btn_max.OnEvent('Click', (con, *) => con.gui.Maximize()) + * + * goo.btn_res := goo.AddButton('xm w100', 'Restore Window') + * goo.btn_res.OnEvent('Click', (con, *) => con.gui.Restore()) + * + * goo.btn_win := goo.AddButton('xm w100', 'Toggle Win Border') + * goo.btn_win.OnEvent('Click', border_toggle) + * + * goo.btn_warn := goo.AddButton('xm w100', 'Focus this button`nUse tab/arrow') + * goo.btn_warn.OnEvent('Focus', (con, *) => con.gui.BackColor := 0xE0E000) + * goo.btn_warn.OnEvent('LoseFocus', (con, *) => con.gui.BackColor := 'Default') + * goo.btn_warn.OnEvent('Click', (*) => MsgBox("Don't click me!")) + * + * goo.btn_exit := goo.AddButton('xm w100', 'Close').OnEvent('Click', quit) + * + * goo.Show('AutoSize') + * + * quit(*) => ExitApp() + * + * border_toggle(con, info) { + * static state := 0 + * state := !state + * if state + * con.gui.Opt('-Caption') + * else con.gui.Opt('+Caption') + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * Sets various options to change a control's appearance or behaviors. + + * @param {String|'Default'|'Border'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Default`: Causes this button to be the default button. + * The default button is the button that's activated when the user presses "Enter". + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con := goo.AddButton('+vExitBtn') ; Set using v option. Can't include a space + * con.Name := 'Exit Btn' ; Set using Name property. Can including a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed immediately by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') + * var := 1 + * con.opt('Disabled' var) + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed immediately by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * @returns {(String)} + * An empty string is always returned. + * @example Show/hide gui control. + * goo := Gui() + * con := goo.AddButton('w100 h50 vBtnShowHide', 'Show') + * con.OnEvent('Click', btn_click) + * con := goo.AddButton('x+10 w100 h50 +Hidden vBtnExit', 'Exit') + * con.OnEvent('Click', btn_click) + * goo.Show() + * + * btn_click(btn, info) { + * switch btn.Name { + * case 'BtnShowHide': + * if (btn.Text = 'Show') { + * btn.Gui['BtnExit'].Opt('-Hidden') + * btn.Text := 'Hide' + * } else { + * btn.Gui['BtnExit'].Opt('+Hidden') + * btn.Text := 'Show' + * } + * case 'BtnExit': ExitApp() + * } + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#CheckBox|`CheckBox`} + * A small box that can be checked or unchecked to represent On/Off, Yes/No, etc. + */ + class CheckBox extends Gui.Control { + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The caption that displays on the checkbox. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to adjust checkbox width if needed. + * @type String + * @example Changing checkbox caption. + * goo := Gui() + * control := goo.AddCheckbox('w100 h50', 'change') + * control.lowercase := 1 + * control.OnEvent('Click', change_text) + * goo.Show('') + * + * change_text(con, info) { + * if (con.lowercase) + * con.Text := StrUpper(con.Text) + * ,con.lowercase := 0 + * else + * con.Text := StrLower(con.Text) + * ,con.lowercase := 1 + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets the checked state. + * Values can be: + * `1`: Checked + * `0`: Unchecked + * `-1`: Grey checked/undetermined ({@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#CheckBox|Check3} option must be enabled) + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|Text property} to set/get the control text. + * @type Integer + */ + Value { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'DoubleClick'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following events. Expected callback format is included. Parameter meanings are listed below the callbacks. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The CheckBox is clicked. + * + * CheckBox_Click(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The CheckBox is double-clicked. + * + * CheckBox_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the CheckBox or presses + * Menu or Shift+F10 while the CheckBox has the keyboard focus. + * + * CheckBox_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The CheckBox gains the keyboard focus. + * + * CheckBox_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The CheckBox loses the keyboard focus. + * + * CheckBox_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the CheckBox's object + * - `Info`: Not used with CheckBox controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example CheckBox hides/shows the exit button + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddButton('x+10 w100 h50 +Hidden vBtnExit', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * goo.Show() + * + * cb_click(btn, info) { + * if (btn.Value = 1) + * btn.Gui['BtnExit'].Opt('-Hidden') + * else btn.Gui['BtnExit'].Opt('+Hidden') + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Check3'|'Checked'|'CheckedGray'|'Background'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Check3`: Adds a 3rd "indeterminate" gray checkmark state to the checkbox. + * This can be used to indicate a 3rd check stat, such as a "maybe", "indeterminate", or "both" type of state. + * - `Checked` or `CheckedGray`: Starts the checkbox checked or checked grey/indeterminate. + * `Checked` may also be followed by a 0 (unchecked), 1 (checked), or -1 (gray checked). + * + * con.opt('+Checked0') + * var := 1, con.opt('+Checked' var) + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vCbOption') ; Set using v option. Can't include a space + * con.Name := 'Cb Option' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * The box will also be moved to the right side of the control. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('Button', 'BackgroundNavy') + * con.opt('Button', 'Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example CheckBox hides/shows the exit button + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddButton('x+10 w100 h50 +Hidden vBtnExit', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * goo.Show() + * + * cb_click(btn, info) { + * if (btn.Value = 1) + * btn.Gui['BtnExit'].Opt('-Hidden') + * else btn.Gui['BtnExit'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Custom|`Custom`} + * Other controls which are not directly supported by AutoHotkey can also be embedded into a GUI window. + * In order to do so, include in Options the word Class followed by the Win32 class name of the desired control. + */ + class Custom extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vcustCon') ; Set using v option. Can't include a space + * con.Name := 'Cust Con' ; Set using Name property. Can include a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DateTime|`DateTime`} + * A box that looks like a single-line edit control but instead accepts a date and/or time. + * A drop-down calendar is also provided. + */ + class DateTime extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * Gets the date from the control, formatted as: M/D/YYYY + * To change the date-time, assign a new date-time stamp in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS} format to the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|Value property}. + * @type String + * @example Showing difference between Text and Value property + * goo := Gui() + * con := goo.AddDateTime('vDTMain') + * + * con := goo.AddButton('vBtnShowText', 'Show DateTime.Text') + * con.OnEvent('Click', btn_click) + * con := goo.AddButton('x+5 vBtnShowValue', 'Show DateTime.Value') + * con.OnEvent('Click', btn_click) + * + * con := goo.AddButton('xm vBtnExit', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * btn_click(btn, info) { + * if InStr(btn.Name, 'ShowText') + * MsgBox(btn.Gui['DTMain'].Text) + * else MsgBox(btn.Gui['DTMain'].Value) + * } + */ + Text { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Gets the control's Date-time stamp in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS format}. + * Use {@link https://www.autohotkey.com/docs/v2/Variables.htm#Now|A_Now} to set Value to current time. + * If the {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ChooseNone|`+2` (No time selected box) option} was used, setting value to 0 will clear the DateTime control. + * @type String + * @example Showing difference between Text and Value property + * goo := Gui() + * con := goo.AddDateTime('vDTMain') + * + * con := goo.AddButton('vBtnShowText', 'Show DateTime.Text') + * con.OnEvent('Click', btn_click) + * con := goo.AddButton('x+5 vBtnShowValue', 'Show DateTime.Value') + * con.OnEvent('Click', btn_click) + * + * con := goo.AddButton('xm vBtnExit', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * btn_click(btn, info) { + * if InStr(btn.Name, 'ShowText') + * MsgBox(btn.Gui['DTMain'].Text) + * else MsgBox(btn.Gui['DTMain'].Value) + * } + */ + Value { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The DateTime's value changes. + * + * DateTime_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the DateTime or presses + * Menu or Shift+F10 while the DateTime has the keyboard focus. + * + * DateTime_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The DateTime gains the keyboard focus. + * + * DateTime_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The DateTime loses the keyboard focus. + * + * DateTime_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the DateTime's object + * - `Info`: Not used with DateTime controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Alert user if DateTime is changed. + * goo := Gui() + * con := goo.AddDateTime('vDTMain') + * con.OnEvent('Change', dt_change) + * + * con := goo.AddButton('xm vBtnExit', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * dt_change(dt, info) { + * TrayTip('Warning. The current DateTime has been changed!') + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Choose'|'ChooseNone'|'Range'|'1'|'2'|'Colors'|'Background'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose`: Pre-select a date or time other than the current date/time. + * Choose should be followed by a DTS in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHHMISS format}. + * When setting the time, the full date and time must be provided. + * `ChooseNone` adds a checkbox to toggle usable state (similar to a checkbox greycheck). + * - `RangeMIN-MAX`: Sets how far back or forward you can set the DateTime control. + * MIN and MAX should be dates. Omitting one leaves that side of the range unrestricted. + * + * con.opt('Range20220101-20221231') + * con.opt('Range-20250101115959') + * - `Right`: Right edge of drop-down calendar aligns with the right side of the control. + * - `Left`: Left edge of drop-down calendar aligns with the left side of the control. + * - `1`: Provide an up-down control to the right of the control to modify date-time values. + * This replaces the button of the drop-down month calendar. Does not work with the `LongDate` option. + * - `2`: Provide a checkbox inside the control, similar to `CheckNone`. + * When unchecked, the control is greyed out and indicates no date/time is selected. + * This option cannot be added or removed after the control is created. + * - `Colors`: Day number colors inside the drop-down calendar obey {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#SetFont|Gui.SetFont()} or the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|C option'}. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vDTMain') ; Set using v option. Can't include a space + * con.Name := 'DT Main' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddDateTime('x+10 w100 h50 +Hidden vDTMain') + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['DTMain'].Opt('-Hidden') + * else cb.Gui['DTMain'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DateTime_SetFormat|`SetFormat()`} + * Sets the display format of a {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DateTime|DateTime} control. + * @param {'ShortDate'|'LongDate'|'Time'} [DateFormat] + * Sets the desired {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DateTimeFormat|display format} of a DateTime control. + * - `ShortDate`: Locale short date format. Example: 6/1/2005 + * ShortDate is used if DateFormat is omitted or is an empty string + * - `LongDate`: Locale long date format. Example: Wednesday, June 01, 2005 + * - `Time`: Shows locale time only. Example: 9:37:45 PM + * The date is still present in the control even though it's not shown. + * It will be retrieved along with the time in the YYYYMMDDHH24MISS format. + * - `Custom`: Any combination of {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|date and time formats}. + * @param {String} [Format] - Sets the display format of a DateTime control. + * @returns {(String)} + * An empty string is always returned. + * @example Different format options + * goo := Gui() + * con := goo.AddDateTime('x+10 vDTMain') + * con := goo.AddButton('xm vShortDate', 'ShortDate') + * con.OnEvent('Click', btn_click) + * con := goo.AddButton('x+5 vLongDate', 'LongDate') + * con.OnEvent('Click', btn_click) + * con := goo.AddButton('x+5 vTime', 'Time') + * con.OnEvent('Click', btn_click) + * con := goo.AddButton('x+5 vCustom', 'Custom') + * con.OnEvent('Click', btn_click) + * goo.Show() + * + * btn_click(btn, info) { + * if (btn.name = 'Custom') + * btn.Gui['DTMain'].SetFormat('HH:MM:ss @ ddMMMyyyy') + * else btn.Gui['DTMain'].SetFormat(btn.name) + * } + */ + SetFormat([DateFormat:='']) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Edit|`Edit`} + * An area where free-form text can be typed by the user. + */ + class Edit extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The text inside the control. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to adjust edit width if needed. + * @type String + * @example Changing edit text. + * goo := Gui() + * goo.edt_main := goo.AddEdit('w100 h30', 'Some Text') + * goo.btn_clear := goo.AddButton('y+5 w100 h30', 'Clear Text') + * goo.btn_clear.OnEvent('Click', clear_text) + * goo.Show() + * + * clear_text(con, info) { + * con.gui.edt_main.Text := '' + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Set or retrieve the text in the control. + * Unlike the Text property, `` `r`n `` is not converted to `` `n ``. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to adjust text width if needed. + * @type String + * @example Changing edit text. + * goo := Gui() + * goo.edt_main := goo.AddEdit('w100 h30', 'Some Text') + * goo.btn_clear := goo.AddButton('y+5 w100 h30', 'Clear Text') + * goo.btn_clear.OnEvent('Click', clear_text) + * goo.Show() + * + * clear_text(con, info) { + * con.gui.edt_main.Value := '' + * } + */ + Value { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'Focus'|'LoseFocus'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The Edit's value changes. + * + * Edit_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The Edit gains the keyboard focus. + * + * Edit_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The Edit loses the keyboard focus. + * + * Edit_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Edit's object + * - `Info`: Not used with Edit controls + * - `Item`: Not used with Edit controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Type in edit box to change Gui title. + * goo := Gui() + * goo.AddText('w300', 'Type to change Gui title:') + * con := goo.AddEdit('xm w300 r1 vEdtBox') + * con.OnEvent('Change', edit_change) + * goo.AddButton('xm', 'Exit').OnEvent('Click', (*) => ExitApp()) + * goo.Show() + * + * edit_change(edt, info) { + * if (edt.Text = '') + * edt.Gui.Title := A_ScriptName + * else edt.Gui.Title := edt.Text + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Limit'|'Lowercase'|'Multi'|'Number'|'Password'|'ReadOnly'|'T'|'Uppercase'|'WantCtrlA'|'WantReturn'|'WantTab'|'AltSubmit'|'Background'|'BackgroundTrans'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Limit`: Restricts input to the visible width of the edit field. + * - `Limit#`: Set the character limit of the control where `#` is the limit number. + * - `Lowercase`: The characters typed by the user are automatically converted to lowercase. + * - `Multi`: Allows more than one line of text. + * - `Number`: Allows only digits to be typed into the edit field. Non-digits can still be pasted in. + * Attaching an {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#UpDown|UpDown} control also forces +Number. + * - `Password`: Hides the user input of a single-lined edit control. + * To change the masking character, include the new mask char immediately after password: + * + * con.opt('+Password*') ; AutoHotkey = ********** + * con.opt('+Password#') ; AutoHotkey = ########## + * - `ReadOnly`: Prevent the user from changing the control's contents, but text can still be copied. + * - `T#`: Set tab stop distance where `#` is the amount of {@link https://learn.microsoft.com/en-us/previous-versions/windows/desktop/bb226789(v=vs.85)|dialog units} to use (a unit determined by the OS). + * A single tab stop sets the default tab distance. Default value is 32. + * Multiple tab stops (up to 50) can be set to define where each tab should go to. + * + * con.opt('T5') + * con.opt('T10 T20 T50 T100') + * - `Uppercase`: Convert all characters in the control to uppercase. + * - `WantCtrlA`: Allow Ctrl+A to highlight all text or `-WantCtrlA` to disable it. + * - `WantReturn`: Allows Enter to create a new line. + * `-WantReturn` causes Enter will activate the Gui's default control. + * New lines can still be added by using Ctrl+Enter. + * - `WantTab`: If enabled, Tab produces a tab character otherwise tab navigates to the next control. + * In a multiline tab, a tab can still be produced with Ctrl+Tab. + * - `Wrap`: Enables word-wrapping in a multi-line edit control. + * This style cannot be changed after the control has been created. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vEdtMain') ; Set using v option. Can't include a space + * con.Name := 'Edt Main' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding an edit box: + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddEdit('x+10 w100 h50 +Hidden vEdtMain') + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['EdtMain'].Opt('-Hidden') + * else cb.Gui['EdtMain'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#GroupBox|`GroupBox`} + * A rectangular border/frame, often used around other controls to indicate they are related. + * In this case, the last parameter is the title of the box, which if present is displayed at its upper-left edge. + */ + class GroupBox extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The caption that displays on the checkbox. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to adjust checkbox width if needed. + * @type String + * @example Changing a GroupBox's text. + * goo := Gui() + * goo.gb := goo.AddGroupBox('w100 h100 Section', 'Options:') + * goo.rad_en := goo.AddRadio('xp+10 yp+20 w80 h20 Checked vEN', 'English') + * goo.rad_en.OnEvent('Click', set_language) + * goo.rad_en := goo.AddRadio('y+5 w80 h20 vES', 'Española') + * goo.rad_en.OnEvent('Click', set_language) + * goo.rad_en := goo.AddRadio('y+5 w80 h20 vDE', 'Deutsch') + * goo.rad_en.OnEvent('Click', set_language) + * goo.Show() + * + * set_language(con, info) { + * switch con.name { + * case 'EN': opt := 'Options' + * case 'ES': opt := 'Opciones' + * case 'DE': opt := 'Optionen' + * } + * con.gui.gb.Text := opt ':' + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'ContextMenu'} EventName + * The following event. Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the GroupBox, presses Menu, or Shift+F10 while the GroupBox has the keyboard focus. + * + * GroupBox_ContextMenu(GuiCtrl, Item, RightClick, X, Y) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the GroupBox's object + * - `Item`: Not used with GroupBox controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Background'|'BackgroundTrans'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vGBRadio') ; Set using v option. Can't include a space + * con.Name := 'GB Radio' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the GroupBox to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * An empty string is always returned. + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Hotkey|`Hotkey`} + * A box that looks like a single-line edit control but instead accepts a keyboard combination pressed by the user. + * For example, if the user presses `Ctrl+Alt+c` on an English layout keyboard, the box would display `Ctrl + Alt + c`. + */ + class Hotkey extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Set or retrieve the current hotkey string. + * Includes modifier keys. + * @type String + * @example + */ + Value { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'ContextMenu'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The Edit's value changes. + * + * Hotkey_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Hotkey control or presses + * Menu or Shift+F10 while the Hotkey control has the keyboard focus. + * + * Hotkey_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Hotkey control's object + * - `Info`: Not used with Hotkey controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Choose a hotkey that exits the script. + * goo := Gui() + * goo.AddText('', 'Choose a hotkey to exit the script:') + * con := goo.AddHotkey('xm vHkQuit') + * con.OnEvent('Change', hk_change) + * goo.Show() + * + * hk_change(hk, info) { + * static last := '' + * if (last != '') + * Hotkey('*' last, 'Off') + * Hotkey('*' hk.Value, quit) + * last := hk.Value + * MsgBox('Hotkey set to: ' hk.value + * '`nPressing that key will quit the script.') + * return + * + * quit(*) { + * ExitApp() + * } + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Limit'|'Background'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Limit#`: Restrict the types of hotkeys the user can enter where `#` is one of the following: + * - 1: Prevent unmodified keys + * - 2: Prevent Shift-only keys + * - 4: Prevent Ctrl-only keys + * - 8: Prevent Alt-only keys + * - 16: Prevent Shift+Ctrl keys + * - 32: Prevent Shift+Alt keys + * - 64: Not supported (will not behave correctly) + * - 128: Prevent Shift+Ctrl+Alt keys + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vHKExit') ; Set using v option. Can't include a space + * con.Name := 'HK Exit' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a hotkey: + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddHotkey('x+10 w100 h50 +Hidden vHKEscape') + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['HKEscape'].Opt('-Hidden') + * else cb.Gui['HKEscape'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Link|`Link`} + * A text control that can contain links similar to those found in a web browser. + * Within the control's text, enclose the link text within and to create a clickable link. + * `myGui.AddLink(, 'Visit the AutoHotkey Website')` + */ + class Link extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The text of the link. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to adjust link width if needed. + * @type String + * @example Changing checkbox caption. + * goo := Gui() + * control := goo.AddLink('w100 h50', 'V2 Docs') + * control.visited := 0 + * control.OnEvent('Click', mark_link_visited) + * goo.Show('') + * + * mark_link_visited(con, info, href) { + * if con.visited = 0 + * con.text .= ' [VISITED]' + * ,con.visited := 1 + * Run(href) + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'ContextMenu'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The Link is clicked. + * + * Link_Click(GuiCtrl, Info, Href) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Link or presses + * Menu or Shift+F10 while the Link has the keyboard focus. + * + * Link_ContextMenu(GuiCtrl, Item, RightClick, X, Y) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Link's object + * - `Href`: The link's HREF attribute. If a Click event callback + * is registered, the HREF attribute is not automatically executed. + * - `Info`: The link's ID attribute (a string) if it has one, otherwise the link's index (an integer). + * - `Item`: Not used with Link controls. + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Opening online and local docs. + * goo := Gui() + * goo.SetFont('s12 Bold') + * con := goo.AddLink('xm w200 vLnkOnlineDocs' + * , 'Online Docs [Click Me]') + * con := goo.AddLink('xm w200 vLnkLocalDocs' + * , 'Local Docs [Click Me]') + * con.OnEvent('Click', open_local_docs) + * goo.Show() + * + * open_local_docs(lnk, info, href) { + * Run(A_AhkPath '\..\AutoHotkey.chm') + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Right'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vLnkV2Docs') ; Set using v option. Can't include a space + * con.Name := 'Lnk V2 Docs' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Right`: Right justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the Picture to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding an a link. + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddLink('x+10 w100 h50 +Hidden vLnkV2Docs' + * , 'AHK Docs') + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['LnkV2Docs'].Opt('-Hidden') + * else cb.Gui['LnkV2Docs'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|`List of Gui Controls`} + * Class for grouping the list controls: ComboBox, DropDownList, ListBox, and Tab + * The class can be seen in the {@link https://www.autohotkey.com/docs/v2/ObjList.htm|Object Hierarchy Page}. + */ + class List extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Add|`Add()`} + * Appends items to a multi-item control (ListBox, DropDownList, ComboBox, or Tab). + * To replace/overwrite the list, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|Delete()} method beforehand. + * @param {(Array)} Items + * An array of strings to be inserted as items at the end of the control's list. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#Add|ListView.Add()} | + * {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm#Add|TreeView.Add()} + * @example Program closer + * goo := Gui() + * con := goo.AddDropDownList('w250 r10 vDDLProcesses') + * refresh(con) + * + * con := goo.AddButton('xm w80', 'Close') + * con.OnEvent('Click', close_app) + * + * con := goo.AddButton('x+5 w80', 'Refresh') + * con.OnEvent('Click', refresh) + * + * con := goo.AddButton('x+5 w80', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * close_app(btn, info) { + * id := btn.gui['DDLProcesses'].Text + * info := StrSplit(id, ',') + * WinClose('ahk_id ' info[2]) + * } + * + * refresh(con, *) { + * goo := con.Gui + * ddl := goo['DDLProcesses'] + * ddl.Delete() + * + * txt_list := '' + * for hwnd in WinGetList() + * txt_list .= WinGetProcessName('ahk_id ' hwnd) ',' hwnd '`n' + * txt_list := Sort(RTrim(txt_list, '`n'), 'C0') + * + * list := [] + * loop parse txt_list, '`n' + * list.Push(A_LoopField) + * ddl.Add(list) + * ddl.Choose(1) + * } + */ + Add(Items) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|`Choose()`} + * Select an item in a multi-item control (ListBox, DropDownList, ComboBox, or Tab). + * Unlike One of the following event(s). Expected callback format is included. event. + * @param {(Integer|String)} Value + * Specify the number of the item. 1 for first item, 2 for second. + * If Value is a `0` or `EmptyString`, any selected value is deselected. + * If Value is a string (including a numeric string), the list item that matches the most leading characters is selected. This search is not case-sensitive. + * If the ListBox is multi-select, all matching items are selected. + * @returns {(String)} + * An empty string is always returned. + * @example Program closer + * goo := Gui() + * con := goo.AddDropDownList('w250 r10 vDDLProcesses') + * refresh(con) + * + * con := goo.AddButton('xm w80', 'Close') + * con.OnEvent('Click', close_app) + * + * con := goo.AddButton('x+5 w80', 'Refresh') + * con.OnEvent('Click', refresh) + * + * con := goo.AddButton('x+5 w80', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * close_app(btn, info) { + * id := btn.gui['DDLProcesses'].Text + * info := StrSplit(id, ',') + * WinClose('ahk_id ' info[2]) + * } + * + * refresh(con, *) { + * goo := con.Gui + * ddl := goo['DDLProcesses'] + * ddl.Delete() + * + * txt_list := '' + * for hwnd in WinGetList() + * txt_list .= WinGetProcessName('ahk_id ' hwnd) ',' hwnd '`n' + * txt_list := Sort(RTrim(txt_list, '`n'), 'C0') + * + * list := [] + * loop parse txt_list, '`n' + * list.Push(A_LoopField) + * ddl.Add(list) + * ddl.Choose(1) + * } + */ + Choose(Value) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|`Delete()`} + * Removes one or all items from a multi-item control (ListBox, DropDownList, ComboBox, or Tab). + * @param {(Integer)} Value + * Item number to be deleted. `1` is first item, `2` is second, etc. + * If value is omitted, all items are deleted. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#Delete|ListView.Delete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm#Delete|TreeView.Delete()} + * @example Program closer + * goo := Gui() + * con := goo.AddDropDownList('w250 r10 vDDLProcesses') + * refresh(con) + * + * con := goo.AddButton('xm w80', 'Close') + * con.OnEvent('Click', close_app) + * + * con := goo.AddButton('x+5 w80', 'Refresh') + * con.OnEvent('Click', refresh) + * + * con := goo.AddButton('x+5 w80', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * close_app(btn, info) { + * id := btn.gui['DDLProcesses'].Text + * info := StrSplit(id, ',') + * WinClose('ahk_id ' info[2]) + * } + * + * refresh(con, *) { + * goo := con.Gui + * ddl := goo['DDLProcesses'] + * ddl.Delete() + * + * txt_list := '' + * for hwnd in WinGetList() + * txt_list .= WinGetProcessName('ahk_id ' hwnd) ',' hwnd '`n' + * txt_list := Sort(RTrim(txt_list, '`n'), 'C0') + * + * list := [] + * loop parse txt_list, '`n' + * list.Push(A_LoopField) + * ddl.Add(list) + * ddl.Choose(1) + * } + */ + Delete([Value]) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ComboBox|`ComboBox`} + * Functions like a DropDownList but also permits free-form text to be entered as an alternative to picking an item from the list. + */ + class ComboBox extends Gui.List { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The text of the selected item or the text of the item to select (case insensitive). + * If no item selected, the control's edit field is retrieved instead. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|Value} property to select an item by its position number. + * @type String + * @example Change Gui color using color selection or RGB number. + * goo := Gui() + * goo.MarginX := goo.MarginY := 20 + * colors := ['Black', 'Gray', 'Silver', 'White', 'Red', 'Maroon', 'Purple', 'Fuchsia', 'Lime', 'Green', 'Olive', 'Yellow', 'Blue', 'Navy', 'Teal', 'Aqua'] + * goo.AddText('w150 h40 BackgroundWhite', 'Select a background color`nOr use an RGB value.') + * con := goo.AddComboBox('w150', colors) + * con.Text := 'FFFF00' + * con.OnEvent('Change', update_background) + * goo.Show() + * return + * + * update_background(combo, info) { + * combo.Gui.BackColor := combo.Text + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets position number of the currently selected item. + * If text is in the ComboBox, the first matching text is used. + * 0 indicates nothing is selected and no matches were made. + * Setting the property to 0 clears any selected item. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|Text property} to set/get the control text. + * @type Integer + */ + Value { + get => Primitive + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Add|`Add()`} + * Appends the specified entries to the control. + * @param {(Array)} Items + * An array of strings to append to the list. + * To replace the list with a new one, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|Delete()} method first and then add the list. + * To pre-select an item, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|Choose()} method. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * goo.letter_combo := goo.AddComboBox('xm ym r6', ['a', 'b', 'c']) + * goo.Show('y300 AutoSize') + * MsgBox('Click OK to add "e", "f", "g" to the ComboBox.') + * goo.letter_combo.Add(['e', 'f', 'g']) + */ + Add(Items) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|`Choose()`} + * Sets a value from the ComboBox to selected. + * @param {(Integer|String)} Value + * Specify the number of the item. 1 for first item, 2 for second. + * If Value is a `0` or `EmptyString`, any selected value is deselected. + * If Value is a string (including a numeric string), the list item that matches the most leading characters is selected. This search is not case-sensitive. + * @returns {(String)} + * An empty string is always returned. + */ + Choose(Value) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|`Delete()`} + * Removes the specified entry or all entries from the ComboBox. + * @param {(Integer)} [Value] + * The index number of the item to delete or all items if value is omitted. + * @returns {(String)} + * An empty string is always returned. + * @example + * + */ + Delete([Value]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'DoubleClick'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The ComboBox's value changes. + * + * ComboBox_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The ComboBox is double-clicked. + * + * ComboBox_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the ComboBox or presses + * Menu or Shift+F10 while the ComboBox has the keyboard focus. + * The context menu does not work with the edit portion of the control. + * + * ComboBox_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The ComboBox gains the keyboard focus. + * + * ComboBox_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The ComboBox loses the keyboard focus. + * + * ComboBox_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the ComboBox's object + * - `Info`: Not used with ComboBox controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Change Gui color using color selection or RGB number. + * goo := Gui() + * goo.MarginX := goo.MarginY := 20 + * colors := ['Black', 'Gray', 'Silver', 'White', 'Red', 'Maroon', 'Purple', 'Fuchsia', 'Lime', 'Green', 'Olive', 'Yellow', 'Blue', 'Navy', 'Teal', 'Aqua'] + * goo.AddText('w150 h40 BackgroundWhite', 'Select a background color`nOr use an RGB value.') + * con := goo.AddComboBox('w150', colors) + * con.Text := 'FFFF00' + * con.OnEvent('Change', update_background) + * goo.Show() + * return + * + * update_background(combo, info) { + * combo.Gui.BackColor := combo.Text + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Choose'|'Uppercase'|'Lowercase'|'Sort'|'Limit'|'Simple'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select an item where `#` is the line number of the item. + * - `Uppercase` or `Lowercase`: Converts all items in the list to uppercase or lowercase. + * - `Sort`: Item list is sorted alphabetically. This option also enables incremental searching. + * Meaning an item can be selected by typing its name. + * - `Limit`: Restrict the user's input to the visible width of the ComboBox's edit field. + * - `Simple`: Replaces the ComboBox's DropDownList with a {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ListBox|ListBox}. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vCBNames') ; Set using v option. Can't include a space + * con.Name := 'CB Names' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position(s) instead of the actual text. + * If no item is selected, the text of the edit field is stored, even if the string is empty. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a combobox. + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddComboBox('x+10 w100 h50 +Hidden vCbList' + * , ['Alpha','Beta','Gamma','Delta']) + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['CbList'].Opt('-Hidden') + * else cb.Gui['CbList'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DropDownList|`DDL`} + * A list of choices that is displayed in response to pressing a small button. + * In this case, the last parameter of MyGui.Add is an Array like `["Choice1","Choice2","Choice3"]`. + */ + class DDL extends Gui.List { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The text of the selected item or the text of the item to select (case insensitive). + * @type String + * @example Program closer + * goo := Gui() + * con := goo.AddDDL('w250 r10 vDDLProcesses') + * refresh(con) + * + * con := goo.AddButton('xm w80', 'Close') + * con.OnEvent('Click', close_app) + * + * con := goo.AddButton('x+5 w80', 'Refresh') + * con.OnEvent('Click', refresh) + * + * con := goo.AddButton('x+5 w80', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * close_app(btn, info) { + * id := btn.gui['DDLProcesses'].Text + * info := StrSplit(id, ',') + * WinClose('ahk_id ' info[2]) + * } + * + * refresh(con, *) { + * goo := con.Gui + * ddl := goo['DDLProcesses'] + * ddl.Delete() + * + * txt_list := '' + * for hwnd in WinGetList() + * txt_list .= WinGetProcessName('ahk_id ' hwnd) ',' hwnd '`n' + * txt_list := Sort(RTrim(txt_list, '`n'), 'C0') + * + * list := [] + * loop parse txt_list, '`n' + * list.Push(A_LoopField) + * ddl.Add(list) + * ddl.Choose(1) + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets position number + * of the currently selected item. + * 0 means nothing is selected. + * Setting Value to 0 clears any selected item. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|Text property} to set/get the control text. + * @type Integer + */ + Value { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Add|`Add()`} + * Appends the specified entries to the DropDownList. + * @param {(Array)} Items + * An array of strings to append to the list. + * To replace the list with a new one, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|Delete()} method first and then add the list. + * To pre-select an item, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|Choose()} method. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * goo.letter_ddl := goo.AddDDL('xm ym', ['a', 'b', 'c']) + * goo.Show('y300 AutoSize') + * MsgBox('Click OK to add "e", "f", "g" to DropDownList') + * goo.letter_ddl.Add(['e', 'f', 'g']) + */ + Add(Items) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|`Choose()`} + * Sets a value from the DropDownList to selected. + * @param {(Integer|String)} Value + * Specify the number of the item. 1 for first item, 2 for second. + * If Value is a `0` or `EmptyString`, any selected value is deselected. + * If Value is a string (including a numeric string), the list item that matches the most leading characters is selected. This search is not case-sensitive. + * @returns {(String)} + * An empty string is always returned. + * @example Program closer + * goo := Gui() + * con := goo.AddDDL('w250 r10 vDDLProcesses') + * refresh(con) + * + * con := goo.AddButton('xm w80', 'Close') + * con.OnEvent('Click', close_app) + * + * con := goo.AddButton('x+5 w80', 'Refresh') + * con.OnEvent('Click', refresh) + * + * con := goo.AddButton('x+5 w80', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * close_app(btn, info) { + * id := btn.gui['DDLProcesses'].Text + * info := StrSplit(id, ',') + * WinClose('ahk_id ' info[2]) + * } + * + * refresh(con, *) { + * goo := con.Gui + * ddl := goo['DDLProcesses'] + * ddl.Delete() + * + * txt_list := '' + * for hwnd in WinGetList() + * txt_list .= WinGetProcessName('ahk_id ' hwnd) ',' hwnd '`n' + * txt_list := Sort(RTrim(txt_list, '`n'), 'C0') + * + * list := [] + * loop parse txt_list, '`n' + * list.Push(A_LoopField) + * ddl.Add(list) + * ddl.Choose(1) + * } */ + Choose(Value) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|`Delete()`} + * Removes the specified entry or all entries from the DropDownList. + * @param {(Integer)} [Value] + * The index number of the item to delete or all items if value is omitted. + * @returns {(String)} + * An empty string is always returned. + * @example Program closer + * goo := Gui() + * con := goo.AddDDL('w250 r10 vDDLProcesses') + * refresh(con) + * + * con := goo.AddButton('xm w80', 'Close') + * con.OnEvent('Click', close_app) + * + * con := goo.AddButton('x+5 w80', 'Refresh') + * con.OnEvent('Click', refresh) + * + * con := goo.AddButton('x+5 w80', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * close_app(btn, info) { + * id := btn.gui['DDLProcesses'].Text + * info := StrSplit(id, ',') + * WinClose('ahk_id ' info[2]) + * } + * + * refresh(con, *) { + * goo := con.Gui + * ddl := goo['DDLProcesses'] + * ddl.Delete() + * + * txt_list := '' + * for hwnd in WinGetList() + * txt_list .= WinGetProcessName('ahk_id ' hwnd) ',' hwnd '`n' + * txt_list := Sort(RTrim(txt_list, '`n'), 'C0') + * + * list := [] + * loop parse txt_list, '`n' + * list.Push(A_LoopField) + * ddl.Add(list) + * ddl.Choose(1) + * } */ + Delete([Value]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The DropDownList's value changes. + * + * DDL_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the DropDownList or presses + * Menu or Shift+F10 while the DropDownList has the keyboard focus. + * + * DDL_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The DropDownList gains the keyboard focus. + * + * DDL_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The DropDownList loses the keyboard focus. + * + * DDL_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the DropDownList's object + * - `Info`: Not used with DropDownList controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Change background color using a DDL + * goo := Gui() + * goo.MarginX := goo.MarginY := 20 + * colors := ['Black', 'Gray', 'Silver', 'White', 'Red', 'Maroon', 'Purple', 'Fuchsia', 'Lime', 'Green', 'Olive', 'Yellow', 'Blue', 'Navy', 'Teal', 'Aqua'] + * con := goo.AddDDL('xm ym w200', colors) + * con.OnEvent('Change', color_change) + * goo.AddButton('xm w200', 'Quit').OnEvent('Click', (*) => ExitApp()) + * goo.Show() + * + * color_change(ddl, info) { + * ddl.Gui.BackColor := ddl.Text + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Choose'|'Uppercase'|'Lowercase'|'Sort'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select an item where `#` is the line number of the item. + * - `Uppercase` or `Lowercase`: Converts all items in the list to uppercase or lowercase. + * - `Sort`: Item list is sorted alphabetically. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vDDLNames') ; Set using v option. Can't include a space + * con.Name := 'DDL Names' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position instead of the actual text. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a DropDownList + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddDDL('x+10 w100 h50 +Hidden vDDLList' + * , ['Alpha','Beta','Gamma','Delta']) + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['DDLList'].Opt('-Hidden') + * else cb.Gui['DDLList'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DropDownList|`DropDownList`} + * A list of choices that is displayed in response to pressing a small button. + * In this case, the last parameter of MyGui.Add is an Array like `["Choice1","Choice2","Choice3"]`. + */ + class DropDownList extends Gui.List { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The text of the selected item or the text of the item to select (case insensitive). + * @type String + * @example Program closer + * goo := Gui() + * con := goo.AddDropDownList('w250 r10 vDDLProcesses') + * refresh(con) + * + * con := goo.AddButton('xm w80', 'Close') + * con.OnEvent('Click', close_app) + * + * con := goo.AddButton('x+5 w80', 'Refresh') + * con.OnEvent('Click', refresh) + * + * con := goo.AddButton('x+5 w80', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * close_app(btn, info) { + * id := btn.gui['DDLProcesses'].Text + * info := StrSplit(id, ',') + * WinClose('ahk_id ' info[2]) + * } + * + * refresh(con, *) { + * goo := con.Gui + * ddl := goo['DDLProcesses'] + * ddl.Delete() + * + * txt_list := '' + * for hwnd in WinGetList() + * txt_list .= WinGetProcessName('ahk_id ' hwnd) ',' hwnd '`n' + * txt_list := Sort(RTrim(txt_list, '`n'), 'C0') + * + * list := [] + * loop parse txt_list, '`n' + * list.Push(A_LoopField) + * ddl.Add(list) + * ddl.Choose(1) + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets position number of the currently selected item. + * 0 means nothing is selected. + * Setting Value to 0 clears any selected item. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|Text property} to set/get the control text. + * @type Integer + */ + Value { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Add|`Add()`} + * Appends the specified entries to the DropDownList. + * @param {(Array)} Items + * An array of strings to append to the list. + * To replace the list with a new one, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|Delete()} method first and then add the list. + * To pre-select an item, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|Choose()} method. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * goo.letter_ddl := goo.AddDropDownList('xm ym', ['a', 'b', 'c']) + * goo.Show('y300 AutoSize') + * MsgBox('Click OK to add "e", "f", "g" to DropDownList') + * goo.letter_ddl.Add(['e', 'f', 'g']) + */ + Add(Items) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|`Choose()`} + * Sets a value from the DropDownList to selected. + * @param {(Integer|String)} Value + * Specify the number of the item. 1 for first item, 2 for second. + * If Value is a `0` or `EmptyString`, any selected value is deselected. + * If Value is a string (including a numeric string), the list item that matches the most leading characters is selected. This search is not case-sensitive. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * goo.combo := goo.AddComboBox('xm ym', ['a', 'b', 'c']) + * goo.combo.Choose(2) + * goo.Show('y300 AutoSize') + */ + Choose(Value) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|`Delete()`} + * Removes the specified entry or all entries from the DropDownList. + * @param {(Integer)} [Value] + * The index number of the item to delete or all items if value is omitted. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Delete([Value]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The DropDownList's value changes. + * + * DropDownList_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the DropDownList or presses + * Menu or Shift+F10 while the DropDownList has the keyboard focus. + * + * DropDownList_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The DropDownList gains the keyboard focus. + * + * DropDownList_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The DropDownList loses the keyboard focus. + * + * DropDownList_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the DropDownList's object + * - `Info`: Not used with DropDownList controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Program closer + * goo := Gui() + * con := goo.AddDropDownList('w250 r10 vDDLProcesses') + * refresh(con) + * + * con := goo.AddButton('xm w80', 'Close') + * con.OnEvent('Click', close_app) + * + * con := goo.AddButton('x+5 w80', 'Refresh') + * con.OnEvent('Click', refresh) + * + * con := goo.AddButton('x+5 w80', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * close_app(btn, info) { + * id := btn.gui['DDLProcesses'].Text + * info := StrSplit(id, ',') + * WinClose('ahk_id ' info[2]) + * } + * + * refresh(con, *) { + * goo := con.Gui + * ddl := goo['DDLProcesses'] + * ddl.Delete() + * + * txt_list := '' + * for hwnd in WinGetList() + * txt_list .= WinGetProcessName('ahk_id ' hwnd) ',' hwnd '`n' + * txt_list := Sort(RTrim(txt_list, '`n'), 'C0') + * + * list := [] + * loop parse txt_list, '`n' + * list.Push(A_LoopField) + * ddl.Add(list) + * ddl.Choose(1) + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Choose'|'Uppercase'|'Lowercase'|'Sort'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select an item where `#` is the line number of the item. + * - `Uppercase` or `Lowercase`: Converts all items in the list to uppercase or lowercase. + * - `Sort`: Item list is sorted alphabetically. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vDDLNames') ; Set using v option. Can't include a space + * con.Name := 'DDL Names' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position instead of the actual text. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a DropDownList + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddDropDownList('x+10 w100 h50 +Hidden vDDLList' + * , ['Alpha','Beta','Gamma','Delta']) + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['DDLList'].Opt('-Hidden') + * else cb.Gui['DDLList'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ListBox|`ListBox`} + * A relatively tall box containing a list of choices that can be selected. + * In this case, the last parameter of MyGui.Add is an Array like `["Choice1","Choice2","Choice3"]`. + */ + class ListBox extends Gui.List { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The text of the selected item or the text of the item to select (case insensitive). + * @type String + * @example + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets the index of the currently selected items. 0 indicates nothing was selected. + * If the {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ListBoxMulti|Multi} option is enabled, an array is returned and contains the index of all selected item. + * If array is empty `array.length = 0`, nothing was selected. + * When setting Value, only integers can be used. + * To set multiple items, loop through them and use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|Choose()} method to select each item. + * @type Integer | Array + * @example Remove items from a listbox + * goo := Gui() + * goo.MarginX := goo.MarginY := 10 + * goo.AddText('xm ym', 'Press delete to remove the highlighted item.' + * '`nYou can highlight multiple items by holding control.') + * goo.AddListBox('xm w205 r5 Multi vLBLetters', [1,2,3,4,5,6,7,8,9,10]) + * con := goo.AddButton('xm w100', 'Delete') + * con.OnEvent('Click', btn_click) + * goo.Show() + * + * btn_click(btn, info) { + * goo := btn.Gui + * lb := goo['LBLetters'] + * remove := lb.Value + * if !remove + * return + * loop remove.Length + * lb.Delete(remove[(remove.Length - A_Index + 1)]) + * } + */ + Value { + get => Integer | Array + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Add|`Add()`} + * Appends the specified entries to the control. + * @param {(Array)} Items + * An array of strings to append to the list. + * To replace the list with a new one, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|Delete()} method first and then add the list. + * To pre-select an item, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|Choose()} method. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * goo.lb := goo.AddListBox('xm ym +Multi', ['a', 'b', 'c']) + * goo.lb.Choose(2) + * goo.Show('y300 AutoSize') + * + * LB_SETSEL := 0x0185 + * MsgBox('Press OK to select all') + * PostMessage(LB_SETSEL, 1, -1, goo.lb) + * + * MsgBox('Press OK to deselect all') + * PostMessage(LB_SETSEL, 0, -1, goo.lb) + */ + Add(Items) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|`Choose()`} + * Select an item in a multi-item control. + * @param {(Integer|String)} Value + * Specify the number of the item. 1 for first item, 2 for second. + * If Value is a `0` or `EmptyString`, any selected value is deselected. + * If Value is a string (including a numeric string), the list item that matches the most leading characters is selected. This search is not case-sensitive. + * If the ListBox is multi-select, all matching items are selected. + * {@link https://www.autohotkey.com/docs/v2/lib/PostMessage.htm|PostMessage()} can be used to select or deselect all items. See {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose_Remarks|example}. + * @returns {(String)} + * An empty string is always returned. + * @example A searchable ListBox + * goo := Gui() + * lb_arr := ['apple', 'apricot', 'avocado', 'banana'] + * goo.listbox := goo.AddListBox('xm ym w300 +Multi r' lb_arr.Length , lb_arr) + * goo.listbox.Choose(2) + * goo.AddText('xm w40 h20 +0x200', 'Search:') + * goo.edit := goo.AddEdit('x+0 w260 h20') + * goo.edit.OnEvent('Change', search_list) + * goo.edit.Focus() + * goo.Show('y300 AutoSize') + * + * search_list(con, info) { + * con.gui.listbox.choose(0) + * try + * con.gui.listbox.Choose(con.value) + * catch + * ToolTip('Invalid character') + * ,SetTimer(Tooltip, -1500) + * } + */ + Choose(Value) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|`Delete()`} + * Removes the specified entry or all entries from the ListBox. + * @param {(Integer)} [Value] + * The index number of the item to delete or all items if value is omitted. + * @returns {(String)} + * An empty string is always returned. + * @example Remove items from a listbox + * goo := Gui() + * goo.MarginX := goo.MarginY := 10 + * goo.AddText('xm ym', 'Press delete to remove the highlighted item.' + * '`nYou can highlight multiple items by holding control.') + * goo.AddListBox('xm w205 r5 Multi vLBLetters', [1,2,3,4,5,6,7,8,9,10]) + * con := goo.AddButton('xm w100', 'Delete') + * con.OnEvent('Click', btn_click) + * goo.Show() + * + * btn_click(btn, info) { + * goo := btn.Gui + * lb := goo['LBLetters'] + * remove := lb.Value + * if !remove + * return + * loop remove.Length + * lb.Delete(remove[(remove.Length - A_Index + 1)]) + * } + */ + */ + Delete([Value]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'DoubleClick'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The ListBox's value changes. + * + * ListBox_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The ListBox is double-clicked. + * + * ListBox_DoubleClick(GuiCtrl, ItemPos) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the ListBox or presses + * Menu or Shift+F10 while the ListBox has the keyboard focus. + * + * ListBox_ContextMenu(GuiCtrl, Item, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The ListBox gains the keyboard focus. + * + * ListBox_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The ListBox loses the keyboard focus. + * + * ListBox_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the ListBox's object + * - `Info`: Position number of the focused item on double click + * - `ItemPos`: Position number of the focused item + * - `Item`: Position number of current focused item + * Right-clicking a standard ListBox does not focus an item + * Meaning this may not be the clicked item + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * goo.MarginX := goo.MarginY := 10 + * colors := ['Black', 'Gray', 'Silver', 'White', 'Red', 'Maroon', 'Purple', 'Fuchsia', 'Lime', 'Green', 'Olive', 'Yellow', 'Blue', 'Navy', 'Teal', 'Aqua'] + * goo.AddText('w150 BackgroundWhite', 'Select a background color.') + * con := goo.AddListBox('w150 r' colors.Length, colors) + * con.OnEvent('Change', update_background) + * goo.Show() + * return + * + * update_background(lb, info) { + * lb.Gui.BackColor := lb.Text + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Choose'|'Multi'|'ReadOnly'|'Sort'|'T'|'0x100'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select an item where `#` is the line number of the item. + * - `Multi`: Multiple items can be selected via Ctrl+Clicking and Shift+Clicking. + * Using Style `+0x8` {@link https://learn.microsoft.com/en-us/windows/win32/controls/list-box-styles#LBS_MULTIPLESEL|LBS_MULTIPLESEL}, item highlighting is toggled on clicked. + * - `ReadOnly`: Items will not be visibly highlighted when selected but still register + * with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit()} and the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|Value} and {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|Text} properties. + * - `Sort`: Item list is sorted alphabetically. This option also enables incremental searching. + * Meaning an item can be selected by typing its name. + * - `T#`: Sets each tab's distance, where `#` is number of dialogue units (a unit determined by the OS) to use. + * If one tab stop is set, that distance is used between all tabs. + * If multiple tab stops are set, each marks the distance the corresponding tab will extend to. + * - `0x100`: Adds the {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm#LBS_NOINTEGRALHEIGHT|LBS_NOINTEGRALHEIGHT} style to the ListBox, preventing a partial + * row from appearing at the bottom and from shrinking when the font is changed. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vLBNames') ; Set using v option. Can't include a space + * con.Name := 'LB Names' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position(s) instead of the actual text. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a ListBox + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * goo.AddListBox('x+10 w100 h50 +Hidden vDDLList' + * , ['Alpha','Beta','Gamma','Delta']) + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['DDLList'].Opt('-Hidden') + * else cb.Gui['DDLList'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab|`Tab`} + * A large control that can contain multiple pages, each of which contains its own set of controls. + * These pages are referred to as "Tabs". + */ + class Tab extends Gui.List { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The text of current tab or the text of the tab to activate (case insensitive). + * @type String + * @example Tab Examples + * goo := Gui() + * + * goo.AddText('xm', 'The title changes with the tab.') + * + * tabcon := goo.AddTab3('xm w200', ['Tab A', 'Tab B', 'Tab C']) + * tabcon.OnEvent('Change', update_title) + * + * ; Tab 1 stuff + * tabcon.UseTab(1) + * goo.AddButton('', 'Button A') + * goo.AddButton('x+5', 'Button Z') + * + * ; Tab 2 stuff + * tabcon.UseTab(2) + * goo.AddButton('', 'Button B') + * goo.AddButton('y+5', 'Button Y') + * + * ; Tab 3 stuff + * tabcon.UseTab(3) + * goo.AddButton('', 'Button C') + * con := goo.AddButton('x+5 y+5', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * update_title(tabcon) + * goo.Show() + * + * update_title(con, *) { + * con.Gui.Title := con.Text + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets position number of the currently selected tab. + * A Value of 0 means no tab is selected. + * A Value **can** be set to 0. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|Text property} to set/get the control text. + * @type Integer + */ + Value { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Add|`Add()`} + * Appends the specified tabs to the control. + * @param {(Array)} Items + * An array of strings to append to the tabs. + * To replace the list with a new one, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|Delete()} method first and then add the list. + * To pre-select an item, use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|Choose()} method. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * goo.letter_tabs := goo.AddTab('xm ym', ['a', 'b', 'c']) + * goo.Show('y300 AutoSize') + * MsgBox('Click OK to add "e" and "f" tabs.') + * goo.letter_tabs.Add(['e', 'f']) + */ + Add(Items) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|`Choose()`} + * Select a tab. + * @param {(Integer|String)} Value + * Specify the number of the item. 1 for first item, 2 for second. + * If Value is a `0` or `EmptyString`, any selected value is deselected. + * If Value is a string (including a numeric string), the list item that matches the most leading characters is selected. This search is not case-sensitive. + * {@link https://www.autohotkey.com/docs/v2/lib/PostMessage.htm|PostMessage()} can be used to select or deselect all items. See example. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * tab_names := ['A','B','C','D'] + * goo.tabs := goo.AddTab3('xm ym w200', tab_names) + * MsgBox('Press OK to select tab C') + * goo.tabs.Choose(3) + * goo.Show('w500 y300 AutoSize') + */ + Choose(Value) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|`Delete()`} + * Removes the specified tab or all tabs from the Tab control. + * Deleting a tab removes only the tab title and does not affect that tab's sub-controls. Instead, the tabs names are shifted left and the last tab's controls are deleted. + * Because of this behavior, if you need a delete-able tab, it should placed at the end of the tab list. Otherwise, the only way to rearrange tabs is to delete and rebuild the tab control. + * The example code below demonstrates this behavior. Tab B is removed, the remaining tabs are shifted left, and tab B's control are now under the C tab. The final tab's controls, tab D, are deleted. + * @param {(Integer)} [Value] + * The index number of the item to delete or all items if value is omitted. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * tab_names := ['A','B','C','D'] + * goo.tabs := goo.AddTab3('xm ym w200 r3 Section', tab_names) + * for i, tname in tab_names + * goo.Tabs.UseTab(A_Index) + * ,goo.AddButton('xs+5 ys+25', '"Tab ' tname '" Button') + * goo.Show('w500 y300 AutoSize') + * MsgBox('Press OK to delete tab "B".') + * goo.tabs.Delete(2) + */ + Delete([Value]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'ContextMenu'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The Tab's value changes. + * + * Tab_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Tab or presses + * Menu or Shift+F10 while the Tab has the keyboard focus. + * + * Tab_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Tab's object + * - `Info`: Not used with Tab controls + * - `RightClick`: + * `1` = Mouse right click was used + * `0` = AppsKey or Shift+F10 was used + * - `X` and `Y`: Right click dependent (Check `RightClick` param) + * Right Clicked = Coords of mouse click + * Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Tab Examples + * goo := Gui() + * + * goo.AddText('xm', 'The title changes with the tab.') + * + * tabcon := goo.AddTab3('xm w200', ['Tab A', 'Tab B', 'Tab C']) + * tabcon.OnEvent('Change', update_title) + * + * ; Tab 1 stuff + * tabcon.UseTab(1) + * goo.AddButton('', 'Button A') + * goo.AddButton('x+5', 'Button Z') + * + * ; Tab 2 stuff + * tabcon.UseTab(2) + * goo.AddButton('', 'Button B') + * goo.AddButton('y+5', 'Button Y') + * + * ; Tab 3 stuff + * tabcon.UseTab(3) + * goo.AddButton('', 'Button C') + * con := goo.AddButton('x+5 y+5', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * update_title(tabcon) + * goo.Show() + * + * update_title(con, *) { + * con.Gui.Title := con.Text + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Choose'|'Buttons'|'Left'|'Right'|'Bottom'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select a Tab where `#` is the tab's positional number. + * - `Buttons`: The Tabs are replaced with clickable buttons. + * - `Left`/`Right`/`Bottom`: Specify the side of the control to show the tabs. + * See {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm#TCS_VERTICAL|TCS_VERTICAL} for Left/Right limitations. + * - `Wrap`: Specify `-Wrap` to keep all tabs on a single row. Scroll buttons are added if there are too many tabs. + * If there are too many tabs, scroll buttons are added to navigate through them. + * - `Tab Icons`: Icons may be added next to tab's via {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage} as demonstrated in {@link https://www.autohotkey.com/board/topic/5692-icons-in-tabs/|this post}. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vTabModes') ; Set using v option. Can't include a space + * con.Name := 'Tab Modes' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position(s) instead of the actual text. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a tab control + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddTab3('x+10 w100 h50 +Hidden vDDLList' + * , ['A','B','C']) + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['DDLList'].Opt('-Hidden') + * else cb.Gui['DDLList'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + + /** + * @definition {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab_UseTab|`UseTab()`} + * Specifies the tab to which subsequently created controls will be added. + * Specify 0 to stop using a tab control. + * @param {(Primitive)} [Value] + * - If value is an integer, it specifies the tab number in order. + * - If value is a string, value need only match the first part of a tab. `Auto` matches `AutoHotkey` + * Strings are not case-sensitive, even with `ExactMatch` set to true. + * If the `ExactMatch` property is set to true, an exact match must be made. `Auto` does not match `AutoHotkey` + * - `0` or Omitted: Controls stop being associated with tabs and become "gui controls" again. + * @param {(Boolean)} [ExactMatch] + * - True: The value and the tab name must be a 1:1 match. The tab cannot contain extra characters. + * - False or Omitted: Value only needs to match the beginning of the tab text. + + * @returns {EmptyString} + */ + UseTab([Value:=0, ExactMatch:=0]) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ListView|`ListView`} + * A ListView is one of the most elaborate controls provided by the operating system. + * In its most recognizable form, it displays a tabular view of rows and columns. + * The most common example would be Explorer's list of files and folders when in detail view. + */ + class ListView extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#Add|`Add()`} + * Adds a new row to the bottom of the list. + * @param {String|'Check'|'Col'|'Focus'|'Icon'|'Select'} [Options] + * If omitted, no options are used. + * - `Check` + * Shows a checkmark in the row. + * Use `LV.Modify(RowNumber, "-Check")` to uncheck. + * - `Col#` + * Specify the column to start at when adding the Cell values. + * - `Focus` + * Set keyboard focus to this row. + * - `Icon#` + * The image to use from ImageList, where `#` is the icon index. + * Use `-1` for a blank icon. + * - `Select` + * Selects the row. + * Use LV.Modify(RowNumber, "-Select") to deselect. + * `Select` may also be followed by a 1 (selected) or a 0 (unselected). + * + * LV.add('+Checked0') + * var := 1, LV.add('+Checked' var) + * @param {(String)} [Col1] + * First column of the row to add data to. + * Starts at column 1 unless the Col# option is specified. + * If omitted, cell is left blank. + * @param {(String)} [ColN] + * Each additional parameter can contain the next column's data. + * If the parameter is blank or omitted, no data is added to that column. + * @returns {(Integer)} + * The new row's number. + * @example Create ListView from script folder files. + * goo := Gui() + * lv := goo.AddListView('xm ym w800 h400', ['Name', 'Dir', 'Extension']) + * loop files A_ScriptDir '\*.*' + * lv.Add('', A_LoopFileName, A_LoopFileDir, A_LoopFileExt) + * + * lv.ModifyCol() + * + * goo.Show() + */ + Add([Options:='', Col1, ColN*]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#Delete|`Delete()`} + * Deletes the specified row or all rows. + * @param {(Integer)} [RowNumber] + * The row number to delete from the ListView. + * If omitted, all rows are deleted. + * @returns {(String)} + * An empty string is always returned. + * @example Removing a row from a ListView. + * goo := Gui() + * lv := goo.AddListView('xm ym w200 h200', ['A Col', 'B Col', 'C Col']) + * loop 3 + * lv.Add('', A_Index, A_Index, A_Index) + * + * lv.Delete(2) + * + * goo.Show() + */ + Delete([RowNumber:=unset]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#DeleteCol|`DeleteCol()`} + * Deletes the specified column and all of the contents beneath it. + * @param {(Integer)} ColumnNumber + * The number of the column to delete. + * All columns to the right of the deleted column are reduced by 1. + * @returns {(String)} + * An empty string is always returned. + * @example Removing a column from a ListView. + * goo := Gui() + * lv := goo.AddListView('xm ym w200 h200', ['A Col', 'B Col', 'C Col']) + * loop 3 + * lv.Add('', A_Index, A_Index, A_Index) + * + * lv.DeleteCol(2) + * + * goo.Show() + */ + DeleteCol(ColumnNumber) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#GetCount|`GetCount()`} + * Returns the number of rows or columns in the control. + * @param {(String)} [Mode] + * - Omit + * Returns the total number of rows in the control. + * - `S` `Selected` + * Only selected/highlighted rows are counted. + * - `Col` `Column` + * The number of columns in the control. + * @returns {(Integer)} + * The number of rows, selected rows, or columns in the control. + * @example + */ + GetCount([Mode:=unset]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#GetNext|`GetNext()`} + * Returns the row number of the next selected, checked, or focused row. + * @param {(Integer)} StartingRowNumber + * The number of the row to begin the search. + * If omitted or less than 1, search starts at top of list. + * @param {(String)} RowType + * - Omit or Empty String + * Search for next selected/highlighted row. + * - `C` `Checked` + * Find next checked row. + * - `F` `Focused` + * Find the focused row. + * The can only be 1 focused row. + * @returns {(Integer)} + * The row number of the next selected, checked, or focused row. + * `0` if none is found. + * @example + */ + GetNext([StartingRowNumber:=0, RowType:='']) => String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#GetText|`GetText()`} + * Retrieves the text at the specified row and column number. + * @param {(Integer)} RowNumber + * The row number to get text from. + * @param {(Integer)} ColumnNumber + * The column number to get text from. + * If omitted, `1` is used. + * @returns {(String)} + * The retrieved text from the specified cell. + * There is an 8191 character limit to this string. + * @example + */ + GetText(RowNumber [,ColumnNumber:=1]) => String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#Insert|`Insert()`} + * Inserts a new row at the specified row number. + * @param {(Integer)} RowNumber + * Row number to insert the new row at. + * All rows below are shifted down. + * If row number is higher than total rows, it's added to the end of the list. + * @param {(String)} [Options] + * If omitted, no options are used. + * - `Check` + * Shows a checkmark in the row. + * Use `LV.Modify(RowNumber, "-Check")` to uncheck. + * - `Col#` + * Specify the column to start at when adding the Cell values. + * - `Focus` + * Set keyboard focus to this row. + * - `Icon#` + * The image to use from ImageList, where `#` is the icon index. + * Use `-1` for a blank icon. + * - `Select` + * Selects the row. + * Use LV.Modify(RowNumber, "-Select") to deselect. + * `Select` may also be followed by a 1 (selected) or a 0 (unselected). + * + * LV.add('+Checked0') + * var := 1, LV.add('+Checked' var) + * @param {(String)} [Col1] + * First column of the row to add data to. + * Starts at column 1 unless the Col# option is specified. + * If omitted, cell is left blank. + * @param {(String)} [ColN] + * Each additional parameter can contain the next column's data. + * If the parameter is blank or omitted, no data is added to that column. + * @returns {(Integer)} + * The row's number is returned. + * @example Inserting a row into a ListView. + * goo := Gui() + * lv := goo.AddListView('xm ym w200 h200', ['A Col', 'B Col', 'C Col']) + * loop 4 + * lv.Add('', A_Index, A_Index, A_Index) + * + * lv.Insert(3, , 'x', 'y', 'z') + * + * goo.Show() + */ + Insert(RowNumber [,Options:='', Col1, ColN*]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#InsertCol|`InsertCol()`} + * Inserts a new column at the specified column number. + * Max number of columns is 200. + * @param {(Integer)} ColumnNumber + * Column number to insert the new column at. + * All columns to the right are shifted right by 1. + * If column number is higher than total columns, it's added to the end of the list. + * @param {(String)} [Options] + * If omitted, no options are used. + * - `Check` + * Shows a checkmark in the row. + * Use `LV.Modify(RowNumber, "-Check")` to uncheck. + * - `Col#` + * Specify the column to start at when adding the Cell values. + * - `Focus` + * Set keyboard focus to this row. + * - `Icon#` + * The image to use from ImageList, where `#` is the icon index. + * Use `-1` for a blank icon. + * - `Select` + * Selects the row. + * Use LV.Modify(RowNumber, "-Select") to deselect. + * `Select` may also be followed by a 1 (selected) or a 0 (unselected). + * + * LV.add('+Checked0') + * var := 1, LV.add('+Checked' var) + * @param {(String)} [ColumnTitle] + * The title to apply to the column header. + * If omitted or an empty string, the header will be blank. + * @returns {(Integer)} + * The inserted column's number. + * @example + */ + InsertCol(ColumnNumber [,Options:='', ColumnTitle:='']) => String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#Modify|`Modify()`} + * Modifies the attributes and/or text of a row. + * @param {(Integer)} RowNumber + * Row number to modify. + * If `0` is used, all rows are modified. + * @param {(String)} Options + * If omitted, no options are used. + * - `Check` + * Shows a checkmark in the row. + * Use `LV.Modify(RowNumber, "-Check")` to uncheck. + * - `Col#` + * Specify the column to start at when adding the Cell values. + * - `Focus` + * Set keyboard focus to this row. + * - `Icon#` + * The image to use from ImageList, where `#` is the icon index. + * Use `-1` for a blank icon. + * - `Select` + * Selects the row. + * Use LV.Modify(RowNumber, "-Select") to deselect. + * `Select` may also be followed by a 1 (selected) or a 0 (unselected). + * + * LV.add('+Checked0') + * var := 1, LV.add('+Checked' var) + * - `Vis` + * Ensures row is visible by scrolling to it (if necessary). + * @param {(String)} [Col1] + * First column of the row to add data to. + * Starts at column 1 unless the Col# option is specified. + * If omitted, cell is left blank. + * @param {(String)} [ColN] + * Each additional parameter can contain the next column's data. + * If the parameter is blank or omitted, no data is added to that column. + * @returns {(String)} An empty string is always returned. + * @example + */ + Modify(RowNumber [,Options:='', Col1, ColN*]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#ModifyCol|`ModifyCol()`} + * Modifies the attributes and/or text of the specified column and its header. + * If all params are omitted, all columns are auto-adjusted to fit contents. + * @param {(Integer)} [ColumnNumber] + * The number of the column to modify. + * @param {(String)} [Options] + * **General options** + * - `#` = New column width where `#` is the number of pixels. + * This can be a pure number if it's the only option. + * - `Auto` = Adjust column width to fit contents. + * Only works in {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#View|Report view mode}. + * - `AutoHdr` = Adjust column width to fit contents, including the header. + * Only works in {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#View|Report view mode}. + * - `Icon#` = Display icon next to column header, where `#` is the icon number of the {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL|ImageList}. + * - `IconRight` = Icon is displayed on the right side of the column. + * + * **Column data type** + * - `Text` = Text-mode sorting, which is the initial default for every column. + * Only the first 8190 characters are used when sorting (4094 if using Logical). + * Text can perform up to x25 slower than Integer. + * - `Integer` = Contains decimal or hexadecimal integers. + * Non-integer values are considered 0 when sorting. + * - `Float` = Contains floating point numbers. + * Float can perform up to x25 slower than Integer. + * + * **Alignment** + * Alignment should come after data type + * - `Center` = Centers the text in the column. + * - `Left` = Left-aligns the column's text. + * Default for Text. + * - `Right` = Right-aligns the column's text. + * Default for Integer and Float. + This attribute need not be specified for Integer and Float columns + because they are right-aligned by default. + That default can be overridden by specifying something such as "Integer Left" + or "Float Center". + * + * **Sorting** + * - `Case` = The sorting of the column is case-sensitive (affects only text columns). If the options Case, CaseLocale, and Logical are all omitted, the uppercase letters A-Z are considered identical to their lowercase counterparts for the purpose of the sort. + * - `CaseLocale` = The sorting of the column is case-insensitive based on the current user's locale (affects only text columns). For example, most English and Western European locales treat the letters A-Z and ANSI letters like Ä and Ü as identical to their lowercase counterparts. This method also uses a "word sort", which treats hyphens and apostrophes in such a way that words like "coop" and "co-op" stay together. + * - `Desc` = Descending order. The column starts off in descending order the first time the user sorts it. + * - `Logical` = Same as CaseLocale except that any sequences of digits in the text are treated as true numbers rather than mere characters. For example, the string "T33" would be considered greater than "T4". Logical and Case are currently mutually exclusive: only the one most recently specified will be in effect. + * - `NoSort` = Prevents a user's click on this column from having any automatic sorting effect. However, the ColClick event is still raised, so the script can respond with a custom sort or other action. To disable sorting for all columns rather than only a subset, include NoSort in the ListView's options. + * - `Sort` = Immediately sorts the column in ascending order (even if it has the Desc option). + * - `SortDesc` = Immediately sorts the column in descending order. + * - `Uni` = Unidirectional sort. This prevents a second click on the same column from reversing the sort direction. + * + * @param {(String)} [ColumnTitle] + * The new header of the column. + * If omitted, the header is left unchanged. + * @returns {()} + * @see @example + */ + ModifyCol([ColumnNumber:=unset, Options:=unset, ColumnTitle:=unset]) => String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'DoubleClick'|'ColClick'|'ContextMenu'|'Focus'|'LoseFocus'|'ItemCheck'|'ItemEdit'|'ItemFocus'|'ItemSelect'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The ListView is clicked. + * + * ListView_Click(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The ListView is double-clicked. + * + * ListView_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ColClick|`ColClick`} - A ListView's column header is clicked. + * + * ListView_ColClick(GuiCtrl, ColNum) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the ListView or presses + * Menu or Shift+F10 while the ListView has the keyboard focus. + * + * ListView_ContextMenu(GuiCtrl, Item, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The ListView gains the keyboard focus. + * + * ListView_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The ListView loses the keyboard focus. + * + * ListView_LoseFocus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemCheck|`ItemCheck`} - The ListView item is checked or unchecked. + * + * ListView_ItemCheck(GuiCtrl, RowNum, RowChecked) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemEdit|`ItemEdit`} - The ListView item's label is edited by the user. + * The One of the following event(s). Expected callback format is included. must be used to edit labels. + * + * ListView_ItemEdit(GuiCtrl, RowNum) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemFocus|`ItemFocus`} - The ListView item receives focus. + * + * ListView_ItemFocus(GuiCtrl, RowNum) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemSelect|`ItemSelect`} - A ListView item is selected or deselected. + * During multiple selections (like click+drag) the event is fired once for each item. + * + * ListView_ItemSelect(GuiCtrl, RowNum, IsSelected) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the ListView's object + * - `Info`: Row number of clicked item or 0 if not over an item + * - `ColNum`: Column number of item + * Column numbers do not change when columns are rearranged + * - `RowNum`: The row number of the item + * - `IsSelected`: + * - `1` = Item selected + * - `0` = Item deselected + * - `RowChecked`: + * - `1` = Row is checked + * - `0` = Row is unchecked + * - `Item`: Item's row or ID number + * 0 if the user clicked somewhere other than an item + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Checked'|'Count'|'Grid'|'Hdr'|'Multi'|'NoSortHdr'|'NoSort'|'ReadOnly'|'Sort'|'SortDesc'|'WantF2'|'Icon'|'Tile'|'IconSmall'|'List'|'Report'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Checked`: Each row has a checkbox to the left side. + * When adding rows, include the word {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm#Check|Check} in its options to check it. + * - `Count#`: Specify an initial amount of rows where `#` is the starting amount. `Count20` + * Using this option increases performance by preventing multiple row addition calls. + * - `Grid`: Provides visual horizontal and vertical boundaries between rows and columns. + * - `Hdr`: To hide the header, use `-Hdr`. + * To make the header visible hte '+Hdr' option. + * - `Multi`: Specify `-Multi` to prevent the user from selecting more than one row at a time. + * - `NoSortHdr`: Makes header unclickable and take on a flat appearance. + * This cannot be changed after the ListView is created. + * - `NoSort`: Turns off automatic sorting on column header click. + * The header still behaves like a button and allows the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ColClick|ColClick event} + * to be raised and allowing for custom sorting or other actions. + * - `ReadOnly`: Using `-ReadOnly` allows the first column to be editable. + * The label can be edited with F2 (see {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#WantF2|WantF2}) or by clicking the label, + * waiting a brief moment, then clicking again. + * - `Sort`: The control is sorted alphabetically by first column contents. + * - `SortDesc`: The control is sorted in reverse alphabetical order by first column contents. + * - `WantF2`: Specify `-WantF2` to prevent F2 from editing the current selected item. WantF2 only works if `-ReadOnly` is also in effect. + * + * **View Modes** + * You can include one of five view modes. The default, and most common view, is `Report`. + * - `Icon`: Shows a large-icon view. In this view and all the others except Report, the text in columns other than the first is not visible. To display icons in this mode, the ListView must have a large-icon ImageList assigned to it. + * - `Tile`: Shows a large-icon view but with ergonomic differences such as displaying each item's text to the right of the icon rather than underneath it. Checkboxes do not function in this view. + * - `IconSmall`: Shows a small-icon view. + * - `List`: Shows a small-icon view in list format, which displays the icons in columns. The number of columns depends on the width of the control and the width of the widest text item in it. + * - `Report`: Switches back to report view, which is the initial default. For example: LV.Opt("+Report"). + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vLV') ; Set using v option. Can't include a space + * con.Name := 'LV' ; Set using Name property. Can including a space + * - `AltSubmit`: Use control's alternate submit method. + * DropDownList, ComboBox, ListBox, Tab: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} uses selected item's position instead of its text. + * ComboBox: If no item is selected, the text of the edit field is instead stored. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Opt(Options) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#SetImageList|`SetImageList()`} + * Sets or replaces an ImageList for displaying icons. + * Destroy the ImageList with {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL_Destroy|IL_Destroy()}. + * @param {(Integer)} ImageListID + * The ID number returned from a previous call to {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL_Create|IL_Create()}. + * @param {(Integer)} IconType + * - Omit = Detected automatically. + * - `0` = Large icons. + * - `1` = Small icons. + * - `2` = State icons. + * Not yet directly supported, but can be used via {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMesage()} + * @returns {(Integer)} + * The ImageList's ID is returned, otherwise `0` on failure. + * @example + */ + SetImageList(ImageListID [,IconType:=unset]) => String + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#MonthCal|`MonthCal`} + * A tall and wide control that displays all the days of the month in calendar format. + * The user may select a single date or a range of dates. + */ + class MonthCal extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets the control's Date-time stamp in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS format}. + * Use {@link https://www.autohotkey.com/docs/v2/Variables.htm#Now|A_Now} to set Value to current time. + * If the {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ChooseNone|choose none `+2` option} was used, setting + * Value to 0 will clear the DateTime control. + * @type String + * @example Set window title to date + * goo := Gui() + * con := goo.AddMonthCal('vMonCal') + * con.OnEvent('Change', update_title) + * update_title(con) + * goo.Show() + * + * update_title(control, *) { + * control.Gui.Title := control.value + * } + */ + Value { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'} EventName + * The following event. Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The MonthCal's value changes. + * + * MonthCal_Click(GuiCtrl, Info) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the MonthCal's object + * - `Info`: Not used with MonthCal controls + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Set window title to date + * goo := Gui() + * con := goo.AddMonthCal('vMonCal') + * con.OnEvent('Change', update_title) + * update_title(con) + * goo.Show() + * + * update_title(control, *) { + * control.Gui.Title := control.value + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Multi'|'Range'|'4'|'8'|'16'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Multi`: Allows multi-select range with shift-click or click-drag to select a range of adjacent dates. + * This option is forced when the control is created with the `Range` option. + * Once the control is created, this option cannot be altered. + * - `RangeMIN-MAX`: Sets how far back or forward you can set the DateTime control. + * MIN and MAX should be dates. Omitting one leaves that side of the range unrestricted. + * + * con.opt('Range20220101-20221231') + * con.opt('Range-20250101115959') + * - `4`: Display week numbers (1-52) to the left of each row of days. + * Week 1 is defined as the first week that contains at least four days. + * - `8`: Prevent the circling of today's date within the control. + * - `16`: Prevent the display of today's date at the bottom of the control. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vMCMain') ; Set using v option. Can't include a space + * con.Name := 'MC Main' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a MonthCal + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddMonthCal('x+10 +Hidden vMonCal') + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['MonCal'].Opt('-Hidden') + * else cb.Gui['MonCal'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Picture|`Pic`} + * An area containing an image. + */ + class Pic extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Set or retrieve the picture file's path. + * If setting a new picture, zero or more options can come before the file path. + * Only 1 space or 1 tab should be used between each option and the file path. + * If both *W and *H are omitted, control's width and height are used. + * - `*W#` and `*H#` = Adjust the width or height of the image, where `#` is the size in pixels. + * Using `*W0` or `*H0` will use the image's native width or height. + * Using `*W-1` or `*H-1` preserves the aspect ratio when setting the other value. + * Only one of the two should be set to -1. + * - `*Icon#` = Select an icon from a group of them. + * Or select an icon resource from a DLL or EXE file. + * @type String + * @example Cycle through AHK's icons + * goo := Gui() + * goo.AddText('xm ym', "Click the icon to cycle through through AHK's built-in icons.") + * con := goo.AddPic('y+5 w0 h0 Icon1', A_AhkPath) + * con.OnEvent('Click', pic_click_cycle_icons) + * goo.Show('') + * + * pic_click_cycle_icons(GuiCtrl, Info) { + * static icon_num := 1 + * + * icon_num_max := 5 + * icon_num++ + * if (icon_num > icon_num_max) + * icon_num := 1 + * + * TraySetIcon(A_AhkPath, icon_num) + * GuiCtrl.value := '*Icon' icon_num ' ' A_AhkPath + * } + */ + Value { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'DoubleClick'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The Picture is clicked. + * + * Pic_Click(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The Picture is double-clicked. + * + * Pic_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Picture or presses + * Menu or Shift+F10 while the Picture has the keyboard focus. + * + * Pic_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The Picture gains the keyboard focus. + * + * Pic_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The Picture loses the keyboard focus. + * + * Pic_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Picture's object + * - `Info`: Not used with Picture controls + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the Picture's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Click picture to launch website + * goo := Gui() + * goo.AddText('xm ym', 'Click the AHK icon in the corner to launch the AHK website!') + * con := goo.AddPic('x+100 y+100', A_AhkPath) + * con.OnEvent('Click', launch) + * goo.Show() + * + * launch(*) { + * Run('https://www.AutoHotkey.com') + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Icon'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Icon#`: Use a specific icon from an icon group where # is the number of the icon. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vPicLogo') ; Set using v option. Can't include a space + * con.Name := 'Pic Logo' ; Set using Name property. Can including a space + * - `AltSubmit`: Use Microsoft's GDIPlus.dll to load the image. + * This might result in a different appearance for GIF, BMP, and icon images. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the Picture to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a picture + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddPic('x+10 w100 h100 +Hidden vAHKIcon', A_AhkPath) + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['AHKIcon'].Opt('-Hidden') + * else cb.Gui['AHKIcon'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Picture|`Picture`} + * An area containing an image. + */ + class Picture extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Set or retrieve the picture file's path. + * If setting a new picture, zero or more options can come before the file path. + * Only 1 space or 1 tab should be used between each option and the file path. + * If both *W and *H are omitted, control's width and height are used. + * - `*W#` and `*H#` = Adjust the width or height of the image, where `#` is the size in pixels. + * Using `*W0` or `*H0` will use the image's native width or height. + * Using `*W-1` or `*H-1` preserves the aspect ratio when setting the other value. + * Only one of the two should be set to -1. + * - `*Icon#` = Select an icon from a group of them. + * Or select an icon resource from a DLL or EXE file. + * @type String + * @example Cycle through AHK's icons + * goo := Gui() + * goo.AddText('xm ym', "Click the icon to cycle through through AHK's built-in icons.") + * con := goo.AddPicture('y+5 w0 h0 Icon1', A_AhkPath) + * con.OnEvent('Click', pic_click_cycle_icons) + * goo.Show('') + * + * pic_click_cycle_icons(GuiCtrl, Info) { + * static icon_num := 1 + * + * icon_num_max := 5 + * icon_num++ + * if (icon_num > icon_num_max) + * icon_num := 1 + * + * TraySetIcon(A_AhkPath, icon_num) + * GuiCtrl.value := '*Icon' icon_num ' ' A_AhkPath + * } + */ + Value { + set => String + get => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'DoubleClick'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The Picture is clicked. + * + * Picture_Click(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The Picture is double-clicked. + * + * Picture_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Picture or presses + * Menu or Shift+F10 while the Picture has the keyboard focus. + * + * Picture_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The Picture gains the keyboard focus. + * + * Picture_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The Picture loses the keyboard focus. + * + * Picture_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Picture's object + * - `Info`: Not used with Picture controls + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the Picture's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Click picture to launch website + * goo := Gui() + * goo.AddText('xm ym', 'Click the AHK icon in the corner to launch the AHK website!') + * con := goo.AddPicture('x+100 y+100', A_AhkPath) + * con.OnEvent('Click', launch) + * goo.Show() + * + * launch(*) { + * Run('https://www.AutoHotkey.com') + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Icon'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Icon#`: Use a specific icon from an icon group where # is the number of the icon. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.opt('+vPicLogo') ; Set using v option. Can't include a space + * con.Name := 'Pic Logo' ; Set using Name property. Can including a space + * - `AltSubmit`: Use Microsoft's GDIPlus.dll to load the image. + * This might result in a different appearance for GIF, BMP, and icon images. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('cRed') + * con.opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.opt('+Disabled') ; Control disabled + * var := 0 + * con.opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the Picture to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.opt('BackgroundNavy') + * con.opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a picture + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddPicture('x+10 w100 h100 +Hidden vAHKIcon', A_AhkPath) + * goo.Show() + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['AHKIcon'].Opt('-Hidden') + * else cb.Gui['AHKIcon'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Progress|`Progress`} + * A dual-color bar typically used to indicate how much progress has been made toward the completion of an operation. + */ + class Progress extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Set or retrieve the new position of the control. + * Relative adjustment can be done with operators like: `+=`, `-=`, `++`, and `--` + * @type String + * @example Fill and drain a progress bar. + * goo := Gui() + * con := goo.AddButton('w100 h50 vBtnInc', 'Increase') + * con.OnEvent('Click', btn_click) + * con.GetPos(, &by, , &bh) + * goo.AddProgress('x+10 w100 h100 vProgBar') + * con := goo.AddButton('y+10 +hidden vBtnExit', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * con := goo.AddButton('xm y' (by + bh + 5) ' w100 h50 vBtnDec', 'Decrease') + * con.OnEvent('Click', btn_click) + * goo.Show() + * + * btn_click(btn, info) { + * pb := btn.Gui['ProgBar'] + * if (btn.name = 'BtnInc' && pb.value < 100) + * pb.Value += 25 + * else if (btn.name = 'BtnDec' && pb.value > 0) + * pb.Value -= 25 + * + * if (pb.Value >= 100) + * btn.Gui['BtnExit'].Visible := 1 + * else btn.Gui['BtnExit'].Visible := 0 + * } + */ + Value { + set => String + get => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'ContextMenu'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Progress bar or presses + * Menu or Shift+F10 while the Progress bar has the keyboard focus. + * + * Pic_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Progress object + * - `Info`: Not used with Progress bar controls + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the Progress bar's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Range'|'Smooth'|'Vertical'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `RangeMIN-MAX`: Sets the minimum and maximum ends of the progress bar. Default is `Range0-100`. + * - `Smooth`: Displays a simple, continuous bar. + * - `Vertical`: Makes the bar rise or fall vertically rather than horizontally. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddProgress('+vPBarDownload') ; Set using v option. Can't include a space + * con.Name := 'PBar Download' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddProgress('cRed') + * goo.AddProgress('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddProgress('+Disabled') ; Control disabled + * var := 0 + * goo.AddProgress('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddProgress('BackgroundNavy') + * goo.AddProgress('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Fill and drain a progress bar. + * goo := Gui() + * con := goo.AddButton('w100 h50 vBtnInc', 'Increase') + * con.OnEvent('Click', btn_click) + * con.GetPos(, &by, , &bh) + * goo.AddProgress('x+10 w100 h100 vProgBar') + * con := goo.AddButton('y+10 +hidden vBtnExit', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * con := goo.AddButton('xm y' (by + bh + 5) ' w100 h50 vBtnDec', 'Decrease') + * con.OnEvent('Click', btn_click) + * goo.Show() + * + * btn_click(btn, info) { + * pb := btn.Gui['ProgBar'] + * if (btn.name = 'BtnInc' && pb.value < 100) + * pb.Value += 25 + * else if (btn.name = 'BtnDec' && pb.value > 0) + * pb.Value -= 25 + * + * if (pb.Value >= 100) + * btn.Gui['BtnExit'].Opt('-Hidden') + * else btn.Gui['BtnExit'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Radio|`Radio`} + * A radio button is a small empty circle that can be checked (on) or unchecked (off). + */ + class Radio extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The caption that displays on the radio button. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to adjust radio width if needed. + * @type String + * @example Radio buttons that change text case. + * goo := Gui() + * goo.AddEdit('r1 w280 vEdtBox', 'Type something here. Click a radio button.') + * rad_btns := Map( + * 'lowercase', 'StrLower', + * 'UPPERCASE', 'StrUpper', + * 'TitleCase', 'StrTitle' + * ) + * for name, fn in rad_btns { + * if (A_Index = 1) + * rad := goo.AddRadio('xm y+5 w100 h20 Checked Border', name) + * else rad := goo.AddRadio('x+5 yp w100 h20 Border', name) + * rad.fn := fn + * rad.OnEvent('Click', on_rad_click) + * } + * goo.Show() + * + * on_rad_click(rad, info) { + * edt := rad.Gui['EdtBox'] + * edt.Text := %rad.fn%(edt.Text) + * } + */ + Text { + set => String + get => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Retrieves or sets the checked state. + * Values can be: + * `1`: Checked + * `0`: Unchecked + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|Text property} to set/get the control text. + * @type Integer + */ + Value { + set => Integer + get => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'DoubleClick'|'ContextMenu'|'Focus'|'LoseFocus'} EventName + * One of the following events: + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The Radio button is clicked. + * + * Radio_Click(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The Radio button is double-clicked. + * + * Radio_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Progress bar or presses + * Menu or Shift+F10 while the Progress bar has the keyboard focus. + * + * Radio_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The Radio button gains the keyboard focus. + * + * Radio_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The Radio button loses the keyboard focus. + * + * Radio_LoseFocus(GuiCtrl, Reserved) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Radio's object + * - `Info`: Not used with Radio button controls + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the Radio button's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Radio buttons that change text case. + * goo := Gui() + * goo.AddEdit('r1 w280 vEdtBox', 'Type something here. Click a radio button.') + * rad_btns := Map( + * 'lowercase', 'StrLower', + * 'UPPERCASE', 'StrUpper', + * 'TitleCase', 'StrTitle' + * ) + * for name, fn in rad_btns { + * if (A_Index = 1) + * rad := goo.AddRadio('xm y+5 w100 h20 Checked Border', name) + * else rad := goo.AddRadio('x+5 yp w100 h20 Border', name) + * rad.fn := fn + * rad.OnEvent('Click', on_rad_click) + * } + * goo.Show() + * + * on_rad_click(rad, info) { + * edt := rad.Gui['EdtBox'] + * edt.Text := %rad.fn%(edt.Text) + * } */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Checked'|'Group'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Left'|'Right'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Checked`: Starts the button in the checked/on state. + * - `Group`: Starts a new radio group. A new group is automatically started when a non-radio control is added. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.Opt('+vRadToggle') ; Set using v option. Can't include a space + * con.Name := 'Rad Toggle' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.Opt('cRed') + * con.Opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.Opt('+Disabled') ; Control disabled + * var := 0 + * con.Opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * The radio button will also be moved to the right side of the control. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.Opt('BackgroundNavy') + * con.Opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding different controls + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddRadio('x+10 w100 +Hidden vRad1 Checked', 'Hide Exit') + * con.OnEvent('Click', rad_click) + * con := goo.AddRadio('xp y+5 w100 +Hidden vRad2', 'Show Exit') + * con.OnEvent('Click', rad_click) + * goo.AddButton('xp y+5 +Hidden vBtnExit', 'Exit').OnEvent('Click', (*) => ExitApp()) + * goo.Show() + * + * cb_click(cb, info) { + * goo := cb.Gui + * for rad in goo { + * if (rad.Type != 'Radio') + * continue + * if (cb.Value = 1) + * rad.Opt('-Hidden') + * else rad.Opt('+Hidden') + * } + * } + * + * rad_click(rad, info) { + * if InStr(rad.Text, 'Hide') + * rad.Gui['BtnExit'].Opt('+Hidden') + * else rad.Gui['BtnExit'].Opt('-Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Slider|`Slider`} + * A sliding bar that the user can move along a vertical or horizontal track. + * The standard volume control in the taskbar's tray is an example of a slider. + */ + class Slider extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Set or retrieve the new position of the control. + * Relative adjustment can be done with operators like: `+=`, `-=`, `++`, and `--` + * @type String + * @example Creating a volume slider GUI. + * goo := Gui() + * start_vol := SoundGetVolume() + * goo.AddText('xm ym w100', 'Volume Slider:') + * goo.txt_vol := goo.AddText('x+10', Round(start_vol)) + * goo.sld_vol := goo.AddSlider('xm w200 AltSubmit Range0-100 cRed', start_vol) + * goo.sld_vol.OnEvent('Change', vol_adjust) + * goo.Show('AutoSize') + * + * vol_adjust(control, *) { + * SoundSetVolume(control.Value) + * control.gui.txt_vol.Value := control.Value + * } + */ + Value { + set => String + get => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'ContextMenu'} EventName + * One of the following events: + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The Slider's value changes. + * + * Slider_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Progress bar or presses + * Menu or Shift+F10 while the Progress bar has the keyboard focus. + * + * Slider_ContextMenu(GuiCtrl, Item, RightClick, X, Y) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Slider's object + * - `Info`: Amount slider has changed between starting and stopping + * If the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#AltSubmit|AltSubmit} option is used the event is raised + * after any type of value change is detected. + * - `Item`: Not used with Slider controls. + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the Slider's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Creating a volume slider GUI. + * goo := Gui() + * start_vol := SoundGetVolume() + * goo.AddText('xm ym w100', 'Volume Slider:') + * goo.txt_vol := goo.AddText('x+10', Round(start_vol)) + * goo.sld_vol := goo.AddSlider('xm w200 AltSubmit Range0-100 cRed', start_vol) + * goo.sld_vol.OnEvent('Change', vol_adjust) + * goo.Show('AutoSize') + * + * vol_adjust(control, *) { + * SoundSetVolume(control.Value) + * control.gui.txt_vol.Value := control.Value + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Background'|'Border'|'Disabled'|'Hidden'|'Redraw'|'Section'|'Theme'|'v'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.Opt('+vSBMain') ; Set using v option. Can't include a space + * con.Name := 'SB Main' ; Set using Name property. Can including a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.Opt('+Disabled') ; Control disabled + * var := 0 + * con.Opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.Opt('BackgroundNavy') + * con.Opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a transparency slider + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show') + * con.OnEvent('Click', cb_click) + * con := goo.AddSlider('x+10 w100 +Hidden vSld Range25-255 AltSubmit', 255) + * con.OnEvent('Change', update_opacity) + * goo.Show() + * + * update_opacity(sld, info) { + * WinSetTransparent(sld.value, 'ahk_id ' sld.Gui.hwnd) + * } + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['Sld'].Opt('-Hidden') + * else cb.Gui['Sld'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#StatusBar|`StatusBar`} + * A row of text and/or icons attached to the bottom of a window, which is typically used to report changing conditions. + */ + class StatusBar extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * The text of the first section of the status bar. + * Use {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#SB_SetText|StatusBar.SetText()} for more text options. + * @type String + * @example Statusbar with active clock and date. + * goo := Gui() + * goo.AddText('xm', 'Click the StatusBar to switch between time and date.') + * goo.AddButton('xm w100', 'Exit').OnEvent('Click', (*) => ExitApp()) + * sb := goo.AddStatusBar('vSB') + * sb.time := 1 + * sb.OnEvent('Click', date_time_switch) + * clock_update(sb) + * goo.Show('h200') + * + * clock_update(con) { + * if con.time + * con.Text := A_Hour ':' A_Min ':' A_Sec + * else con.Text := A_MMM A_DD ', ' A_YYYY + * SetTimer(clock_update.Bind(con), -100) + * } + * + * date_time_switch(sb, info) { + * sb.time := !sb.time + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'DoubleClick'|'ContextMenu'} EventName + * One of the following events: + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The StatusBar is clicked. + * + * Ctrl_Click(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The StatusBar is double-clicked. + * + * Ctrl_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the StatusBar or presses + * Menu or Shift+F10 while the StatusBar has the keyboard focus. + * + * Ctrl_ContextMenu(GuiCtrl, Item, RightClick, X, Y) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the StatusBar's object + * - `Info`: The section number of the status bar clicked + * - `Item`: + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the StatusBar's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Statusbar with active clock and date. + * goo := Gui() + * goo.AddText('xm', 'Click the StatusBar to switch between time and date.') + * goo.AddButton('xm w100', 'Exit').OnEvent('Click', (*) => ExitApp()) + * sb := goo.AddStatusBar('vSB') + * sb.time := 1 + * sb.OnEvent('Click', date_time_switch) + * clock_update(sb) + * goo.Show('h200') + * + * clock_update(con) { + * if con.time + * con.Text := A_Hour ':' A_Min ':' A_Sec + * else con.Text := A_MMM A_DD ', ' A_YYYY + * SetTimer(clock_update.Bind(con), -100) + * } + * + * date_time_switch(sb, info) { + * sb.time := !sb.time + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Background'|'Border'|'Disabled'|'Hidden'|'Redraw'|'Section'|'Theme'|'v'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.Opt('+vSBMain') ; Set using v option. Can't include a space + * con.Name := 'SB Main' ; Set using Name property. Can including a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.Opt('+Disabled') ; Control disabled + * var := 0 + * con.Opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.Opt('BackgroundNavy') + * con.Opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Showing/hiding a StatusBar. + * goo := Gui() + * con := goo.AddCheckbox('w100 h50 vCbShowHide', 'Show StatusBar') + * con.OnEvent('Click', cb_click) + * con := goo.AddStatusBar('x+10 w100 h50 +Hidden vSB', A_ScriptFullPath) + * goo.Show('w200 h200') + * + * cb_click(cb, info) { + * if (cb.Value = 1) + * cb.Gui['SB'].Opt('-Hidden') + * else cb.Gui['SB'].Opt('+Hidden') + * } + */ + Opt(Options) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#SB_SetText|`SetText()`} + * Displays NewText in the specified part of the status bar. + * @param {(String)} NewText + * The new text to put into the `SectionNumber`. + * Text can be broken up into three sections: Left, Center, and Right + * Text starts left justified. + * If a tab `` `t `` is encountered, text becomes center justified. + * If another tab `` `t `` is encountered, text becomes right justified. + * @param {(Integer)} [SectionNumber] + * The StatusBar section number to set the text to. + * This number should be between 1 and 256, inclusive. + * If omitted, default is 1. + * @param {(Integer)} [Style] + * The border around this `SectionNumber`: + * - `0` or Omitted = Traditional border + * - `1` = No border + * - `2` = Raised border + * @returns {(String)} + * An empty string is always returned. + * @example ListView and StatusBar example + * goo := Gui() + * lv := goo.AddListView('xm ym w900 h400', ['Name', 'Dir', 'Extension']) + * loop files A_ScriptDir '\*.*' + * lv.Add('', A_LoopFileName, A_LoopFileDir, A_LoopFileExt) + * + * lv.ModifyCol() + * + * sb := goo.AddStatusBar() + * sb.SetParts(150, 300) + * + * loop 3 { + * i := A_Index + * sb.SetText('Sec' i 'L`tSec' i 'C`tSec' i 'R', i) + * } + * + * goo.Show() + */ + SetText(NewText [,SectionNumber:=1, Style:=0]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#SB_SetParts|`SetParts()`} + * Divides the bar into multiple sections according to the specified widths, in pixels. + * @param [SectionWidth] + * Split the StatusBar into multiple sections. + * Each parameter should contain the width, in pixels, of a each section in the StatusBar. + * There can be a max of 255 sections. + * If omitted, all sections are removed and only one section will statusbar section remains. + * Any area leftover area becomes the last section. + * @returns {(Integer)} + * The HWND of the status bar is returned. + * @example ListView and StatusBar example + * goo := Gui() + * lv := goo.AddListView('xm ym w900 h400', ['Name', 'Dir', 'Extension']) + * loop files A_ScriptDir '\*.*' + * lv.Add('', A_LoopFileName, A_LoopFileDir, A_LoopFileExt) + * + * lv.ModifyCol() + * + * sb := goo.AddStatusBar() + * sb.SetParts(150, 300) + * + * loop 3 { + * i := A_Index + * sb.SetText('Sec' i 'L`tSec' i 'C`tSec' i 'R', i) + * } + * + * goo.Show() + */ + SetParts([SectionWidth*]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#SB_SetIcon|`SetIcon()`} + * @param FileName + * The path to an icon, image file, {@link https://www.autohotkey.com/docs/v2/misc/ImageHandles.htm|bitmap, or icon handle}. + * Supported types: .ICO .CUR .ANI .EXE .DLL .CPL .SCR {@link https://www.autohotkey.com/docs/v2/misc/ImageHandles.htm|Icon Handle "HICON:"} or another icon resource. + * @param [IconNumber] + * The number of the icon group to use from the chosen file. + * If omitted, it defaults to 1. + * @param {(Integer)} [SectionNumber] + * The StatusBar section number to set the text to. + * This number should be between 1 and 256, inclusive. + * If omitted, default is 1. + * @returns {(Integer)} + * A `HICON`, handle to the added icon. + * @example Using AHK's native icons in the statusbar. + * goo := Gui() + * sb := goo.AddStatusBar() + * sb.SetParts(150, 150, 150, 150) + * + * loop 5 { + * i := A_Index + * sb.SetIcon(A_AhkPath, i, i) + * sb.SetText('AHK Icon #' i, i) + * } + * + * goo.Show('w750 h200') + */ + SetIcon(FileName [,IconNumber:=1, SectionNumber:=1]) => Integer + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Text|`Text`} + * A region containing borderless text that the user cannot edit. Often used to label other controls. + */ + class Text extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Set or retrieve the text in the control. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to adjust text width if needed. + * @type String + * @example Text click game + */ + Value { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|`Text`} + * Set or retrieve the text in the control. + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to adjust text width if needed. + * @type String + * @example Changing text case. + * goo := Gui() + * control := goo.AddText('w100 h30', 'Change Case') + * control.case := 0 + * control.OnEvent('Click', change_text) + * goo.Show() + * + * change_text(con, info) { + * con.case++ + * switch con.case { + * case 1: con.Text := StrLower(con.text) + * case 2: con.Text := StrUpper(con.text) + * default: con.Text := StrTitle(con.text), con.case := 0 + * } + * } + */ + Text { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'DoubleClick'|'ContextMenu'} EventName + * One of the following events: + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The Text is clicked. + * + * Ctrl_Click(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The Text is double-clicked. + * + * Ctrl_DoubleClick(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the Text or presses + * Menu or Shift+F10 while the Text has the keyboard focus. + * + * Ctrl_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the Text's object + * - `Info`: Not used with Text controls + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the Text's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example Text Clicker Mini Game + * goo := Gui() + * con := goo.AddText('x100 y100 w100 vstep1', 'Click Here') + * con.OnEvent('Click', text_click) + * if random(1, 0) + * t1 := 'yes', t2 := 'no' + * else t1 := 'no', t2 := 'yes' + * con := goo.AddText('x50 y100 w80 +Hidden vstep2' t1, 'Pick One') + * con.OnEvent('Click', text_click) + * con := goo.AddText('x200 y100 w80 +Hidden vstep2' t2, 'Pick One') + * con.OnEvent('Click', text_click) + * con := goo.AddText('x0 y0 w80 +Hidden vstep3', 'Catch Me') + * con.OnEvent('Click', text_click) + * con := goo.AddButton('x0 y0 h300 w300 +Hidden vBtnExit', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * goo.Show('w300 h300') + * + * + * text_click(tCon, info) { + * static con_shuffle := 0 + * , shuffle_spd := 100 + * goo := tCon.Gui + * switch (tCon.Name) { + * case 'step1': + * hide('step1') + * show('step2yes') + * show('step2no') + * case 'step2yes': + * hide('step2yes') + * hide('step2no') + * show('step3') + * con_shuffle := 1 + * move_con(goo['step3']) + * case 'step2no': reset() + * case 'step3': + * con_shuffle := 0 + * reset() + * hide('step1') + * Sleep(1000) + * show('BtnExit') + * } + * + * show(name) => goo[name].Visible := 1 + * hide(name) => goo[name].Opt('+Hidden') + * reset() { + * for con in tCon.Gui + * if (con.Type = 'Text') + * con.Visible := 0 + * tCon.Gui['step1'].Opt('-Hidden') + * } + * move_con(con) { + * if !con_shuffle + * return + * shuffle_spd += 5 + * con.Gui.GetPos(,, &gw, &gh) + * con.GetPos(,, &cw, &ch) + * x := Random(5, gw-cw-5) + * y := Random(5, gh-ch-5) + * con.Move(x, y) + * SetTimer(move_con.Bind(con), -shuffle_spd) + * } + * } + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Background'|'BackgroundTrans'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Left'|'Right'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.Opt('+vTxtHeader') ; Set using v option. Can't include a space + * con.Name := 'Txt Header' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.Opt('cRed') + * con.Opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.Opt('+Disabled') ; Control disabled + * var := 0 + * con.Opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the text control to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.Opt('BackgroundNavy') + * con.Opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example Text Clicker Mini Game + * goo := Gui() + * con := goo.AddText('x100 y100 w100 vstep1', 'Click Here') + * con.OnEvent('Click', text_click) + * if random(1, 0) + * t1 := 'yes', t2 := 'no' + * else t1 := 'no', t2 := 'yes' + * con := goo.AddText('x50 y100 w80 +Hidden vstep2' t1, 'Pick One') + * con.OnEvent('Click', text_click) + * con := goo.AddText('x200 y100 w80 +Hidden vstep2' t2, 'Pick One') + * con.OnEvent('Click', text_click) + * con := goo.AddText('x0 y0 w80 +Hidden vstep3', 'Catch Me') + * con.OnEvent('Click', text_click) + * con := goo.AddButton('x0 y0 h300 w300 +Hidden vBtnExit', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * goo.Show('w300 h300') + * + * + * text_click(tCon, info) { + * static con_shuffle := 0 + * , shuffle_spd := 100 + * goo := tCon.Gui + * switch (tCon.Name) { + * case 'step1': + * hide('step1') + * show('step2yes') + * show('step2no') + * case 'step2yes': + * hide('step2yes') + * hide('step2no') + * show('step3') + * con_shuffle := 1 + * move_con(goo['step3']) + * case 'step2no': reset() + * case 'step3': + * con_shuffle := 0 + * reset() + * hide('step1') + * Sleep(1000) + * show('BtnExit') + * } + * + * show(name) => goo[name].Visible := 1 + * hide(name) => goo[name].Opt('+Hidden') + * reset() { + * for con in tCon.Gui + * if (con.Type = 'Text') + * con.Visible := 0 + * tCon.Gui['step1'].Opt('-Hidden') + * } + * move_con(con) { + * if !con_shuffle + * return + * shuffle_spd += 5 + * con.Gui.GetPos(,, &gw, &gh) + * con.GetPos(,, &cw, &ch) + * x := Random(5, gw-cw-5) + * y := Random(5, gh-ch-5) + * con.Move(x, y) + * SetTimer(move_con.Bind(con), -shuffle_spd) + * } + * } + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#TreeView|`TreeView`} + * A TreeView displays a hierarchy of items by indenting child items beneath their parents. + * The most common example is Explorer's tree of drives and folders. + */ + class TreeView extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Click'|'DoubleClick'|'ContextMenu'|'Focus'|'LoseFocus'|'ItemCheck'|'ItemEdit'|'ItemExpand'|'ItemSelect'} EventName + * One of the following event(s). Expected callback format is included. + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Click|`Click`} - The TreeView is clicked. + * + * TreeView_Click(GuiCtrl, ItemID) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DoubleClick|`DoubleClick`} - The TreeView is double-clicked. + * + * TreeView_DoubleClick(GuiCtrl, ItemID) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the TreeView or presses + * Menu or Shift+F10 while the TreeView has the keyboard focus. + * + * TreeView_ContextMenu(GuiCtrl, Item, RightClick, X, Y) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Focus|`Focus`} - The TreeView gains the keyboard focus. + * + * TreeView_Focus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#LoseFocus|`LoseFocus`} - The TreeView loses the keyboard focus. + * + * TreeView_LoseFocus(GuiCtrl, Reserved) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemCheck|`ItemCheck`} - The TreeView item is checked or unchecked. + * + * TreeView_ItemCheck(GuiCtrl, ItemID, IsChecked) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemEdit|`ItemEdit`} - The TreeView item's label is edited by the user. + * The {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm#ReadOnly|`-ReadOnly` option} must be used to edit labels. + * + * TreeView_ItemEdit(GuiCtrl, ItemID) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemExpand|`ItemExpand`} - The TreeView item becomes expanded or collapsed. + * + * TreeView_ItemExpand(GuiCtrl, ItemID, IsExpanded) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ItemSelect|`ItemSelect`} - A TreeView item is selected or deselected. + * + * TreeView_ItemSelect(GuiCtrl, ItemID) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the TreeView's object + * - `ItemID`: Unique ID of that TreeView item + * - `Item`: Item ID of clicked item or 0 if not over an item + * - `IsChecked`: + * - `1` = Item is checked + * - `0` = Item is unchecked + * _ `IsExpanded`: + * - `1` = Item is set to expanded + * - `0` = Item is set to collapsed + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the control's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Buttons'|'Checked'|'ImageList'|'Lines'|'ReadOnly'|'WantF2'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Buttons`: Specifying `-Buttons` to remove the `+` and `-` symbols from the left of each item. + * - `Checked`: Add a checkbox at left of each item. + * When {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm#Add|adding an item}, use the {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm#Check|Check option} to start it checked. + * - `ImageList#`: Add icons to a TreeView where `#` is the {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL|ImageListID} returned from a previous call to {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL_Create|IL_Create()}. + * This option can only be used when creating a TreeView. Use {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#SetImageList|SetImageList()}. + * - `Lines`: Specify `-Lines` disables the connecting lines between parents and children. + * This also prevents the `+` and `-` buttons from being shown for top-level items. + * - `ReadOnly`: Specify `-ReadOnly` to allow the editing of each item. + * The items can be edited with F2 (see {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#WantF2|WantF2}) or by clicking the label, + * waiting a brief moment, then clicking again. + * - `WantF2`: Specify `-WantF2` to prevent F2 from editing the current selected item. + * WantF2 only works if `-ReadOnly` is also in effect. + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.Opt('+vTVFolderView') ; Set using v option. Can't include a space + * con.Name := 'TV FolderView' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.Opt('cRed') + * con.Opt('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.Opt('+Disabled') ; Control disabled + * var := 0 + * con.Opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * con.Opt('BackgroundNavy') + * con.Opt('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#UpDown|`UpDown`} + * A pair of arrow buttons that, by default, will attach to the previous control and can be used to increase or decrease that control's value. + */ + class UpDown extends Gui.Control { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|`Value`} + * Set or retrieve the new position of the control. + * Relative adjustment can be done with operators like: `+=`, `-=`, `++`, and `--` + * @type String + * @example + */ + Value { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Change'|'ContextMenu'} EventName + * One of the following events: + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`Change`} - The UpDown's value changes. + * + * Ctrl_Change(GuiCtrl, Info) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Ctrl-ContextMenu|`ContextMenu`} - The user right-clicks the UpDown or presses + * Menu or Shift+F10 while the UpDown has the keyboard focus. + * + * Ctrl_ContextMenu(GuiCtrl, Info, RightClick, X, Y) + * - Callback Params: + * - `GuiCtrlObj`: Reference to the ListView's object + * - `Info`: Not used with UpDown controls + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `X` and `Y`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the UpDown's upper left corner + * @param {(String|FuncObj)} Callback + * A function, method, or object that is called when the event is raised. + * A callback's first parameter is always the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl} that raised the event. + * @param {(Integer)} [AddRemove] + * Adjust callback order or delete callback. + * - `1` = Add the callback after any previously registered callbacks. + * - `-1` = Add the callback before any previously registered callbacks. + * - `0` = Remove the callback. + * + * If multiple callbacks are registered, a callback that returns + * a non-empty string will stop all remaining callbacks from running. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the control + * @param {String|'Horz'|'Left'|'Right'|'Range'|'Wrap'|'-16'|'0x80'|'Increments'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Horz`: Arrow buttons point left/right, become wider, and show under the Buddy. + * Buttons are visually disconnected from the control. + * Adding option `+16` forces the buttons to attach to their original position. + * - `Left`/`Right`: The side of the Buddy the UpDown attaches to. Right is default. + * This option cannot be changed after control creation. + * - `RangeMIN-MAX`: Set slider value range, where `MIN` is the minimum and `MAX` is the maximum. + * Default is `Range0-100`. + * - `Wrap`: Going past the max range causes the number to start back at minimum. + * Going below minimum wraps back around to max. + * - `16`: Specify `-16` to detach the UpDown from its Buddy. + * It can now be positioned like a standard control with `W`, `H`, `X`, `Y` options. + * - `0x80`: Removes the 3 digit separator from being being displayed in the Buddy. + * These separators are removed automatically when value is gotten from the UpDown control. + * script retrieves it from the UpDown control itself rather than the buddy control. + * - `Increments`: {@link https://www.autohotkey.com/docs/v2/scripts/index.htm#Custom_Increments_for_UpDown_Controls|Guide to changing UpDown inc/decrementation} + * - `Hexadecimal Format`: To change display to hex, use this UpDown {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|Message}: + * + * UDM_SETBASE := 0x046D, SendMessage(UDM_SETBASE, 16, 0, "msctls_updown321") + * + * **Positioning and Sizing of Controls** + * Use the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Move|Move()} method to change control size/position. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con.Opt('+UDAge') ; Set using v option. Can't include a space + * con.Name := 'UD Age' ; Set using Name property. Can including a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * con.Opt('+Disabled') ; Control disabled + * var := 0 + * con.Opt('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Opt(Options) => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#BackColor|`BackColor`} + * Retrieves or sets the background color of the window. + * When setting BackColor, a string or number can be used: + * - Hex value: String or number. `0x000000` to `0xFFFFFF`. + * If value is a string, the 0x prefix is optional. + * - {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Color name}: Black, Silver, Gray, White, Maroon, Red, Purple, Fuchsia, Green, Lime, Olive, Yellow, Navy, Blue, Teal, Aqua + * - Default color: The word `default` or an empty string. + * When retrieving backcolor, a string containing the hex value of the current color is returned. + * To set the color of a One of the following event(s). Expected callback format is included. method. + * @type Number|String + * @example Changing background color with Drop Down List of colors. + * color_list := ['Default', 'Red','Yellow','Green','Cyan','Blue','Magenta'] + * goo := Gui() + * goo.ddl := goo.AddDDL('xm ym Choose1', color_list) + * goo.ddl.OnEvent('Change', color_change) + * goo.Show('w200 h100') + * + * color_change(con, info) { + * color_map := Map('Red' ,0xFF0000 ,'Yellow',0xFFFF00 ,'Green',0xFF00 + * ,'Cyan',0xFFFF ,'Magenta',0xFF00FF,'Blue',0xFF ) + * color_map.Default := 'Default' + * con.gui.BackColor := color_map[con.Text] + * } + */ + BackColor { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#FocusedCtrl|`FocusedCtrl`} + * Retrieves the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl object} of the Gui's focused control. + * If the window is minimized or hidden, this property may not be effective. + * @type GuiControl + * @example Focusing a specific control. + * goo := Gui() + * goo.btn_exit := goo.AddButton('xm ym w100', 'Exit Script') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * goo.btn_msg := goo.AddButton('xm w100', 'PopUp Msg') + * goo.btn_msg.OnEvent('Click', (*) => MsgBox('Pop Up!')) + * goo.btn_exit.Focus() + * txt := 'Even though "PopUp Msg" was added last, the ' + * . '`nFocused button was set to "' goo.FocusedCtrl.Text '"' + * goo.AddText('xm', txt) + * goo.Show('y200') + */ + FocusedCtrl { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Hwnd|`Hwnd`} + * Retrieves the window handle (HWND) of the GUI window. + * @type Integer + * @example A GUI that can be hidden and shown with F1. + * *F1::toggle_gui() + * + * toggle_gui() + * + * toggle_gui() { + * static goo := make_gui() + * if WinExist('ahk_id ' goo.hwnd) + * goo.Hide() + * else goo.Show() + * return + * + * make_gui() { + * goo := Gui() + * goo.AddText('xm ym w150', 'Press F1 to hide/show GUI.') + * goo.btn_exit := goo.AddButton('xm w150', 'Click to close Script') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * return goo + * } + * } + */ + Hwnd { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#MarginX|`MarginX`} + * Retrieves or sets the size of horizontal margins between sides and subsequently created controls. + * @type Integer + * @example Showing how margin settings affect padding. + * goo := Gui() + * goo.MarginX := 20 + * goo.MarginY := 20 + * loop 9 + * if Mod(A_Index-1, 3) + * goo.AddButton('x+m w100', 'Button ' A_Index) + * else goo.AddButton('xm y+m w100', 'Button ' A_Index) + * goo.Show() + */ + MarginX { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#MarginY|`MarginY`} + * Retrieves or sets the size of vertical margins between sides and subsequently created controls. + * @type Integer + * @example Showing how margin settings affect padding. + * goo := Gui() + * goo.MarginX := 20 + * goo.MarginY := 20 + * loop 9 + * if Mod(A_Index-1, 3) + * goo.AddButton('x+m w100', 'Button ' A_Index) + * else goo.AddButton('xm y+m w100', 'Button ' A_Index) + * goo.Show() + */ + MarginY { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#MenuBar|`MenuBar`} + * Retrieves or sets the window's menu bar. + * This property is not set by default and a {@link |Menu() object} must be created and assigned to it. + * @type MenuBar + * @example Creating a custom GUI menu. + * make_gui() + * + * make_gui() { + * static goo := Gui() + * goo.edit := goo.AddEdit('xm ym r50 w500 -Wrap +HScroll') + * + * m_file := Menu() + * m_file.Add('&Open', get_file) + * m_file.Add() + * m_file.Add('E&xit', (*) => ExitApp()) + * + * m_about := Menu() + * m_about.Add('&Website', (*) => Run('https://www.autohotkey.com')) + * m_about.Add('&Docs', (*) => Run('https://www.autohotkey.com/docs/v2/')) + * m_about.Add('&Version', (*) => MsgBox('AHK Version ' A_AhkVersion)) + * + * gu_menu := MenuBar() + * gu_menu.Add('&File', m_file) + * gu_menu.Add('&About', m_about) + * + * goo.MenuBar := gu_menu + * + * goo.Show('AutoSize') + * return + * + * get_file(name, pos, control) { + * path := FileSelect(,,,'*.txt') + * if FileExist(path) + * goo.edit.Value := FileRead(path) + * } + * } + */ + MenuBar { + get => MenuBar + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Name|`Name`} + * Retrieves or sets a custom name for the GUI window. + * @type String + * @example Setting and retrieving a GUI name. + * goo := Gui() + * goo.Name := 'Main' + * goo.Show('w500 h200') + * MsgBox('Gui name is: ' goo.Name) + */ + Name { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Title|`Title`} + * Retrieves or sets the GUI's title. + * @type String + * @example Make an edit box that lets you change the GUI title. + * goo := Gui() + * goo.AddText('xm ym w400', 'Enter text to change window title:') + * goo.Edit := goo.AddEdit('xm w400 r1 +BackgroundBlack') + * goo.Edit.SetFont('s10 cWhite' ,'Courier New') + * goo.Edit.OnEvent('Change', update_title) + * goo.Show('AutoSize') + * + * update_title(con, info) { + * if (con.Value = '') + * con.gui.title := A_ScriptName + * else con.gui.title := con.Value + * } + */ + Title { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#__Item|`__Item`} + * Is the name of the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl object} associated with the specified {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|name}, {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|text}, {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#ClassNN|ClassNN} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Hwnd|HWND}. + * @type GuiControl + * @example Program closer + * goo := Gui() + * con := goo.AddDropDownList('w250 r10 vDDLProcesses') + * refresh(con) + * + * con := goo.AddButton('xm w80', 'Close') + * con.OnEvent('Click', close_app) + * + * con := goo.AddButton('x+5 w80', 'Refresh') + * con.OnEvent('Click', refresh) + * + * con := goo.AddButton('x+5 w80', 'Exit') + * con.OnEvent('Click', (*) => ExitApp()) + * + * goo.Show() + * + * close_app(btn, info) { + * id := btn.gui['DDLProcesses'].Text + * info := StrSplit(id, ',') + * WinClose('ahk_id ' info[2]) + * } + * + * refresh(con, *) { + * goo := con.Gui + * ddl := goo['DDLProcesses'] + * ddl.Delete() + * + * txt_list := '' + * for hwnd in WinGetList() + * txt_list .= WinGetProcessName('ahk_id ' hwnd) ',' hwnd '`n' + * txt_list := Sort(RTrim(txt_list, '`n'), 'C0') + * + * list := [] + * loop parse txt_list, '`n' + * list.Push(A_LoopField) + * ddl.Add(list) + * ddl.Choose(1) + * } + */ + __Item[Name] => Gui.Control + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|`GUI`} + * Creates a new Gui object. + * @param {String|'AlwaysOnTop'|'Border'|'Caption'|'Disabled'|'DPIScale'|'LastFound'|'MaximizeBox'|'MaxSize'|'MinimizeBox'|'MinSize'|'OwnDialogs'|'Owner'|'Parent'|'Resize'|'SysMenu'|'Theme'|'ToolWindow'} [Options] + * Zero or more Gui options, separated by spaces and/or tabs. + * For best performance, set all options in 1 call and do so before the window is created. + * Use `-` before an option to remove it or `+` to add it. Using no sign is the same as using `+`. + * - `AlwaysOnTop`: Makes the window stay on top of all other windows. Same effect as {@link https://www.autohotkey.com/docs/v2/lib/WinSetAlwaysOnTop.htm|WinSetAlwaysOnTop}. + * - `Border`: Provides a thin-line border around the window. + * - `Caption`: Include the standard title bar and a thick window border/edge. If using {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransColor.htm|WinSetTransColor}, remove Caption only after setting the TransColor. + * - `Disabled`: Disables the window, which prevents the user from interacting with its controls. This is often used on a window that owns other windows (see {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Owner|Owner}). + * - `DPIScale`: If DPI scaling is enabled, coordinates and sizes passed to or retrieved from the Gui and GuiControl methods/properties are automatically scaled based on screen DPI. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScreenDPI|A_ScreenDPI} contains the system's current DPI. + * DPI scaling only applies to the Gui and GuiControl methods/properties, so coordinates coming directly from other sources such as ControlGetPos or WinGetPos will not work. + * - `LastFound`: Sets the window to {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|last found window}. This is done automatically in a GUI thread to allow functions such as {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|WinGetStyle} and {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransparent.htm|WinSetTransparent} to operate on it even if it is hidden. + * - `MaximizeBox`: Enables the maximize button in the title bar. This is included when the Resize option is used. + * - `MinimizeBox`: Enables the minimize button in the title bar. + * - `MaxSize` or `MinSize`: Set, adjust, or remove the minimum/maximum size of the client area of the window, such as when the user drags its edges to resize it. + * `+MaxSize`/`+MinSize` uses the current window size as the maximum/minimum. + * Alternatively, `+MaxSize640x480`/`+MinSize640x480` would set the max/min size to 640 pixels wide by 480 pixels tall and the width or height may be omitted, though the `x` separator must always be present. + * - `OwnDialogs`: Should be specified in each thread for which subsequently displayed MsgBox, InputBox, FileSelect, and DirSelect dialogs should be owned by the window. + * These dialogs become modal, meaning that the user cannot interact with the Gui until the dialog box is dismissed. + * ToolTip cannot become modal even though they become owned. Instead, they will stay always on top of the owner. + * - `Owner`: Causes the window to be owned by another. Include the handle (HWND) to another window after the word owner to make the Gui owned by that Window. + * Omitting a handle (HWND) will make the Gui owned by the script's main window. + * - `Parent`: Use `+Parent` immediately followed by the handle (HWND) of any window or control to use it as the parent of this window while `-Parent` will revert it back to a top-level window. + * - `Resize`: Makes the window resizable and enables its maximize button in the title bar. The maximize button can be removed with `-MaximizeBox`. + * - `SysMenu`: Adds or removes the system menu and icon in the window's upper left corner. This includes the minimize, maximize, and close buttons in the title bar. + * - `Theme`: If `-Theme` is used, all subsequently created controls in the window will have the Classic Theme appearance. + * Theme can also be used in a control's options during its creation such as `g.AddButton('-Theme')`. + * - `ToolWindow`: Provides a narrower title bar, removes the taskbar button, and hides both the maximize and minimize buttons. + * - `0x0` Unnamed Style: Specify a plus or minus sign followed immediately by a decimal or hexadecimal style number. + * - `E0x0` Unnamed ExStyle: Specify a plus or minus sign followed immediately by the letter E and a decimal or hexadecimal extended style number. For styles not {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|documented here}, see {@link https://learn.microsoft.com/windows/win32/winmsg/extended-window-styles|Extended Window Styles | Microsoft Docs} for a complete list. + * @param {(String)} [Title] + * The window title. If omitted, it defaults to the current value of {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptName|A_ScriptName}. + * @param {(Object)} [EventObj] + * An "event sink", or object to bind events to. + * If EventObj is specified, {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|OnEvent()} + * , {@link https://www.autohotkey.com/docs/v2/lib/GuiOnNotify.htm|OnNotify()} + * , and {@link https://www.autohotkey.com/docs/v2/lib/GuiOnCommand.htm|OnCommand()} + * can be used to register methods of EventObj to be called when an event is raised. + * If omitted or empty, any string passed to OnEvent's Function parameter is interpreted as a function name. + * @returns {(Gui)} + * New gui object + * @example Basic GUI example. + * goo := Gui() + * goo.btn_exit := goo.AddButton('xm ym w100', 'Exit Script') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * goo.Show('AutoSize') + */ + Static Call([Options:='', Title:=A_ScriptName, EventObj:=unset]) => Gui + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`Add()`} + * Creates and adds a control to the Gui, such as text, a button, or a checkbox. + * Each control type has it's own `AddType()` function such as `AddButton()` or `AddText()`. + * @param {'ActiveX'|'Button'|'Checkbox'|'ComboBox'|'Custom'|'DateTime'|'DDL'|'DropDownList'|'Edit'|'GroupBox'|'Hotkey'|'Link'|'ListBox'|'ListView'|'MonthCal'|'Pic'|'Picture'|'Progress'|'Radio'|'Slider'|'StatusBar'|'Tab'|'Tab2'|'Tab3'|'Text'|'TreeView'|'UpDown'} ControlType + * One of the following control types: + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ActiveX|`ActiveX`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Button|`Button`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Checkbox|`Checkbox`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ComboBox|`ComboBox`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Custom|`Custom`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DateTime|`DateTime`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DropDownList|`DDL` / `DropDownList`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Edit|`Edit`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#GroupBox|`GroupBox`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Hotkey|`Hotkey`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Link|`Link`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ListBox|`ListBox`} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm|`ListView`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#MonthCal|`MonthCal`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Picture|`Pic` / `Picture`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Progress|`Progress`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Radio|`Radio`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Slider|`Slider`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#StatusBar|`StatusBar`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab|`Tab` / `Tab2` / `Tab2`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Text|`Text`} | + * {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm|`TreeView`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#UpDown|`UpDown`} + * @param {String|'AltSubmit'|'Background'|'BackgroundTrans'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows. This number can be a float. `r` takes precedence over `h`. + * - GroupBox = The number of controls to vertically accommodate. + * - DDL, ComboBox, Listbox = Number of items shown in the list at any given time. + * - All other controls = The number of rows of text that can visibly fit in the control. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con := goo.Add('Button', '+vExitBtn') ; Set using v option. Can't include a space + * con.Name := 'Exit Btn' ; Set using Name property. Can including a space + * - `AltSubmit`: Use control's alternate submit method. + * DropDownList, ComboBox, ListBox, Tab: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} uses selected item's position instead of its text. + * ComboBox: If no item is selected, the text of the edit field is instead stored. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * This option does not affect {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Button|buttons} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#StatusBar|status bars}. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.Add('Button', 'cRed') + * goo.Add('Button', 'cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed immediately by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.Add('Button', '+Disabled') + * var := 1 + * goo.Add('Button', 'Disabled' var) + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed immediately by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * Applies to: Button, Checkbox, DateTime, Edit, GroupBox, Radio, Slider, Tab, Tab2, Text, UpDown + * - `Right`: Right justify control text within its available width. + * Checkbox and Radio Buttons have their box moved to the right side of the control. + * Applies to: Button, Checkbox, DateTime, Edit, GroupBox, Link, Radio, Slider, Tab, Tab2, Text, UpDown + * - `Center`: Center justify control text within its available width. + * Applies to: Button, Checkbox, Edit, GroupBox, Radio, Slider, Text + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the Picture to show through. Use `+Background` to remove this option later. + * Applies to: Text, Picture, GroupBox + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.Add('Button', 'BackgroundNavy') + * goo.Add('Button', 'Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String|Number|Array)} [ControlSpecific] + * Control specific setting. + * @returns {(GuiControl)} + * GuiControl Object + * @example Adding an exit button to a GUI. + * goo := Gui() + * btn := goo.Add('Button', 'xm ym w100', 'Exit Script') + * btn.OnEvent('Click', (*) => ExitApp()) + * goo.Show('AutoSize') + */ + Add(ControlType [,Options:='', ControlSpecific:=unset]) => Gui.Control + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddActiveX()`} + * Adds an ActiveX control to the Gui. + * When the control is created, the ActiveX object can be retrieved via GuiCtrl.Value + * @param {String|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con := goo.AddActiveX('+vAXMain') ; Set using v option. Can't include a space + * con.Name := 'AX Main' ; Set using Name property. Can including a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed immediately by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddActiveX('+Disabled') + * var := 1 + * goo.AddActiveX('Disabled' var) + * - `Hidden`: The control is initially invisible. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * @param {(String)} [ActiveXName] + * The ActiveX component name to add. + * @returns {(Gui.ActiveX)} + * ActiveX Control Object + * @see {@link https://learn.microsoft.com/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752085(v=vs.85)|WebBrowser Object} + * @example Adding an ActiveX control to a GUI. + * goo := Gui() + * goo.MarginX := goo.MarginY := 0 + * goo.web := goo.AddActiveX("x0 y0 w1024 h768", "Shell.Explorer") + * ; The ActiveX object is stored in the 'value' property + * goo.web.value.Navigate("https://www.autohotkey.com/docs/v2/index.htm") + * goo.Show() + */ + AddActiveX([Options:='', ActiveXName:=unset]) => Gui.ActiveX + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddButton()`} + * Adds a push button, which can be pressed to trigger an action. + * @param {String|'Default'|'Border'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Default`: Causes this button to be the default button. + * The default button is the button that's activated when the user presses "Enter". + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * con := goo.AddButton('+vExitBtn') ; Set using v option. Can't include a space + * con.Name := 'Exit Btn' ; Set using Name property. Can including a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed immediately by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddButton('+Disabled') + * var := 1 + * goo.AddButton('Disabled' var) + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed immediately by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * @param {(String)} [BtnText] + * Text on buttons can include new lines `` `n ``. + * An ampersand `&` before a letter in the text causes `Alt` plus that letter to become a shortcut. + * To include a literal ampersand, use 2 ampersands in a row `&&`. + * @returns {(Gui.Button)} + * Button Control Object + * @example Adding an exit button to a GUI. + * goo := Gui() + * goo.btn_exit := goo.AddButton('xm ym w100 h40', 'Exit`nScript') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * goo.Show('AutoSize') + */ + AddButton([Options:='', BtnText:='']) => Gui.Button + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddCheckbox()`} + * Adds a Checkbox control that can be checked or unchecked to represent a toggle-able state. + * If the {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#CheckBox|Check3} option is used, checkboxes have a 3rd "graycheck" state. + * @param {String|'Check3'|'Checked'|'CheckedGray'|'Background'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Check3`: Adds a 3rd "indeterminate" gray checkmark state to the checkbox. + * This can be used to indicate a 3rd check stat, such as a "maybe", "indeterminate", or "both" type of state. + * - `Checked` or `CheckedGray`: Starts the checkbox checked or checked grey/indeterminate. + * `Checked` may also be followed by a 0 (unchecked), 1 (checked), or -1 (gray checked). + * + * goo.AddCheckBox('+Checked0') + * var := 1, goo.AddCheckBox('+Checked' var) + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddCheckBox('+vCbOption') ; Set using v option. Can't include a space + * con.Name := 'Cb Option' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddCheckBox('cRed') + * goo.AddCheckBox('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddCheckBox('+Disabled') ; Control disabled + * var := 0 + * goo.AddCheckBox('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * The box will also be moved to the right side of the control. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.Add('Button', 'BackgroundNavy') + * goo.Add('Button', 'Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Label] + * Label to display next to the checkbox. Can include linefeeds `` `n ``. + * @returns {(Gui.Checkbox)} + * Checkbox Control Object + * @example Make a checkbox to enable/disable a control. + * goo := Gui() + * goo.cb_lock := goo.AddCheckbox('xm ym w200 Checked', 'Disable close button') + * goo.cb_lock.OnEvent('Click', toggle_lock) + * goo.btn_exit := goo.AddButton('xm w200 Disabled', 'Close') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * goo.Show('AutoSize') + * + * toggle_lock(ctrl, info) { + * ctrl.gui.btn_exit.Enabled := !ctrl.Value + * } + */ + AddCheckbox([Options:='', Label:='']) => Gui.Checkbox + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddCustom()`} + * Add a custom control that is not directly supported by AutoHotkey. + * To do so, include the word "Class" followed by the {@link https://learn.microsoft.com/en-us/windows/win32/controls/individual-control-info|Win32 class name} of the desired control in the options field. + * @param {String|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddCustom('+vcustCon') ; Set using v option. Can't include a space + * con.Name := 'Cust Con' ; Set using Name property. Can including a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddCustom('+Disabled') ; Control disabled + * var := 0 + * goo.AddCustom('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * @param {(String)} [ControlSpecific] + * @returns {(Gui.Custom)} + * Custom Control Object + * @example Adding a ComboBoxEx to a GUI. + * goo := Gui() + * goo.ComboBoxEx := goo.AddCustom('ClassComboBoxEx32') + * goo.Show('AutoSize') + */ + AddCustom([Options:='', ControlSpecific:='']) => Gui.Custom + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddDateTime()`} + * Adds a DateTime control to the Gui that provides a single-lined control for the date and/or time along with a calendar dropdown button. + * @param {String|'Choose'|'ChooseNone'|'Range'|'1'|'2'|'Colors'|'Background'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose`: Pre-select a date or time other than the current date/time. + * Choose should be followed by a DTS in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHHMISS format}. + * When setting the time, the full date and time must be provided. + * `ChooseNone` adds a checkbox to toggle usable state (similar to a checkbox greycheck). + * - `RangeMIN-MAX`: Sets how far back or forward you can set the DateTime control. + * MIN and MAX should be dates. Omitting one leaves that side of the range unrestricted. + * + * goo.AddDateTime('Range20220101-20221231') + * goo.AddDateTime('Range-20250101115959') + * - `Right`: Right edge of drop-down calendar aligns with the right side of the control. + * - `Left`: Left edge of drop-down calendar aligns with the left side of the control. + * - `1`: Provide an up-down control to the right of the control to modify date-time values. + * This replaces the button of the drop-down month calendar. Does not work with the `LongDate` option. + * - `2`: Provide a checkbox inside the control, similar to `CheckNone`. + * When unchecked, the control is greyed out and indicates no date/time is selected. + * This option cannot be added or removed after the control is created. + * - `Colors`: Day number colors inside the drop-down calendar obey {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#SetFont|Gui.SetFont()} or the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|C option'}. + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddDateTime('+vDTMain') ; Set using v option. Can't include a space + * con.Name := 'DT Main' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddDateTime('cRed') + * goo.AddDateTime('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddDateTime('+Disabled') ; Control disabled + * var := 0 + * goo.AddDateTime('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddDateTime('BackgroundNavy') + * goo.AddDateTime('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [DateFormat] + * Sets the desired {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DateTimeFormat|display format} of a DateTime control. + * - `ShortDate`: Locale short date format. Example: 6/1/2005 + * - `LongDate`: Locale long date format. Example: Wednesday, June 01, 2005 + * - `Time`: Shows locale time only. Example: 9:37:45 PM + * The date is still present in the control even though it's not shown. + * It will be retrieved along with the time in the YYYYMMDDHH24MISS format. + * - `Custom`: Any combination of {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|date and time formats}. + * @returns {(Gui.DateTime)} + * DateTime Control Object + * @example Adding a DateTime control set to v2's release date. + * goo := Gui() + * goo.date := goo.AddDateTime('xm ym choose20221220021600', 'LongDate') + * goo.date := goo.AddDateTime('xm', "'Date:' MM/dd/yy 'Time:' hh:mm:ss tt") + * goo.Show('AutoSize') + */ + AddDateTime([Options:='', DateFormat:='ShortDate']) => Gui.DateTime + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddEdit()`} + * Adds a control that provides a free-form text area for the user to type in. + * @param {String|'Limit'|'Lowercase'|'Multi'|'Number'|'Password'|'ReadOnly'|'T'|'Uppercase'|'WantCtrlA'|'WantReturn'|'WantTab'|'AltSubmit'|'Background'|'BackgroundTrans'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Limit`: Restricts input to the visible width of the edit field. + * - `Limit#`: Set the character limit of the control where `#` is the limit number. + * - `Lowercase`: The characters typed by the user are automatically converted to lowercase. + * - `Multi`: Allows more than one line of text. + * - `Number`: Allows only digits to be typed into the edit field. Non-digits can still be pasted in. + * Attaching an {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#UpDown|UpDown} control also forces +Number. + * - `Password`: Hides the user input of a single-lined edit control. + * To change the masking character, include the new mask char immediately after password: + * + * goo.AddEdit('+Password*') ; AutoHotkey = ********** + * goo.AddEdit('+Password#') ; AutoHotkey = ########## + * - `ReadOnly`: Prevent the user from changing the control's contents, but text can still be copied. + * - `T#`: Set tab stop distance where `#` is the amount of {@link https://learn.microsoft.com/en-us/previous-versions/windows/desktop/bb226789(v=vs.85)|dialog units} to use (a unit determined by the OS). + * A single tab stop sets the default tab distance. Default value is 32. + * Multiple tab stops (up to 50) can be set to define where each tab should go to. + * + * goo.AddEdit('T5') + * goo.AddEdit('T10 T20 T50 T100') + * - `Uppercase`: Convert all characters in the control to uppercase. + * - `WantCtrlA`: Allow Ctrl+A to highlight all text or `-WantCtrlA` to disable it. + * - `WantReturn`: Allows Enter to create a new line. + * `-WantReturn` causes Enter will activate the Gui's default control. + * New lines can still be added by using Ctrl+Enter. + * - `WantTab`: If enabled, Tab produces a tab character otherwise tab navigates to the next control. + * In a multiline tab, a tab can still be produced with Ctrl+Tab. + * - `Wrap`: Enables word-wrapping in a multi-line edit control. + * This style cannot be changed after the control has been created. + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddEdit('+vEdtMain') ; Set using v option. Can't include a space + * con.Name := 'Edt Main' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddEdit('cRed') + * goo.AddEdit('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddEdit('+Disabled') ; Control disabled + * var := 0 + * goo.AddEdit('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddEdit('BackgroundNavy') + * goo.AddEdit('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Text] + * The initial text of the control. + * @returns {(Gui.Edit)} + * Edit Control Object + * @example Make an edit box that lets you change the GUI title. + * goo := Gui() + * goo.AddText('xm ym w400', 'Enter text to change window title:') + * goo.Edit := goo.AddEdit('xm w400 r1 +BackgroundBlack') + * goo.Edit.SetFont('s10 cWhite' ,'Courier New') + * goo.Edit.OnEvent('Change', update_title) + * goo.Show('AutoSize') + * + * update_title(con, info) { + * if (con.Value = '') + * con.gui.title := A_ScriptName + * else con.gui.title := con.Value + * } + */ + AddEdit([Options:='', Text:='']) => Gui.Edit + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddGroupBox()`} + * Adds a rectangular border/frame control that can be labeled and used to group related controls. + * @param {String|'Background'|'BackgroundTrans'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'Left'|'r'|'Redraw'|'Right'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * - `r#`: The number of controls to vertically accommodate where `#` is the total controls. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddGroupBox('+vGBRadio') ; Set using v option. Can't include a space + * con.Name := 'GB Radio' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddGroupBox('cRed') + * goo.AddGroupBox('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddGroupBox('+Disabled') ; Control disabled + * var := 0 + * goo.AddGroupBox('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the GroupBox to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddGroupBox('BackgroundNavy') + * goo.AddGroupBox('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Label] + * The text label to display at the top of the GroupBox. + * @returns {(Gui.GroupBox)} + * GroupBox Control Object + * @example Create a GUI that toggles AlwaysOnTop. + * goo := Gui() + * goo.gb_radio := goo.AddGroupBox('xm ym w160 Section Center', 'Set AlwaysOnTop:') + * goo.rad_on := goo.AddRadio('xs+10 ys+25 w60', 'Enable') + * goo.rad_on.OnEvent('Click', set_aot) + * goo.rad_off := goo.AddRadio('x+20 w60 Right', 'Disable') + * goo.rad_off.OnEvent('Click', set_aot) + * goo.Show('AutoSize') + * + * set_aot(control, info) { + * if (control.Text = 'Enable') + * control.gui.Opt('+AlwaysOnTop') + * else control.gui.Opt('-AlwaysOnTop') + * } + */ + AddGroupBox([Options:='', Label:='']) => Gui.GroupBox + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddHotkey()`} + * Adds a Hotkey control to the Gui that looks similar to an edit control but will detect and show what keys are being pressed. + * @param {String|'Limit'|'Background'|'Border'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'Wrap'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Limit#`: Restrict the types of hotkeys the user can enter where `#` is one of the following: + * - 1: Prevent unmodified keys + * - 2: Prevent Shift-only keys + * - 4: Prevent Ctrl-only keys + * - 8: Prevent Alt-only keys + * - 16: Prevent Shift+Ctrl keys + * - 32: Prevent Shift+Alt keys + * - 64: Not supported (will not behave correctly) + * - 128: Prevent Shift+Ctrl+Alt keys + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddHotkey('+vHKExit') ; Set using v option. Can't include a space + * con.Name := 'HK Exit' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddHotkey('cRed') + * goo.AddHotkey('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddHotkey('+Disabled') ; Control disabled + * var := 0 + * goo.AddHotkey('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddHotkey('BackgroundNavy') + * goo.AddHotkey('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [DefaultKey] + * A string in {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Hotkey Format}. See {@link https://www.autohotkey.com/docs/v2/KeyList.htm|key list} for key names. + * The only supported modifiers are `+` Shift, `!` Alt, and `^` Control. + * + * @returns {(Gui.Hotkey)} + * Hotkey Control Object + * @example Use Hotkey control to create a GUI close hotkey. + * goo := Gui() + * goo.AddText('xm ym', 'Set a hotkey to close script:') + * goo.Hotkey_Close := goo.AddHotkey('xm', '^+F1') + * goo.Button_Set := goo.AddButton('xm', 'Set') + * goo.Button_Set.OnEvent('Click', create_hotkey) + * goo.Show() + * + * create_hotkey(*) => Hotkey(goo.Hotkey_Close.Value, (*) => ExitApp()) + */ + AddHotkey([Options:='', DefaultKey:='']) => Gui.Hotkey + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddLink()`} + * Adds a text control that accepts hyperlinks. + * Use {@link https://www.w3schools.com/tags/tag_a.asp|HTML anchor tags ``} to create a hyperlink. + * `Google Search` + * @param {String|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Right'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddLink('+vLnkV2Docs') ; Set using v option. Can't include a space + * con.Name := 'Lnk V2 Docs' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddLink('cRed') + * goo.AddLink('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddLink('+Disabled') ; Control disabled + * var := 0 + * goo.AddLink('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Right`: Right justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the Picture to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddLink('BackgroundNavy') + * goo.AddLink('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Text] + * Text to include along with any HTML anchor tags to create the link. + * @returns {(Gui.Link)} + * Link Control Object + * @example Adding text with a hyperlink to a GUI. + * goo := Gui() + * urlV1 := 'https://www.autohotkey.com/docs/v1/' + * urlV2 := 'https://www.autohotkey.com/docs/v2/' + * goo.AddLink('xm ym', 'Link to ' make_url_tag(urlV1, 'v1 Docs') + * . '`nAnd the ' make_url_tag(urlV2, 'v2 Docs')) + * goo.Show('w200 h100') + * + * make_url_tag(url, text) => '' text '' + */ + AddLink([Options:='', Text:='']) => Gui.Link + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddListView()`} + * Adds an elaborate control that handles + * rows and columns of information in a grid. Similar to Windows Explorer in Detail View mode. + * @param {String|'Checked'|'Count'|'Grid'|'Hdr'|'Multi'|'NoSortHdr'|'NoSort'|'ReadOnly'|'Sort'|'SortDesc'|'WantF2'|'Icon'|'Tile'|'IconSmall'|'List'|'Report'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'V'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Checked`: Each row has a checkbox to the left side. + * When adding rows, include the word {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm#Check|Check} in its options to check it. + * - `Count#`: Specify an initial amount of rows where `#` is the starting amount. `Count20` + * Using this option increases performance by preventing multiple row addition calls. + * - `Grid`: Provides visual horizontal and vertical boundaries between rows and columns. + * - `Hdr`: To hide the header, use `-Hdr`. + * To make the header visible hte '+Hdr' option. + * - `Multi`: Specify `-Multi` to prevent the user from selecting more than one row at a time. + * - `NoSortHdr`: Makes header unclickable and take on a flat appearance. + * This cannot be changed after the ListView is created. + * - `NoSort`: Turns off automatic sorting on column header click. + * The header still behaves like a button and allows the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ColClick|ColClick event} + * to be raised and allowing for custom sorting or other actions. + * - `ReadOnly`: Using `-ReadOnly` allows the first column to be editable. + * The label can be edited with F2 (see {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#WantF2|WantF2}) or by clicking the label, + * waiting a brief moment, then clicking again. + * - `Sort`: The control is sorted alphabetically by first column contents. + * - `SortDesc`: The control is sorted in reverse alphabetical order by first column contents. + * - `WantF2`: Specify `-WantF2` to prevent F2 from editing the current selected item. WantF2 only works if `-ReadOnly` is also in effect. + * + * **View Modes** + * You can include one of five view modes. The default, and most common view, is `Report`. + * - `Icon`: Shows a large-icon view. In this view and all the others except Report, the text in columns other than the first is not visible. To display icons in this mode, the ListView must have a large-icon ImageList assigned to it. + * - `Tile`: Shows a large-icon view but with ergonomic differences such as displaying each item's text to the right of the icon rather than underneath it. Checkboxes do not function in this view. + * - `IconSmall`: Shows a small-icon view. + * - `List`: Shows a small-icon view in list format, which displays the icons in columns. The number of columns depends on the width of the control and the width of the widest text item in it. + * - `Report`: Switches back to report view, which is the initial default. For example: LV.Opt("+Report"). + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of height at creation, where # is the the number of rows that should be inside the control. + * If the ListView is created with a view mode other than report view, the control is sized to fit rows of icons instead of rows of text. + * Adding icons to a ListView's rows will increase the height of each row, which will make this option inaccurate. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddListView('+vLV') ; Set using v option. Can't include a space + * con.Name := 'LV' ; Set using Name property. Can including a space + * - `AltSubmit`: Use control's alternate submit method. + * DropDownList, ComboBox, ListBox, Tab: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} uses selected item's position instead of its text. + * ComboBox: If no item is selected, the text of the edit field is instead stored. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddListView('cRed') + * goo.AddListView('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddListView('+Disabled') ; Control disabled + * var := 0 + * goo.AddListView('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddListView('BackgroundNavy') + * goo.AddListView('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(Array)} [ColumnTitles] + * An array of strings to use as the title/header for each column. + * @returns {(Gui.ListView)} + * ListView Control Object + * @example Create ListView from script folder files. + * goo := Gui() + * lv := goo.AddListView('xm ym w800 h400', ['Name', 'Dir', 'Extension']) + * loop files A_ScriptDir '\*.*' + * lv.Add('', A_LoopFileName, A_LoopFileDir, A_LoopFileExt) + * + * lv.ModifyCol() + * + * goo.Show() + */ + AddListView([Options:='', ColumnTitles:=Array]) => Gui.ListView + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddMonthCal()`} + * Adds a tall and wide control that displays all the days of the month in calendar format. + * The user may select a single date or a range of dates. + * @param {String|'Multi'|'Range'|'4'|'8'|'16'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Multi`: Allows multi-select range with shift-click or click-drag to select a range of adjacent dates. + * This option is forced when the control is created with the `Range` option. + * Once the control is created, this option cannot be altered. + * - `RangeMIN-MAX`: Sets how far back or forward you can set the DateTime control. + * MIN and MAX should be dates. Omitting one leaves that side of the range unrestricted. + * + * goo.AddMonthCal('Range20220101-20221231') + * goo.AddMonthCal('Range-20250101115959') + * - `4`: Display week numbers (1-52) to the left of each row of days. + * Week 1 is defined as the first week that contains at least four days. + * - `8`: Prevent the circling of today's date within the control. + * - `16`: Prevent the display of today's date at the bottom of the control. + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddMonthCal('+vMCMain') ; Set using v option. Can't include a space + * con.Name := 'MC Main' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddMonthCal('cRed') + * goo.AddMonthCal('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddMonthCal('+Disabled') ; Control disabled + * var := 0 + * goo.AddMonthCal('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddMonthCal('BackgroundNavy') + * goo.AddMonthCal('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(Integer)} [Date] + * Set the highlighted date. + * @returns {(Gui.MonthCal)} + * MonthCal Control Object + * @example Adding a Month Calendar to a GUI. + * goo := Gui() + * goo.txt := goo.AddText('xm ym', 'Hold shift or control to select a range of dates:') + * goo.Cal := goo.AddMonthCal('xm Multi', 20221220) + * goo.Show('AutoSize') + */ + AddMonthCal([Options:='', Date:=A_Now]) => Gui.MonthCal + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddPic()`} + * Adds control containing an image. + * Types: `ICO`,`CUR`,`ANI`,`EXE`,`DLL`,`CPL`,`SCR`,`PNG`,`TIF`,`Exif`,`WMF`,`EMF`, Other Icon Resources + * GDIPlus (AltSubmit): `GIF`,`JPG`,`BMP`,`ICO`,`CUR`,`ANI`,`PNG`,`TIF`,`Exif`,`WMF`,`EMF` + * @param {String|'Icon'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Icon#`: Use a specific icon from an icon group where # is the number of the icon. + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddPic('+vPicLogo') ; Set using v option. Can't include a space + * con.Name := 'Pic Logo' ; Set using Name property. Can including a space + * - `AltSubmit`: Use Microsoft's GDIPlus.dll to load the image. + * This might result in a different appearance for GIF, BMP, and icon images. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddPic('cRed') + * goo.AddPic('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddPic('+Disabled') ; Control disabled + * var := 0 + * goo.AddPic('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the Picture to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddPic('BackgroundNavy') + * goo.AddPic('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Path] + * Path to the image file. + * If a full path isn't provided, {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir} is used as the starting directory. + * @returns {(Gui.Pic)} + * Picture Control Object + * @example Using picture controls to view AHK's 5 built-in icons. + * ; Adding AHK's tray icons to a GUI + * goo := Gui() + * loop 5 + * goo.AddPic('ym Icon' A_Index, A_AhkPath) + * goo.Show() + */ + AddPic([Options:='', Path:=A_WorkingDir]) => Gui.Pic + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddPicture()`} + * Adds control containing an image. + * Types: `ICO`,`CUR`,`ANI`,`EXE`,`DLL`,`CPL`,`SCR`,`PNG`,`TIF`,`Exif`,`WMF`,`EMF`, Other Icon Resources + * GDIPlus (AltSubmit): `GIF`,`JPG`,`BMP`,`ICO`,`CUR`,`ANI`,`PNG`,`TIF`,`Exif`,`WMF`,`EMF` + * @param {String|'Icon'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Icon#`: Use a specific icon from an icon group where # is the number of the icon. + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddPicture('+vPicLogo') ; Set using v option. Can't include a space + * con.Name := 'Pic Logo' ; Set using Name property. Can including a space + * - `AltSubmit`: Use Microsoft's GDIPlus.dll to load the image. + * This might result in a different appearance for GIF, BMP, and icon images. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddPicture('cRed') + * goo.AddPicture('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddPicture('+Disabled') ; Control disabled + * var := 0 + * goo.AddPicture('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the Picture to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddPicture('BackgroundNavy') + * goo.AddPicture('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Path] + * Path to the image file. + * If a full path isn't provided, {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir} is used as the starting directory. + * @returns {(Gui.Pic)} + * Picture Control Object + * @example Using picture controls to view AHK's 5 built-in icons. + * ; Adding AHK's tray icons to a GUI + * goo := Gui() + * loop 5 + * goo.AddPicture('ym Icon' A_Index, A_AhkPath) + * goo.Show() + */ + AddPicture([Options:='', Path:=A_WorkingDir]) => Gui.Pic + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddProgress()`} + * Adds a dual-color bar that can progress from empty to full to indicate a filled range. + * Commonly used to show the completion status of an operation. + * @param {String|'Range'|'Smooth'|'Vertical'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `RangeMIN-MAX`: Sets the minimum and maximum ends of the progress bar. Default is `Range0-100`. + * - `Smooth`: Displays a simple, continuous bar. + * - `Vertical`: Makes the bar rise or fall vertically rather than horizontally. + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddProgress('+vPBarDownload') ; Set using v option. Can't include a space + * con.Name := 'PBar Download' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddProgress('cRed') + * goo.AddProgress('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddProgress('+Disabled') ; Control disabled + * var := 0 + * goo.AddProgress('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddProgress('BackgroundNavy') + * goo.AddProgress('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String|Number)} [StartingPos] + * Sets the starting position of the progress bar. + * If omitted, it starts as close to 0 as the control allows. + * @returns {(Gui.Progress)} + * Progress Control Object + * @example Using a Progress Bar to simulate a loading bar. + * goo := Gui() + * goo.btn := goo.AddButton('xm ym w100 h30 Center', 'Start') + * goo.btn.OnEvent('Click', btn_click) + * goo.prog_bar := goo.AddProgress('x+5 w300 h30 cLime +BackgroundBlack Smooth') + * goo.Show() + * + * btn_click(btn, info) { + * switch btn.Text { + * case 'Finished!': ExitApp() + * case 'Start': fill_bar(btn.gui) + * } + * } + * + * fill_bar(goo) { + * goo.prog_bar.Value += Random(2, 10) + * if (goo.prog_bar.Value < 100) + * goo.btn.Text := goo.prog_bar.Value '%' + * ,callback := fill_bar.Bind(goo) + * ,SetTimer(callback, -400) + * else goo.btn.Text := 'Finished!' + * } + */ + AddProgress([Options:='', StartingPos:=0]) => Gui.Progress + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddRadio()`} + * Adds a small button that can be clicked. + * Radio buttons are added in groups and only 1 button in the group can be active at a time. + * @param {String|'Checked'|'Group'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Left'|'Right'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Checked`: Starts the button in the checked/on state. + * - `Group`: Starts a new radio group. A new group is automatically started when a non-radio control is added. + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddRadio('+vRadToggle') ; Set using v option. Can't include a space + * con.Name := 'Rad Toggle' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddRadio('cRed') + * goo.AddRadio('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddRadio('+Disabled') ; Control disabled + * var := 0 + * goo.AddRadio('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * The radio button will also be moved to the right side of the control. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddRadio('BackgroundNavy') + * goo.AddRadio('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Label] + * Text label to show next to the button. + * Text appears left of the control when the `Right` option is being used. + * @returns {(Gui.Radio)} + * Radio Control Object + * @example Add a radio button that switches background colors. + * goo := Gui() + * goo.BackColor := 0x40FF00 + * goo.rad_g := goo.AddRadio('xm w150 v0x40FF00', 'Green') + * goo.rad_g.OnEvent('Click', color_change) + * goo.rad_y := goo.AddRadio('xm w150 v0xFFFF00', 'Yellow') + * goo.rad_y.OnEvent('Click', color_change) + * goo.Show('AutoSize') + * + * color_change(con, inf) => con.gui.BackColor := con.Name + */ + AddRadio([Options:='', Label:='']) => Gui.Radio + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddSlider()`} + * Adds a sliding bar (Trackbar) the user can move + * along a vertical or horizontal track to adjust values between a defined range. + * Window's volume bar is an example of a commonly used slider. + * @param {String|'Buddy1'|'Buddy2'|'Invert'|'NoTicks'|'Line'|'Page'|'Range'|'Thick'|'TickInterval'|'ToolTip'|'ToolTipLeft'|'ToolTipRight'|'ToolTipTop'|'ToolTipBottom'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Left'|'Right'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * **Control Specific Options** + * - `Buddy1#` and `Buddy2#`: Specify controls to automatically reposition + * at the ends of the slider, where `#` is the name or HWND of the control. + * The {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|control Text} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#ClassNN|ClassNN} can also be used, but only up to the first space or tab. + * Buddy1 appears left/top of the slider and Buddy2 appears right/bottom of it. + * - `Invert`: Reverses the slider direction. Low goes on the right/bottom and high on the left/top. + * This option will not work with the `ToolTip` option. + * - `Left`: The slider (thumb) will point upward, or to the left if `Vertical`. + * - `Center`: The slider (thumb) is blunt on both ends instead of pointed at one end. + * - `Right`: The slider (thumb) will point downward, or to the right if `Vertical`. + * - `NoTicks`: Omit tickmarks alongside the slider track. + * - `Line#`: Distance to move when an arrow key is pressed, where `#` is the number of positions. + * - `Page#`: Distance to move when PgUp\PgDn is pressed, where `#` is the number of positions. + * - `RangeMIN-MAX`: Set slider value range, where `MIN` is the minimum and `MAX` is the maximum. + * Default is `Range0-100`. + * - `Thick#`: Set slider (thumb) thickness where `#` is pixels. + * - `TickInterval#`: Add marks along the track where `#` is how often each tick should show. + * - `ToolTip`: When dragging the thumb, the current value is shown in a tooltip. + * To adjust tooltip position, use `ToolTipTop`, `ToolTipBottom`. + * `ToolTipLeft`, `ToolTipRight` are used with `Vertical` sliders. + * This option does not work with the `Invert` option. + * + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddSlider('+vSldVolume') ; Set using v option. Can't include a space + * con.Name := 'Sld Volume' ; Set using Name property. Can including a space + * - `AltSubmit`: While dragging the slider (thumb), the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Change|`change event`} fires continuously. + * Normally, the change event only fires on mouse release. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddSlider('cRed') + * goo.AddSlider('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddSlider('+Disabled') ; Control disabled + * var := 0 + * goo.AddSlider('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * Applies to: Button, Checkbox, DateTime, Edit, GroupBox, Radio, Slider, Tab, Tab2, Text, UpDown + * - `Right`: Right justify control text within its available width. + * Checkbox and Radio Buttons have their box moved to the right side of the control. + * Applies to: Button, Checkbox, DateTime, Edit, GroupBox, Link, Radio, Slider, Tab, Tab2, Text, UpDown + * - `Center`: Center justify control text within its available width. + * Applies to: Button, Checkbox, Edit, GroupBox, Radio, Slider, Text + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddSlider('BackgroundNavy') + * goo.AddSlider('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [StartingPos] + * Sets the starting position of the slider bar. + * @returns {(Gui.Slider)} + * Slider Control Object + * @example Creating a volume slider GUI. + * goo := Gui() + * start_vol := SoundGetVolume() + * goo.AddText('xm ym w100', 'Volume Slider:') + * goo.txt_vol := goo.AddText('x+10', Round(start_vol)) + * goo.sld_vol := goo.AddSlider('xm w200 AltSubmit Range0-100 cRed', start_vol) + * goo.sld_vol.OnEvent('Change', vol_adjust) + * goo.Show('AutoSize') + * + * vol_adjust(control, *) { + * SoundSetVolume(control.Value) + * control.gui.txt_vol.Value := control.Value + * } + */ + AddSlider([Options:='', StartingPos:=0]) => Gui.Slider + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddStatusBar()`} + * Adds a row of text and/or icons to the bottom + * of a window and typically reports conditions and information about the GUI. + * @param {String|'Background'|'Border'|'Disabled'|'Hidden'|'Redraw'|'Section'|'Theme'|'v'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddStatusBar('+vSBMain') ; Set using v option. Can't include a space + * con.Name := 'SB Main' ; Set using Name property. Can including a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddStatusBar('+Disabled') ; Control disabled + * var := 0 + * goo.AddStatusBar('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddStatusBar('BackgroundNavy') + * goo.AddStatusBar('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Label] + * Sets the text for the first area of the status bar. + * @returns {(Gui.StatusBar)} + * StatusBar Control Object + * @example Creating a Status Bar to show Edit Control info. + * goo := Gui() + * goo.MarginX := goo.MarginY := 0 + * goo.edit := goo.AddEdit('x0 y0 w400 h400') + * goo.edit.OnEvent('Change', update_sb) + * goo.sb := goo.AddStatusBar('xm ym w100') + * goo.sb.SetParts(100, 100) + * update_sb(goo.sb) + * goo.Show('AutoSize') + * + * update_sb(control, *) { + * chars := control.gui.edit.Value + * StrReplace(chars, '`n', '`n', 1, &lines) + * control.gui.sb.SetText('Total Chars: ' StrLen(chars), 1) + * control.gui.sb.SetText('Lines: ' (lines+1), 2) + * } + */ + AddStatusBar([Options:='', Label:='']) => Gui.StatusBar + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddText()`} + * Adds a control for text that the user cannot edit. + * Often used to label other controls or give details/instructions. + * @param {String|'Background'|'BackgroundTrans'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Center'|'Left'|'Right'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddText('+vTxtHeader') ; Set using v option. Can't include a space + * con.Name := 'Txt Header' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddText('cRed') + * goo.AddText('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddText('+Disabled') ; Control disabled + * var := 0 + * goo.AddText('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Left`: Left justify control text within its available width. + * - `Right`: Right justify control text within its available width. + * - `Center`: Center justify control text within its available width. + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `BackgroundTrans`: Uses a transparent background, which allows any control that lies behind the text control to show through. Use `+Background` to remove this option later. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddText('BackgroundNavy') + * goo.AddText('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Text] + * The text to display in the control. + * @returns {(Gui.Text)} + * Text Control Object + * @example Making a scrolling ticker using a Text Control. + * goo := Gui() + * text := ' Creating scrolling text. ' + * goo.txt := goo.AddText('xm ym w200 h20 -Wrap', text) + * goo.txt.SetFont('S10', 'Consolas') + * ticker(goo.txt) + * goo.Show() + * + * ticker(con) { + * con.Text := SubStr(con.Text, 2) SubStr(con.Text, 1, 1) + * callback := ticker.Bind(con) + * SetTimer(callback, -100) + * } + */ + AddText([Options:='', Text:='']) => Gui.Text + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddTreeView()`} + * Adds a TreeView display to represent a hierarchy of items by indenting child items beneath their parents. + * Window's Explorer drive/folder tree is a common example of a TreeView. + * @param {String|'Buttons'|'Checked'|'ImageList'|'Lines'|'ReadOnly'|'WantF2'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Buttons`: Specifying `-Buttons` to remove the `+` and `-` symbols from the left of each item. + * - `Checked`: Add a checkbox at left of each item. + * When {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm#Add|adding an item}, use the {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm#Check|Check option} to start it checked. + * - `ImageList#`: Add icons to a TreeView where `#` is the {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL|ImageListID} returned from a previous call to {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL_Create|IL_Create()}. + * This option can only be used when creating a TreeView. Use {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#SetImageList|SetImageList()}. + * - `Lines`: Specify `-Lines` disables the connecting lines between parents and children. + * This also prevents the `+` and `-` buttons from being shown for top-level items. + * - `ReadOnly`: Specify `-ReadOnly` to allow the editing of each item. + * The items can be edited with F2 (see {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#WantF2|WantF2}) or by clicking the label, + * waiting a brief moment, then clicking again. + * - `WantF2`: Specify `-WantF2` to prevent F2 from editing the current selected item. + * WantF2 only works if `-ReadOnly` is also in effect. + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddTreeView('+vTVFolderView') ; Set using v option. Can't include a space + * con.Name := 'TV FolderView' ; Set using Name property. Can including a space + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddTreeView('cRed') + * goo.AddTreeView('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddTreeView('+Disabled') ; Control disabled + * var := 0 + * goo.AddTreeView('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddTreeView('BackgroundNavy') + * goo.AddTreeView('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Text] + * @returns {(Gui.TreeView)} + * TreeView Control Object + * @example Creating a TreeView with multiple parents and children. + * goo := Gui() + * goo.tree := goo.AddTreeView('xm ym w200 h200') + * goo.tree.OnEvent('Click', lv_click) + * loop 3 { + * p_num := A_Index + * parent := goo.tree.Add('Parent ' p_num, 0) + * loop 3 + * child := goo.tree.Add('Child ' p_num '-' A_Index, parent) + * } + * goo.Show('AutoSize') + * + * lv_click(con, info) { + * con.gui.Title := con.GetText(con.GetSelection()) + * } + */ + AddTreeView([Options:='', Text:='']) => Gui.TreeView + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddUpDown()`} + * Attaches a clickable up and down arrow button to the previous control (called a `Buddy`) that can increase or decrease the Buddy's value. + * @param {String|'Horz'|'Left'|'Right'|'Range'|'Wrap'|'-16'|'0x80'|'Increments'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Horz`: Arrow buttons point left/right, become wider, and show under the Buddy. + * Buttons are visually disconnected from the control. + * Adding option `+16` forces the buttons to attach to their original position. + * - `Left`/`Right`: The side of the Buddy the UpDown attaches to. Right is default. + * This option cannot be changed after control creation. + * - `RangeMIN-MAX`: Set slider value range, where `MIN` is the minimum and `MAX` is the maximum. + * Default is `Range0-100`. + * - `Wrap`: Going past the max range causes the number to start back at minimum. + * Going below minimum wraps back around to max. + * - `16`: Specify `-16` to detach the UpDown from its Buddy. + * It can now be positioned like a standard control with `W`, `H`, `X`, `Y` options. + * - `0x80`: Removes the 3 digit separator from being being displayed in the Buddy. + * These separators are removed automatically when value is gotten from the UpDown control. + * script retrieves it from the UpDown control itself rather than the buddy control. + * - `Increments`: {@link https://www.autohotkey.com/docs/v2/scripts/index.htm#Custom_Increments_for_UpDown_Controls|Guide to changing UpDown inc/decrementation} + * - `Hexadecimal Format`: To change display to hex, use this UpDown {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|Message}: + * + * UDM_SETBASE := 0x046D, SendMessage(UDM_SETBASE, 16, 0, "msctls_updown321") + * + * **Positioning and Sizing of Controls** + * - `r#`: Rows of text where `#` is the number of rows of text that can visibly fit in the control. + * This number can be a float. `r` takes precedence over `h`. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddUpDown('+UDAge') ; Set using v option. Can't include a space + * con.Name := 'UD Age' ; Set using Name property. Can including a space + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddUpDown('+Disabled') ; Control disabled + * var := 0 + * goo.AddUpDown('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * @param {(String)} [StartingPos] + * Sets the starting position of the buddy control. + * @returns {(Gui.UpDown)} + * UpDown Control Object + * @example Using UpDown controls to change window width. + * goo := Gui() + * goo.AddText('xm ym w150 +Wrap', 'Adjust window width with ' + * 'up/down keys scroll wheel, or up/down control arrows.' + * '`nMin width: 200' + * '`nMax width: 300') + * goo.edit := goo.AddEdit('xm w150 +ReadOnly') + * goo.edit.OnEvent('Change', update_win_size) + * goo.ud_edit := goo.AddUpDown('+Range200-300', 250) + * goo.ud_edit.OnEvent('Change', update_win_size) + * goo.Show('') + * update_win_size(goo.edit) + * + * update_win_size(con, *) => con.gui.Move(,,con.Value) + */ + AddUpDown([Options:='', StartingPos:=0]) => Gui.UpDown + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddComboBox()`} + * Adds a control that is combination of a DropDownList and an edit control. + * @param {String|'Choose'|'Uppercase'|'Lowercase'|'Sort'|'Limit'|'Simple'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select an item where `#` is the line number of the item. + * - `Uppercase` or `Lowercase`: Converts all items in the list to uppercase or lowercase. + * - `Sort`: Item list is sorted alphabetically. This option also enables incremental searching. + * Meaning an item can be selected by typing its name. + * - `Limit`: Restrict the user's input to the visible width of the ComboBox's edit field. + * - `Simple`: Replaces the ComboBox's DropDownList with a {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ListBox|ListBox}. + * + * **Positioning and Sizing of Controls** + * - `r#`: Max amount of items to show in the control list without needing to scroll, where `#` is the number of visible rows. This number can be a float. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddComboBox('+vCBNames') ; Set using v option. Can't include a space + * con.Name := 'CB Names' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position(s) instead of the actual text. + * If no item is selected, the text of the edit field is stored, even if the string is empty. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddComboBox('cRed') + * goo.AddComboBox('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddComboBox('+Disabled') ; Control disabled + * var := 0 + * goo.AddComboBox('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddComboBox('BackgroundNavy') + * goo.AddComboBox('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(String)} [Text] + * An array of strings to populate the ComboBox. + * @returns {(Gui.ComboBox)} + * ComboBox Control Object + * @example Showcasing different ComboBox setups. + * goo := Gui() + * con_w := 250 + * item_list := ['Banana', 'Cherry', 'Apple'] + * goo.AddText('xm ym w' con_w, 'Unsorted Normal Combo Box' + * . '`nItem 2 pre-selected:') + * goo.AddText('x+50 yp w' con_w, 'Sorted Simple Combo Box' + * . '`nItem 2 pre-selected:') + * goo.AddComboBox('xm w' con_w ' Choose2', item_list) + * goo.AddComboBox('x+50 w' con_w ' Choose2 Simple Sort', item_list) + * goo.Show('AutoSize') + */ + AddComboBox([Options:='', Text:=Array]) => Gui.ComboBox + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddDDL()`} + * Adds a single-lined control that, when clicked, produces a list of items to select from. + * @param {String|'Choose'|'Uppercase'|'Lowercase'|'Sort'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select an item where `#` is the line number of the item. + * - `Uppercase` or `Lowercase`: Converts all items in the list to uppercase or lowercase. + * - `Sort`: Item list is sorted alphabetically. + * + * **Positioning and Sizing of Controls** + * - `r#`: Max amount of items to show in the control list without needing to scroll, where `#` is the number of visible rows. This number can be a float. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddDDL('+vDDLNames') ; Set using v option. Can't include a space + * con.Name := 'DDL Names' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position instead of the actual text. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddDDL('cRed') + * goo.AddDDL('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddDDL('+Disabled') ; Control disabled + * var := 0 + * goo.AddDDL('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddDDL('BackgroundNavy') + * goo.AddDDL('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(Array)} [List] + * An array of strings to represent each choice in the list. + * @returns {(Gui.DDL)} + * DropDownList Control Object + * @example Changing background color with Drop Down List of colors. + * color_list := ['Default', 'Red','Yellow','Green','Cyan','Blue','Magenta'] + * goo := Gui() + * goo.ddl := goo.AddDDL('xm ym Choose1', color_list) + * goo.ddl.OnEvent('Change', color_change) + * goo.Show('w200 h100') + * + * color_change(con, info) { + * color_map := Map('Red' ,0xFF0000 ,'Yellow',0xFFFF00 ,'Green',0xFF00 + * ,'Cyan',0xFFFF ,'Magenta',0xFF00FF,'Blue',0xFF ) + * color_map.Default := 'Default' + * con.gui.BackColor := color_map[con.Text] + * } + */ + AddDDL([Options:='', List:=Array]) => Gui.DDL + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddDropDownList()`} + * Adds a single-line control that, when clicked, drops down a list of choices to select from. + * @param {String|'Choose'|'Uppercase'|'Lowercase'|'Sort'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select an item where `#` is the line number of the item. + * - `Uppercase` or `Lowercase`: Converts all items in the list to uppercase or lowercase. + * - `Sort`: Item list is sorted alphabetically. + * + * **Positioning and Sizing of Controls** + * - `r#`: Max amount of items to show in the control list without needing to scroll, where `#` is the number of visible rows. This number can be a float. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddDropDownList('+vDDLNames') ; Set using v option. Can't include a space + * con.Name := 'DDL Names' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position instead of the actual text. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddDropDownList('cRed') + * goo.AddDropDownList('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddDropDownList('+Disabled') ; Control disabled + * var := 0 + * goo.AddDropDownList('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `Wrap`: Enables word-wrapping of the control's contents within its available width and is enabled by default with most controls. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddDropDownList('BackgroundNavy') + * goo.AddDropDownList('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(Array)} [List] + * An array of strings to represent each choice in the list. + * @returns {(Gui.DDL)} + * DropDownList Control Object + * @example Changing background color with Drop Down List of colors. + * color_list := ['Default', 'Red','Yellow','Green','Cyan','Blue','Magenta'] + * goo := Gui() + * goo.ddl := goo.AddDropDownList('xm ym Choose1', color_list) + * goo.ddl.OnEvent('Change', color_change) + * goo.Show('w200 h100') + * + * color_change(con, info) { + * color_map := Map('Red' ,0xFF0000 ,'Yellow',0xFFFF00 ,'Green',0xFF00 + * ,'Cyan',0xFFFF ,'Magenta',0xFF00FF,'Blue',0xFF ) + * color_map.Default := 'Default' + * con.gui.BackColor := color_map[con.Text] + * } + */ + AddDropDownList([Options:='', List:=Array]) => Gui.DDL + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddListBox()`} + * Adds a box control containing a list of choices that can be chosen from. + * This is the same list type used with {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ComboBox|Simple ComboBoxes}. + * @param {String|'Choose'|'Multi'|'ReadOnly'|'Sort'|'T'|'0x100'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select an item where `#` is the line number of the item. + * - `Multi`: Multiple items can be selected via Ctrl+Clicking and Shift+Clicking. + * Using Style `+0x8` {@link https://learn.microsoft.com/en-us/windows/win32/controls/list-box-styles#LBS_MULTIPLESEL|LBS_MULTIPLESEL}, item highlighting is toggled on clicked. + * - `ReadOnly`: Items will not be visibly highlighted when selected but still register + * with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit()} and the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|Value} and {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Text|Text} properties. + * - `Sort`: Item list is sorted alphabetically. This option also enables incremental searching. + * Meaning an item can be selected by typing its name. + * - `T#`: Sets each tab's distance, where `#` is number of dialogue units (a unit determined by the OS) to use. + * If one tab stop is set, that distance is used between all tabs. + * If multiple tab stops are set, each marks the distance the corresponding tab will extend to. + * - `0x100`: Adds the {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm#LBS_NOINTEGRALHEIGHT|LBS_NOINTEGRALHEIGHT} style to the ListBox, preventing a partial + * row from appearing at the bottom and from shrinking when the font is changed. + * + * **Positioning and Sizing of Controls** + * - `r#`: Max amount of items to show in the control list without needing to scroll, where `#` is the number of visible rows. This number can be a float. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddListBox('+vLBNames') ; Set using v option. Can't include a space + * con.Name := 'LB Names' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position(s) instead of the actual text. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddListBox('cRed') + * goo.AddListBox('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddListBox('+Disabled') ; Control disabled + * var := 0 + * goo.AddListBox('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddListBox('BackgroundNavy') + * goo.AddListBox('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(Array)} [List] + * Array of strings to populate the ListBox. + * @returns {(Gui.ListBox)} + * ListBox Control Object + * @example ListBox of items that adjusts GUI size. + * goo := Gui() + * rez := ['Minimal', '640 x 360','640 x 480','720 x 480','1280 x 720','1920 x 1080'] + * goo.AddText('xm ym', 'Select a window size') + * con := goo.AddListBox('xm ym w200 r' rez.Length, rez) + * con.OnEvent('Change', update_win_size) + * goo.Show() + * + * update_win_size(con, *) { + * if InStr(con.Text, ' x ') + * rez := StrSplit(con.Text, 'x', ' ')0 + * ,con.gui.Move(,,rez[1], rez[2]) + * else goo.Show('AutoSize') + * } + */ + AddListBox([Options:='', List:=Array]) => Gui.ListBox + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab|`AddTab()`} + * Use {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab|AddTab3()} instead of `AddTab()`. + * `AddTab()` and `AddTab2()` are for backward compatibility only. + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|AddTab()} adds a large control used to contain organize other controls. + * Each tab acts as it's own "page" of individual controls. + */ + AddTab([Options:='', TabTitles:=Array]) => Gui.Tab + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab|`AddTab2()`} + * Use {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab|AddTab3()} instead of `AddTab2()`. + * `AddTab()` was {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab_vs|retained for compatibility} but has issues. + * `AddTab2()` fixed those issues but {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab2_Issues|introduced new ones}. + */ + AddTab2([Options:='', TabTitles:=Array]) => Gui.Tab + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Add|`AddTab3()`} + * Adds a large control used to contain organize other controls. + * Each tab acts as it's own "page" of individual controls. + * Avoid using AddTab() and AddTab2() as they're only kept for backward compatibility. + * @param {String|'Choose'|'Buttons'|'Left'|'Right'|'Bottom'|'AltSubmit'|'Background'|'c'|'cBlack'|'cSilver'|'cGray'|'cWhite'|'cMaroon'|'cRed'|'cPurple'|'cFuchsia'|'cGreen'|'cLime'|'cOlive'|'cYellow'|'cNavy'|'cBlue'|'cTeal'|'cAqua'|'Wrap'|'Border'|'Disabled'|'h'|'hp'|'Hidden'|'HScroll'|'r'|'Redraw'|'Section'|'Tabstop'|'Theme'|'v'|'VScroll'|'w'|'wp'|'x'|'xp'|'xs'|'y'|'yp'|'ys'} Options + * Any {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#OtherOptions|general} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|control-specific} options, separated by spaces/tabs. + * All control events are handled using the {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|`OnEvent()` method}. + * **Control Specific Options** + * - `Choose#`: Pre-select a Tab where `#` is the tab's positional number. + * - `Buttons`: The Tabs are replaced with clickable buttons. + * - `Left`/`Right`/`Bottom`: Specify the side of the control to show the tabs. + * See {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm#TCS_VERTICAL|TCS_VERTICAL} for Left/Right limitations. + * - `Wrap`: Specify `-Wrap` to keep all tabs on a single row. Scroll buttons are added if there are too many tabs. + * If there are too many tabs, scroll buttons are added to navigate through them. + * - `Tab Icons`: Icons may be added next to tab's via {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage} as demonstrated in {@link https://www.autohotkey.com/board/topic/5692-icons-in-tabs/|this post}. + * + * **Positioning and Sizing of Controls** + * - `r#`: Max amount of items to show in the control list without needing to scroll, where `#` is the number of visible rows. This number can be a float. + * - `w#` or `h#`: Width or height of a control, where `#` is a number of pixels. + * If omitted, each control has a specific way of defaulting its width and height. Covered in the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#PosSize|`Add()` docs}. + * - `wp+#` or `hp+#`: Use previous control's width `wp` or height `hp`, adjusted by any `#` provided. + * - `x#` or `y#`: Static x or y coordinates where `#` is the pixel location on the Gui. + * - `x+#` or `y+#`: Position this control relative to the right edge `x+#` or bottom edge `y+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xp+#` or `yp+#`: Position this control relative to the left edge `xp+#` or top edge `yp+#` of the previous control. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xm+#` or `ym+#`: Position this control relative to the left margin `xm+#` or top margin `ym+#` of the GUI. + * `#` is an optional offset in pixels and can be positive or negative. + * - `xs+#` or `ys+#`: Position this control relative to the left edge `xs+#` or top edge `ys+#` of the last control marked with the "Section" option. + * `#` is an optional offset in pixels and can be positive or negative. + * + * **Common Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `v#`: Assign a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Name|Name} to a control, where `#` is a new name. + * A control's name can be used to get a reference to that control from a GUI object. + * Using the `Name` property allows you to set a name without any restrictions. + * + * goo.AddTab3('+vTabModes') ; Set using v option. Can't include a space + * con.Name := 'Tab Modes' ; Set using Name property. Can including a space + * - `AltSubmit`: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|Gui.Submit} will record the item position(s) instead of the actual text. + * - `C#`: Set text color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `CDefault` or `C` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddTab3('cRed') + * goo.AddTab3('cFF0000') + * - `Disabled`: Disables the control preventing user focus or modifications of the contents. + * To enable, set {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiCtrl.Enabled} to true or use `-Disabled` with {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|Opt()}. + * The word `Disabled` can be followed by `1` to indicate true (true, it should be disabled) or `0` (false, it should not be disabled). + * + * goo.AddTab3('+Disabled') ; Control disabled + * var := 0 + * goo.AddTab3('Disabled' var) ; Control enabled + * - `Hidden`: The control is initially invisible. + * The word `Hidden` can be followed by `1` to indicate true (true, it should be Hidden) or `0` (false, it should not be Hidden). + * - `Section`: Sets current control as the new Section for use with the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#xs|XS and YS} positioning options. + * - `Tabstop`: Disabling Tabstop of a control prevents the user from tabbing to that control. + * - `VScroll`: Provide or remove a vertical scroll bar if appropriate for this type of control. + * - `HScroll`: Provide or remove a horizontal scroll bar if appropriate for this type of control. + * + * **Uncommon Styles and Options** + * Prefix with `-` to disable an option and `+` (or no sign) to add an option. + * - `Background#`: Sets control background color where `#` is a hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * - RGB hex value (0x prefix is optional): `C0x000000` to `CFFffFF` + * - Reset/Default Color: `BackgroundDefault` or `Background` + * - Color Name: Full color chart at bottom of options. Scroll down. + * + * goo.AddTab3('BackgroundNavy') + * goo.AddTab3('Background000080') + * - `Border`: Add thin-line border around control. You may need to increase the control's width and height by 1 pixel. + * - `Redraw`: Enable/disable redrawing (visual updates) of a control. + * This is typically used to increase performance when a control will have multiple items added to it. + * `-Redraw` prior to adding the items and then `+Redraw` after all have been added. + * Uses: {@link https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw|WM_SETREDRAW}. + * - `Theme`: Used to override the window's {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|current Theme setting} for the newly created control. + * This setting has no effect when used on an existing control. + * See: {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Theme|GUI's +/-Theme option} for details. + * - {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Number} `+0x0`: Specify a plus or minus sign followed by a decimal or hexadecimal style number. + * - {@link https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles|ExStyle Number} `+E0x0`: Specify a plus or minus sign followed by the letter E and a decimal or hexadecimal extended style number. + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(Array)} [TabTitles] + * Array of strings to use as tab titles. + * @returns {(Gui.Tab)} + * Tab Control Object + * @example Creating a gui with 3 tabs. + * goo := Gui() + * goo.tabs := goo.AddTab3('xm ym w200 h100 Section', ['Tab 1', 'Tab 2', 'Tab 3']) + * loop 3 { + * goo.tabs.UseTab(A_Index) + * goo.AddButton('x20 y30', 'Button ' A_Index) + * } + * goo.Show() + */ + AddTab3([Options:='', TabTitles:=Array]) => Gui.Tab + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Destroy|`Destroy()`} + * Removes the window and all its controls, freeing the corresponding memory and system resources. + * @returns {(String)} + * An empty string is always returned. + * @example + * goo := Gui() + * con := goo.AddButton('xm ym w100', 'Destroy GUI') + * con.OnEvent('Click', destroy_gui) + * goo.Show('AutoSize') + * + * destroy_gui(con, *) { + * con.gui.Destroy() + * } + */ + Destroy() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Flash|`Flash()`} + * Causes the Gui's title bar and taskbar to blink. + * This is done by inverting their colors once per call. By calling flash multiple times, the button and window appear to "blink". + * @param {(Boolean)} [Blink] + * Any true value will cause the color inversion to continue. + * Setting Blink to false will reset the flash by removing the color inversion if present. + * @returns {(String)} + * An empty string is always returned. + * @example Make a flashing GUI. + * goo := Gui() + * goo.AddButton('xm ym w100') + * goo.Show('AutoSize') + * loop 6 + * goo.Flash() + * goo.Flash(0) + * MsgBox('Done flashing and flash is reset') + */ + Flash([Blink:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#GetClientPos|`GetClientPos()`} + * Retrieves the position and size of the window's client area. + * Client area is the main area of a program and it excludes the window's title bar, standard menus, and window borders. + * Unlike {@link https://www.autohotkey.com/docs/v2/lib/WinGetClientPos.htm|WinGetClientPos}, this method applies {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#DPIScale|DPI scaling} to width and height. + * @param {(VarRef)} [X] + * Variable to store the x coordinate of the client area. + * This is the left edge of the area. + * @param {(VarRef)} [Y] + * Variable to store the y coordinate of the client area. + * This is the top edge of the area. + * @param {(VarRef)} [Width] + * Variable to store the width of the client area. + * To get the right edge of the area, add width and x. + * @param {(VarRef)} [Height] + * Variable to store the height of the client area. + * To get the bottom edge of the area, add height and y. + * @returns {(String)} + * An empty string is always returned. + * @example Getting active info on a Window. + * WM_MOVE := 0x0003 + * + * goo := Gui('+Resize') + * goo.txt := goo.AddText('xm ym w300 h400') + * goo.Show('x100 y100 w300 h400') + * + * callback := update_pos_info.Bind(goo) + * callback() + * goo.OnEvent('Size', callback) + * OnMessage(WM_MOVE, callback) + * + * update_pos_info(goo, *) { + * goo.GetPos(&X, &Y, &Width, &Height) + * ,goo.GetClientPos(&cX, &cY, &cWidth, &cHeight) + * ,goo.txt.Text := 'Window X: ' x '`nWindow y: ' y '`nWindow width: ' width '`nWindow height: ' height + * . '`nClient X: ' x '`nClient y: ' y '`nClient width: ' width '`nClient height: ' height + * } + */ + GetClientPos([&X, &Y, &Width, &Height]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#GetPos|`GetPos()`} + * Retrieves the position and size of the window. + * Unlike {@link https://www.autohotkey.com/docs/v2/lib/WinGetClientPos.htm|WinGetClientPos}, this method applies {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#DPIScale|DPI scaling} to width and height. + * @param {(VarRef)} [X] + * Variable to store the x coordinate of the Gui. + * This is the left edge of the Gui. + * @param {(VarRef)} [Y] + * Variable to store the y coordinate of the Gui. + * This is the top edge of the Gui. + * @param {(VarRef)} [Width] + * Variable to store the width of the Gui. + * To get the right edge of the Gui, add width and x. + * @param {(VarRef)} [Height] + * Variable to store the height of the Gui. + * To get the bottom edge of the Gui, add height and y. + * @returns {(String)} + * An empty string is always returned. + * @example Getting active info on a Window. + * WM_MOVE := 0x0003 + * + * goo := Gui('+Resize') + * goo.txt := goo.AddText('xm ym w300 h400') + * goo.Show('x100 y100 w300 h400') + * + * callback := update_pos_info.Bind(goo) + * callback() + * goo.OnEvent('Size', callback) + * OnMessage(WM_MOVE, callback) + * + * update_pos_info(goo, *) { + * goo.GetPos(&X, &Y, &Width, &Height) + * ,goo.GetClientPos(&cX, &cY, &cWidth, &cHeight) + * ,goo.txt.Text := 'Window X: ' x '`nWindow y: ' y '`nWindow width: ' width '`nWindow height: ' height + * . '`nClient X: ' x '`nClient y: ' y '`nClient width: ' width '`nClient height: ' height + * } + */ + GetPos([&X, &Y, &Width, &Height]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Hide|`Hide()`} + * Hides the Gui window from view but does not destroy it. + * @returns {(String)} + * An empty string is always returned. + * @example A GUI that can be hidden and shown with F1. + * *F1::toggle_gui() + * + * toggle_gui() + * + * toggle_gui() { + * static goo := make_gui() + * if WinExist('ahk_id ' goo.hwnd) + * goo.Hide() + * else goo.Show() + * return + * + * make_gui() { + * goo := Gui() + * goo.AddText('xm ym w150', 'Press F1 to hide/show GUI.') + * goo.btn_exit := goo.AddButton('xm w150', 'Click to close Script') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * return goo + * } + * } + */ + Hide() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Maximize|`Maximize()`} + * Unhides the window if hidden and then maximizes it. + * @returns {(String)} + * An empty string is always returned. + * @example GUI with max, min, and restore buttons. + * goo := Gui() + * goo.btn_max := goo.AddButton('xm ym w100', 'Maximize Window') + * goo.btn_max.OnEvent('Click', (con, *) => con.gui.Maximize()) + * goo.btn_res := goo.AddButton('xm w100', 'Restore Window') + * goo.btn_res.OnEvent('Click', (con, *) => con.gui.Restore()) + * goo.btn_min := goo.AddButton('xm w100', 'Minimize Window') + * goo.btn_min.OnEvent('Click', (con, *) => con.gui.Minimize()) + * goo.Show() + */ + Maximize() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Minimize|`Minimize()`} + * Unhides the window if hidden and then minimizes it. + * @returns {(String)} + * An empty string is always returned. + * @example GUI with max, min, and restore buttons. + * goo := Gui() + * goo.btn_max := goo.AddButton('xm ym w100', 'Maximize Window') + * goo.btn_max.OnEvent('Click', (con, *) => con.gui.Maximize()) + * goo.btn_res := goo.AddButton('xm w100', 'Restore Window') + * goo.btn_res.OnEvent('Click', (con, *) => con.gui.Restore()) + * goo.btn_min := goo.AddButton('xm w100', 'Minimize Window') + * goo.btn_min.OnEvent('Click', (con, *) => con.gui.Minimize()) + * goo.Show() + */ + Minimize() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Move|`Move()`} + * Used to adjust the position (x,y coords), height, and/or width of the GUI. + * Unlike {@link https://www.autohotkey.com/docs/v2/lib/WinMove.htm|WinMove}, this method applies {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#DPIScale|DPI scaling} to width and height. + * @param {(Integer)} [X] + * New x coordinate of the Gui. + * @param {(Integer)} [Y] + * New y coordinate of the Gui. + * @param {(Integer)} [Width] + * New Gui width. + * @param {(Integer)} [Height] + * New Gui height. + * @returns {(String)} + * An empty string is always returned. + * @example Create a button to randomly move the GUI. + * goo := Gui() + * goo.btn_b1 := goo.AddButton('xm w100', 'Random Position') + * goo.btn_b1.OnEvent('Click', random_pos) + * goo.btn_b2 := goo.AddButton('xm w100', 'Close Script') + * goo.btn_b2.OnEvent('Click', (*) => ExitApp()) + * goo.Show() + * + * random_pos(control, info) { + * MonitorGetWorkArea(MonitorGetPrimary(), &left, &top, &right, &bottom) + * x := Random(left, right) + * y := Random(top, bottom) + * control.Gui.move(x, y) + * } + */ + Move([X:=unset, Y:=unset, Width:=unset, Height:=unset]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Events|`OnEvent()`} + * Assigns a {@link https://www.autohotkey.com/docs/v2/Functions.htm|Function}, {@link https://www.autohotkey.com/docs/v2/Concepts.htm#methods|Method}, {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}, or {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} to be called when the specified event is raised. + * @param {'Close'|'ContextMenu'|'DropFiles'|'Escape'|'Size'} EventName + * One of the following event(s). Expected callback format is included. + * Gui Events: + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Close|`Close`} - Window is closed. + * + * Gui_Close(GuiObj) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#ContextMenu|`ContextMenu`} - User right-clicks within the window or presses Menu or Shift+F10. + * + * Gui_ContextMenu(GuiObj, GuiCtrl, Item, RightClick, CX, CY) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#DropFiles|`DropFiles`} - Files/folders are dragged and dropped onto the window. + * + * Gui_DropFiles(GuiObj, GuiCtrl, FileArray, FX, FY) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Escape|`Escape`} - User presses Esc while the GUI window is active. + * + * Gui_Escape(GuiObj) + * - {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm#Size|`Size`} - Window is resized, minimized, maximized or restored. + * + * Gui_Size(GuiObj, MinMax, Width, Height) + * - Callback Params: + * - `GuiObj`: Reference to the GUI. + * - `GuiCtrl`: GUI control that received the event. Empty string of none. + * - `Item`: The ListBox, ListView, or TreeView item number that was right clicked, otherwise unused. + * - `RightClick`: Context menu activation + * - `1` = Activated by right click + * - `0` = Activated by `AppsKey` or `Shift+F10` + * - `CX` and `CY`: Check `RightClick` param + * - Right Clicked = Coords of mouse click + * - Keyboard = Coords of the Slider's upper left corner + * - `FileArray`: Array containing one or more file paths. + * - `FX` and `FY`: Coords where file(s) were dropped. + * - Right Clicked = Coords of mouse click + * - `MinMax`: + * - `1` = Window is maximized. + * - `-1` = Window is minimized. + * - `0` = Window is neither min or max. + * - `Width` and `Height`: The new width and height of the GUI. + * @param {(String|FuncObj)} Callback + * The function, method, boundfunc, or object to be called when the event is raised. + * A callback's first parameter is the One of the following event(s). Expected callback format is included.. + * If multiple callbacks have been registered for an event, a callback may return a non-empty string to prevent any remaining callbacks from being called. + * @param {(Integer)} [AddRemove=1] + * Adjust callback order or delete callback. If omitted, parameter defaults to 1. + * - `1`: Add the callback after any previously registered callbacks. + * - `-1`: Add the callback before any previously registered callbacks. + * - `0`: Remove the callback. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|OnEvent()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#Variadic|Variadic Functions} + * @example Making a script exit when a GUI is closed. + * goo := Gui() + * goo.OnEvent('Close', exit_script) + * goo.OnEvent('Escape', exit_script) + * goo.AddText('xm ym', 'To close the gui:' + * '`n`n- Press the "Escape" key' + * '`n- Close the GUI') + * goo.Show('h100') + * + * exit_script(*) => ExitApp() + */ + OnEvent(EventName, Callback [,AddRemove:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Opt|`Opt()`} + * Sets various options and styles for the appearance and behavior of the window. + * @param {(String)} ControlType + * One of the following control types: + * - **Buttons** + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Button|`Button`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Checkbox|`Checkbox`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Radio|`Radio`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Slider|`Slider`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#UpDown|`UpDown`} + * - **Text** + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Text|`Text`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Link|`Link`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Edit|`Edit`} | + * - **Lists and views** + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ComboBox|`ComboBox`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DropDownList|`DDL`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DropDownList|`DropDownList`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab|`Tab`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab|`Tab2`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Tab|`Tab3`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ListBox|`ListBox`} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm|`ListView`} | + * {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm|`TreeView`} | + * - **Graphical** + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Picture|`Pic`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Picture|`Picture`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Progress|`Progress`} | + * - **Date/Time** + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DateTime|`DateTime`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#MonthCal|`MonthCal`} | + * - **Misc** + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#ActiveX|`ActiveX`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Custom|`Custom`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#GroupBox|`GroupBox`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Hotkey|`Hotkey`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#StatusBar|`StatusBar`} | + * @param {String|'AlwaysOnTop'|'Border'|'Caption'|'Disabled'|'DPIScale'|'LastFound'|'MaximizeBox'|'MaxSize'|'MinimizeBox'|'MinSize'|'OwnDialogs'|'Owner'|'Parent'|'Resize'|'SysMenu'|'Theme'|'ToolWindow'} Options + * Zero or more Gui options, separated by spaces and/or tabs. + * For best performance, set all options in 1 call and do so before the window is created. + * Use `-` before an option to remove it or `+` to add it. Using no sign is the same as using `+`. + * - `AlwaysOnTop`: Makes the window stay on top of all other windows. Same effect as {@link https://www.autohotkey.com/docs/v2/lib/WinSetAlwaysOnTop.htm|WinSetAlwaysOnTop}. + * - `Border`: Provides a thin-line border around the window. + * - `Caption`: Include the standard title bar and a thick window border/edge. If using {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransColor.htm|WinSetTransColor}, remove Caption only after setting the TransColor. + * - `Disabled`: Disables the window, which prevents the user from interacting with its controls. This is often used on a window that owns other windows (see {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Owner|Owner}). + * - `DPIScale`: If DPI scaling is enabled, coordinates and sizes passed to or retrieved from the Gui and GuiControl methods/properties are automatically scaled based on screen DPI. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScreenDPI|A_ScreenDPI} contains the system's current DPI. + * DPI scaling only applies to the Gui and GuiControl methods/properties, so coordinates coming directly from other sources such as ControlGetPos or WinGetPos will not work. + * - `LastFound`: Sets the window to {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|last found window}. This is done automatically in a GUI thread to allow functions such as {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|WinGetStyle} and {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransparent.htm|WinSetTransparent} to operate on it even if it is hidden. + * - `MaximizeBox`: Enables the maximize button in the title bar. This is included when the Resize option is used. + * - `MinimizeBox`: Enables the minimize button in the title bar. + * - `MaxSize` or `MinSize`: Set, adjust, or remove the minimum/maximum size of the client area of the window, such as when the user drags its edges to resize it. + * `+MaxSize`/`+MinSize` uses the current window size as the maximum/minimum. + * Alternatively, `+MaxSize640x480`/`+MinSize640x480` would set the max/min size to 640 pixels wide by 480 pixels tall and the width or height may be omitted, though the `x` separator must always be present. + * - `OwnDialogs`: Should be specified in each thread for which subsequently displayed MsgBox, InputBox, FileSelect, and DirSelect dialogs should be owned by the window. + * These dialogs become modal, meaning that the user cannot interact with the Gui until the dialog box is dismissed. + * ToolTip cannot become modal even though they become owned. Instead, they will stay always on top of the owner. + * - `Owner`: Causes the window to be owned by another. Include the handle (HWND) to another window after the word owner to make the Gui owned by that Window. + * Omitting a handle (HWND) will make the Gui owned by the script's main window. + * - `Parent`: Use `+Parent` immediately followed by the handle (HWND) of any window or control to use it as the parent of this window while `-Parent` will revert it back to a top-level window. + * - `Resize`: Makes the window resizable and enables its maximize button in the title bar. The maximize button can be removed with `-MaximizeBox`. + * - `SysMenu`: Adds or removes the system menu and icon in the window's upper left corner. This includes the minimize, maximize, and close buttons in the title bar. + * - `Theme`: If `-Theme` is used, all subsequently created controls in the window will have the Classic Theme appearance. + * Theme can also be used in a control's options during its creation such as `g.AddButton('-Theme')`. + * - `ToolWindow`: Provides a narrower title bar, removes the taskbar button, and hides both the maximize and minimize buttons. + * - `0x0` Unnamed Style: Specify a plus or minus sign followed immediately by a decimal or hexadecimal style number. + * - `E0x0` Unnamed ExStyle: Specify a plus or minus sign followed immediately by the letter E and a decimal or hexadecimal extended style number. For styles not {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|documented here}, see {@link https://learn.microsoft.com/windows/win32/winmsg/extended-window-styles|Extended Window Styles | Microsoft Docs} for a complete list. + * @returns {(String)} + * An empty string is always returned. + * @example Creating a resizable GUI with no window. + * goo := Gui() + * goo.Opt('-Caption +Border +Resize') + * goo.btn := goo.AddButton('w100', 'Close Script') + * goo.btn.OnEvent('Click', exit_script) + * goo.Show('AutoSize') + */ + Opt(Options) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Restore|`Restore()`} + * Unhides and restores the window, if it was minimized or maximized beforehand. + * @returns {(String)} + * An empty string is always returned. + * @example GUI with max, min, and restore buttons. + * goo := Gui() + * goo.btn_max := goo.AddButton('xm ym w100', 'Maximize Window') + * goo.btn_max.OnEvent('Click', (con, *) => con.gui.Maximize()) + * goo.btn_res := goo.AddButton('xm w100', 'Restore Window') + * goo.btn_res.OnEvent('Click', (con, *) => con.gui.Restore()) + * goo.btn_min := goo.AddButton('xm w100', 'Minimize Window') + * goo.btn_min.OnEvent('Click', (con, *) => con.gui.Minimize()) + * goo.Show() + */ + Restore() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#SetFont|`SetFont()`} + * Sets the typeface, size, style, and text color for subsequently created controls. + * @param {String|'bold'|'italic'|'strike'|'underline'|'norm'|'c'|'s'|'w'|'q'} [Options] + * Zero or more options separated by spaces. + * Styling words are applied in order. + * `norm italic` would disable all options and apply only italics + * - `bold` - Adds a heavy weight/boldness to text. + * - `italic` - Italicizes text. + * - `strike` - Strikes out text by adding a horizontal line through it. + * - `underline` - Underlines text. + * - `norm`- Disables all aforementioned settings. + * + * Other options: + * - `C#`: Set text color where `#` is one of the following: + * - RGB hex value (0x prefix is optional): + * `C0x000000` to `CFFffFF` + * - {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}: + * | | | | | + * | :-- | :-- | :-- | :-- | + * | `Silver` | `Black` | `White` | `Gray` | + * | `Silver` | `Black` | `White` | `Gray` | + * | `Olive` | `Yellow` | `Lime` | `Green` | + * | `Teal` | `Aqua` | `Navy` | `Blue` | + * + * - Reset/Default: + * `CDefault` or `C` + * The color option does not affect {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#Button|buttons} or {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#StatusBar|status bars}. + * - `S#`: Size in points where `#` is a decimal value. + * - `W#`: Weight/boldness where `#` is a decimal value between 1 and 1000. 400 is normal. 700 is bold. + * - `Q#`: {@link https://learn.microsoft.com/windows/win32/api/wingdi/nf-wingdi-createfonta|Text rendering quality} where `#` is an integer between 0 and 5. + * - 0 - Window Constant: `DEFAULT_QUALITY` - Appearance of the font does not matter. + * - 1 - Window Constant: `DRAFT_QUALITY` - Appearance of the font is less important than when the PROOF_QUALITY value is used. + * - 2 - Window Constant: `PROOF_QUALITY` - Character quality of the font is more important than exact matching of the logical-font attributes. + * - 3 - Window Constant: `NONANTIALIASED_QUALITY` - Font is never antialiased, that is, font smoothing is not done. + * - 4 - Window Constant: `ANTIALIASED_QUALITY` - Font is antialiased, or smoothed, if the font supports it and the size of the font is not too small or too large. + * - 5 - Window Constant: `CLEARTYPE_QUALITY` - If set, text is rendered (when possible) using ClearType antialiasing method. + * @param {(String)} [FontName] + * the name of any font, such as one from the {@link https://www.autohotkey.com/docs/v2/misc/FontsStandard.htm|font table}. + * If FontName is omitted or does not exist on the system, the previous font typeface will be used, otherwise the system's default Gui typeface is used. + * @returns {(String)} + * An empty string is always returned. + * @example Setting the default font of the + * goo := Gui() + * goo.SetFont('s20 cRed italic', 'Courier New') + * goo.SetFont('', 'Consolas') + * goo.AddText('xm ym', 'Default text is set to:' + * '`n20 pt, red, with italics and Consolas font.' + * '`n`nCourier New is the backup font if Consolas isn`'t present.') + * goo.Show('AutoSize') + */ + SetFont([Options:='', FontName:=PriorFont]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Show|`Show()`} + * Makes the window visible, un-minimizes it (if necessary) and {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|activates} it. + * @param {String|'x'|'y'|'w'|'h'|'Center'|'xCenter'|'yCenter'|'AutoSize'|'Maximize'|'Minimize'|'Restore'|'NoActivate'|'NA'|'Hide'} [Options] + * Zero or more option separated by spaces. + * If X, Y, W, and H are omitted, the Gui will retrain its previous size and position otherwise it will be auto-centered. + * Only decimal numbers should be used. Hex is invalid. + * **Options** + * - `W#` and `H#`: The Width/Height of the window's client area in pixels. This does not include the window area, border, or title bar. + * - `X#` and `Y#`: The Window's X/Y position on the screen in pixels. + * - `Center`: Centers the window horizontally and vertically on the screen. + * - `xCenter`: Centers the window horizontally on the screen. + * - `yCenter`: Centers the window vertically on the screen. + * - `AutoSize`: Resizes the window to accommodate only its currently visible controls. + * + * **Only one of the following Options can be included** + * - `Minimize`: Minimizes the window and activates the one beneath it. + * - `Maximize`: Maximizes and activates the window. + * - `Restore`: Un-minimizes or un-maximizes the window, if necessary. The window is also shown and activated, if necessary. + * - `NoActivate`: Un-minimizes or un-maximizes the window, if necessary. The window is also shown without activating it. + * - `NA`: Shows the window without activating it. If the window is minimized, it will stay that way but will usually rise higher in the z-order. + * - `Hide`: Hides the window and activates the one beneath it. This allows a hidden window to be moved or resized without showing it. + * @returns {(String)} + * An empty string is always returned. + * @example A GUI that can be hidden and shown with F1. + * toggle_gui() + * + * *F1::toggle_gui() + * + * toggle_gui() { + * static goo := make_gui() + * if WinExist('ahk_id ' goo.hwnd) + * goo.Hide() + * else goo.Show() + * return + * + * make_gui() { + * goo := Gui() + * goo.AddText('xm ym w150', 'Press F1 to hide/show GUI.') + * goo.btn_exit := goo.AddButton('xm w150', 'Click to close Script') + * goo.btn_exit.OnEvent('Click', (*) => ExitApp()) + * return goo + * } + * } + */ + Show([Options:='']) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Submit|`Submit()`} + * Collects the values from named controls and composes them into an {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object}. Optionally hides the window. + * @param {(Boolean)} [Hide] + * If omitted or true, window is hidden. If false, the window will not be hidden. + * @returns {(Object)} + * An object is returned with a property for each input-capable control. + * The control must be one with a {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|value property} and have been given a {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Name|name}. + * For DropDownList, ComboBox, ListBox, and Tab, the text of the selected item/tab is stored. + * If the control uses AltSubmit or if the ComboBox's text matches an item in the list, the position number is used. + * @example Using submit to get all the controls from a GUI. + * goo := Gui() + * goo.text := goo.AddText('xm +Border', 'Basic text control') + * goo.text.Name := 'TextControl' + * goo.combo := goo.AddEdit('xm w100', 'Combo Box Text') + * goo.combo.Name := 'EditControl' + * goo.ddl := goo.AddDDL('xm choose2', ['Apple', 'Banana', 'Cherry']) + * goo.ddl.Name := 'DDLControl' + * goo.Show('y200 AutoSize') + * + * results := goo.Submit(0) + * str := 'Control Info`nNotice that submit doesn`'t get text controls.' + * for name, value in results.OwnProps() + * str .= '`n`nControl name: ' name + * . '`nControl value: ' value + * MsgBox(str) + */ + Submit([Hide:=1]) => Object + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#__Enum|`__Enum()`} + * Creates an {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|enumerator object} that iterates through each control of the GUI. + * This method is typically not called but instead is used by a {@link https://www.autohotkey.com/docs/v2/lib/For.htm|for-loop} to get each control and its index number. + * @returns {(Enumerator)} + * Enumerable function object. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|Enumerator Object} + * @example For-loop through all controls using GUI enumerator. + * + * goo := Gui() + * goo.text := goo.AddText('xm +Border', 'Basic text control') + * goo.text.Name := 'TextControl' + * goo.combo := goo.AddEdit('xm w100', 'Combo Box Text') + * goo.combo.Name := 'EditControl' + * goo.ddl := goo.AddDDL('xm choose2 AltSubmit', ['Apple', 'Banana', 'Cherry']) + * goo.ddl.Name := 'DDLControl' + * goo.Show('y200 AutoSize') + * + * str := 'Control Info' + * for hwnd, control in goo + * str .= '`n`nName: ' control.Name + * . '`nHandle: ' hwnd + * . '`nText: ' control.Text + * MsgBox(str) + */ + __Enum() => Enumerator + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#__New|`__New()`} + * Constructs a new Gui instance. + * @param {String|'AlwaysOnTop'|'Border'|'Caption'|'Disabled'|'DPIScale'|'LastFound'|'MaximizeBox'|'MaxSize'|'MinimizeBox'|'MinSize'|'OwnDialogs'|'Owner'|'Parent'|'Resize'|'SysMenu'|'Theme'|'ToolWindow'} [Options] + * Zero or more Gui options, separated by spaces and/or tabs. + * For best performance, set all options in 1 call and do so before the window is created. + * Use `-` before an option to remove it or `+` to add it. Using no sign is the same as using `+`. + * - `AlwaysOnTop`: Makes the window stay on top of all other windows. Same effect as {@link https://www.autohotkey.com/docs/v2/lib/WinSetAlwaysOnTop.htm|WinSetAlwaysOnTop}. + * - `Border`: Provides a thin-line border around the window. + * - `Caption`: Include the standard title bar and a thick window border/edge. If using {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransColor.htm|WinSetTransColor}, remove Caption only after setting the TransColor. + * - `Disabled`: Disables the window, which prevents the user from interacting with its controls. This is often used on a window that owns other windows (see {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Owner|Owner}). + * - `DPIScale`: If DPI scaling is enabled, coordinates and sizes passed to or retrieved from the Gui and GuiControl methods/properties are automatically scaled based on screen DPI. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScreenDPI|A_ScreenDPI} contains the system's current DPI. + * DPI scaling only applies to the Gui and GuiControl methods/properties, so coordinates coming directly from other sources such as ControlGetPos or WinGetPos will not work. + * - `LastFound`: Sets the window to {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|last found window}. This is done automatically in a GUI thread to allow functions such as {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|WinGetStyle} and {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransparent.htm|WinSetTransparent} to operate on it even if it is hidden. + * - `MaximizeBox`: Enables the maximize button in the title bar. This is included when the Resize option is used. + * - `MinimizeBox`: Enables the minimize button in the title bar. + * - `MaxSize` or `MinSize`: Set, adjust, or remove the minimum/maximum size of the client area of the window, such as when the user drags its edges to resize it. + * `+MaxSize`/`+MinSize` uses the current window size as the maximum/minimum. + * Alternatively, `+MaxSize640x480`/`+MinSize640x480` would set the max/min size to 640 pixels wide by 480 pixels tall and the width or height may be omitted, though the `x` separator must always be present. + * - `OwnDialogs`: Should be specified in each thread for which subsequently displayed MsgBox, InputBox, FileSelect, and DirSelect dialogs should be owned by the window. + * These dialogs become modal, meaning that the user cannot interact with the Gui until the dialog box is dismissed. + * ToolTip cannot become modal even though they become owned. Instead, they will stay always on top of the owner. + * - `Owner`: Causes the window to be owned by another. Include the handle (HWND) to another window after the word owner to make the Gui owned by that Window. + * Omitting a handle (HWND) will make the Gui owned by the script's main window. + * - `Parent`: Use `+Parent` immediately followed by the handle (HWND) of any window or control to use it as the parent of this window while `-Parent` will revert it back to a top-level window. + * - `Resize`: Makes the window resizable and enables its maximize button in the title bar. The maximize button can be removed with `-MaximizeBox`. + * - `SysMenu`: Adds or removes the system menu and icon in the window's upper left corner. This includes the minimize, maximize, and close buttons in the title bar. + * - `Theme`: If `-Theme` is used, all subsequently created controls in the window will have the Classic Theme appearance. + * Theme can also be used in a control's options during its creation such as `g.AddButton('-Theme')`. + * - `ToolWindow`: Provides a narrower title bar, removes the taskbar button, and hides both the maximize and minimize buttons. + * - `0x0` Unnamed Style: Specify a plus or minus sign followed immediately by a decimal or hexadecimal style number. + * - `E0x0` Unnamed ExStyle: Specify a plus or minus sign followed immediately by the letter E and a decimal or hexadecimal extended style number. For styles not {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|documented here}, see {@link https://learn.microsoft.com/windows/win32/winmsg/extended-window-styles|Extended Window Styles | Microsoft Docs} for a complete list. + * @param {(String)} [Title] + * The window title. If omitted, it defaults to the current value of {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptName|A_ScriptName)}. + * @param {(Object)} [EventObj] + * An "event sink", or object to bind events to. + * If EventObj is specified, {@link https://www.autohotkey.com/docs/v2/lib/GuiOnEvent.htm|OnEvent()}, {@link https://www.autohotkey.com/docs/v2/lib/GuiOnNotify.htm|OnNotify} and {@link https://www.autohotkey.com/docs/v2/lib/GuiOnCommand.htm|OnCommand} can be used to register methods of EventObj to be called when an event is raised. + * If omitted or empty, any string passed to OnEvent's Function parameter is interpreted as a function name. + * @returns {(Gui)} + * New gui object + * @example ? + */ + __New([Options, Title, EventObj]) => Gui +} /** - * Place the message in the message queue of the window or control. + * {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm|InputHook} + * An object which can be used to capture and interpret keyboard input. + * @property {(String)} EndKey - Returns the name of the end key which was pressed to terminate the Input. + * @property {(String)} EndMods - Returns a string of the modifiers which were logically down when Input was terminated. + * @property {(String)} EndReason - Returns an EndReason string indicating how Input was terminated. + * @property {(Boolean)} InProgress - Returns 1 (true) if the Input is in progress, otherwise 0 (false). + * @property {(String)} Input - Returns any text collected since the last time Input was started. + * @property {(String)} Match - Returns the MatchList item which caused the Input to terminate. + * @property {(FuncObj)} OnEnd - Retrieves or sets the function object which is called when Input is terminated. + * @property {(FuncObj)} OnChar - Retrieves or sets the function object which is called after a character is added to the input buffer. + * @property {(FuncObj)} OnKeyDown - Retrieves or sets the function object which is called when a notification-enabled key is pressed. + * @property {(FuncObj)} OnKeyUp - Retrieves or sets the function object which is called when a notification-enabled key is released. + * @property {(Boolean)} BackspaceIsUndo - Controls whether the Backspace key removes the most recently pressed character from the end of the Input buffer. + * @property {(Boolean)} CaseSensitive - Controls whether MatchList is case-sensitive. + * @property {(Boolean)} FindAnywhere - Controls whether each match can be a substring of the input text. + * @property {(Integer)} MinSendLevel - Retrieves or sets the minimum send level of input to collect. + * @property {(Boolean)} NotifyNonText - Controls whether the OnKeyDown and OnKeyUp callbacks are called whenever a non-text key is pressed. + * @property {(Float)} Timeout - Retrieves or sets the timeout value in seconds. + * @property {(Boolean)} VisibleNonText - Controls whether keys or key combinations which do not produce text are visible (not blocked). + * @property {(Boolean)} VisibleText - Controls whether keys or key combinations which produce text are visible (not blocked). */ -PostMessage(Msg, wParam := 0, lParam := 0 [, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +class InputHook extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndKey|`EndKey`} + * The normalized name of the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndKeys|end key} pressed to terminate the InputHook. + * EndKey is empty if {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndReason|`EndReason`} is not `EndKey`. + * @type String + * @example + */ + EndKey { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndMods|`EndMods`} + * Returns a string of the modifiers which were logically down when InputHook was terminated. + * Expected modifiers: `<^ >^ ! <+ >+ <# >#` + * @type String + * @example + */ + EndMods { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndReason|`EndReason`} + * The {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndReasons|EndReason string} indicating how InputHook was terminated. + * - Empty String = The InputHook is still in progress. + * - `Stopped ` = The {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#Stop|Stop()} method has not been called since the last {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#Start|Start()}. + * - `Max` = Maximum allowed length has been reached. + * - `Timeout` = + * - `Match` = + * - `EndKey` = + * @type String + * @example + */ + EndReason { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#InProgress|`InProgress`} + * The current progress status. + * `1` if the InputHook is in progress, otherwise `0`. + * @type Boolean + * @example + */ + InProgress { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#Input|`Input`} + * Any text collected since the last time the InputHook was started. + * Can be used while in progress. + * @type String + * @example + */ + Input { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#Match|`Match`} + * Returns the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#MatchList|MatchList} word that caused the InputHook to terminate. + * @type String + * @example + */ + Match { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#OnEnd|`OnEnd`} + * Retrieves or sets the {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} called when InputHook is terminated. + * Expected callback format: + * + * IH_OnEnd(InputHookObj) + * @type FuncObj + * @example + */ + OnEnd { + get => Func + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#OnChar|`OnChar`} + * Retrieves or sets the {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} called when a character is added to the InputHook buffer. + * This callback is not activated on an EndKey press. + * Expected callback format: + * + * IH_OnChar(InputHookObj, Char) + * @type FuncObj + * @example + */ + OnChar { + get => Func + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#OnKeyDown|`OnKeyDown`} + * Retrieves or sets the {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} called when a notification-enabled key is pressed. + * Notification is enabled with {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#KeyOpt|KeyOpt()} or the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#NotifyNonText|NotifyNonText} property. + * Expected callback format: + * + * IH_OnKeyDown(InputHookObj, VirtualKey, ScanCode) + * @type FuncObj + * @example + */ + OnKeyDown { + get => Func + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#OnKeyUp|`OnKeyUp`} + * Retrieves or sets the {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} called when a notification-enabled key is released. + * Notification is enabled with {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#KeyOpt|KeyOpt()} or the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#NotifyNonText|NotifyNonText} property. + * Expected callback format: + * + * IH_OnKeyUp(InputHookObj, VirtualKey, ScanCode) + * @type FuncObj + * @example + */ + OnKeyUp { + get => Func + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#BackspaceIsUndo|`BackspaceIsUndo`} + * Controls whether Backspace removes the most recent character from the end of the InputHook buffer. + * `1` for enabled, otherwise `0`. + * @type Boolean + * @example + */ + BackspaceIsUndo { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#CaseSensitive|`CaseSensitive`} + * Controls whether {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#MatchList|MatchList} is case-sensitive. + * `1` for enabled, otherwise `0`. + * @type Boolean + * @example + */ + CaseSensitive { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#FindAnywhere|`FindAnywhere`} + * Controls whether a match can happen in the middle of other text. + * `1` for enabled, otherwise `0`. + * @type Boolean + * @example + */ + FindAnywhere { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#MinSendLevel|`MinSendLevel`} + * Retrieves or sets the minimum {@link https://www.autohotkey.com/docs/v2/lib/SendLevel.htm|send level} of input to collect. + * This should be an integer between `0` and `101` + * @type Integer + * @example + */ + MinSendLevel { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#NotifyNonText|`NotifyNonText`} + * Controls whether {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#OnKeyDown|OnKeyDown} and {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#OnKeyUp|OnKeyUp} callbacks are called when a non-text key is pressed. + * `1` for enabled, otherwise `0`. + * @type Boolean + * @example + */ + NotifyNonText { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#Timeout|`Timeout`} + * Retrieves or sets the timeout value, in seconds, to wait after starting an InputHook. + * Use `0` for no timeout. + * @type Float + * @example + */ + Timeout { + get => Float + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#VisibleNonText|`VisibleNonText`} + * Controls whether keys or combinations which do not produce text are visible/allowed. + * `1` for enabled, otherwise `0`. + * @type Boolean + * @example + */ + VisibleNonText { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#VisibleText|`VisibleText`} + * Controls whether keys or combinations which produce text are visible/allowed. + * `1` for enabled, otherwise `0`. + * @type Boolean + * @example + */ + VisibleText { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm|`Call()`} + * @param {String|'B'|'C'|'E'|'I'|'L'|'M'|'T'|'V'|'*'} [Options] + * A string of zero or more options, with optional spaces between: + * - `B` = Sets the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#BackspaceIsUndo|BackspaceIsUndo} property to `0`. Backspace is ignored. + * - `C` = Sets the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#CaseSensitive|CaseSensitive} property to `1`, making the MatchList parameter case-sensitive. + * - `E` = Handle single-character end keys by character code instead of by keycode. + * That can provide more consistent results in some cases. + * - `I#` = Sets the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#MinSendLevel|MinSendLevel} property, where `#` is the new {@link https://www.autohotkey.com/docs/v2/lib/SendLevel.htm|send level}. + * - `L#` = Sent maximum length of InputHook, where `#` is the max amount of characters to capture. + * If max length is reached, {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndReason|EndReason} is set to `Max`. + * Max length is 1023. + * - `M` = Ctrl+a through ctrl+z keystrokes are transcribed to ASCII characters if they have an associated value. + * - `T#` = Sets the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#Timeout|timeout} property, in seconds, to wait after starting an InputHook. + * This number can be a float. + * - `V` = Sets the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#VisibleText|VisibleText} and {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#VisibleNonText|VisibleNonText} properties to `1`. + * Sends the user's keystrokes through instead of blocking them when captured. + * - `*` = Wildcard. Sets the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#FindAnywhere|FindAnywhere} property to `1`. + * Allows matches to found at any point during Input. + * @param {String|'{All}'|'{Alt}'|'{AppsKey}'|'{Backspace}'|'{Browser_Back}'|'{Browser_Favorites}'|'{Browser_Forward}'|'{Browser_Home}'|'{Browser_Refresh}'|'{Browser_Search}'|'{Browser_Stop}'|'{CapsLock}'|'{Control}'|'{CtrlBreak}'|'{Delete}'|'{Down}'|'{End}'|'{Enter}'|'{Escape}'|'{F1}'|'{F10}'|'{F11}'|'{F12}'|'{F13}'|'{F14}'|'{F15}'|'{F16}'|'{F17}'|'{F18}'|'{F19}'|'{F2}'|'{F20}'|'{F21}'|'{F22}'|'{F23}'|'{F24}'|'{F3}'|'{F4}'|'{F5}'|'{F6}'|'{F7}'|'{F8}'|'{F9}'|'{Help}'|'{Home}'|'{Insert}'|'{LAlt}'|'{Launch_App1}'|'{Launch_App2}'|'{Launch_Mail}'|'{Launch_Media}'|'{LButton}'|'{LControl}'|'{Left}'|'{LShift}'|'{LWin}'|'{MButton}'|'{Media_Next}'|'{Media_Play_Pause}'|'{Media_Prev}'|'{Media_Stop}'|'{NumLock}'|'{Numpad0}'|'{Numpad1}'|'{Numpad2}'|'{Numpad3}'|'{Numpad4}'|'{Numpad5}'|'{Numpad6}'|'{Numpad7}'|'{Numpad8}'|'{Numpad9}'|'{NumpadAdd}'|'{NumpadClear}'|'{NumpadDel}'|'{NumpadDiv}'|'{NumpadDot}'|'{NumpadDown}'|'{NumpadEnd}'|'{NumpadEnter}'|'{NumpadHome}'|'{NumpadIns}'|'{NumpadLeft}'|'{NumpadMult}'|'{NumpadPgDn}'|'{NumpadPgUp}'|'{NumpadRight}'|'{NumpadSub}'|'{NumpadUp}'|'{Pause}'|'{PgDn}'|'{PgUp}'|'{PrintScreen}'|'{RAlt}'|'{RButton}'|'{RControl}'|'{Right}'|'{RShift}'|'{RWin }'|'{SC###}'|'{ScrollLock}'|'{Shift}'|'{Sleep}'|'{Space}'|'{Tab}'|'{Up}'|'{VK##}'|'{Volume_Down}'|'{Volume_Mute}'|'{Volume_Up}'|'{WheelDown}'|'{WheelLeft}'|'{WheelRight}'|'{WheelUp}'|'{XButton1}'|'{XButton2}'} [EndKeys] + * List of zero or more keys that will end the running InputHook. + * The {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#FindAnywhere|EndReason} property is set to `EndKey`. + * The {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndKey|EndKey} property is set to the name of the key pressed. + * A list of keys. Use braces to enclose key names/virtual codes/scan codes. + * Literal braces should be enclosed in braces: `{{}` `{}}` + * Use `{All}` to apply `KeyOptions` to all VK and all SC. + * @param {(String)} [MatchList] + * A comma-separated list of words that will terminate the InputHook. + * Use 2 commas in a row to indicate a literal comma: `,,` + * The {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndReason|EndReason} property is set to `Match`. + * @returns {(InputHook)} + * An InputHook object is returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/KeyWait.htm|KeyWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm|InputBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InstallKeybdHook.htm|InstallKeybdHook()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstrings::} + * @example + */ + static Call([Options, EndKeys, MatchList]) => InputHook + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#KeyOpt|`KeyOpt()`} + * Sets options for a key or list of keys. + * @param {(String)} Keys + * A list of keys. + * Use braces to enclose key names/virtual codes/scan codes. + * Literal braces should be enclosed in braces: `{{}` `{}}` + * Use `{All}` to apply `KeyOptions` to all VK and all SC. + * @param {String|'E'|'I'|'N'|'S'|'V'} KeyOptions + * One or more of the following, separated by spaces/tabs. + * Use `-` to remove options and `+` to add them: + * - `E` = Set End key to terminate InputHook. + * Sets {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndReason|EndReason} prop to the word `EndKey`. + * The {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndKey|EndKey} property is set to the keys normalized name. + * - `I` = Ignore. This key's text is ignored and treated like {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#VisibleNonText|nonvisible text}. + * - `N` = Notify. {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#OnKeyDown|OnKeyDown} and {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#OnKeyUp|OnKeyUp} callbacks are called on key press. + * - `S` = Suppress. Blocks key after processing it. + * Overrides {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#VisibleText|VisibleText} and {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#VisibleNonText|VisibleNonText} properties until `-S` is used. + * `+S` implies `-V` + * - `V` = Visible. Prevents a key from being suppressed. + * Overrides {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#VisibleText|VisibleText} and {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#VisibleNonText|VisibleNonText} properties until `-S` is used. + * `+V` implies `-S` + * @returns {(String)} An empty string is always returned. + * @see @example + */ + KeyOpt(Keys, KeyOptions) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#Start|`Start()`} + * Starts collecting input and has no effect if already started. + * Newly started InputHooks are placed on top of the {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#stack|InputHook stack}. + * @returns {(String)} An empty string is always returned. + * @example + */ + Start() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#Stop|`Stop()`} + * Terminates the InputHook and sets {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndReason|EndReason} property to `Stopped`. + * @returns {(String)} An empty string is always returned. + * @example + */ + Stop() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#Wait|`Wait()`} + * Waits until the InputHook is terminated. + * Same as {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#InProgress|InProgress} property being false. + * @prop {(Float)} MaxTime - The maximum number of seconds to wait. + * If omitted, wait time is indefinite. + * @returns {(String)} The {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm#EndReason|EndReason}. + * @example + */ + Wait([MaxTime:=unset]) => String +} /** - * Forcibly close the first matching process. - * @param PIDOrName specifies the number (PID) or process name: - * - * PID: Process ID, a number that uniquely identifies a specific process (this number is meaningful only during the lifetime of the process). The PID of the newly running process can be obtained through the Run function. Similarly, the PID of the window can be obtained through WinGetPID . ProcessExist can also be used to obtain PID. - * - * Name: The name of the process, usually the same as its executable file name (without path), such as notepad.exe or winword.exe. Since a name may match multiple running processes, it will only be the first The operation is performed by each process. The name is not case sensitive. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm|`Map`} + * An object that stores data using an associated key. + * Keys can be strings, integers, or object references. + * @property {(Integer)} Count - Retrieves the number of key-value pairs present in a map. + * @property {(Integer)} Capacity - Retrieves or sets the current capacity of a map. + * @property {(Integer)} CaseSense - Retrieves or sets a map's case sensitivity setting. + * @property {(Any)} Default - Defines the default value returned when a key is not found. */ -ProcessClose(PIDOrName) => Integer +class Map extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Count|`Count`} + * Retrieves the number of key-value pairs in a map. + * @type Integer + * @example + */ + Count { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Capacity|`Capacity`} + * Retrieves or sets the current capacity of a map. + * The maximum amount of key-value pairs it can hold before the object size needs to be expanded. + * @type Integer + * @example + */ + Capacity { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#CaseSense|`CaseSense`} + * Retrieves or sets a map's case sensitivity setting. + * `1` or `On` to enable case sensitivity, otherwise `0` or `Off`. + * @type String|Integer + * @example + */ + CaseSense { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Default|`Default`} + * Defines the default value returned when a key is not found. + * This also prevents an {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#UnsetError|UnsetItemError} from being thrown when a key cannot be found. + * @type Any + * @example + */ + Default { + get => Any + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#__Item|`__Item`} + * Retrieves or sets the value of a key-value pair. + * Returns the {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Default|Default} property if key is not found. + * @type Any + * @example + */ + __Item[Key] => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Call|`Map()`} + * Creates a new Map object and optionally populates it. + * @param {(String|Integer|Object)} [KeyN] + * The identifying key of the value. + * Any number of `Key, Value,` pairs can be added. + * @param {(Any)} [ValueN] + * The value to associate with the key. + * Any number of `Key, Value,` pairs can be added. + * @example + * empty_map := Map() + * phonetic_map := Map('a', 'Alpha', 'b', 'Bravo', ) + * MsgBox('b is pronounced: ' phonetic_map['b']) + */ + static Call([KeyN, ValueN], *) => Map + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Clear|`Clear()`} + * Removes all key-value pairs from a map. + * @returns {(String)} An empty string is always returned. + * @example + */ + Clear() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Clone|`Clone()`} + * Returns a shallow copy of the map. + * Each property or method owned by the object is copied into the clone. + * Shallow copy means: + * - Primitive values are copied + * - Object **references** are copied. The objects themselves are not duplicated. + * Meaning the original and clone will reference the same objects. + * - Dynamic properties are copied but not invoked. + * @returns {(Map)} + * A shallow copy of the map is returned. + * @example + */ + Clone() => Map + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Delete|`Delete()`} + * Removes a key-value pair from a map. + * @param {(String|Integer|Object)} Key + * The identifying key of the key-value pair to delete. + * @returns {(Any)} + * The removed map element value is returned. + * @throws UnsetItemError - The map does not contain the specified key or a defined {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Default|Default} property. + * @example + */ + Delete(Key) => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Get|`Get()`} + * Returns the value associated with a key, or a default value if one is provided. + * @param {(String|Integer|Object)} Key + * The identifying key of the key-value pair to delete. + * @param {(Any)} [Default] + * A default value to use if the provided Key is not found. + * @returns {(Any)} + * The value associated with Key. + * Otherwise, the provided Default parameter is used. + * Otherwise, the defined {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Default} property is used. + * Otherwise, an UnsetItemError is thrown. + * @throws UnsetItemError - Value not set, no default parameter provided, and default property not defined. + * @example + */ + Get(Key [,Default:=unset]) => Any + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Has|`Has()`} + * Returns true if the specified key has an associated value within a map. + * @param {(String|Integer|Object)} Key + * The identifying key of the key-value pair to delete. + * @returns {(Boolean)} + * `1` if the map contains the provided key, otherwise `0`. + * @example + */ + Has(Key) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Set|`Set()`} + * Sets zero or more key-value pairs. + * If all parameters are omitted, Capacity is automatically adjusted to avoid expanding multiple times during a single call. + * @param {(String|Integer|Object)} [KeyN] + * The identifying key of the value. + * Any number of `Key, Value,` pairs can be added. + * @param {(Any)} [ValueN] + * The value to associate with the key. + * Any number of `Key, Value,` pairs can be added. + * @returns {(Map)} + * A reference to the map is always returned. + * @example + */ + Set([KeyN, ValueN], *) => Map + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#__Enum|`__Enum()`} + * Creates an {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|enumerator object} that iterates through each key-value pair of the map. + * This method is typically not called but instead is used by a {@link https://www.autohotkey.com/docs/v2/lib/For.htm|for-loop} to get each value and its index number. + * @returns {(Enumerator)} + * Enumerable function object. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|Enumerator Object} + * @example Manually using an enumerator. + * mapo := Map('v1.0', 'Good', 'v1.1', 'Great', 'v2.0', 'Best') + * + * For key, value in mapo + * MsgBox('key: ' key '`nvalue: ' value) + * + * enum := mapo.__Enum() + * While enum(&key, &value) + * MsgBox('Key: ' key '`nValue: ' value) + */ + __Enum() => Enumerator + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#__New|`__New()`} + * Sets items. Equivalent to {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Set|Set}. + * This method exists to support {@link https://www.autohotkey.com/docs/v2/lib/Map.htm#Call|Call()}, and is not intended to be called directly. + * @param {(String|Integer|Object)} [KeyN] + * The identifying key of the value. + * Any number of `Key, Value,` pairs can be added. + * @param {(Any)} [ValueN] + * The value to associate with the key. + * Any number of `Key, Value,` pairs can be added. + */ + __New([KeyN, ValueN, *]) => EmptyString +} /** - * Check if the specified process exists. - * @param PIDOrName If empty or omitted, use the script's own process. Otherwise, specify a number (PID) or process name: - * - * PID: Process ID, it is a number that uniquely identifies a specific process (this number is only valid during the existence period of the process). The PID of the newly started process can be determined by the Run function. Similarly, the PID of the window can also be used WinGetPID to determine. - * - * Name: The name of the process is usually the same as its executable file (no path), such as notepad.exe or winword.exe. Since the name may match multiple running processes, only the first matching process is operated on. The name is not case sensitive. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|`Menu`} + * An object used to define, modify, and display popup menus. + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Call|Menu()}, {@link https://www.autohotkey.com/docs/v2/lib/MenuFromHandle.htm|MenuFromHandle()} and {@link https://www.autohotkey.com/docs/v2/Variables.htm#TrayMenu|A_TrayMenu} return an object of this type. + * @property {(Integer)} ClickCount - Retrieves or sets how many times the tray icon must be clicked to select its default menu item. + * @property {(Any)} Default - Retrieves or sets the default menu item. + * @property {(Integer)} Handle - Retrieves the menu's Win32 handle. */ -ProcessExist(PIDOrName?) => Integer +class Menu extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#ClickCount|`ClickCount`} + * Get or set the number of times the {@link https://www.autohotkey.com/docs/v2/Program.htm#tray-icon|tray icon} must be clicked to activate the {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Default|default} menu item. + * This value must be a `1` or `2` and is 2 by default. + * @type Integer + * @throws ValueError - A number other than 1 or 2 was assigned + * @example + */ + ClickCount { + get => Integer + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Default|`Default`} + * Get or set the default menu item. + * When no Default is set, this is an empty string. + * @type Menu|String + * @example + */ + Default { + get => Menu | String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Handle|`Handle`} + * Retrieves the menu's {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Win32_Menus|Win32 handle}. + * @type Integer + * @example + */ + Handle { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Handle|`Menu()`} + * Creates a new Menu object. + * @returns {(Menu)} + * A new menu object. + */ + static Call() => Menu + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Add|`Add()`} + * Add or modify a menu item. + * To add a menu separator, omit all parameters. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the menu text to display or the position of an existing item to modify. + * Names are limited to 260 characters. + * @param {(FuncObj|Menu)} [CallbackOrSubmenu] + * A callback or submenu item to call as a new {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread}. + * Can be omitted when updating an existing item. + * Expected callback format: + * + * menu_callback(ItemName, ItemPos, MenuRef) + * @param {String|'P'|'Radio'|'Right'|'Break'|'BarBreak'} [Options] + * Zero or more of the following options, separated by spaces/tabs. + * If omitted, no options are used. + * - `P#` + * Set {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread priority}, where `#` is the new priority level. + * This is 0 by default. + * - `Radio` + * Uses a radio button instead of a checkbox. + * - `Right` + * The string is right-justified. + * Only applies to {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#MenuBar|menu bars}. + * - `Break` + * The item begins a new column in a popup menu. + * - `BarBreak` + * Same as the `Break` option with a dividing line added between columns. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Add([MenuItemName:=unset, CallbackOrSubmenu:=unset, Options:=unset]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#AddStandard|`AddStandard()`} + * Adds the standard tray menu items. + * @returns {(String)} + * An empty string is always returned. + * @example Standard Menu Layout. + * + *; ___________________ Position Number + *; | &Open | 1 + *; | &Help | 2 + *; | ---------------- | 3 + *; | &Window Spy | 4 + *; | &Reload Script | 5 + *; | &Edit Script | 6 + *; | ---------------- | 7 + *; | &Suspend Hotkeys | 8 + *; | &Pause Script | 9 + *; | E&xit | 10 + *; |__________________| + * + */ + AddStandard() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Check|`Check()`} + * Adds a visible checkmark next to a menu item. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item to check. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Check(MenuItemName) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Delete|`Delete()`} + * Deletes one or all menu items. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item to delete. + * If omitted, all menu items are deleted. + * To delete a separator, use its position number. + * + * ; If 3rd item is a separator + * menu_ref.Delete('&3') + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Delete([MenuItemName:=unset]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Disable|`Disable()`} + * Grays out a menu item to indicate that the user cannot select it. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item to disable. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Disable(MenuItemName) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Enable|`Enable()`} + * Allows the user to once again select a menu item if it was previously disabled (grayed out). + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item to enable. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Enable(MenuItemName) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Insert|`Insert()`} + * Inserts a new item at the specified location, moving all other items down. + * Omit all parameters to insert a menu separator. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item to insert an item at. + * If omitted, item will be added to the bottom of the menu. + * @param {(String)} [Item] + * The name of a new menu item. + * A new item is always created, even if the item already exists. + * @param {(FuncObj|Menu)} [CallbackOrSubmenu] + * A callback or submenu item to call as a new {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread}. + * Can be omitted when updating an existing item. + * Expected callback format: + * + * menu_callback(ItemName, ItemPos, MenuRef) + * @param {String|'P'|'Radio'|'Right'|'Break'|'BarBreak'} [Options] + * Zero or more of the following options, separated by spaces/tabs. + * If omitted, no options are used. + * - `P#` + * Set {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread priority}, where `#` is the new priority level. + * This is 0 by default. + * - `Radio` + * Uses a radio button instead of a checkbox. + * - `Right` + * The string is right-justified. + * Only applies to {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#MenuBar|menu bars}. + * - `Break` + * The item begins a new column in a popup menu. + * - `BarBreak` + * Same as the `Break` option with a dividing line added between columns. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Insert([MenuItemName:=unset, Item:=unset, CallbackOrSubmenu:=unset, Options:=unset]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Rename|`Rename()`} + * Renames a menu item. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item to rename. + * @param {(String)} [NewName] + * The new menu name. + * If omitted, menu item is converted to a menu separator. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Rename(MenuItemName [,NewName:=unset]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#SetColor|`SetColor()`} + * Changes the background color of the menu. + * @param {(String|Integer)} ColorValue + * A hex value, {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name}, the word Default, or omitted. + * If omitted, `Default` is used + * - RGB hex value (0x prefix is optional): `0x000000` to `FFffFF` + * - Default Color: `Default` + * - Color Name: + * + * Color Chart: + * | Color | RGB | Color | RGB | Color | RGB | Color | RGB | + * | --: | :-- | --: | :-- | --: | :-- | --: | :-- | + * | `Black` | 000000 | `Gray` | 808080 | `Silver` | C0C0C0 | `White` | FFFFFF | + * | `Red` | FF0000 | `Maroon` | 800000 | `Purple` | 800080 | `Fuchsia` | FF00FF | + * | `Lime` | 00FF00 | `Green` | 008000 | `Olive` | 808000 | `Yellow` | FFFF00 | + * | `Blue` | 0000FF | `Navy` | 000080 | `Teal` | 008080 | `Aqua` | 00FFFF | + * @param {(Boolean)} ApplyToSubmenus + * `1` = Color is applied to all menu submenus. + * `0` = Color only applied to the specified menu. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + SetColor([ColorValue:='Default', ApplyToSubmenus:=1]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#SetIcon|`SetIcon()`} + * Sets the icon to be displayed next to a menu item. + * @param {(String)} MenuItemName + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item. + * @param {(String)} FileName + * The path to an icon, image file, {@link https://www.autohotkey.com/docs/v2/misc/ImageHandles.htm|bitmap, or icon handle}. + * Supported types: .ICO .CUR .ANI .EXE .DLL .CPL .SCR {@link https://www.autohotkey.com/docs/v2/misc/ImageHandles.htm|Icon Handle "HICON:"} or another icon resource + * Use a `*` or an empty string to remove the icon from the menu. + * @param {(Integer)} [IconNumber] + * The icon number of the icon group from FileName. + * If omitted, `1` is used. + * @param {(Integer)} [IconWidth] + * The desired icon width. + * If `0` is used, the original width is applied. + * If omitted, the OS default small icon width is used, usually 16 pixels. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + SetIcon(MenuItemName, FileName [,IconNumber:=1, IconWidth:=unset]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Show|`Show()`} + * Displays the menu. + * @param {(Integer)} [X] + * The x coordinate of the menu's upper left corner. + * If omitted, the mouse's x coord is used. + * @param {(Integer)} [Y] + * The y coordinate of the menu's upper left corner. + * If omitted, the mouse's y coord is used. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Show([X, Y]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#ToggleCheck|`ToggleCheck()`} + * Toggles the checkmark next to a menu item. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + ToggleCheck(MenuItemName) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#ToggleEnable|`ToggleEnable()`} + * Enables or disables a menu item. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + ToggleEnable() => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Uncheck|`Uncheck()`} + * Removes the checkmark (if there is one) from a menu item. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item to uncheck. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Uncheck() => EmptyString +} /** - * Returns the name of the specified process. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|`MenuBar`} + * An object used to define and modify a Gui's menu bar through the {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#MenuBar|Gui.MenuBar property}. + * @property {(Integer)} ClickCount - Retrieves or sets how many times the tray icon must be clicked to select its default menu item. + * @property {(Any)} Default - Retrieves or sets the default menu item. + * @property {(Integer)} Handle - Retrieves the menu's Win32 handle. */ -ProcessGetName(PIDOrName?) => String +class MenuBar extends Menu { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Handle|`Menu()`} + * Creates a new MenuBar object. + * @returns {(Menu)} + * A new MenuBar object. + */ + static Call() => MenuBar + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Add|`Add()`} + * Add or modify a menu bar item. + * To add a menu separator, omit all parameters. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the menu text to display or the position of an existing item to modify. + * Names are limited to 260 characters. + * @param {(FuncObj|Menu)} [CallbackOrSubmenu] + * A callback or submenu item to call as a new {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread}. + * Can be omitted when updating an existing item. + * Expected callback format: + * + * menu_callback(ItemName, ItemPos, MenuRef) + * @param {String|'P'|'Radio'|'Right'|'Break'|'BarBreak'} [Options] + * Zero or more of the following options, separated by spaces/tabs. + * If omitted, no options are used. + * - `P#` + * Set {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread priority}, where `#` is the new priority level. + * This is 0 by default. + * - `Radio` + * Uses a radio button instead of a checkbox. + * - `Right` + * The string is right-justified. + * - `Break` + * The item begins a new column in a popup menu. + * - `BarBreak` + * Same as the `Break` option with a dividing line added between columns. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Add([MenuItemName:=unset, CallbackOrSubmenu:=unset, Options:=unset]) => EmptyString + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Insert|`Insert()`} + * Inserts a new item at the specified location, moving all other items down. + * Omit all parameters to insert a menu separator. + * @param {(String)} [MenuItemName] + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#MenuItemName|MenuItemame} is the name or the position of an existing item to insert an item at. + * If omitted, item will be added to the bottom of the menu. + * @param {(String)} [Item] + * The name of a new menu item. + * A new item is always created, even if the item already exists. + * @param {(FuncObj|Menu)} [CallbackOrSubmenu] + * A callback or submenu item to call as a new {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread}. + * Can be omitted when updating an existing item. + * Expected callback format: + * + * menu_callback(ItemName, ItemPos, MenuRef) + * @param {String|'P'|'Radio'|'Right'|'Break'|'BarBreak'} [Options] + * Zero or more of the following options, separated by spaces/tabs. + * If omitted, no options are used. + * - `P#` + * Set {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread priority}, where `#` is the new priority level. + * This is 0 by default. + * - `Radio` + * Uses a radio button instead of a checkbox. + * - `Right` + * The string is right-justified. + * - `Break` + * The item begins a new column in a popup menu. + * - `BarBreak` + * Same as the `Break` option with a dividing line added between columns. + * @returns {(String)} + * An empty string is always returned. + * @example + */ + Insert([MenuItemName:=unset, Item:=unset, CallbackOrSubmenu:=unset, Options:=unset]) => EmptyString + + /** + * An error is thrown when a MenuBar object tries to use the `Show()` method. + */ + Show() => Error +} /** - * Returns the process ID (PID) of the process which created the specified process. + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObjec|`RegExMatchInfo`} + * An object with multiple properties containing information about a {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|RegExMatch()} result. + * @property {(Integer)} Count - Returns the total number of captured subpatterns. + * @property {(Integer)} Len - The length of the overall match or a captured subpattern. + * @property {(Integer)} Mark - Returns the NAME of the last encountered `(*MARK:NAME)`, when applicable. + * @property {(Integer)} Match - Returns the overall match or a captured subpattern. + * @property {(Integer)} Name - The name of the overall match or a captured subpattern, if it has one. */ -ProcessGetParent(PIDOrName?) => Integer +class RegExMatchInfo extends Object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|`Count`} + * Returns the total number of captured subpatterns. + * This is also the max number [N] can be for any other method or property calls. + * @type Integer + * @example + */ + Count { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|`Len[]`} + * The length of the overall match or a captured subpattern. + * @param {(Integer|String)} [N] + * The number of a captured subpattern. + * Named subpatterns can be referenced by number or name. + * If omitted or `0`, the overall match is returned. + * @type Integer + * @example + */ + Len[N:=0] { + get => Integer + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|Mark} + * Returns the NAME of the last encountered `(*MARK:NAME)`, when applicable. + * Mark can be used for internal engine backtracking. + * @type String + * @example + */ + Mark { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|`Match`} + * Returns the overall match or a captured subpattern. + * @param {(Integer|String)} [N] + * The number of a captured subpattern. + * Named subpatterns can be referenced by number or name. + * If omitted or `0`, the overall match is returned. + * As a shorthand method, the word Match can be omitted if there is no space in the subpattern name. + * + * rgxObj.Match['Something'] => 'Some value' + * rgxObj.Something => 'Some value' + * @type Integer + * @example + */ + Match[N:=0] { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|`Name[]`} + * The name of the overall match or a captured subpattern, if it has one. + * @param {(Integer|String)} [N] + * The number of a captured subpattern. + * Named subpatterns can be referenced by number or name. + * If omitted or `0`, the overall match is returned. + * @type String + * @example + */ + Name[N:=0] { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|`Pos[]`} + * The string position of the overall match or a captured subpattern. + * @param {(Integer|String)} [N] + * The name or number of a captured subpattern. + * If omitted or `0`, the overall match is returned. + * @type Integer + * @example + */ + Pos[N:=0] { + get => String + set => Error + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|`Len()`} + * The length of the overall match or a captured subpattern. + * @param {(Integer|String)} [N] + * The number of a captured subpattern. + * Named subpatterns can be referenced by number or name. + * If omitted or `0`, the overall match is returned. + * @returns {(Integer)} + * The length of the specified subpattern or overall match. + * @example + */ + Len([N:=0]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|`Name()`} + * Returns the name of the given subpattern, if it has one. + * @param {(Integer|String)} [N] + * The number of a captured subpattern. + * Named subpatterns can be referenced by number or name. + * If omitted or `0`, the overall match is returned. + * @returns {(String)} + * The captured text. + * @example + */ + Name([N:=0]) => String + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|`Pos()`} + * The string position of the overall match or a captured subpattern. + * @param {(Integer|String)} [N] + * The number of a captured subpattern. + * Named subpatterns can be referenced by number or name. + * If omitted or `0`, the overall match is returned. + * @returns {(Integer)} + * The string position of the specified subpattern or overall match. + * @example + */ + Pos([N:=0]) => Integer +} -/** - * Returns the path of the specified process. - */ -ProcessGetPath(PIDOrName?) => String +class Primitive extends Any { + +} -/** - * Change the priority of the first matching process. - * @param {'Low'|'BelowNormal'|'Normal'|'AboveNormal'|'High'|'Realtime'} Level - */ -ProcessSetPriority(Level, PIDOrName?) => Integer +Class String extends Primitive { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/String.htm|`String()`} + * Converts a value to string type. + * @param {(String|Number|Object)} Value + * Dependent on object type: + * - `String` = No conversion happens. + * - `Number` = Converted using {@link https://www.autohotkey.com/docs/v2/Concepts.htm#number-default-format|default decimal formatting}. + * - `Object` = Uses a user-defined `ToString()` method. + * If ToString() has not been defined, an error is thrown. + * @returns {(String)} + * The value converted to a string + * @throws MethodError - Invalid value type + * @see {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Integer.htm|Integer()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Float.htm|Float()} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#values|Values} | + * {@link https://www.autohotkey.com/docs/v2/Language.htm#expressions|Expressions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} + * @example + */ + static Call(Value) => String +} -/** - * Wait for the specified process to exist. - */ -ProcessWait(PIDOrName [, Timeout]) => Integer +class Number extends Primitive { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/String.htm|`String()`} + * Converts a numeric string to a pure integer or float type. + * @param {(String)} Value + * A string representing a number. + * @returns {(Integer|Float)} + * An integer or float version of value. + * @throws TypeError - Value cannot be converted + * To prevent this, use {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#number|IsNumber()} first. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Integer.htm|Integer()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Float.htm|Float()} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#values|Values} | + * {@link https://www.autohotkey.com/docs/v2/Language.htm#expressions|Expressions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} + * @example + */ + static Call(Value) => Number +} -/** - * Wait for the matching process to close. - */ -ProcessWaitClose(PIDOrName [, Timeout]) => Integer +Class Float extends Number { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Float.htm|`Float()`} + * Converts a numeric string or integer value to a float type. + * @param {(String|Integer)} Value + * A string or integer to convert to float type. + * @returns {(Float)} + * The numerical version of value. + * @throws TypeError - Value cannot be converted + * To prevent this, use {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#number|IsNumber()} first. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Integer.htm|Integer()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Number.htm|Number()} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#values|Values} | + * {@link https://www.autohotkey.com/docs/v2/Language.htm#expressions|Expressions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} + * @example + */ + static Call(Value) => Float +} -/** - * Generate a pseudo-random number. - * - * The minimum and/or maximum quantities to be generated are specified in either order. If only one parameter is specified, the other parameter defaults to 0. If both are omitted, the default is 0.0 to 1.0. - * - * For integers, the minimum and maximum values are included in the set of possible numbers that may be returned. The full range of 64-bit integers is supported. - * - * For floating point numbers, the maximum value is usually not included. - */ -Random([A, B]) => Float | Integer +Class Integer extends Number { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Float.htm|`Float()`} + * Converts a numeric string or float value to an integer type. + * @param {(String|Float)} Value + * A string or integer to convert to float type. + * @returns {(Integer)} + * The numerical version of value. + * @throws TypeError - Value cannot be converted + * To prevent this, use {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#number|IsNumber()} first. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Integer.htm|Integer()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Float.htm|Float()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Number.htm|Number()} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#values|Values} | + * {@link https://www.autohotkey.com/docs/v2/Language.htm#expressions|Expressions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} + * @example + */ + static Call(Value) => Integer +} -/** - * Creates a registry key without writing a value. - */ -RegCreateKey(KeyName?) => void +class VarRef extends Any { + +} /** - * Delete the value from the registry. + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|`ComValue`} + * Wraps a value, SafeArray, or COM object for use by the script or for passing to a COM method. */ -RegDelete([KeyName, ValueName]) => void +class ComValue extends Any { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|`ComValue`} + * Wraps a value, SafeArray or COM object for use by the script or for passing to a COM method. + * @param {(Integer)} VarType + * An integer to indicate the {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm#vt|type of value}. + * | Name | Value | Definition | + * | :-- | --: | :-- | + * | `VT_EMPTY` | `0x0` | No value | + * | `VT_NULL` | `0x1` | SQL-style Null | + * | `VT_I2` | `0x2` | 16-bit signed int | + * | `VT_I4` | `0x3` | 32-bit signed int | + * | `VT_R4` | `0x4` | 32-bit floating-point number | + * | `VT_R8` | `0x5` | 64-bit floating-point number | + * | `VT_CY` | `0x6` | Currency | + * | `VT_DATE` | `0x7` | Date | + * | `VT_BSTR` | `0x8` | COM string (Unicode string with length prefix) | + * | `VT_DISPATCH` | `0x9` | COM object | + * | `VT_ERROR` | `0xA` | Error code (32-bit integer) | + * | `VT_BOOL` | `0xB` | Boolean True (-1) or False (0) | + * | `VT_VARIANT` | `0xC` | VARIANT (used with VT_ARRAY or VT_BYREF) | + * | `VT_UNKNOWN` | `0xD` | IUnknown interface pointer | + * | `VT_DECIMAL` | `0xE` | (not supported) | + * | `VT_I1` | `0x10` | 8-bit signed int | + * | `VT_UI1` | `0x11` | 8-bit unsigned int | + * | `VT_UI2` | `0x12` | 16-bit unsigned int | + * | `VT_UI4` | `0x13` | 32-bit unsigned int | + * | `VT_I8` | `0x14` | 64-bit signed int | + * | `VT_UI8` | `0x15` | 64-bit unsigned int | + * | `VT_INT` | `0x16` | Signed machine int | + * | `VT_UINT` | `0x17` | Unsigned machine int | + * | `VT_RECORD` | `0x24` | User-defined type -- NOT SUPPORTED | + * | `VT_ARRAY` | `0x2000` | SAFEARRAY | + * | `VT_BYREF` | `0x4000` | Pointer to another type of value | + * @param {(Any)} Value - The value to wrap. + * @param {(Integer)} [Flags] - {@link https://www.autohotkey.com/docs/v2/lib/ComObjFlags.htm|Flags} affecting the behaviour of the wrapper object. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComObjFromPtr.htm|ComObjFromPtr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|ComObjGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjConnect.htm|ComObjConnect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjFlags.htm|ComObjFlags()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ObjAddRef.htm|ObjAddRef()/ObjRelease()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjQuery.htm|ComObjQuery()} | + * {@link https://learn.microsoft.com/windows/win32/api/oleauto/nf-oleauto-getactiveobject|GetActiveObject (Microsoft Docs)} + * @returns {(Object)} + * A wrapper object containing the {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm#vt|variant type}. + * Type can be: `ComValue`, `ComValueRef`, `ComObjArray`, or `ComObject`. + */ + static Call(VarType, Value [,Flags:=unset]) => Object +} /** - * Delete subkeys from the registry. + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjArray.htm|`ComObjArray`} + * Creates a SafeArray for use with COM. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm|ComObjType} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjValue.htm|ComObjValue} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjActive.htm|ComObjActive} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjFlags.htm|ComObjFlags} | + * {@link https://learn.microsoft.com/previous-versions/windows/desktop/automat/array-manipulation-functions|Array Manipulation Functions (Microsoft Docs)} */ -RegDeleteKey([KeyName]) => void +class ComObjArray extends ComValue { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|`ComValue()`} + * @param {(Integer)} VarType + * An integer to indicate the {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm#vt|type of value}. + * | Name | Value | Definition | + * | :-- | --: | :-- | + * | `VT_EMPTY` | `0x0` | No value | + * | `VT_NULL` | `0x1` | SQL-style Null | + * | `VT_I2` | `0x2` | 16-bit signed int | + * | `VT_I4` | `0x3` | 32-bit signed int | + * | `VT_R4` | `0x4` | 32-bit floating-point number | + * | `VT_R8` | `0x5` | 64-bit floating-point number | + * | `VT_CY` | `0x6` | Currency | + * | `VT_DATE` | `0x7` | Date | + * | `VT_BSTR` | `0x8` | COM string (Unicode string with length prefix) | + * | `VT_DISPATCH` | `0x9` | COM object | + * | `VT_ERROR` | `0xA` | Error code (32-bit integer) | + * | `VT_BOOL` | `0xB` | Boolean True (-1) or False (0) | + * | `VT_VARIANT` | `0xC` | VARIANT (used with VT_ARRAY or VT_BYREF) | + * | `VT_UNKNOWN` | `0xD` | IUnknown interface pointer | + * | `VT_DECIMAL` | `0xE` | (not supported) | + * | `VT_I1` | `0x10` | 8-bit signed int | + * | `VT_UI1` | `0x11` | 8-bit unsigned int | + * | `VT_UI2` | `0x12` | 16-bit unsigned int | + * | `VT_UI4` | `0x13` | 32-bit unsigned int | + * | `VT_I8` | `0x14` | 64-bit signed int | + * | `VT_UI8` | `0x15` | 64-bit unsigned int | + * | `VT_INT` | `0x16` | Signed machine int | + * | `VT_UINT` | `0x17` | Unsigned machine int | + * | `VT_RECORD` | `0x24` | User-defined type -- NOT SUPPORTED | + * | `VT_ARRAY` | `0x2000` | SAFEARRAY | + * | `VT_BYREF` | `0x4000` | Pointer to another type of value | + * @param {(Integer)} ArrSize1 + * The size of the first array. + * @param {(Integer)} [ArrSize2to8] + * The size of each additional array dimension. + * Up to 8 dimensions are supported. + * @returns {(ComObjArray)} + * A wrapper object containing a new SafeArray. + */ + Call(VarType, ArrSize1 [,ArrSize2to8*]) => ComObjArray + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjArray.htm#Methods|`MaxIndex()`} + * Returns the upper bound of the dimension. + * @param [ArrDim] + * The dimension (depth) of the array to use. + * If ArrDim is omitted, it defaults to 1. + * @returns {(Integer)} + */ + MaxIndex([ArrDim:=1]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjArray.htm#Methods|`MinIndex()`} + * Returns the lower bound of the nth dimension. If n is omitted, it defaults to 1. + * @param [ArrDim] + * The dimension (depth) of the array to use. + * If ArrDim is omitted, it defaults to 1. + * @returns {(Integer)} + * + */ + MinIndex([ArrDim:=1]) => Integer + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjArray.htm#Methods|`Clone()`} + * Returns a copy of the array. + * @returns {(ComObjArray)} + * A copy of the current ComObjArray. + */ + Clone() => ComObjArray + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjArray.htm#Methods|`__Enum()`} + * Creates an {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|enumerator object} that iterates through each element pair of the SafeArray. + * This method is typically not called but instead is used by a {@link https://www.autohotkey.com/docs/v2/lib/For.htm|for-loop} to get each element and its index number. + * @returns {(Enumerator)} + * Enumerable function object. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|Enumerator Object} + */ + __Enum() => Enumerator +} /** - * Determine whether the string contains a certain matching pattern (regular expression). + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|`ComObject`} + * Creates a COM object. */ -RegExMatch(Haystack, NeedleRegEx, &OutputVar?: VarRef, StartingPosition := 1) => Integer +class ComObject extends ComValue { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|`ComObject`} + * Creates a COM object. + * @param {(String)} CLSID + * CLSID or human-readable Prog ID of the COM object to create. + * @param {(String)} [IID] + * Specify the identifier of the interface to return. + * If omitted, it defaults to IID_IDispatch: + * `{00020400-0000-0000-C000-000000000046}` + * @returns {(Object)} + * A COM wrapper object. Type is dependent on the IID parameter. + * \- IID_IDispatch = {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject} = VT_DISPATCH (9) + * \- Any other IID = {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} = VT_UNKNOWN (13) + * @example Toggle active window taskbar button. + * $F1::toggle_taskbutton('hide') + * $F2::toggle_taskbutton('show') + * + * toggle_taskbutton(opt:='') { + * ; ITaskbarList + * ; https://learn.microsoft.com/windows/win32/api/shobjidl_core/nn-shobjidl_core-itaskbarlist + * CLSID_TaskbarList := '{56FDF344-FD6D-11d0-958A-006097C9A090}' + * IID_ITaskbarList := '{56FDF342-FD6D-11d0-958A-006097C9A090}' + * tbl := ComObject(CLSID_TaskbarList, IID_ITaskbarList) + * activeHwnd := WinExist('A') + * ComCall(3, tbl) + * switch opt { + * case 'hide': ComCall(5, tbl, 'ptr', activeHwnd) + * case 'show': ComCall(4, tbl, 'ptr', activeHwnd) + * } + * tbl := '' + * } + */ + static Call(CLSID [,IID:='{00020400-0000-0000-C000-000000000046}']) => Object +} /** - * Replace the place where the matching pattern (regular expression) appears in the string. - * @param {String} Replacement - * @param {(m: RegExMatchInfo) => String} Replacement [@since v2.1 or ahk_h v2.0] + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|`ComValueRef`} + * Used for VT_BYREF com values. */ -RegExReplace(Haystack, NeedleRegEx, Replacement?, &OutputVarCount?: VarRef, Limit := -1, StartingPosition := 1) => String +class ComValueRef extends ComValue { +} +;@endregion -/** - * Read the value from the registry. - */ -RegRead([KeyName, ValueName, Default]) => String +;@region typedef +class $InputBoxObject extends object { + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm#return|`Result`} + * Indicates how the InputBox was closed: + * - `OK` = OK was pressed. + * - `Cancel` = Cancel or the window X was pressed. + * - `Timeout` = InputBox window timed out. + * @type String + */ + Result { + get => String + set => EmptyString + } + + /** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm#return|`Value`} + * The text entered by the user. + * @type String + */ + Value{ + get => String + set => EmptyString + } +} +;@endregion +;@region functions /** - * Write the value to the registry. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Abs|`Abs()`} + * Returns the absolute value of the specified number. + * Absolute value is the greatest magnitude of the number regardless of its sign. + * @param {(Number)} Num + * Number to get absolute value of. + * @returns {(Number)} + * Absolute value of number + * @example Absolute value examples. + * x := Abs(-50) ; => 50 + * y := Abs(15) ; => 15 + * z := Abs(-5.5) ; => 5.5 + * MsgBox(x '`n' y '`n' z) + */ +Abs(Num) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#ASin|`ASin()`} + * Returns the arcsine in radians. + * Arcsine is the inverse trigonometric function of the sine function. + * @param {(Number)} Num + * The sine number. Must be between 1 and -1. + * @returns {(Number)} + * Arcsine in radians. + * @example + * ASin(0.2) ; => 0.201358 + * ASin(0) ; => 0.0 + * ASin(1) ; => 1.570796 + */ +ASin(Num) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#ACos|`ACos()`} + * Returns the arccosine in radians. + * Arccosine is the inverse trigonometric function of the cosine function. + * @param {(Number)} Num + * The cosine number. This must be between 1 and -1. + * @returns {(Number)} + * Arccosine in radians. + * @example + * ACos(0.2) ; => 1.369438 + * ACos(0) ; => 1.570796 + * ACos(1) ; => 0.0 + */ +ACos(Num) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#ATan|`ATan()`} + * Returns the arctangent in radians. + * Arctangent is the inverse trigonometric function of the tangent function. + * @param {(Number)} Num + * The tangent number. + * @returns {(Number)} + * Arctangent in radians. + * @example + * ATan(1.2) ; => 0.876058 + * ATan(0) ; => 0.0 + * ATan(1) ; => 1.557408 + */ +ATan(Num) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|`BlockInput()`} + * Disables or enables the user's + * ability to interact with the computer via keyboard and mouse. + * @param {'On'|'Off'|'Send'|'Mouse'|'Default'|'MouseMove'|'MouseMoveOff'} [Mode] + * A mode from one of the the 3 groups. + * Each of the 3 groups operate independently of each other. + * - OnOff Group: + * - `1` or `On` = Mouse and keyboard input is disabled. + * - `0` or `Off` = Mouse and keyboard input is enabled. + * + * - SendMouse Group: + * - `Send` = Keyboard and mouse input is disabled while a {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendEvent|SendEvent} is running, preventing disruption of keys being sent. + * - `Mouse` = Keyboard and mouse input is disabled while {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()}, {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()}, {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()}, or {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()} is running and prevents user input from disrupting mouse events. + * - `SendAndMouse` = Enables both `Send` and `Mouse` modes. + * - `Default` = Disables both `Send` and `Mouse` modes if they're on. + * This is the "Off" setting for SendMouse modes. + * + * - MouseMove Group: + * - `MouseMove` = User mouse movement is disabled. + * DirectInput applications are a possible exception. + * - `MouseMoveOff` = Disables `MouseMove` if it's enabled. + * This is the "Off" setting for Mouse modes. + * @returns {(String)} + * An empty string is always returned. + * @example Hotkey to toggle keyboard and mouse input on/off. + * *F1:: { + * Static lock := 0 + * lock := !lock + * TrayTip(lock) + * if lock + * BlockInput(1) + * else BlockInput('Off') + * } + */ +BlockInput([Mode]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm|`CallbackCreate()`} + * Creates a machine-code address that when called, + * redirects the call to a function in the script. + * @param {(FuncObj)} Function + * A {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} to call when + * the created callback address is called. + * @param {'&var'|'Fast'|'CDecl'} Options + * + * - Empty String = A new {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread} is created. + * - `Fast` or `F` = Avoid starting a new thread each time the Function Object is called. + * - `CDecl` or `C` = Causes address to conform to the 'C' calling convention. + * Typically omitted because standard calling is much more common for callbacks. + * - `&` = Causes the address of the parameter list to be passed to Function. + * Parameter values can be retrieved using NumGet. + * When using the standard 32-bit calling convention, + * ParamCount must specify the size of the parameter list in DWORDs (the number of bytes divided by 4). + * @param {(Integer)} ParamCount + * If omitted, {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#MinParams|Function.MinParams} is used. + * Otherwise, the number of parameters that Address' caller will pass to it. + * In either case, ensure that the caller passes exactly this number of parameters + * @returns {(Integer)} + * A machine code address. + * @example Enumerating through all windows. + * enumerate_windows() + * + * enumerate_windows() { + * output := 'HWND`tTitle`tClass`n' + * callback := CallbackCreate(EnumWindowsProc, 'Fast') + * DetectHiddenWindows(true) + * DllCall('EnumWindows', 'Ptr', callback, 'Ptr') + * MsgBox(Output) + * CallbackFree(callback) + * return + * + * EnumWindowsProc(hwnd, lParam){ + * win_title := WinGetTitle(hwnd) + * if win_title + * Output .= 'HWND: ' hwnd + * . '`tTitle: ' win_title + * . '`tClass: ' WinGetClass(hwnd) '`n' + * return true + * } + * } + */ +CallbackCreate(Function [,Options:='', ParamCount:=unset]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm#CallbackFree|`CallbackFree()`} + * Frees a callback created by {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm#CallbackFree|CallbackCreate()}. + * @param {(Integer)} Address + * A callback address. + * @returns {(String)} + * An empty string is always returned. + * @example Enumerating through all windows. + * enumerate_windows() + * + * enumerate_windows() { + * output := 'HWND`tTitle`tClass`n' + * callback := CallbackCreate(EnumWindowsProc, 'Fast') + * DetectHiddenWindows(true) + * DllCall('EnumWindows', 'Ptr', callback, 'Ptr') + * MsgBox(Output) + * CallbackFree(callback) + * return + * + * EnumWindowsProc(hwnd, lParam){ + * win_title := WinGetTitle(hwnd) + * if win_title + * Output .= 'HWND: ' hwnd + * . '`tTitle: ' win_title + * . '`tClass: ' WinGetClass(hwnd) '`n' + * return true + * } + * } + */ +CallbackFree(Address) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/CaretGetPos.htm|`CaretGetPos()`} + * Retrieves the current position of the text caret. + * @param {(VarRef)} [CaretX] + * The variable to store the caret's X client coordinate (if provided). + * @param {(VarRef)} [CaretY] + * The variable to store the caret's Y client coordinate (if provided). + * @returns {(Boolean)} + * Returns true if caret found, otherwise returns false: + * - `1` Caret found + * - `0` Caret not found + * @example Show caret position at all times. + * SetTimer(WatchCaret, 100) + * + * WatchCaret() { + * if CaretGetPos(&x, &y) + * ToolTip('x' x ', y' y, x, y - 20) + * else ToolTip('No caret') + * } + */ +CaretGetPos([&CaretX, &CaretY]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Ceil|`Ceil()`} + * Rounds a number up to the nearest integer. + * @param {(Number)} Num + * The number to round up. + * @returns {(Integer)} + * The rounded up integer. + * @example + * Ceil(1.1) ; => 2 + * Ceil(1.9) ; => 2 + * Ceil(1.0) ; => 1 + * Ceil(-4.5) ; => -4 + * Ceil(9.0001) ; => 10 + */ +Ceil(Num) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Chr.htm|`Chr()`} + * Returns the string (usually a single character) corresponding to the character code indicated by the specified number. + * @param {(Integer)} UnicodeNumber + * A Unicode number between 0x0 and 0x10FFFF. + * Numbers in the range 0x10000 to 0x10FFFF produce 2 characters. + * 0 produces a binary null character, not an empty string. + * @returns {(String)} + * The character(s) of the UnicodeNumber. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Ord.htm|Ord()} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#string-encoding|String Encoding} | + * {@link https://raw.githubusercontent.com/GroggyOtter/GroggyRepo/master/AHK/Groggy's%20ASCII%20Tables.txt|ASCII Table} + * @example Convert char codes to characters. + * MsgBox(Chr(65) Chr(72) Chr(75)) ; => AHK + * MsgBox(Chr(0xCA0) '_' Chr(0xCA0)) ; => ಠ_ಠ + */ +Chr(UnicodeNumber) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|`Click()`} + * Sends a mouse click or mouse movement event. + * This function is unique and can be written multiple ways [See example section]: + * - Multiple individual parameters can be used for each option. + * - Or ALL options can be put in 1 string and passed in as the first parameter. + * - Only the "number" options must be in order: X coord, Y coord, and click count + * - One number used = Click count. + * - Two numbers used = X coord > Y coord. + * - Three numbers used = X coord > Y coord > click count. + * Omit all parameters to send a single left click. + * @param {'Left'|'Right'|'Middle'|'X1'|'X2'|'WheelUp'|'WheelDown'|'WheelRight'|'WheelLeft'} [Button] + * Mouse button to click. + * If omitted, `Left` is used. + * - `Left` or `L` + * - `Right` or `R` + * - `Middle` or `M` + * - `X1` (Mouse4) + * - `X2` (Mouse5) + * - `WheelUp` or `WU` + * - `WheelDown` or `WD` + * - `WheelRight` or `WR` + * - `WheelLeft` or `WL` + * @param {(String|Integer)} [X] + * The X coordinate to click at. + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} dictates where x0 y0 starts. + * Client is usually the best choice. + * If the `Relative` param is used, x0 y0 starts at the mouse cursor. + * If omitted, the mouse's current X value is used. + * If `X` or `Y` is omitted, both must be omitted. You cannot provide only 1 coordinate value. + * @param {(String|Integer)} [Y] + * The Y coordinate to click at + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} dictates where x0 y0 starts. + * Client is usually the best choice. + * If the `Relative` param is used, x0 y0 starts at the mouse cursor. + * If omitted, the mouse's current Y value is used. + * If `X` or `Y` is omitted, both must be omitted. You cannot provide only 1 coordinate value. + * @param {(Number)} [Count] + * Number of clicks to send + * If omitted, `1` is used + * If there are X and Y coordinates in the call, count must come AFTER them. + * AHK always interprets 3 numbers as `X > Y > Count` + * @param {'Down'|'Up'} [State] + * Set the button's logical state to down (held) or up (released). + * - Omit = A full click (down then up) is sent. + * - `Down` or `D` = The button is logically held down. + * - `Up` or `U` = The button is logically released. + * + * Note: `WheelLeft` and `WheelRight` tilt buttons are unique as they do not have 'up' states. + * This is not an AHK thing. These buttons are momentary switches and physically do not send an 'up state' on release. + * @param {'Rel'} [Relative] + * - `Rel` or `Relative` = Click relative to the mouse cursor. + * Mouse cursor becomes x0 y0. + * `X` and `Y` parameters are offsets from there. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetDefaultMouseSpeed.htm|SetDefaultMouseSpeed()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|MouseGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlClick.htm|ControlClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|BlockInput()} + * @example Different Click() examples. + * ; Left click + * Click() + * + * ; Right click + * Click('Right') + * Click('R') + * + * ; Double left click + * Click(2) + * Click('Left', 2) + * + * ; Hold down XButton1 + * Click('X1 D') + * Click('X1', 'D') + * + * ; Move cursor without clicking + * Click('100 500 0') + * Click(100, '500', 0) + * + * ; Left click 10 pixels up and 10 pixels right from cursor + * Click(10, -10, 'Rel') + * + * ; Move mouse cursor 50 pixels to the right without clicking + * Click('0 50 0 Rel') + * + * ; Scroll mouse x5 faster + * $WheelUp::Click('WU', 5) + * $WheelDown::Click('WD', 5) + * + * ; The only thing that must be in order is coordinate and click count + * ; All of these click events do the same thing. + * ; The only order rule is X first, then Y, then click count + * Click('50', 20, 'Left Down', 2, 'Rel') + * Click('Left Down Rel', 50, 20, 2) + * Click('Down Left', 50, 20, 'Rel', 2) + * Click('Rel 50 Left Down 20 2') + * Click('Rel', 50, 'Down', 20, 'Left', 2) + */ +Click([Button:='L', X:=unset, Y:=unset, Count:=1, State:=unset, Relative:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ClipWait.htm|`ClipWait()`} + * Waits until the clipboard contains data. + * + Make sure to clear the clipboard prior to using ClipWait() `A_Clipboard := 0` + * + * @param {(Number)} [TimeoutInSec] + * Time to wait in seconds. + * This can be a float fractions of a second. + * If omitted, function will wait indefinitely. + * @param {(Integer)} [WaitForType] + * Type of data to check for: + * - `0` = Wait for text + * - `1` = Wait for any type of data + * @returns {(Boolean)} + * `0` if timed out, otherwise `1`. + * @see {@link https://www.autohotkey.com/docs/v2/lib/A_Clipboard.htm|A_Clipboard()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyWait.htm|KeyWait()} + * @example Copy highlighted text to variable. + * *F1:: { + * str := save_clip() + * MsgBox(str) + * } + * + * save_clip() { + * backup := ClipboardAll() + * A_Clipboard := '' + * Send('^c') + * if !ClipWait(1, 1) + * return (A_Clipboard := backup) + * txt := A_Clipboard + * A_Clipboard := backup + * return txt + * } + */ +ClipWait([TimeoutInSec:=unset, WaitForType:=0]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComCall.htm|`ComCall()`} + * Calls a native COM interface method by index. + * @param {(Integer)} Index + * The zero-based index of the method + * within the virtual function table. Corresponds to the method's + * position within the original interface definition. + * An invalid index can cause undefined behaviour, up to program termination. + * @param {(Integer|Object)} ComObj + * The target COM object. + * Pointer value can be passed directly or encapsulated within an object + * with the Ptr property, such as a {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} with variant type VT_UNKNOWN. + * @param {{'Str'|'WStr'|'AStr'|'Int64'|'Int'|'Short'|'Char'|'Float'|'Double'|'UInt'|'UShort'|'UChar'|'Ptr'}} [TypeN] + * Arg's data type. + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#str|`String`}: `Str`, `WStr`, `AStr` + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#Int|`Integer`}: `Int64`, `Int`, `Short`, `Char` + * - `Float`: `Float`, `Double` + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#unsigned|`Unsigned numbers`}: `UInt`, `UShort`, `UChar`, `UPtr` (only 32-bit pointers) + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#ptr|`Pointer`}: `Ptr`, `* or P [suffix]` + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#HRESULT|`COM`}: `HRESULT` + * + * Multiple `type, arg` parameter pairs can be listed sequentially: + * + * ComCall(5, some_com, 'int', x, 'int', y, 'uint', width, 'uint', height) + * @param {(String)} [ArgN] + * The argument being passed. + * There can be be multiple `type, arg` parameter pairs listed subsequently. + * + * ComCall(5, some_com, 'int', width, 'int', height) + * @param {{'Str'|'WStr'|'AStr'|'Int64'|'Int'|'Short'|'Char'|'Float'|'Double'|'UInt'|'UShort'|'UChar'|'Ptr'}} [TypeN] + * @param {(String)} [ReturnType] + * If omitted, return type defaults to {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#HRESULT|HRESULT} + * If there is no return type (such as C's `void`), specify `Int` or another numeric type. + * `Cdecl` is supported but is generally not used by COM interface methods. + * @returns {(String|Integer)} + * The actual value returned by the method + * @throws OSError - Any result indicating failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer object} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjQuery.htm|ComObjQuery()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} | + * {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm|CallbackCreate()} + * @example Toggle active window taskbar button. + * $F1::toggle_taskbutton('hide') + * $F2::toggle_taskbutton('show') + * + * toggle_taskbutton(opt:='') { + * ; ITaskbarList + * ; https://learn.microsoft.com/windows/win32/api/shobjidl_core/nn-shobjidl_core-itaskbarlist + * static CLSID_TaskbarList := '{56FDF344-FD6D-11d0-958A-006097C9A090}' + * , IID_ITaskbarList := '{56FDF342-FD6D-11d0-958A-006097C9A090}' + * tbl := ComObject(CLSID_TaskbarList, IID_ITaskbarList) + * activeHwnd := WinExist('A') + * ComCall(3, tbl) + * switch opt { + * case 'hide': ComCall(5, tbl, 'ptr', activeHwnd) + * case 'show': ComCall(4, tbl, 'ptr', activeHwnd) + * } + * tbl := '' + * } + */ +ComCall(Index, ComObj [,TypeN:=unset, ArgN:=unset, ReturnType:='HRESULT'], *) => Primitive + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjActive.htm|`ComObjActive()`} + * Retrieves a registered COM object. + * @param {(String)} CLSID + * CLSID or human-readable Prog ID of the COM object to retrieve. + * @returns {(ComObject)} + * A COM wrapper object with the {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm#vt|variant type VT_DISPATCH (9)}. + * @throws {{Error}} - An exception is thrown on failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|ComObjGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjFlags.htm|ComObjFlags()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjConnect.htm|ComObjConnect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ObjAddRef.htm|ObjAddRef()/ObjRelease()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjQuery.htm|ComObjQuery()} | + * {@link https://learn.microsoft.com/windows/win32/api/oleauto/nf-oleauto-getactiveobject|GetActiveObject (Microsoft Docs)} + * @example Use {@link https://learn.microsoft.com/office/vba/api/Word.Application|`Word COM`} to view the current opened MS Word doc. + * word_com := ComObjActive('Word.Application') + * if !word_com + * MsgBox("Word isn't open.") + * else + * MsgBox(word.ActiveDocument.FullName) + */ +ComObjActive(CLSID) => ComObject + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjConnect.htm|`ComObjConnect()`} + * Connects a COM object's event source to the script, enabling events to be handled. + * @param {(ComObject)} ComObj + * An object which raises events. + * An error is shown if the object does not support {@link https://learn.microsoft.com/en-us/windows/win32/api/ocidl/nn-ocidl-iconnectionpointcontainer|IConnectionPointContainer}. + * @param {(String|Object)} [PrefixOrSink] + * If omitted, the object is "disconnected". + * Otherwise, specify a string to prefix to the event name to determine which + * global function to call when an event occurs. + * Or an {@link https://www.autohotkey.com/docs/v2/lib/ComObjConnect.htm#event-sink|event sink object} with static methods for each event handler. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|ComObjGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjActive.htm|ComObjActive()} | + * {@link https://learn.microsoft.com/previous-versions/ccxe1xe6(v=vs.85)|WScript.ConnectObject (Microsoft Docs)} + * @example + */ +ComObjConnect(ComObj [,PrefixOrSink:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjFlags.htm|`ComObjFlags()`} + * Retrieves or changes flags which control a COM wrapper object's behaviour. + * @param {(Object)} ComObj + * A COM wrapper object. See {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue}. + * @param {(Integer)} NewFlags + * New values for the flags identified by Mask, or flags to add or remove. + * - `1` = F_OWNVALUE + * - SafeArray = SafeArray is destroyed when wrapper object is freed. + * - BSTR = BSTR is freed when wrapper object is freed. + * @param {(Integer)} Mask + * A bitmask of flags to change. + * @returns {(Integer)} + * New flags of the specified COM object + * @throws TypeError - If `ComObj` not a valid COM wrapper object + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjActive.htm|ComObjActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjArray.htm|ComObjArray()} + * @example Checks for the F_OWNVALUE flag. + * arr := ComObjArray(0xC, 1) + * if ComObjFlags(arr) & 1 + * MsgBox('arr will be automatically destroyed.') + * else + * MsgBox('arr will not be automatically destroyed.') + */ +ComObjFlags(ComObj [,NewFlags:=unset, Mask:=unset]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjFromPtr.htm|`ComObjFromPtr()`} + * Wraps a raw {@link https://learn.microsoft.com/windows/win32/api/oaidl/nn-oaidl-idispatch|IDispatch} pointer (COM object) for use by the script. + * @param {(Integer)} DispPtr + * A non-null interface pointer for IDispatch or a derived interface. + * @returns {(ComObject)} + * A wrapper object containing the {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm#vt|variant type VT_DISPATCH} and the given pointer. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|ComObjGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjConnect.htm|ComObjConnect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjFlags.htm|ComObjFlags()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ObjAddRef.htm|ObjAddRef()/ObjRelease()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjQuery.htm|ComObjQuery()} | + * {@link https://learn.microsoft.com/windows/win32/api/oleauto/nf-oleauto-getactiveobject|GetActiveObject (Microsoft Docs)} + * @example + */ +ComObjFromPtr(DispPtr) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|`ComObjGet()`} + * Returns a reference to an object provided by a COM component. + * @param {(String)} Name + * The display name of the object to be retrieved. + * See: {@link https://learn.microsoft.com/windows/win32/api/objbase/nf-objbase-mkparsedisplayname|MkParseDisplayName (Microsoft Docs)} + * @returns {(ComObject)} + * A new COM wrapper object with the {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm#vt|variant type VT_DISPATCH (9)}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjActive.htm|ComObjActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjConnect.htm|ComObjConnect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjQuery.htm|ComObjQuery()} | + * {@link https://learn.microsoft.com/windows/win32/api/objbase/nf-objbase-cogetobject|CoGetObject (Microsoft Docs)} + * @example Hotkey to show launch command line + * +Esc:: { + * pid := WinGetPID('A') + * wmi := ComObjGet('winmgmts:') + * query := 'Select * from Win32_Process where ProcessId=' pid + * queryEnum := wmi.ExecQuery(query)._NewEnum() + * if queryEnum(&proc) + * MsgBox(proc.CommandLine, 'Command line', 0) + * else + * MsgBox('Process not found!') + * } */ -RegWrite(Value [, ValueType, KeyName, ValueName]) => void +ComObjGet(Name) => ComObject /** - * Replaces the currently running instance of the script with a new one. + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjQuery.htm|`ComObjQuery()`} + * Queries a COM object for an interface or service. + * @param {(Object|Integer)} ComObj + * A COM wrapper object, interface pointer, or object with a Ptr property which returns an interface pointer. + * SID and IID should be in GUID format: `{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}` + * @param {(String)} IIDorSID + * Either an IID or an SID + * - IID: Interface Identifier (GUID) + * - SID: Service Identifier + * An IID must be passed to the 3rd param. + * @param {(String)} [IID_of_SID] + * The interface identifier of the service identifier in parameter 2. + * @returns {(ComObject|ComValue)} + * A COM wrapper object based on the IID + * - `IID_IDispatch` => ({@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject}) VT_Dispatch (9) + * The script can call properties/methods using normal {@link https://www.autohotkey.com/docs/v2/Objects.htm#Usage_Objects|object syntax}. + * - `Any other IID` => ({@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue}) - VT_UNKNOWN (13) + * Provides a `Ptr` property that can be passed to {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} or {@link https://www.autohotkey.com/docs/v2/lib/ComCall.htm|ComCall}. + * @throws Error - Any failure, such as "interface not supported." + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|ComObjGet()} + * {@link https://www.autohotkey.com/docs/v2/lib/ComCall.htm|ComCall()} + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjActive.htm|ComObjActive()} + * @example + * @returns {string} + */ +ComObjQuery(ComObj, IIDorSID [,IID_of_SID]) => ComObject | ComValue + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm|`ComObjType()`} + * Retrieves type information from a COM object. + * @param {(Object)} ComObj + * A wrapper object containing a COM object or typed value. + * zSee {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} for details. + * @param {'Name'|'IID'|'Class'|'CLSID'} [InfoType] + * - Omitted = Integer {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm#vt|variant type code} indicating COM type is retrieved. + * - `Name` = Name of the object's default interface. + * - `IID` = Object's default interface GUID. + * - `Class` = Object's class name (Not the same as Prog ID) + * - `CLSID` = Object's class GUID. + * @returns {(Primitive)} + * Return value depends on `InfoType` and can be integer or string. + * Empty string is returned if param is invalid or info can't be retrieved. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjValue.htm|ComObjValue()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|ComObjGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|ComObjGet()} + * @example + * d := ComObject('Scripting.Dictionary') + * MsgBox('Variant type:`t' ComObjType(d) + * '`nInterface name:`t' ComObjType(d, 'Name') + * '`nInterface ID:`t' ComObjType(d, 'IID') + * '`nClass name:`t' ComObjType(d, 'Class') + * '`nClass ID (CLSID):`t' ComObjType(d, 'CLSID') + * ) + */ +ComObjType(ComObj [,InfoType:=unset]) => Primitive + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ComObjValue.htm|`ComObjValue()`} + * Retrieves the value or pointer stored in a COM wrapper object. + * @param {(Object)} ComObj + * A wrapper object containing a COM object or typed value. See {@link https://www.autohotkey.com/docs/v2/lib/ComValue.htm|ComValue} for details. + * @returns {(Integer)} + * A 64-bit signed integer + * @throws TypeError - `ComObj` is not a COM wrapper object + * @see {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjType.htm|ComObjType()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|ComObjGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComObjGet.htm|ComObjGet()} + * @example + */ +ComObjValue(ComObj) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlAddItem.htm|`ControlAddItem()`} + * Adds the specified string as a new entry + * at the bottom of a ListBox or ComboBox. + * @param {(String)} Str + * String to add. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * Index of the new item + * @throws TargetError - Window or control could not be found + * Or control's class does not contain `Combo` or `List` + * @throws Error|OSError - Item could not be added + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlDeleteItem.htm|ControlDeleteItem()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlFindItem.htm|ControlFindItem()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Add|GuiControl.Add()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Adding an item to a ListBox. + * goo := Gui() + * goo.AddButton('xm ym vbtn_add','Add Item') + * goo['btn_add'].OnEvent('Click', add_item) + * goo.AddListBox('x+5 ym vListBox', ['Alpha', 'Bravo']) + * goo.Show('w200 h100') + * + * add_item(control, info) { + * ib := InputBox('Item to add to ListBox:',,,'Charlie') + * if (ib.Result = 'OK') + * ControlAddItem(ib.Value, control.gui['ListBox']) + * } + */ +ControlAddItem(Str, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlChooseIndex.htm|`ControlChooseIndex()`} + * Sets the selection in a ListBox, ComboBox, or Tab control to specified index. + * @param {(Integer)} N + * The index number to select. + * 0 deselects all entries of a Listbox or ComboBox. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlGetIndex.htm|ControlGetIndex()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlChooseString.htm|ControlChooseString()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|GuiControl.Choose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Selecting item(s) in a ListBox. + * items := ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo'] + * goo := Gui() + * goo.AddButton('xm ym vbtn_add','Select Item(s)') + * goo['btn_add'].OnEvent('Click', choose_item) + * goo.AddListBox('x+5 ym vListBox Multi r5', items) + * goo.Show('w250 h100') + * + * choose_item(control, info) { + * ib := InputBox('One or more numbers separated by spaces:') + * if (ib.Result = 'OK') + * loop parse ib.value, ' ' + * ControlChooseIndex(A_LoopField, control.gui['ListBox']) + * } + */ +ControlChooseIndex(N, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlChooseString.htm|`ControlChooseString()`} + * Sets the selection in a ListBox, or ComboBox to be the first entry that matches the specified string. + * @param {(String)} Str + * The string to choose. This is not case-sensitive. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The index of the chosen item. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlChooseIndex.htm|ControlChooseIndex()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetChoice.htm|ControlGetChoice()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|GuiControl.Choose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Choosing ListBox string(s). + * items := ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo'] + * goo := Gui() + * goo.AddButton('xm ym vbtn_add','Select Item(s)') + * goo['btn_add'].OnEvent('Click', choose_item) + * goo.AddListBox('x+5 ym vListBox Multi r5', items) + * goo.Show('w250 h100') + * + * choose_item(control, info) { + * ib := InputBox('One or more strings separated by commas:') + * if (ib.Result = 'OK') + * loop parse ib.value, ',', ' ' + * ControlChooseString(A_LoopField, control.gui['ListBox']) + * } + */ +ControlChooseString(Str, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlClick.htm|`ControlClick()`} + * Sends a mouse button or mouse wheel event to a control. + * @param {(String|Integer|Object)} [ConOrPos] + * - Omitted: The target window itself is clicked. + * - Position: Specify an x and y value separated by a space/tab. + * + * ControlClick('x100 y200') + * - Control: A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter} + * + * ControlClick('Button2') + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [Button] + * If omitted, defaults to left click. + * `L`/`Left`, `R`/`Right`, `M`/`Middle`, `X1` (XButton1), `X2` (XButton2) + * `WU`/`WheelUp`, `WD`/`WheelDown`, `WR`/`WheelRight`, `WL`/`WheelLeft` + * @param {(Integer)} [Count] + * Number of times to click. Defaults to 1. + * @param {String|'NA'|'D'|'U'|'Pos'|'x y '} [Options] + * One or more of the following options, separated by spaces: + * - Omitted: Down and then up events are sent to the middle of the control. + * - `NA`: May improve {@link https://www.autohotkey.com/docs/v2/lib/ControlClick.htm#Reliability|reliability}. + * - `D`: Set mouse button state to Down (hold). + * - `U`: Set mouse button state to Up (release). + * - `Pos`: Forces the `ConOrPos` variable to be Position (coordinates). + * - `X`\`Y`: Set the X and Y position of the click on the control itself. + * The upper left corner of the control is x0 y0. + * Coordinates must be decimal (base 10). + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - The target window or target control could not be found. + * @throws OSError - X and Y coords were omitted and control's position was undetermined. + * @throws ValueError|TypeError - Invalid parameters were detected. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + * ; Click on the 2nd edit field of the active window + * ControlClick('Edit2', 'A') + * ; Click at x200 y300 in My Program + * ControlClick('x200 y300', 'My Program ahk_exe myprog.exe') + * ; Send a double click to the target window + * ControlClick( , 'ahk_class my_prog', , 'Left', 2) + * ; Click and hold right mouse button on the first radio + * ControlClick('Radio1', 'A', , 'Right', , 'D') + * ; Click the upper-left-most part of the AHK GUI's button + * ; goo is a Gui object + * ControlClick(goo['BtnName'], , , , , , 'x0 y0') + */ +ControlClick([ConOrPos:=unset, WinTitle:='', WinText:='', Button:='Left', Count:=1, Options:=unset, NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlDeleteItem.htm|`ControlDeleteItem()`} + * Deletes the specified entry number from a ListBox or ComboBox. + * @param {(Integer)} N + * The index of the item to delete. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * Or control's class does not contain `Combo` or `List` + * @throws Error|OSError - Item could not be added + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlAddItem.htm|ControlAddItem()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlFindItem.htm|ControlFindItem()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Delete|GuiControl.Delete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Adding an item to a ListBox. + * goo := Gui() + * goo.AddButton('xm ym vbtn_add','Delete Item(s)') + * goo['btn_add'].OnEvent('Click', delete_item) + * goo.AddListBox('x+5 ym vListBox', ['Alpha', 'Bravo', 'Charlie']) + * goo.Show('h100') + * + * delete_item(control, info) { + * ib := InputBox('Item index to delete:',,,'2') + * if (ib.Result = 'OK') + * ControlDeleteItem(ib.Value, control.gui['ListBox']) + * } + */ +ControlDeleteItem(N, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlFindItem.htm|`ControlFindItem()`} + * Returns the entry number of a ListBox or ComboBox + * that is a complete match for the specified string. + * @param {(String)} Str + * The string to find. This is not case-sensitive. + * The entire text must match, not just the leading part. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The index of the found item. + * If no match is found, an exception is thrown. + * @throws TargetError - Window or control could not be found + * Or control's class does not contain `Combo` or `List` + * @throws Error - Item could not be found. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlAddItem.htm|ControlAddItem()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlDeleteItem.htm|ControlDeleteItem()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Checking a ListBox for a specific string. + * goo := Gui() + * goo.AddButton('xm ym vbtn_add','Check for item') + * goo['btn_add'].OnEvent('Click', check_item) + * goo.AddListBox('x+5 ym vListBox', ['Alpha', 'Bravo', 'Charlie']) + * goo.Show('h100') + * + * check_item(control, info) { + * ib := InputBox('Item index to delete:',,,'2') + * pos := 0 + * if (ib.Result = 'OK') { + * try pos := ControlFindItem(ib.Value, control.gui['ListBox']) + * if pos + * MsgBox(ib.Value ' was found at position ' pos '.') + * else MsgBox(ib.Value ' was not found...') + * } + * } + */ +ControlFindItem(Str, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlFocus.htm|`ControlFocus()`} + * Sets input focus to a given control on a window. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The index of the found item. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetFocus.htm|ControlGetFocus()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @throws TargetError - Window or control could not be found + * @example + * goo := Gui() + * loop 3 { + * opt := 'xm vrad_' A_Index + * con := goo.AddRadio(opt, 'Focus Button ' A_Index) + * con.target := 'btn_' A_Index + * con.OnEvent('Click', focus_btn) + * } + * + * btn_w := 70 + * loop 3 { + * opt := 'x+5 ym w' btn_w ' vbtn_' A_Index + * goo.AddButton(opt, 'Button ' A_Index) + * } + * con := goo.AddButton('xp y+5 w' btn_w, 'Quit') + * con.OnEvent('Click', (*) => ExitApp()) + * goo.Show() + * + * focus_btn(con, info) => ControlFocus(con.gui[con.target]) + */ +ControlFocus(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetChecked.htm|`ControlGetChecked()`} + * Returns a non-zero value if the checkbox or radio button is checked. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Boolean)} + * - `1` Checkbox/Radio is checked + * - `0` Checkbox/Radio is unchecked + * @throws TargetError - Window or control could not be found + * @throws OSError - Message could not be sent to the control + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlSetChecked.htm|ControlSetChecked()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|GuiControl.Value} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Checkbox to verify script exit. + * goo := Gui() + * goo.AddButton('xm ym vbtn_close', 'Exit Script') + * goo['btn_close'].OnEvent('Click', exit_script) + * goo.AddCheckbox('x+10 ym vcb_close checked', 'Verify exit') + * goo.Show('w200') + * + * exit_script(control, info) { + * if !ControlGetChecked(control.gui['cb_close']) + * ExitApp() + * if (MsgBox('Do you want to exit?', , 'Y/N') = 'Yes') + * ExitApp() + * } + */ +ControlGetChecked(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetChoice.htm|`ControlGetChoice()`} + * Returns the name of the currently selected entry in a ListBox or ComboBox. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The name of the selected entry in a ListBox or ComboBox + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlChooseIndex.htm|ControlChooseIndex()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlChooseString.htm|ControlChooseString()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|GuiControl.Choose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|GuiControl.Value} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + * goo := Gui() + * goo.AddButton('xm ym vbtn_choice', 'Get choice') + * goo['btn_choice'].OnEvent('Click', get_choice) + * goo.AddListBox('x+5 ym vListBox Multi', ['Alpha', 'Bravo', 'Charlie']) + * goo.Show('h100') + * + * get_choice(control, info) { + * Try MsgBox(ControlGetChoice(control.gui['ListBox'])) + * catch + * MsgBox('No entry selected.') + * } + */ +ControlGetChoice(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetClassNN.htm|`ControlGetClassNN()`} + * Returns the ClassNN of the specified control. + * This is the name of the control class followed by its sequence number. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The ClassNN of the control + * @throws TargetError - A problem determining the target window or control + * @throws Error|OSError - ClassNN could not be determined + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetControls.htm|WinGetControls()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|MouseGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#ClassNN|GuiControl.ClassNN} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Controls named after their ClassNN. + * goo := Gui() + * loop 2 + * con := goo.AddButton('xm w80') + * ,con.Text := ControlGetClassNN(con) + * loop 2 + * con := goo.AddEdit('xm w80') + * ,con.Text := ControlGetClassNN(con) + * loop 2 + * con := goo.AddText('xm w80') + * ,con.Text := ControlGetClassNN(con) + * loop 2 + * con := goo.AddRadio('xm w80') + * ,con.Text := ControlGetClassNN(con) + * con := goo.AddDropDownList('xm') + * con.Add([ControlGetClassNN(con)]) + * con.Choose(1) + * loop 2 + * con := goo.AddCheckbox('xm w80') + * ,con.Text := ControlGetClassNN(con) + * goo.Show() + */ +ControlGetClassNN(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetEnabled.htm|`ControlGetEnabled()`} + * Returns a non-zero value if the specified control is enabled. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Boolean)} + * - `1` Control is enabled + * - `0` Control is disabled + * @throws TargetError - The window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlSetEnabled.htm|ControlSetEnabled()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinSetEnabled.htm|WinSetEnabled()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Enabled|GuiControl.Enabled} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Report all disabled controls in a GUI. + * goo := Gui() + * goo.AddButton('xm ym vbtn1 w80 +Disabled', 'Alpha') + * goo.AddButton('ym vbtn2 w80', 'Bravo') + * goo.AddButton('ym vbtn3 w80 +Disabled', 'Charlie') + * con := goo.AddButton('xm w260 vcheck_btn', 'Check Button States') + * con.OnEvent('Click', check_buttons) + * goo.Show() + * + * check_buttons(control, info) { + * str := 'Disabled controls:' + * for _, c in control.gui + * if !ControlGetEnabled(c) + * str .= '`n' c.Text ' ' c.Type + * MsgBox(str) + * } + */ +ControlGetEnabled(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetFocus.htm|`ControlGetFocus()`} + * Retrieves the focused control of the target window, if any. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|handle (HWND)} of the focused control. + * `0` if none of the controls have focus or if focus cannot be determined. + * @throws TargetError - Problem determining the target window or control + * @throws OSError - Problem determining the control focus + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlFocus.htm|ControlFocus()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Show focused control HWND in statusbar. + * goo := Gui() + * loop 3 + * goo.AddButton('ym vbtn' A_Index, 'Button ' A_Index) + * goo.AddStatusBar('vstatus') + * goo.Show() + * callback := sb_refresh.Bind(goo) + * SetTimer(callback, 500) + * + * sb_refresh(guiObj) { + * con := ControlGetFocus('ahk_id ' guiObj.hwnd) + * guiObj['status'].Text := 'Focused control HWND: ' con + * } + */ +ControlGetFocus([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetHwnd.htm|`ControlGetHwnd()`} + * Returns the unique ID number (handle) of the specified control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * Specify the letter `A` to use the active window. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|handle (HWND)} of the specified control. + * @throws TargetError - The target window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Hwnd|GuiControl.Hwnd} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + * ; Get HWND of the first button on the active window + * hwnd := ControlGetHwnd('Button1', 'A') + * ; Get HWND of the checkbox from an AHK GUI + * hwnd := ControlGetHwnd(GuiObj['my_checkbox']) + * ; Get HWND of Notepad's main Edit window + * hwnd := ControlGetHwnd('Edit1', 'ahk_class Notepad') + */ +ControlGetHwnd(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetIndex.htm|`ControlGetIndex()`} + * Returns the index of the current selected entry/tab of a ListBox, ComboBox or Tab control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The index of the tab or the ListBox/ComboBox selected entry. + * `0` if no tab/entry is selected. + * @throws TargetError - The window or control could not be found + * Or the control's class name does not contain "Combo", "List" or "Tab" + * @throws OSError - Message could not be sent to the control + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlChooseIndex.htm|ControlChooseIndex()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetChoice.htm|ControlGetChoice()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlChooseString.htm|ControlChooseString()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|GuiControl.Value} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Choose|GuiControl.Choose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example Get the index of a selected ListBox item. + * goo := Gui() + * goo.AddButton('xm ym vbtn_choice', 'get_choice') + * goo['btn_choice'].OnEvent('Click', get_choice) + * goo.AddListBox('x+5 ym vListBox Multi', ['Alpha', 'Bravo', 'Charlie']) + * goo['ListBox'].Choose(2) + * goo.Show('h100') + * + * get_choice(control, info) { + * Try MsgBox('Index position: ' ControlGetIndex(control.gui['ListBox'])) + * catch + * MsgBox('No entry selected.') + * } + */ +ControlGetIndex(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetItems.htm|`ControlGetItems()`} + * Returns an array of items/rows from a ListBox, ComboBox, or DropDownList. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Array)} + * An array containing the text of each item or row. + * @throws TargetError - The window or control could not be found + * Or the control's class name does not contain "Combo" or "List" + * @see {@link https://www.autohotkey.com/docs/v2/lib/ListViewGetContent.htm|ListViewGetContent()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetList.htm|WinGetList()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlGetItems(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Array + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetPos.htm|`ControlGetPos()`} + * Retrieves the position and size of a control. + * @param {(VarRef)} [OutX] + * The x coordinate of the control's upper left corner. + * Coordinates are relative to the {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm#Client|client area}. + * @param {(VarRef)} [OutY] + * The y coordinate of the control's upper left corner. + * Coordinates are relative to the {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm#Client|client area}. + * @param {(VarRef)} [OutWidth] + * Width of the control in pixels. + * @param {(VarRef)} [OutHeight] + * Height of the control in pixels. + * @param {(String|Integer|Object)} [Control] + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * If omitted, the main window is targeted. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - The window or control could not be found. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlMove.htm|ControlMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPos.htm|WinGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlGetPos([&OutX, &OutY, &OutWidth, &OutHeight, Control:=unset, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetStyle.htm|`ControlGetStyle()`} + * Gets a control's style number. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {{Integer}} The controls' style number. + * @throws TargetError - Window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlSetStyle.htm|ControlSetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|WinGetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Styles Table} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlGetStyle(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetStyle.htm|`ControlGetExStyle()`} + * Gets a control's extended style number. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {{Integer}} The controls' style number. + * @throws TargetError - Window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlSetStyle.htm|ControlSetExStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|WinGetExStyle()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Styles Table} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlGetExStyle(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetText.htm|`ControlGetText()`} + * Retrieves text from a control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The text from the specified control. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlSetText.htm|ControlSetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetText.htm|WinGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlGetText(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlGetVisible.htm|`ControlGetVisible()`} + * Returns a non-zero value if the specified control is visible. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {{Boolean}} `1` if control is visible, otherwise `0` + * @throws TargetError - The window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlHide.htm|ControlHide()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlShow.htm|ControlShow()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiControl.Visible} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlGetVisible(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlHide.htm|`ControlHide()`} + * Hides the specified control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - The window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlShow.htm|ControlShow()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetVisible.htm|ControlGetVisible()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinHide.htm|WinHide()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiControl.Visible} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlHide(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlHideDropDown.htm|`ControlHideDropDown()`} + * Hides the drop-down list of a ComboBox control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - The window or control could not be found + * @throws OSError - Message could not be sent to the control + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlShowDropDown.htm|ControlShowDropDown()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlHideDropDown(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlMove.htm|`ControlMove()`} + * Moves or resizes a control. + * @param {(Integer)} [X] + * The new x coordinate of the control's upper left corner. + * Coordinates are relative to the {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm#Client|client area}. + * @param {(Integer)} [Y] + * The new y coordinate of the control's upper left corner. + * Coordinates are relative to the {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm#Client|client area}. + * @param {(Integer)} [Width] + * The new width of the control. + * @param {(Integer)} [Height] + * The new height of the control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @throws OSError - Control's current position could not be determined + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlGetPos.htm|ControlGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMove.htm|WinMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlMove([X, Y, Width, Height, Control, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|`ControlSend()`} + * Sends simulated keystrokes to a window or control. + * @param {(String)} Keys + * The keystrokes to send to the specified control. + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} syntax is used, including {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Raw|Raw}, {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Text|Text}, and {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Blind|Blind} modes. + * @param {(String|Integer|Object)} [Control] + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * If omitted, the main window is targeted. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Winamp.htm|Automating Winamp} | + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape Sequences} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlSend(Keys [,Control:=unset, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|`ControlSendText()`} + * Sends simulated text to a window or control. + * Keystrokes are sent explicitly because [`{Text}` mode](https://www.autohotkey.com/docs/v2/lib/Send.htm#Text) is enforced. + * @param {(String)} Keys + * The keystrokes to send to the specified control. + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} syntax is not supported due to {Text} mode being enforced. + * @param {(String|Integer|Object)} [Control] + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * If omitted, the main window is targeted. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Winamp.htm|Automating Winamp} | + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape Sequences} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlSendText(Keys [,Control:=unset, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlSetChecked.htm|`ControlSetChecked()`} + * Turns on/checks or + * turns off/unchecks a checkbox or radio button. + * @param {(Integer)} NewSetting + * Sets new checkbox/radio state. + * - `1` = Turn on/check + * - `0` = Turn off/uncheck + * - `-1` = Toggle/opposite of current state + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @throws OSError - A message could not be sent to the control + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlGetChecked.htm|ControlGetChecked()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Value|GuiControl.Value} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlSetChecked(NewSetting, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlSetEnabled.htm|`ControlSetEnabled()`} + * Enables or disables the specified control. + * @param {(Integer)} NewSetting + * Sets new checkbox/radio state. + * - `1` = Turn on/enable + * - `0` = Turn off/disable + * - `-1` = Toggle/opposite of current state + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlGetEnabled.htm|ControlGetEnabled()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinSetEnabled.htm|WinSetEnabled()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Enabled|GuiControl.Enabled} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlSetEnabled(NewSetting, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlSetStyle.htm|`ControlSetStyle()`} + * Changes the style of the specified control. + * @param {(Integer|String)} Value + * Pass a positive integer to completely + * overwrite/set the window's style. {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Table}. + * - `+` Add: '+0x80' = `NewStyle := CurrentStyle | Value` + * - `-` Remove: '-0x80' = `NewStyle := CurrentStyle & ~Value` + * - `^` Toggle: '^0x80' = `NewStyle := CurrentStyle ^ Value` + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @throws OSError - The style could not be changed + * Partial change is considered a success. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlGetStyle.htm|ControlGetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinSetStyle.htm|WinSetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Styles Table} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlSetStyle(Value, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlSetStyle.htm|`ControlSetExStyle()`} + * Changes the extended style of the specified control. + * @param {(Integer|String)} Value + * Pass a positive integer to completely + * overwrite/set the window's style. {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Style Table}. + * - `+` Add: '+0x80' = `NewStyle := CurrentStyle | Value` + * - `-` Remove: '-0x80' = `NewStyle := CurrentStyle & ~Value` + * - `^` Toggle: '^0x80' = `NewStyle := CurrentStyle ^ Value` + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @throws OSError - The style could not be changed + * Partial change is considered a success. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlGetStyle.htm|ControlGetExStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinSetStyle.htm|WinSetExStyle()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Styles Table} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlSetExStyle(Value, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlSetText.htm|`ControlSetText()`} + * Changes the text of a control. + * @param {(String)} NewText + * Text to assign to the control. + * A blank line can be used to clear the control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetText.htm|ControlGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlSetText(NewText, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlShow.htm|`ControlShow()`} + * Shows the specified control if it was previously hidden. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlHide.htm|ControlHide()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetVisible.htm|ControlGetVisible()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinShow.htm|WinShow()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#Visible|GuiControl.Visible} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlShow(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ControlShowDropDown.htm|`ControlShowDropDown()`} + * Shows the drop-down list of a ComboBox control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @throws OSError - Message could not be sent to the control + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlHideDropDown.htm|ControlHideDropDown()} + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +ControlShowDropDown(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|`CoordMode()`} + * Determines where x0/y0 starts for various built-in functions. Relative to Client, Window, or Screen. + * {@link https://i.imgur.com/bZXILwM.png|Image showing each coord mode's x0 y0 start point} + * Orange is screen, blue is window, green is client area + * @param {'ToolTip'|'Pixel'|'Mouse'|'Caret'|'Menu'} TargetType + * Set group type: + * - `ToolTip` = Affects: {@link https://www.autohotkey.com/docs/v2/lib/ToolTip.htm|`ToolTip()`} + * - `Pixel` = Affects: {@link https://www.autohotkey.com/docs/v2/lib/PixelGetColor.htm|`PixelGetColor()`}, {@link https://www.autohotkey.com/docs/v2/lib/PixelSearch.htm|`PixelSearch()`}, {@link https://www.autohotkey.com/docs/v2/lib/ImageSearch.htm|`ImageSearch()`} + * - `Mouse` = Affects: {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|`MouseGetPos()`}, {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|`Click()`}, {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|`MouseMove()`}, {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|`MouseClick()`}, {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|`MouseClickDrag()`} + * - `Caret` = Affects: {@link https://www.autohotkey.com/docs/v2/lib/CaretGetPos.htm|`CaretGetPos()`} + * - `Menu` = Affects: {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Show|`Menu.Show()`} + * @param {'Client'|'Screen'|'Window'} [RelativeTo] + * Set x0 y0 position: + * - `Client`: Upper left of main window area of the program. + * This is usually the best choice. + * - `Window`: Upper left corner of the Window. + * Window is the area around the client, including the + * title bar and border around the client. + * - `Screen`: Upper left corner of the primary monitor. + * Rarely the best choice. Screen should be used + * when working with the desktop or arranging windows. + * - Omitted: Defaults to `Screen` + * @returns {(String)} + * The previous setting is always returned. + * - `Client` + * - `Window` + * - `Screen` + * @see {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|MouseGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ToolTip.htm|ToolTip()} | + * {@link https://www.autohotkey.com/docs/v2/lib/PixelGetColor.htm|PixelGetColor()} | + * {@link https://www.autohotkey.com/docs/v2/lib/PixelSearch.htm|PixelSearch()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu.Show()} | + * @example + */ +CoordMode(TargetType [,RelativeTo:='Screen']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Cos|`Cos()`} + * Returns the trigonometric cosine of the number. + * Convert radians to degrees: `Value * 180/pi` (180/pi = ~57.29578) + * Convert degrees to radians: `Value * pi/180` (pi/180 = ~0.01745329252) + * @param {(Number)} Num + * The number to get the cosine value of. + * Must be expressed in radians. + * @returns {(Float)} + * Cosine of `Num`. + * @example Cosine Example. + * Cos(1.2) => 0.362358 + */ +Cos(Num) => Float + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm|`Critical()`} + * Enables or disables {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|current thread} the ability to interrupt other threads. + * @param {'On'|'Off'} [Setting] + * New critical setting: + * - `On` = Current thread is set to critical. + * It cannot be interrupted by another thread. + * - `Off` = Current thread immediately becomes interruptible. + * This is regardless of the {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm#Interrupt|Thread Interrupt} settings. + * See {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm#Off|"Critical Off"} for details. + * - Positive Number = Enables Critical and uses the number as milliseconds between {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm#Interval|Message Checks}. + * - `0` = Turns off critical. + * - `-1` = Turns on critical but disables {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm#Interval|internal message checking}. + * Message checking still occurs during sleeps, delays, and waits. + * @returns {(Integer)} + * The previous setting is always returned. + * `0` for off, otherwise an integer greater than 0. + * @see {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm|Thread()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu Object} | + * {@link https://www.autohotkey.com/docs/v2/lib/_MaxThreadsPerHotkey.htm|#MaxThreadsPerHotkey} | + * {@link https://www.autohotkey.com/docs/v2/lib/_MaxThreadsBuffer.htm|#MaxThreadsBuffer} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm|OnMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm|CallbackCreate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm|SetTimer()} + * @example + */ +Critical([Setting:='On']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DateAdd.htm|`DateAdd()`} + * Adds or subtracts time from a date-time value. + * @param {(String)} DateTime + * A date-time stamp in the {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS date-time stamp} format. + * @param {(Number)} Time + * Amount of time to add or subtract. + * @param {'Seconds'|'Minutes'|'Hours'|'Days'} TimeUnits + * The type of time unit used in the `Time` parameter. + * - `S` / `Seconds` + * - `M` / `Minutes` + * - `H` / `Hours` + * - `D` / `Days` + * @returns {(String)} + * The `DateTime` after alteration in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS} format. + * @throws ValueError - `DateTime` is invalid or prior to 1601 + * @see {@link https://www.autohotkey.com/docs/v2/lib/DateDiff.htm|DateDiff()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetTime.htm|FileGetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|FormatTime()} + * @example + */ +DateAdd(DateTime, Time, TimeUnits) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DateDiff.htm|`DateDiff()`} + * Compares two {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|date-time values} and returns the difference. + * Values are always rounded down to the nearest integer. + * For higher precision, use `Seconds` and divide by 60/3600/86400 for minutes/hours/days (respectively). + * @param {(String)} [DateTime1] + * First {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS date-time stamp} to compare. + * If omitted, {@link https://www.autohotkey.com/docs/v2/Variables.htm#Now|A_Now} (current date-time) is used. + * @param {(String)} [DateTime2] + * Second {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS date-time stamp} to compare. + * If omitted, {@link https://www.autohotkey.com/docs/v2/Variables.htm#Now|A_Now} (current date-time) is used. + * @param {'Seconds'|'Minutes'|'Hours'|'Days'} TimeUnits + * Unit of time to get the difference in. + * - `S` / `Seconds` + * - `M` / `Minutes` + * - `H` / `Hours` + * - `D` / `Days` + * @returns {(Integer)} + * Difference between the two timestamps in the units requested. + * The difference is negative if DateTime1 is earlier than DateTime2. + * @throws ValueError - If a date-time stamp is invalid or year is prior to 1601 + * @see {@link https://www.autohotkey.com/docs/v2/lib/DateAdd.htm|DateAdd()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetTime.htm|FileGetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|FormatTime()} + * @example + */ +DateDiff(DateTime1, DateTime2, TimeUnits) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|`DetectHiddenText()`} + * Determines whether invisible text in a window is "seen" for the purpose of finding the window. This affects windowing functions such as WinExist and WinActivate. + * By default, this is on. + * @param {(Boolean)} NewSetting + * - `1` = Hidden text detected. + * - `0` = Hidden text ignored. + * @returns {(Boolean)} + * The previous setting is always returned: + * - `1` = Hidden text detected + * - `0` = Hidden text ignored + * @see {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} + * @example + */ +DetectHiddenText(NewSetting) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|`DetectHiddenWindows()`} + * Determines whether invisible windows are "seen" by the script. + * By default, this is off. + * @param {(Boolean)} NewSetting + * - `1` = Hidden windows are detected. + * - `0` = Hidden windows are ignored. + * @returns {(Boolean)} + * The previous setting is always returned: + * - `1` = Hidden text detected + * - `0` = Hidden text ignored + * @see {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} + * @example + */ +DetectHiddenWindows(NewSetting) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DirCopy.htm|`DirCopy()`} + * Copies a folder along with all its sub-folders and files (similar to xcopy). + * @param {(String)} Source + * Path to source directory. + * If a full path isn't used, Source is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(String)} Dest + * Path to destination directory. + * If a full path isn't used, Dest is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(Integer)} [Overwrite] + * Overwrite if destination already exists + * - `0` = Do not overwrite existing files. + * - `1` = Overwrite existing files. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - An exception is thrown if any error occurs + * @see {@link https://www.autohotkey.com/docs/v2/lib/DirMove.htm|DirMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileCopy.htm|FileCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileMove.htm|FileMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|FileDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SplitPath.htm|SplitPath()} + * @example + */ +DirCopy(Source, Dest [,Overwrite:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DirCreate.htm|`DirCreate()`} + * Creates a folder. + * @param {(String)} DirName + * Path to directory. + * If a full path isn't used, DirName is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Any errors occur. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/DirDelete.htm|DirDelete()} + * @example + */ +DirCreate(DirName) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DirDelete.htm|`DirDelete()`} + * Deletes a folder. + * @param {(String)} DirName + * Path to directory. + * If a full path isn't used, DirName is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(Boolean)} Recurse + * Recursively remove sub-contents: + * - `1` = The directory, all files, and subdirectories are removed. + * Similar to cmd's {@link https://www.computerhope.com/rmdirhlp.htm#syntax|`rmdir /S`} + * - `0` = If directory contains anything (files or sub-directories), directory is not deleted. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Any errors occur. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/DirCreate.htm|DirCreate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|FileDelete()} + * @example + */ +DirDelete(DirName [,Recurse:=0]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DirExist.htm|`DirExist()`} + * Checks for the existence of a folder and returns its attributes. + * @param {(String)} FilePattern + * Directory path or name to check. + * If a full path isn't used, FilePattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @returns {(String)} + * A string of all attributes found for the directory. + * - Empty String = The directory wasn't found + * - `R` = ReadOnly + * - `A` = Archive + * - `S` = System + * - `H` = Hidden + * - `D` = Directory + * - `O` = Offline + * - `C` = Compressed + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileExist.htm|FileExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetAttrib.htm|FileGetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} + * @example + */ +DirExist(FilePattern) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DirMove.htm|`DirMove()`} + * Moves a folder along with all its sub-folders and files. + * Can also be used to rename a folder. + * @param {(String)} Source + * Path to source directory. + * If a full path isn't used, Source is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(String)} Dest + * Path to destination directory. + * If a full path isn't used, Dest is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {'0'|'1'|'2'|'R'} [OverwriteRename] + * + * - `0` = Do not overwrite exiting files. + * Function fails if Dest already exists. + * - `1` = Overwrite with limitation. + * Files/Folders in the Dest folder are overwritten only if Source has the same files/folders. + * - `2` = Overwrite explicitly. + * All files/folders are overwritten. + * - `R` = Rename instead of moving. + * Renaming is all-or-none and cannot be partially successful. + * The function fails if `Dest` already exists. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - An exception is thrown if any error occurs. + * @see {@link https://www.autohotkey.com/docs/v2/lib/DirCopy.htm|DirCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileCopy.htm|FileCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileMove.htm|FileMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|FileDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SplitPath.htm|SplitPath()} + * @example + */ +DirMove(Source, Dest [,OverwriteOrRename:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|`DirSelect()`} + * Displays a standard dialog that allows the user to select a folder. + * @param {(String)} [StartingFolder] + * Directory to start in. + * The path to a directory. `C:\Some\Path` + * Include an asterisk `*` before the path to allow the users to navigate upward. `*c:\some\path` + * To set limit to how far upward the user can navigate, include the folder before it. `c:\some *c:\some\path` + * A CLSID folder can be used such as `::{20D04FE0-3AEA-1069-A2D8-08002B30309D}` + * @param {(Integer)} [Options] + * - `0` = All options disabled. + * - `+1` = A "New Folder" button is provided. + * - `+2` = Add 2 to provide an edit field for typing the name of a folder. + * - `+4` = Add 4 to omit the BIF_NEWDIALOGSTYLE style. + * This removes the "make new folder" button but ensures DirSelect works in PEs. + * @param {(String)} [Prompt] + * Instruction text to display. + * @returns {(String)} + * Full path to the selected folder. + * An empty string is returned if the user cancels. + * Root directories include trailing backslash `C:\` and can be removed with RTrim() + * + * path := RTrim(path, '\') + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|FileSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|MsgBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm|InputBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ToolTip.htm|ToolTip()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|GUI} | + * {@link https://www.autohotkey.com/docs/v2/misc/CLSID-List.htm|CLSID List} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirCopy.htm|DirCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirMove.htm|DirMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SplitPath.htm|SplitPath()} + * @example + */ +DirSelect([StartingFolder:=A_MyDocuments, Options:=1, Prompt:='Select Folder - ']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|`DllCall()`} + * Calls a function inside a DLL, such as a standard Windows API function. + * @param {(String|Integer|Object)} DLLNameOrPath + * Path to DLL or EXE, backslash, and function name. + * If a full path isn't used, DLLNameOrPath is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * Path can be omitted when using `User32.dll`, `Kernel32.dll`, `ComCtl32.dll`, or `Gdi32.dll`. + * A `W` (unicode) prefix is added if no function can be found. + * Performance can be increased by {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#load|preloading DLLs}. + * An integer function address can be used. + * If an object is passed, the `Ptr` property value is used. + * @param {{'Str'|'WStr'|'AStr'|'Int64'|'Int'|'Short'|'Char'|'Float'|'Double'|'UInt'|'UShort'|'UChar'|'Ptr'}} [TypeN] + * Multiple Type/Arg pairs can be included. + * Arg's data type. + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#str|`String`}: `Str`, `WStr`, `AStr` + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#Int|`Integer`}: `Int64`, `Int`, `Short`, `Char` + * - `Float`: `Float`, `Double` + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#unsigned|`Unsigned numbers`}: `UInt`, `UShort`, `UChar`, `UPtr` (only 32-bit pointers) + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#ptr|`Pointer`}: `Ptr`, `* or P [suffix]` + * - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#HRESULT|`COM`}: `HRESULT` + * + * @param {(String)} [ArgN] + * The argument being passed. + * Multiple `Type`/`Arg` pairs can be included. + * @param {(String)} [ReturnType] + * Specify the expected returned data type. + * ReturnType can be omitted if the return type is `Int`, `BOOL`, or nothing, + * `Cdecl` can be be included before the return type for C calling conventions, but this only works on 32-bit versions of AHK. + * Most C++ object-oriented functions use `thiscall` which is NOT supported by AHK. + * @param {(String)} [ReturnType] + * If omitted, return type defaults to {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#HRESULT|HRESULT} + * If there is no return type (such as C's `void`), specify `Int` or another numeric type. + * `Cdecl` is supported but is generally not used by COM interface methods. + * @throws PropertyError - An object passed to DLLNameOrPath is missing or has an invalid `Ptr` property + * @throws OSError - {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#HRESULT|HRESULT} type used and function {@link https://learn.microsoft.com/windows/win32/api/winerror/nf-winerror-failed|returned error}. + * @throws TypeError - The DLLNameOrPath parameter is a floating point number. A string or positive integer is required. + * @throws TypeError - An argument was passed a value of an unexpected type. + * @throws ValueError - The {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#types|return type} or one of the specified {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#types|arg types} is invalid. + * @throws Error - The specified DllFile could not be accessed or loaded. + * @throws Error - The specified function could not be found inside the DLL. + * @throws Error - The function was called but it aborted with a fatal exception. + * The {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Extra|Error.Extra} property contains the exception code. + * @throws Error - Too many or too few arguments were passed to the function. + * The {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Extra|Error.Extra} property contains the number of bytes the data type was off by. + * @returns {(Primitive)} + * The value returned by Function. + * If Function return type does not return a value, the result is an undefined value of ReturnType. + * @see {@link https://www.autohotkey.com/docs/v2/Compat.htm#DllCall|Binary Compatibility} | + * {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer object} | + * {@link https://www.autohotkey.com/docs/v2/lib/ComCall.htm|ComCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/PostMessage.htm|PostMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm|OnMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm|CallbackCreate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/VarSetStrCapacity.htm|VarSetStrCapacity()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm|SysGet()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm|Functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/_DllLoad.htm|#DllLoad} | + * {@link https://learn.microsoft.com/windows/win32/apiindex/windows-api-list|Windows API Index} + * @example + */ +DllCall(DLLNameOrPath [,Type1, Arg1, ReturnType:='Int'], *) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Download.htm|`Download()`} + * Downloads a file from the Internet. + * Any proxies configured for IE are used. + * @param {(String)} URL + * URL to download. + * FTP and Gopher URLS are supported. + * @param {(String)} SaveFile + * Path to save downloaded file. + * If a full path isn't used, SaveFile is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * To download to a variable, see {@link https://www.autohotkey.com/docs/v2/lib/Download.htm#ExWHR|this example}. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - An exception is thrown on failure. + * Note that a download may seem successful only because an "error page" is returned. + * That error page is what gets saved. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileRead.htm|FileRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileCopy.htm|FileCopy()} + * @example + */ +Download(URL, SaveFile) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveEject.htm|`DriveEject()`} + * Ejects the tray of the specified CD/DVD drive, or ejects a removable drive. + * This function waits for the ejection or retraction to complete before continuing. + * @param {(String)} [Drive] + * The path to an optical drive. + * Drive letter can be used. `:` and `\` are optional. `E`, `E:`, `E:\` + * Device paths can be used and gotten from {@link https://learn.microsoft.com/windows-server/administration/windows-commands/mountvol|mountvol}. `\\?\Volume{...}` + * @returns {(String)} + * An empty string is always returned. + * @throws Error - No drive was found + * The underlying system functions do not always report failure. + * An exception may or may not be thrown. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} + * {@link https://www.autohotkey.com/docs/v2/lib/DriveGetStatusCD.htm|DriveGetStatusCD()} | + * @example + */ +DriveEject([Drive:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveGetCapacity.htm|`DriveGetCapacity()`} + * Returns the total capacity of the drive which contains the specified path, in megabytes. + * @param {(String)} Path + * Any path contained by the drive. + * May work with UNC paths and mapped drives. + * @returns {(Integer)} + * Total capacity of the drive in megabytes. + * @throws Error - An exception is thrown on failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DriveGetSpaceFree.htm|DriveGetSpaceFree()} + * @example + */ +DriveGetCapacity(Path) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveGetFileSystem.htm|`DriveGetFileSystem()`} + * Returns the type of the specified drive's file system. + * @param {(String)} Drive + * Drive letter followed by a colon. Backslash is optional. + * @returns {(String)} + * The file system type for the provided Drive. + * Including (but not limited to): `NTFS`, `HPFS`, `FAT32`, `FAT`, `CDFS`, `UDF` + * @throws Error - An exception is thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} + * @example + */ +DriveGetFileSystem(Drive) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveGetLabel.htm|`DriveGetLabel()`} + * Returns the volume label of the specified drive. + * @param {(String)} Drive + * Drive letter followed by a colon. Backslash is optional. + * UNC names are allowed. `\srv1\dir1` + * @returns {(String)} + * - Volume name of Drive + * @throws Error - An exception is thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DriveSetLabel.htm|DriveSetLabel()} + * @example + */ +DriveGetLabel(drive) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveGetList.htm|`DriveGetList()`} + * Returns a string of letters. + * There is no separators between characters. + * @param {'CDROM'|'REMOVABLE'|'FIXED'|'NETWORK'|'RAMDISK'|'UNKNOWN'} [DriveType] + * Omit DriveType to retrieve all types. + * Or use one of the following words: + * - `CDROM` + * - `REMOVABLE` + * - `FIXED` + * - `NETWORK` + * - `RAMDISK` + * - `UNKNOWN` + * @returns {(String)} + * String of drive letters. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * @example Show all system drive letters. + * List := DriveGetList() + * MsgBox(list) + */ +DriveGetList([DriveType:=unset]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveGetSerial.htm|`DriveGetSerial()`} + * Returns the volume serial number of the specified drive. + * @param {(String)} Drive + * Drive letter followed by a colon. Backslash is optional. + * UNC names are allowed. `\srv1\dir1` + * @returns {(Integer)} + * Drive's volume serial. + * To convert to hex, use {@link https://www.autohotkey.com/docs/v2/lib/Format.htm|Format()}. See example below. + * @throws Error - An exception is thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * @example + * serial := DriveGetSerial('C:') + * hex_serial := Format('{:X}', serial) + * MsgBox('Serial: ' serial '`nHex: ' hex_serial) */ -Reload() => void +DriveGetSerial(Drive) => Integer /** - * Return the number, rounded to N digits after the decimal point + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveGetSpaceFree.htm|`DriveGetSpaceFree()`} + * Returns the free disk space of the drive which contains the specified path, in megabytes. + * @param {(String)} Path + * Any path contained by the drive. + * May work with UNC paths and mapped drives. + * @returns {(Integer)} + * The free amount of disk space on the drive Path belongs to in megabytes. + * @throws Error - An exception is thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DriveGetCapacity.htm|DriveGetCapacity()} + * @example */ -Round(Number, N := 0) => Integer | String +DriveGetSpaceFree(Path) => Integer /** - * Trim characters from the end of the string. + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveGetStatus.htm|`DriveGetStatus()`} + * Returns the status of the drive which contains the specified path. + * @param {(String)} Path + * Any path contained by the drive. + * May work with UNC paths and mapped drives. + * @returns {(String)} + * The status of the drive that Path belongs to. + * - `Ready` = This is the most common. + * - `NotReady` = Typical for removable drives that don't contain media. + * - `Unknown` = Might indicate unformatted/RAW file system. + * - `Invalid` = Path does not exist or is a network drive that is presently inaccessible, etc. + * @throws Error - An exception is thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} + * @example + */ +DriveGetStatus(Path) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveGetStatusCD.htm|`DriveGetStatusCD()`} + * Returns the media status of the specified CD/DVD drive. + * @param {(String)} [Drive] + * Drive letter followed by a colon. + * If omitted, the default CD/DVD drive will be used. + * @returns {(String)} + * The media status of Drive + * - `not ready` = The drive is not ready to be accessed or is busy. + * Known limitation: Can occur when drive contains a DVD instead of a CD. + * - `open` = The drive contains no disc, or the tray is ejected. + * - `playing` = The drive is playing a disc. + * - `paused` = The previously playing audio or video is now paused. + * - `seeking` = The drive is seeking. + * - `stopped` = The drive contains a CD but is not currently accessing it. + * @throws Error - An exception is thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DriveEject.htm|DriveEject()} + * @example + */ +DriveGetStatusCD([Drive:=unset]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveGetType.htm|`DriveGetType()`} + * Returns the type of the drive which contains the specified path. + * @param {(String)} Path + * Any path contained by the drive. + * May work with UNC paths and mapped drives. + * @returns {(String)} + * The type of drive that Path belongs to. + * An empty string is returned if Path is invalid. Otherwise: + * - `Unknown` + * - `Removable` + * - `Fixed` + * - `Network` + * - `CDROM` + * - `RAMDisk` + * @throws Error - An exception is thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * @example + */ +DriveGetType(Path) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveLock.htm|`DriveLock()`} + * Prevents the eject feature of the specified drive from working. + * To unlock a drive, call {@link https://www.autohotkey.com/docs/v2/lib/DriveUnlock.htm|DriveUnlock()}. + * @param {(String)} Drive + * Drive letter followed by a colon. Backslash is optional. + * May work with UNC paths and mapped drives. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - Drive does not exist or does not support the locking feature + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DriveUnlock.htm|DriveUnlock()} + * @example + */ +DriveLock(Drive) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveEject.htm|`DriveEject()`} + * Ejects the tray of the specified CD/DVD drive, or ejects a removable drive. + * This function waits for the ejection or retraction to complete before continuing. + * @param {(String)} [Drive] + * The path to an optical drive. + * Drive letter can be used. `:` and `\` are optional. `E`, `E:`, `E:\` + * Device paths can be used and gotten from {@link https://learn.microsoft.com/windows-server/administration/windows-commands/mountvol|mountvol}. `\\?\Volume{...}` + * @returns {(String)} + * An empty string is always returned. + * @throws Error - No drive was found + * The underlying system functions do not always report failure. + * An exception may or may not be thrown. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} + * {@link https://www.autohotkey.com/docs/v2/lib/DriveGetStatusCD.htm|DriveGetStatusCD()} | + * @example + */ +DriveRetract([Drive:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveSetLabel.htm|`DriveSetLabel()`} + * Changes the volume label of the specified drive. + * @param {(String)} Drive + * Drive letter followed by a colon. Backslash is optional. + * May work with UNC paths and mapped drives. + * @param {(String)} [NewLabel] + * New drive label. + * If omitted, drive label is blanked. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - An exception is thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DriveGetLabel.htm|DriveGetLabel()} + * @example + */ +DriveSetLabel(Drive [,NewLabel:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/DriveUnlock.htm|`DriveUnlock()`} + * Restores the eject feature of the specified drive. + * This may need to be called multiple times if the drive was locked multiple times. + * @param {(String)} Drive + * Drive letter followed by a colon. Backslash is optional. + * May work with UNC paths and mapped drives. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - An exception is thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/Drive.htm|Drive functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DriveLock.htm|DriveLock()} + * @example + */ +DriveUnlock(Drive) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Edit.htm|`Edit()`} + * Opens the current script for editing in the default editor. + * Uses the associated "edit" verb in the registry. Notepad by default. + * Registry location: `HKCU\Software\Classes\AutoHotkeyScript\shell\edit\command` + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Reload.htm|Reload()} | + * {@link https://www.autohotkey.com/docs/v2/Program.htm#edit|How to edit a script} | + * {@link https://www.autohotkey.com/docs/v2/misc/Editors.htm|Editors with AutoHotkey support} + * @example + */ +Edit() => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentCol.htm|`EditGetCurrentCol()`} + * Returns the column number in an Edit control where the caret (text insertion point) resides. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title must not contain this text. + * @param {(String)} [NoWinText] + * Window text must not contain this text. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The column number in the Edit control where the caret resides. + * @throws Error - Window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentLine.htm|EditGetCurrentLine()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetLineCount.htm|EditGetLineCount()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetLine.htm|EditGetLine()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetSelectedText.htm|EditGetSelectedText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditPaste.htm|EditPaste()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +EditGetCurrentCol(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentLine.htm|`EditGetCurrentLine()`} + * Returns the line number in an Edit control where the caret (text insert point) resides. + * @param {(String|Integer|Object)} Control - A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The line number in the Edit control where the caret resides. + * @throws Error - Window or control could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentCol.htm|EditGetCurrentCol()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetLineCount.htm|EditGetLineCount()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetLine.htm|EditGetLine()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetSelectedText.htm|EditGetSelectedText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditPaste.htm|EditPaste()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +EditGetCurrentLine(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/EditGetLine.htm|`EditGetLine()`} + * Returns the text of the specified line in an Edit control. + * @param {(Integer)} N + * Number of the line to get. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * Text from line N of the Edit control. + * May end in `` `r `` or `` `r`n ``, depending on the control. + * @throws TargetError - Window or control could not be found + * @throws ValueError - N is out of range or otherwise invalid + * @throws OSError - Message could not be sent to the control + * @see {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentCol.htm|EditGetCurrentCol()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentLine.htm|EditGetCurrentLine()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetLineCount.htm|EditGetLineCount()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetSelectedText.htm|EditGetSelectedText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditPaste.htm|EditPaste()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +EditGetLine(N, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/EditGetLineCount.htm|`EditGetLineCount()`} + * Returns the number of lines in an Edit control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The number of lines in an Edit control. + * All Edit controls have at least 1 line, even if it has no text. + * @throws TargetError - Window or control could not be found + * @throws OSError - Message could not be sent to the control + * @see {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentCol.htm|EditGetCurrentCol()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentLine.htm|EditGetCurrentLine()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetLine.htm|EditGetLine()} + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetSelectedText.htm|EditGetSelectedText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditPaste.htm|EditPaste()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +EditGetLineCount(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/EditGetSelectedText.htm|`EditGetSelectedText()`} + * Returns the selected text in an Edit control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The selected text in the Edit control. + * An empty string is returned if no text is selected. + * @throws TargetError - Window or control could not be found + * @throws Error|OSError - There was a problem retrieving the text + * @see {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentCol.htm|EditGetCurrentCol()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetCurrentLine.htm|EditGetCurrentLine()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetLine.htm|EditGetLine()} + * {@link https://www.autohotkey.com/docs/v2/lib/EditPaste.htm|EditPaste()} | + * {@link https://www.autohotkey.com/docs/v2/lib/EditGetLineCount.htm|EditGetLineCount()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +EditGetSelectedText(Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/EditPaste.htm|`EditPaste()`} + * Pastes the specified string at the caret in an Edit control. + * @param {(String)} Text + * String to paste into Edit control. + * @param {(String|Integer|Object)} Control + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @throws OSError - A message could not be sent to the control + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlSetText.htm|ControlSetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +EditPaste(Text, Control [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/EnvGet.htm|`EnvGet()`} + * Retrieves an environment variable. + * @param {(String)} EnvVar + * Name of the environment variable. + * @returns {(String)} + * The value of EnvVar. + * An empty string is returned if EnvVar has no value. + * @see {@link https://www.autohotkey.com/docs/v2/lib/EnvSet.htm|EnvSet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|RunWait()} + * @example + */ +EnvGet(EnvVar) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/EnvSet.htm|`EnvSet()`} + * Writes a value to a variable contained in the environment. + * @param {(String)} EnvVar + * Name of the environment variable. + * @param {(String)} [Value] + * Value to write. + * Omitting value deletes the variable. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Any failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/EnvGet.htm|EnvGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|RunWait()} + * @example + */ +EnvSet(EnvVar [,Value:=unset]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Exit.htm|`Exit()`} + * Exits the {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|current thread}. + * If the script isn't {@link https://www.autohotkey.com/docs/v2/lib/Persistent.htm|Persistent}, Exit() acts as {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|ExitApp()} as killing the thread also kills the script. + * @param {(Integer)} [ExitCode] + * Any integer between -2147483648 and 2147483647. + * This code is accessible to any program that spawned the script. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|ExitApp()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnExit.htm|OnExit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Return.htm|Return()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Persistent.htm|Persistent()} + * {@link https://www.autohotkey.com/docs/v2/Functions.htm|Functions} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * @example + */ +Exit([ExitCode:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|`ExitApp()`} + * Terminates the script. + * @param {(Integer)} [ExitCode] + * Any integer between -2147483648 and 2147483647. + * This code is accessible to any program that spawned the script. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Exit.htm|Exit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnExit.htm|OnExit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Persistent.htm|Persistent()} + * @example Example of a kill switch. + * ; Extremely useful to have a way to always end the script + * *Esc::ExitApp() + */ +ExitApp([ExitCode:=0]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Exp|`Exp()`} + * Returns the result of raising e/Euler's number (2.71828182845905) to the Nth power. + * This is not for exponents. See the {@link https://www.autohotkey.com/docs/v2/Variables.htm#pow|`**` exponent operator}. + * @param {(Number)} N + * The power to raise e to. + * N can be negative. + * @returns {(Number)} + * Result of calculation. + * @example + */ +Exp(N) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileAppend.htm|`FileAppend()`} + * Writes text or binary data to the end of a file. + * File is created first if it does not exist. + * To overwrite a file, use {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|FileDelete()}. + * @param {(String|Object)} Text + * Text to append to file. + * If no text is provided, a new, blank file is still created. + * A {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|`buffer-like`} object can be passed to append raw binary data. + * Any object using {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Ptr|Ptr} and {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Size|Size} properties can be used. + * BOM (byte order mark) is only written if `UTF-8` or `UTF-16` encoding is used. + * @param {(String)} [Filename] + * Name of the file to be appended. + * If a full path isn't used, Filename is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * Use an asterisk `*` as the Filename to send Text to standard out (stdout). + * FileName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} that's using an {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm#OutputFile|OutputFile}. + * @param {'CP0'|'UTF-8'|'UTF-8-RAW'|'UTF-16'|'UTF-16-RAW'|'CPnnn'|'RAW'|'`n'|String|Integer} [Options] + * Zero or more options separated by spaces/tabs. + * - `Encoding` = Any of the {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm#Parameters|FileEncoding()} names. + * - `CP0`: The system default ANSI code page. + * - `UTF-8`: Unicode UTF-8 (equivalent to CP65001). + * - `UTF-8-RAW`: UTF-8 but no byte order mark is written when a new file is created. + * - `UTF-16`: Unicode UTF-16 with little endian byte order (CP1200). + * - `UTF-16-RAW`: UTF-16 but no byte order mark is written when a new file is created. + * - `CPnnn`: A code page with numeric identifier nnn. See {@link https://learn.microsoft.com/windows/win32/intl/code-page-identifiers|Code Page Identifiers}. + * - `nnn`: A numeric code page identifier. + * - `RAW` = Write the Text bytes to the file as-is, without any conversion. + * - `` `n ``= A carriage return `` `r `` is inserted before all linefeeds `` `n ``. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm|FileEncoding()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm|FileOpen()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileRead.htm|FileRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OutputDebug.htm|OutputDebug()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|FileDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/IniWrite.htm|IniWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} | + * {@link https://www.autohotkey.com/docs/v2/lib/File.htm|File Object} | + * {@link https://www.autohotkey.com/docs/v2/Scripts.htm#continuation|Continuation Sections} + * @example + */ +FileAppend(Text [,Filename:=unset, Options:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileCopy.htm|`FileCopy()`} + * Copies one or more files. + * @param {(String)} SourcePattern + * Name of a file, a folder, or a wildcard `*` pattern. + * If a full path isn't used, SourcePattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * All AHK files: `'folder\*.ahk'` + * All files that start with Project: `folder\project*.*` + * @param {(String)} DestPattern + * Name or pattern of the destination. + * If a full path isn't used, DestPattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * An asterisk before the file ext dot will be replaced with the SourcePattern's file name. + * An asterisk after the file ext dot will be replaced with the SourcePattern's file ext. + * A simple 1:1 copy while retaining the original: + * + * FileCopy('D:\Scripts\*.ahk', 'D:\Scripts\backup\*.*') + * @param {(Integer)} [Overwrite] + * - `0` = Do not overwrite existing files. + * - `1` = Overwrite existing files. + * If DestPattern doesn't have a complimentary file/subfolder in SourcePattern, it will not be deleted. + * + * Other values are reserved for future use. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - If any files failed to be copied. + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Extra|Error.Extra} is set to the number of failures. + * @throws Error - The specific file was not found. + * Patterns using broad matching with `?` and `*` do not error on match failure. + * @throws Error - Copying a file over itself, even with a OverWrite set to 1. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileMove.htm|FileMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirCopy.htm|DirCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirMove.htm|DirMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|FileDelete()} + * @example + */ +FileCopy(SourcePattern, DestPattern [,Overwrite:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileCreateShortcut.htm|`FileCreateShortcut()`} + * Creates a shortcut (.lnk) file. + * @param {(String)} File + * File to create a shortcut for. + * File path might not be needed if file is part of the PATH {@link https://www.autohotkey.com/docs/v2/Concepts.htm#environment-variables|environment variable}. + * @param {(String)} Link + * Name of the new shortcut link. + * @param {(String)} [WorkingDir] + * Directory for File's current working directory. + * If blank or omitted, the new shortcut has a blank "Start in" field. + * @param {(String)} [Args] + * Parameters to be passed to Link when launched. + * If blank or omitted, Link launches File with no parameters. + * @param {(String)} [Description] + * Comments describing the new Link. + * If blank of omitted, shortcut will have no description. + * @param {(String)} [IconFile] + * Full path and name of the icon to use for shortcut. + * If blank of omitted, shortcut will use File's icon. + * @param {(String)} [ShortcutKey] + * A single letter, number, or key name from the {@link https://www.autohotkey.com/docs/v2/KeyList.htm|key list} to launch the Link. + * If blank or omitted, no shortcut key is assigned. + * All shortcuts use the `Ctrl+Alt` modifiers and cannot be changed. + * @param {(Integer)} [IconNumber] + * The number of the icon to use from IconFile. + * If blank or omitted, it defaults to 1. + * @param {(Integer)} [RunState] + * Window state when Link is launched: + * - `1` = Normal + * - `3` = Maximized + * - `7` = Minimized + * @returns {(String)} + * An empty string is always returned. + * @throws Error - Any failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileGetShortcut.htm|FileGetShortcut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileAppend.htm|FileAppend()} + * @example + */ +FileCreateShortcut(File, LinkFile [,WorkingDir:=A_WorkingDir, Args:=unset, Description:='', IconFile:='', ShortcutKey:='', IconNumber:=1, RunState:=1]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|`FileDelete()`} + * Deletes one or more files. + * To delete an entire folder/subfolders, use {@link https://www.autohotkey.com/docs/v2/lib/DirDelete.htm|DirDelete()}. + * @param {(String)} FilePattern + * Name of a file or a wildcard `*` pattern. + * If a full path isn't used, FilePattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - Any files failed to delete. + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Extra|Error.Extra} is set to the number of failures. + * Patterns using broad matching with `?` and `*` do not error on match failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileRecycle.htm|FileRecycle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirDelete.htm|DirDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileCopy.htm|FileCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileMove.htm|FileMove()} + * @example + */ +FileDelete(FilePattern) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm|`FileEncoding()`} + * Sets the default encoding for {@link https://www.autohotkey.com/docs/v2/lib/FileRead.htm|FileRead()}, {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Read}, {@link https://www.autohotkey.com/docs/v2/lib/FileAppend.htm|FileAppend()}, and {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm|FileOpen()}. + * @param {'CP0'|'UTF-8'|'UTF-8-RAW'|'UTF-16'|'UTF-16-RAW'|'CPnnn'|'RAW'|'`n'|String|Integer} [Encoding] + * One of the following values: + * - `Encoding` = Any of the {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm#Parameters|FileEncoding()} names. + * - `CP0`: The system default ANSI code page. + * - `UTF-8`: Unicode UTF-8 (equivalent to CP65001). + * - `UTF-8-RAW`: UTF-8 but no byte order mark is written when a new file is created. + * - `UTF-16`: Unicode UTF-16 with little endian byte order (CP1200). + * - `UTF-16-RAW`: UTF-16 but no byte order mark is written when a new file is created. + * - `CPnnn`: A code page with numeric identifier nnn. See {@link https://learn.microsoft.com/windows/win32/intl/code-page-identifiers|Code Page Identifiers}. + * - `nnn`: A numeric code page identifier. + * - `RAW` = Write the Text bytes to the file as-is, without any conversion. + * - `` `n ``= Inserts a carriage return `` `r `` before all linefeeds `` `n ``. + * @returns {(String)} + * The previous setting is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm|FileOpen()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrGet.htm|StrGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrPut.htm|StrPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileRead.htm#Binary|Reading Binary Data} + * @example + */ +FileEncoding(Encoding) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileExist.htm|`FileExist()`} + * Checks for the existence of a file or folder and returns its attributes. + * @param {(String)} FilePattern + * The path, filename, or file pattern to check. + * If a full path isn't used, FilePattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @returns {(String)} + * A string of all attributes found for file or directory. + * - Empty String = No file or folder was found. + * - `R` = ReadOnly + * - `A` = Archive + * - `S` = System + * - `H` = Hidden + * - `N` = Normal + * - `D` = Directory + * - `O` = Offline + * - `C` = Compressed + * - `T` = Temporary + * - `L` = REPARSE_POINT (typically a symbolic link) + * - `X` = File has no attributes (rare) + * @see {@link https://www.autohotkey.com/docs/v2/lib/DirExist.htm|DirExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetAttrib.htm|FileGetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} + * @example + */ +FileExist(FilePattern) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileInstall.htm|`FileInstall()`} + * Includes the specified file inside the {@link https://www.autohotkey.com/docs/v2/Scripts.htm#ahk2exe|compiled version} of the script. + * @param {(String)} Source + * Name of a single file to add to the EXE. + * Source must be a string, cannot be a variable of any type, and must be on the same line as the FileInstall() function. + * If a full path isn't used, Source is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(String)} Dest + * Name of the file when it is extracted from the EXE. + * If a full path isn't used, Dest is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * The destination directory *must* already exist. + * @param {(Integer)} [Overwrite] + * If omitted, 0 is used. + * - `0` = Do not overwrite existing files. The operation fails. + * - `1` = Overwrite existing files. + * + * Other values are reserved for future use. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - An exception is thrown on failure + * @throws Error - Any case where the file cannot be written to the destination + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileCopy.htm|FileCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/_Include.htm|#Include} + * @example + */ +FileInstall(Source, Dest [,Overwrite:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileGetAttrib.htm|`FileGetAttrib()`} + * Reports the attributes of a file or folder. + * @param {(String)} [Filename] + * Name of the file to be appended. + * If a full path isn't used, Filename is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * FileName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} that's using an {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm#OutputFile|OutputFile}. + * @returns {(String)} + * A string of all attributes found for file or directory. + * - Empty String = No file or folder was found. + * - `R` = ReadOnly + * - `A` = Archive + * - `S` = System + * - `H` = Hidden + * - `N` = Normal + * - `D` = Directory + * - `O` = Offline + * - `C` = Compressed + * - `T` = Temporary + * - `L` = REPARSE_POINT (typically a symbolic link) + * @throws OSError - Thrown on failure. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileExist.htm|FileExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirExist.htm|DirExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSetAttrib.htm|FileSetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetTime.htm|FileGetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|FileSetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetSize.htm|FileGetSize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetVersion.htm|FileGetVersion()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} + * @example + */ +FileGetAttrib([Filename]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileGetShortcut.htm|`FileGetShortcut()`} + * Retrieves information about a shortcut (.lnk) file, such as its target file. + * @param {(VarRef)} LinkFile + * Name of the shortcut file to be analyzed. Include the `.lnk` ext. + * If a full path isn't used, LinkFile is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(VarRef)} [OutFile] + * Get target file of the shortcut. + * @param {(VarRef)} [OutDir] + * Get LinkFile's working directory. + * @param {(VarRef)} [OutArgs] + * Get function arguments for LinkFile. + * @param {(VarRef)} [OutDesc] + * Get LinkFile's description. + * @param {(VarRef)} [OutIcon] + * Get icon file for LinkFile. + * @param {(VarRef)} [OutIconNum] + * Get the icon number used with the icon file. + * Normally, this is 1. + * @param {(VarRef)} [OutState] + * Get window launch state of LinkFile. + * - `1` = Normal + * - `3` = Maximized + * - `7` = Minimized + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileCreateShortcut.htm|FileCreateShortcut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SplitPath.htm|SplitPath()} + * @example + */ +FileGetShortcut(LinkFile [,&OutFile, &OutDir, &OutArgs, &OutDesc, &OutIcon, &OutIconNum, &OutState]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileGetSize.htm|`FileGetSize()`} + * Retrieves the size of a file. + * @param {(String)} [Filename] + * Name of the file to get the size of. + * If a full path isn't used, Filename is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * FileName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} that's using an {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm#OutputFile|OutputFile}. + * @param {'B'|'K'|'M'} [Units] + * Unit type to return: + * - `B` or Omitted = Bytes + * - `K` = Kilobytes + * - `M` = Megabytes + * @returns {(Integer)} + * The size of the specified file, rounded down to the nearest whole number. + * @throws OSError - Thrown on failure. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileGetAttrib.htm|FileGetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSetAttrib.htm|FileSetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetTime.htm|FileGetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|FileSetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetVersion.htm|FileGetVersion()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} | + * @example + */ +FileGetSize([Filename:=unset, Units:='B']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileGetTime.htm|`FileGetTime()`} + * Retrieves the datetime stamp of a file or folder. + * @param {(String)} [Filename] + * Name of the file to get the size of. + * If a full path isn't used, Filename is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * FileName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} that's using an {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm#OutputFile|OutputFile}. + * @param {'A'|'C'|'M'} [TimeType] + * Specify which time type to change: + * - `M` or Omitted = Modification time + * - `C` = Creation time + * - `A` = Last Access time + * @returns {(String)} + * Get file time in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS} format. + * Time is in local time, not UTC/GMT. + * @throws OSError - Thrown on failure. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|FileSetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|FormatTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetAttrib.htm|FileGetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSetAttrib.htm|FileSetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetSize.htm|FileGetSize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetVersion.htm|FileGetVersion()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DateAdd.htm|DateAdd()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DateDiff.htm|DateDiff()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} + * @example + */ +FileGetTime([Filename:=unset, TimeType:='M']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileGetVersion.htm|`FileGetVersion()`} + * Retrieves the version of a file. + * @param {(String)} [Filename] + * Name of the file to get the version of. + * If a full path isn't used, this function uses the search sequence specified by the system {@link https://learn.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya|LoadLibrary} function. + * FileName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} that's using an {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm#OutputFile|OutputFile}. + * @returns {(String)} + * Version number of the specified file + * @throws OSError - Thrown on failure. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|FileSetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetTime.htm|FileGetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetAttrib.htm|FileGetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSetAttrib.htm|FileSetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetSize.htm|FileGetSize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} + * @example + */ +FileGetVersion([Filename]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileMove.htm|`FileMove()`} + * Moves or renames one or more files. + * @param {(String)} SourcePattern + * Name of a file or a wildcard `*` pattern. + * If a full path isn't used, SourcePattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(String)} DestPattern + * Name or pattern of the destination. + * If a full path isn't used, DestPattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * An asterisk before the file ext dot will be replaced with the SourcePattern's file name. + * An asterisk after the file ext dot will be replaced with the SourcePattern's file ext. + * A simple 1:1 move retaining the original file names: + * + * FileMove('D:\Scripts\*.ahk', 'D:\Scripts\backup\*.*') + * @param {(Integer)} [Overwrite] + * - `0` = Do not overwrite existing files. + * - `1` = Overwrite existing files. + * If DestPattern doesn't have a complimentary file/subfolder in SourcePattern, it will not be deleted. + * + * Other values are reserved for future use. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - If any files failed to be moved. + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Extra|Error.Extra} is set to the number of failures. + * Patterns using broad matching with `?` and `*` do not error on match failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileCopy.htm|FileCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirCopy.htm|DirCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirMove.htm|DirMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|FileDelete()} + * @example + */ +FileMove(SourcePattern, DestPattern [,Overwrite:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm|`FileOpen()`} + * Opens a file to read specific content from it and/or to write new content into it. + * @param {'*'|'**'|String} Filename + * The path of the file to open. + * If a full path isn't used, Filename is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * To used stdin, stdout, or stderr: + * - `stdin` Standard In: + * + * FileOpen('*', 'r')` + * - `stdout` Standard Out: + * + * FileOpen('*', 'w') + * - `stderr` Error stream: + * + * FileOpen('**', 'w') + * @param {'r'|'w'|'a'|'rw'|'h'|'rwd'|'`n'|'`r'} Flags + * This can be either a string of flag characters or an integer sum of the desired options options. + * Integer can be decimal or hexadecimal. + * ### {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm#Access_modes|Access modes (mutually-exclusive)} + * - | -Flag- | -Dec- | -Hex- | -Description- | + * | :--- | :--- | :--- | :--- | + * | `r` | `0` | `0x0` | Read: Fails if the file doesn't exist. | + * | `w` | `1` | `0x1` | Write: Create a new file, overwriting existing file. | + * | `a` | `2` | `0x2` | Append: Create a new file, otherwise move file pointer to end of file. | + * | `rw` | `3` | `0x3` | Read/Write: Creates a new file if the file didn't exist. | + * | `h` | | | Indicates that Filename is a file handle to wrap in an object. {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm#Access_modes|More info.} | + * + * ### {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm#Sharing_mode_flags|Sharing mode flags} + * - | -Flag- | -Dec- | -Hex- | -Description- | + * | :--- | :--- | :--- | :--- | + * | `-rwd` | | | Lock read, write, and/or delete access. Any combination may be used. | + * | `-` | | | Infers -rwd. | + * | | `0` | `0x0` | If `Flags` is numeric, no sharing mode flag causes the file to be locked. | + * | | `256` | `0x100` | Shares read access. | + * | | `512` | `0x200` | Shares write access. | + * | | `1024` | `0x400` | Shares delete access. | + * + * ### {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm#EOL_options|End of line (EOL) options} + * - | -Flag- | -Dec- | -Hex- | -Description- | + * | :--- | :--- | :--- | :--- | + * | `` `n `` | `4` | `0x4` | Reading: Replaces `` `r`n `` with `` `n `` | + * | | | | Writing: Replaces `` `n `` with `r`n when writing. | + * | `` `r `` | `8` | `0x8` | Replace standalone `r with `n when reading. | + * + * @param {'CP0'|'UTF-8'|'UTF-8-RAW'|'UTF-16'|'UTF-16-RAW'|'CPnnn'|'RAW'|'`n'|String|Integer} [Encoding] + * One of the following values: + * - `Encoding` = Any of the {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm#Parameters|FileEncoding()} names. + * - `CP0`: The system default ANSI code page. + * - `UTF-8`: Unicode UTF-8 (equivalent to CP65001). + * - `UTF-8-RAW`: UTF-8 but no byte order mark is written when a new file is created. + * - `UTF-16`: Unicode UTF-16 with little endian byte order (CP1200). + * - `UTF-16-RAW`: UTF-16 but no byte order mark is written when a new file is created. + * - `CPnnn`: A code page with numeric identifier nnn. See {@link https://learn.microsoft.com/windows/win32/intl/code-page-identifiers|Code Page Identifiers}. + * - `nnn`: A numeric code page identifier. + * - `RAW` = Write the Text bytes to the file as-is, without any conversion. + * - `` `n ``= Inserts a carriage return `` `r `` before all linefeeds `` `n ``. + * @returns {(File)} + * A new {@link https://www.autohotkey.com/docs/v2/lib/File.htm|File object} to handle the file. + * A File object uses properties and methods to work with a text file. + * @throws OSError - The file cannot be opened + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm|FileEncoding()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileRead.htm|FileRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/File.htm|File Object} + * @example + */ +FileOpen(Filename, Flags [,Encoding]) => File + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileRead.htm|`FileRead()`} + * Retrieves the contents of a file. + * @param {(String)} Filename + * name of the file to read + * If a full path isn't used, Filename is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {'CP0'|'UTF-8'|'UTF-8-RAW'|'UTF-16'|'UTF-16-RAW'|'CPnnn'|'RAW'|'`n'|String|Integer} [Options] + * Zero or more options, separated by spaces/tabs + * - `Encoding` = + * - `CP0`: The system default ANSI code page. + * - `UTF-8`: Unicode UTF-8 (equivalent to CP65001). + * - `UTF-8-RAW`: UTF-8 but no byte order mark is written when a new file is created. + * - `UTF-16`: Unicode UTF-16 with little endian byte order (CP1200). + * - `UTF-16-RAW`: UTF-16 but no byte order mark is written when a new file is created. + * - `CPnnn`: A code page with numeric identifier nnn. See {@link https://learn.microsoft.com/windows/win32/intl/code-page-identifiers|Code Page Identifiers}. + * - `nnn`: A numeric code page identifier. + * - `m#` = Memory limitation where `#` is the number of bytes. + * Only the leading part up to that amount is loaded from the file. + * If omitted, the entire file is loaded + * - `RAW` = Write the Text bytes to the file as-is, without any conversion. + * - `` `n ``= Inserts a carriage return `` `r `` before all linefeeds `` `n ``. + * @returns {(String|Object)} + * Returns the contents of the of Filename. + * If the `RAW` option is used, a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer object} is returned. + * Otherwise, a string is returned. + * An empty string is returned if the file does not exist or cannot be opened. + * @throws OSError - Problem opening or reading the file + * @throws MemoryError - A file is greater than 4GB in size + * @throws MemoryError - The program is unable to allocate enough memory for the requested size + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm|FileEncoding()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileOpen.htm|FileOpen()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetSize.htm|FileGetSize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileAppend.htm|FileAppend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/IniRead.htm|IniRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Sort.htm|Sort()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Download.htm|Download()} | + * {@link https://www.autohotkey.com/docs/v2/lib/File.htm|File Object} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} + * @example + */ +FileRead(Filename [,Options]) => String | Object + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileRecycle.htm|`FileRecycle()`} + * Sends a file or directory to the recycle bin if possible, or permanently deletes it. + * @param {(String)} FilePattern + * Name of a file, a folder, or a wildcard `*` pattern. + * To recycle an entire directory, provide the name without a trailing backslash. + * If a full path isn't used, FilePattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - An exception is thrown on failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileRecycleEmpty.htm|FileRecycleEmpty()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|FileDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileCopy.htm|FileCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileMove.htm|FileMove()} + * @example + */ +FileRecycle(FilePattern) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileRecycleEmpty.htm|`FileRecycleEmpty()`} + * Empties the recycle bin. + * @param {(String)} [DriveLetter] + * Drive letter followed by a colon. Backslash is optional. + * Omit DriveLetter to empty all drive recycle bins. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileRecycle.htm|FileRecycle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileDelete.htm|FileDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileCopy.htm|FileCopy()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileMove.htm|FileMove()} + * @example + */ +FileRecycleEmpty([DriveLetter:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|`FileSelect()`} + * Displays a standard dialog that allows the user to open or save file(s). + * @param {String|'D'|'M'|'S'} [Options] + * Zero or more options separated by spaces/tabs. + * - Empty string = No options. + * - `D` = Directory Select. + * Select a folder instead of a file. + * The Filter param must be empty. + * - `M` = Multi Select. + * More than one file can be selected via shift+click, alt+click, etc. + * - `S` = Save Dialog. + * Changes the `Open` button to a `Save` button. + * - Any sum of these number options: + * - `0` = No options. + * - `1` = File must exist. + * - `2` = Path must exist. + * - `8` = Prompt to create new file. + * - `16` = Prompt to overwrite file. + * Also forces `S` option. + * - `32` = Shortcuts are targeted instead of resolving to their target file. + * @param {(String)} [RootOrFilename] + * Root directory, filename, or both. + * - `Root` = A path to use as a starting directory for the dialog box. + * If a full path isn't used, Root is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * - `Filename` = Default text to show in the file name edit box. + * This does not have to be a valid file name. Any text will show. + * - `Root\Filename` = Root directory followed by the default Filename: `Root\Filename.ext` + * Root sets the starting directory. Everything past the last backslash populates the file name edit box. + * Do not treat this as a full file path. + * @param {(String)} [Title] + * Title of the window. + * If omitted, `'Select File - ' A_ScriptName` is used. + * @param {(String)} [Filter] + * Restricts which file types to show. + * - Filter format: + * + * FileSelect(,,, 'Text File (*.txt)') + * - Multiple type format: + * + * FileSelect(,,, 'AHK Script (*.ahk; *.ah2; *.ahk2)') + * - Omit filter: If no filter is provided, All Files is used + * + * FileSelect(,,, 'All Files (*.*)') + * @returns {(String|Array)} + * Returns the path of the select filed. + * A string of paths is returned if multi-select is in use. + * @see {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|MsgBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm|InputBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ToolTip.htm|ToolTip()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SplitPath.htm|SplitPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|GUI} | + * {@link https://www.autohotkey.com/docs/v2/misc/CLSID-List.htm|CLSID List} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopParse.htm|Loop-Parse} + * @example + */ +FileSelect([Options:=0, RootOrFilename:=A_WorkingDir, Title:=unset, Filter:='']) => String | Array + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileSetAttrib.htm|`FileSetAttrib()`} + * Changes the attributes of one or more files or folders. Wildcards are supported. + * @param {String|'R'|'A'|'S'|'H'|'N'|'O'|'T'} Attributes + * Alter an attribute. + * Add `+`, remove `-`, or toggle `^` an attribute. + * Multiple attributes can be be adjusted at once: `+RAH` + * - `R` = READONLY + * - `A` = ARCHIVE + * - `S` = SYSTEM + * - `H` = HIDDEN + * - `N` = NORMAL (Only works when used by itself) + * - `O` = OFFLINE + * - `T` = TEMPORARY + * @param {(String)} [FilePattern] + * Name of the file to get the version of. + * If a full path isn't used, FilePattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * FilePattern can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} that's using an {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm#OutputFile|OutputFile}. + * @param {String|'F'|'D'|'R'} [Mode] + * - `D` = Directory. Includes folders + * - `F` = Files. Include files + * - `R` = Recurse. Recurses into all sub-folders + * @returns {(String)} + * An empty string is always returned. + * @throws Error - Any files failed to be changed. + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Extra|Error.Extra} is set to the number of failures. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to 0 if files are found, otherwise it gets the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileGetAttrib.htm|FileGetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetTime.htm|FileGetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|FileSetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetSize.htm|FileGetSize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetVersion.htm|FileGetVersion()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} + * @example Different examples. + * ; Add ReadOnly and Hidden to all files in C:\MyFiles\ + * FileSetAttrib('+RH', 'C:\MyFiles\*.*', 'DF') + * ; Toggle the hidden state of the C:\MyFiles directory + * FileSetAttrib('^H', 'C:\MyFiles') + * ; Remove ReadOnly and Hidden then add Archive to New Text File.txt + * FileSetAttrib('-RH+A', 'C:\New Text File.txt') + * ; Add Archive to all ini files in C: + * FileSetAttrib('+A', 'C:\*.ini', 'R') + */ +FileSetAttrib(Attributes [,FilePattern:=unset, Mode:='F']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|`FileSetTime()`} + * Changes the datetime stamp of one or more files or folders. Wildcards are supported. + * @param {(String)} [DateTimeStamp] + * A date-time in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#Remarks|YYYYMMDDHH24MISS} format. + * @param {(String)} [FilePattern] + * Name of the file to change time of. + * If a full path isn't used, FilePattern is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * FilePattern can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} that's using an {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm#OutputFile|OutputFile}. + * @param {'M'|'C'|'A'} [TimeType] + * Specify which time type to change: + * - `M` or Omitted = Modification time + * - `C` = Creation time + * - `A` = Last Access time + * @param {String|'F'|'D'|'R'} [Mode] + * - `D` = Directory. Includes folders + * - `F` = Files. Include files + * - `R` = Recurse. Recurses into all sub-folders + * @returns {(String)} + * An empty string is always returned. + * @throws Error - Any files failed to be changed. + * {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#Extra|Error.Extra} is set to the number of failures. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to 0 if files are found, otherwise it gets the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileGetTime.htm|FileGetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetAttrib.htm|FileGetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSetAttrib.htm|FileSetAttrib()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetSize.htm|FileGetSize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetVersion.htm|FileGetVersion()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|FormatTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DateAdd.htm|DateAdd()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DateDiff.htm|DateDiff()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm|Loop-Files} + * @example + */ +FileSetTime([DateTimeStamp:=A_Now, FilePattern:=unset, TimeType:='M', Mode:='F']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Floor|`Floor()`} + * Returns the specified number rounded down to the nearest integer. + * @param {(Number)} Num + * The number to round down. + * @returns {(Integer)} + * The floored value of Num. + * @example + * Floor(1.1) ; => 1 + * Floor(1.9) ; => 1 + * Floor(2.0) ; => 2 + * Floor(-4.5) ; => -5 + * Floor(9.999) ; => 9 + */ +Floor(Num) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Format.htm|`Format()`} + * Takes in variables and creates custom-formatted string. + * Can be used to transform data types, align, pad, prefix, or build entire strings. + * @param {'{:}'|String} FormStr + * A string of text that describes how the finished string should be displayed. + * Special tags are used to transform variables appearance and data type: `{ParamNum:NewFormat}` + * To use literal curly braces in this string, they must be wrapped in curly braces: `{{}` `{}}`. + * - `ParamNum` + * All parameters after `FormStr` are numbered 1, 2, 3, etc. + * `ParamNum` indicates the variable's parameter number spot. + * If an array is used, `ParamNum` indicates the array index to use. + * If omitted, the number used is 1 higher than the previous number, or 1 if it's the first tag. + * - `NewFormat` + * A string that describes how the value should be transformed. + * Options need to be in the following order and should have no separators: + * `Flags Width .Precision StrCase DataType` + * Examples: `+08.3f` or `-10.10Ts` + * + * ### Flags + * Alignment, prefix, padding, and display options: + * - `-` = Align text to the left of the given space. + * The right side is padded with spaces to meet the width requirement. + * Right alignment is used when this flag is omitted. + * + * Format('{1:-5}', 1) ; => '1 ' + * - `+` = Show positive sign. + * + * Format('{1:+d}', 100) ; => '+100' + * - `0` = Pad with zeroes. + * The `-` "Left Align" flag overrides this flag. + * + * Format('{1:+04}', 1) ; => '0001' + * - ` ` Space = Add space if signed and positive. + * The `+` "Show Positive Sign" flag overrides this flag. + * + * Format('{1: 04i}', 1) ; => ' 001' + * - `#` = Show prefix or decimal + * Dependent on the `DataType` used: + * - `c` `d` `i` `u` `s` = No effect. + * - `o` = Add octal `0` prefix. + * + * Format('{1:#o}', 128) ; => '0200' + * - `x`/`X` = Add hex `0x`/`0X` prefix. + * + * Format('{1:#x}', 255) ; => '0xff' + * Format("0x{1:X}", 1194684) ; => '0xABC123' + * - `e` `E` `f` `a` `A` = Force decimal point to show. + * + * Format('{1:#.0f}', 10) ; => '10.' + * - `g` `G` = Force decimal point to show and trailing zeroes are not truncated. + * + * Format('{1:g}', 4.2e01) ; => '42' + * Format('{1:#g}', 4.2e01) ; => '42.000' + * + * ### Width + * - The expected width, in characters, after all transformations are made. + * Value is padded with spaces and right-aligned by default. + * The `-` "Left Align` flag and `0` 'Pad With Zeroes" flag can override this. + * + * Format('{1:7d}', 1234) ; => ' 1234' + * Format('{1:-7d}', 1234) ; => '1234 ' + * Format('{1:07d}', 1234) ; => '0001234' + * + * ### .Precision + * - Precision of the value. The dot `.` is required. + * Dependent on the `DataType` used: + * - `f` `e` `E` = Set number of decimal places. + * Default: 6 + * + * Format('{1:.3f}', 0.123456) ; => '0.123' + * Format('{1:.0f}', 42) ; => '42.0' + * - `g` `G` = Sets max significant digits. + * Default: 6 + * + * Format('{1:.4g}', 123456) ; => '1.235e+05' + * - `s` = Set max number of characters to use. + * + * Format('{1:.8s}', 'Hello World') ; => 'Hello Wo' + * - `d` `i` `u` `x` `X` `o` = Set width and pad with zeroes. + * This will override the combination of `0` 'Pad With Zeroes" + a Width value. + * Default: 1 + * + * Format('|{1:#.6x}|', 0xABC) ; => '0x000abc' + * Format('|{1:010.5d}|', 123) ; => '00123' + * + * ### StrCase + * Adjust the case type of a string. + * Only works when the `DataType` is `s` + * - `U` = STRING UPPERCASE. + * - `L` = string lowercase. + * - `T` = String Title Case. + * + * ### DataType + * The expected data type after transformation: + * - Integer + * - `d` `i` = Signed Decimal + * + * Format('{1:d}', -1.5) ; => '1' + * - `u` = Unsigned Decimal + * + * Format('{1:u}', -1.5) ; => '18446744073709551615' + * - `x` `X` = Unsigned Hexadecimal + * Case of `x`/`X` sets hex case `abcdef`/`ABCDEF` + * + * Format('{1:x}', 1194684) ; => '123abc' + * Format('0x{1:X}', 1194684) ; => '0xABC123' + * - `o` = Unsigned Octal + * + * Format('{1:o}', 128) ; => '200' + * - `p` = Hexadecimal Address + * Width is determined by pointer size. + * + * Format('{:p}', 956887554989) ; => '000000DECAF15BAD' ; 64-bit + * Format('{:p}', 1194684) ; => '00123ABC' ; 32-bit + * - Floating-point + * Decimal length is set by `.Precision` + * - `f` = Float + * `[-]123456789.000000` + * + * Format('{1:f}', 123) ; => '123.000000' + * - `e` `E` = Float with exponent + * `[-]123456789.000000[eE][-+]000` + * Exponent is always 2-3 digits. + * `e`/`E` case sets exponent symbol case `e`/`E` + * + * Format('{:e}', 12345.6789) ; => '1.234568e+04' + * - `g` `G` = General format + * Uses `e` or `f` format, whichever is more compact. + * `e` is used if exponent is less than e-4 or greater than .Precision. + * `g`/`G` case sets exponent symbol case `e`/`E`. + * + * Format('{:.4g}', 0.0000042) ; => '4.2e-06' + * Format('{:.4g}', 1.2e+02) ; => '120' + * - `a` `A` = Hexadecimal double precision + * `[-]0xFEDCBA987.654321[pP][-+]0` + * Exponent is denoted with p/P as e/E is a hex value. + * `a`/`A` case sets exponent symbol case `p`/`P`. + * + * Format('{:A}', -255.8) ; => '-0x1.ff9999999999aP+7' + * - String + * - `s` String + * Numeric values are converted to string. + * `Width` affects total chars, adding spaces for padding + * `.Precision` determines number of chars to use from `ParamNum` + * + * Format('{2:.4s}{1:.6s}', 'Hotkey()', 'Automation') ; => 'AutoHotkey' + * - `c` Character Code + * Converts number to its ordinal value just like {@link https://www.autohotkey.com/docs/v2/lib/Chr.htm|Chr()} + * + * Format('{:c}{:c}{:c}', 65, 72, 75) ; => 'AHK' + * Format('¯\_({1:c})_/¯', 0x30C4) ; => '¯\_(ツ)_/¯' + * @param {(Primitive|Array)} [Values] + * One or more variables to be used in the `FormStr` parameter. + * Any number of parameter values can be passed in. + * + * Format('{1:Us}{2:Ls}{3:Ts}', var1, var2, var3) + * An array of values can be used if it's the only value and is marked {@link https://www.autohotkey.com/docs/v2/Functions.htm#VariadicCall|variadic*}. + * + * arr := ['World', 'Hello'] + * Format('{2}, {1}!', arr*) ; => 'Hello, World!' + * @returns {(String)} + * The string after formatting. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|FormatTime()} + * @example + */ +Format(FormStr [,Values*]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|`FormatTime()`} + * Transforms a YYYYMMDDHH24MISS timestamp into the specified date/time format. + * @param {String|'R'|'L'|'D'|'T'} [DateTimeStamp] + * All or the leading part of a {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS} date time stamp. + * If omitted, A_Now (the current DTS) is used. + * Any of the following options can be included after the date timestamp: + * - `R` = Reverse. The time and date order when `Form` is blank. + * - `L#` = Set Locale, where `#` is a {@link https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/70feba9f-294e-491e-b6eb-56532684c37f|local identifier (LCID)}. + * Use `LSys` to use the system locale. + * If omitted, user's current locale is used. + * - `D#` = Date options, where `#` is one of the following numbers: + * - `0` = Force default options to be used. Short date is used. + * - `1` = Use short date. Incompatible with `D2` or `D8`. Only usable when `Form` is blank. + * - `2` = Use long date. Incompatible with `D1` or `D8`. Only usable when `Form` is blank. + * - `4` = Use alternate calendar (if any). + * - `8` = User Year-Month format. Incompatible with `D1` or `D2`. Only usable when `Form` is blank. + * - `0x10` = Add left-to-right reading order layout marks. + * - `0x20` = Add right-to-left reading order layout marks. + * - `0x40000000` = For string translation, use system ANSI code page instead of locale's code page. + * - `0x80000000` = Ignore all user overrides in effect for the system's default date format. + * - `T#` = Time options, where `#` is one of the following numbers: + * - `0` = Force default options to be used. Minutes and seconds are shown. + * - `1` = Omit minutes and seconds. + * - `2` = Omit seconds. + * - `4` = Omit time marker (AM/PM). + * - `8` = Always use 24-hour time. + * - `12` = Combination of options `4` and `8`. + * - `0x40000000` = For string translation, use system ANSI code page instead of locale's code page. + * - `0x80000000` = Ignore all user overrides in effect for the system's default time format. + * @param {String|'d'|'dd'|'ddd'|'dddd'|'M'|'MM'|'MMM'|'MMMM'|'y'|'yy'|'yyyy'|'gg'|'h'|'hh'|'H'|'HH'|'m'|'mm'|'s'|'ss'|'t'|'tt'|'Time'|'ShortDate'|'LongDate'|'YearMonth'|'YDay'|'YDay0'|'WDay'|'YWeek'|String} [Form] + * The desired format. + * If omitted, `Time` + `LongDate` are used. + * To put literal text in the string without having it formatted should be enclosed in single quotes. + * To make a literal single quote, use two in a row `''` + * + * FormatTime(A_Now, "'Date:' MM/dd/yy 'Time:' hh:mm:ss tt") => 'Date: 12/03/23 Time: 05:03:58 PM' + * **{@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm#Date_Formats|Date Formats}** + * - `d` = Day of the month: `1-31` + * - `dd` = 2 digit day of the month: `01-31` + * - `ddd` = Day name abbr (based on language): `Sun-Sat` + * - `dddd` = Day name (based on language): `Sunday-Saturday` + * - `M` = Month of the year: `1-12` + * - `MM` = 2 digit month of the year: `01-12` + * - `MMM` = Month name abbr (based on language): `Jan-Dec` + * - `MMMM` = Full month name (based on language): `January-December` + * - `y` = Year, no century: `0-99` + * - `yy` = 2 digit year, no century: `00-99` + * - `yyyy` = Full year: `1601-9999` + * - `gg` = Period/era: `A.D.` + * **{@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm#Time_Formats|Time Formats}** + * - `h` = 12 hour format: `1-12` + * - `hh` = 2 digit 12 hour format: `01-12` + * - `H` = 24 hour format: `0-23` + * - `HH` = 2 digit 24 hour format: `00-23` + * - `m` = Minutes: `0-59` + * - `mm` = 2 digit minutes: `00-59` + * - `s` = Seconds: `0-59` + * - `ss` = 2 digit seconds: `00-59` + * - `t` = Locale time marker abbr: `A-P` + * - `tt` = Locale time marker full: `AM-PM` + * **{@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm#Standalone_Formats|Premade Formats}** + * - Empty String = `Time` and `LongDate` are used: + * + * FormatTime(v2_release) => '02:16 PM Monday, December 12, 2022' + * - `Time` = Locale time + * + * FormatTime(A_Now, 'Time') => '3:40 PM' + * - `ShortDate` = Locale short date + * + * FormatTime(A_Now, 'ShortDate') => '11/30/2023' + * - `LongDate` = Locale long date + * + * FormatTime(unix_epoch, 'LongDate') => 'Thursday, January 1, 1970' + * - `YearMonth` = Month followed by year + * + * FormatTime(judge_day, 'YearMonth') => 'August 1977' + * - `YDay` = Day of the year: 1-366 + * + * FormatTime(heart_day, 'YDay') => '45' + * - `YDay0` = 3-digit day of the year: 001-366 + * + * FormatTime(heart_day, 'YDay0') => '045' + * - `WDay` = Current day of the week. + * 1 = Sunday, 7 = Saturday + * + * FormatTime(hump_day, 'WDay') => '4' + * - `YWeek` = {@link https://www.rfc-editor.org/rfc/rfc3339#ref-ISO8601|ISO 8601} year/week YYYYWW number format. + * The first week of January must have 4 days to be considered week 1. + * Otherwise, that week is considered part of the prior year. + * + * FormatTime(A_Now, 'YWeek') => '202348' + * @returns {(String)} + * Formatted date timestamp. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Format.htm|Format()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileGetTime.htm|FileGetTime()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm#DateTime|Gui.DateTime} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#date|Built-in Date and Time Variables} + * @example + */ +FormatTime([DateTimeStamp:=A_Now, Form:=unset]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GetKeyName.htm|`GetKeyName()`} + * Retrieves the name/text of a key. + * @param {'Alt'|'AppsKey'|'Backspace'|'Browser_Back'|'Browser_Favorites'|'Browser_Forward'|'Browser_Home'|'Browser_Refresh'|'Browser_Search'|'Browser_Stop'|'CapsLock'|'Control'|'CtrlBreak'|'Delete'|'Down'|'End'|'Enter'|'Escape'|'F1'|'F10'|'F11'|'F12'|'F13'|'F14'|'F15'|'F16'|'F17'|'F18'|'F19'|'F2'|'F20'|'F21'|'F22'|'F23'|'F24'|'F3'|'F4'|'F5'|'F6'|'F7'|'F8'|'F9'|'Help'|'Home'|'Insert'|'LAlt'|'Launch_App1'|'Launch_App2'|'Launch_Mail'|'Launch_Media'|'LButton'|'LControl'|'Left'|'LShift'|'LWin'|'MButton'|'Media_Next'|'Media_Play_Pause'|'Media_Prev'|'Media_Stop'|'NumLock'|'Numpad0'|'Numpad1'|'Numpad2'|'Numpad3'|'Numpad4'|'Numpad5'|'Numpad6'|'Numpad7'|'Numpad8'|'Numpad9'|'NumpadAdd'|'NumpadClear'|'NumpadDel'|'NumpadDiv'|'NumpadDot'|'NumpadDown'|'NumpadEnd'|'NumpadEnter'|'NumpadHome'|'NumpadIns'|'NumpadLeft'|'NumpadMult'|'NumpadPgDn'|'NumpadPgUp'|'NumpadRight'|'NumpadSub'|'NumpadUp'|'Pause'|'PgDn'|'PgUp'|'PrintScreen'|'RAlt'|'RButton'|'RControl'|'Right'|'RShift'|'RWin '|'SC###'|'ScrollLock'|'Shift'|'Sleep'|'Space'|'Tab'|'Up'|'VK##'|'Volume_Down'|'Volume_Mute'|'Volume_Up'|'WheelDown'|'WheelLeft'|'WheelRight'|'WheelUp'|'XButton1'|'XButton2'} KeyName + * A key from the {@link https://www.autohotkey.com/docs/v2/KeyList.htm|Key List}. + * Or a virtual key `vkFF`, scan code `sc01D`, or combination of the two in hexadecimal format. + * + * GetKeyName('vk1Bsc001') => 'Escape' + * @returns {(String)} + * Name of the key + * An empty string is returned if the key is invalid or unnamed. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GetKeyVK.htm|GetKeyVK()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeySC.htm|GetKeySC()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|GetKeyState()} | + * {@link https://www.autohotkey.com/docs/v2/KeyList.htm|Key List} + * @example */ -RTrim(String, OmitChars := ' `t') => String +GetKeyName(KeyName) => String /** - * Run external programs. - * @param Options If omitted, the function will start Target normally. To change this behavior, please specify one or more of the following words: - * - * Max: Maximum operation + * @description {@link https://www.autohotkey.com/docs/v2/lib/GetKeyVK.htm|`GetKeyVK()`} + * Retrieves the virtual key code of a key. + * @param {'Alt'|'AppsKey'|'Backspace'|'Browser_Back'|'Browser_Favorites'|'Browser_Forward'|'Browser_Home'|'Browser_Refresh'|'Browser_Search'|'Browser_Stop'|'CapsLock'|'Control'|'CtrlBreak'|'Delete'|'Down'|'End'|'Enter'|'Escape'|'F1'|'F10'|'F11'|'F12'|'F13'|'F14'|'F15'|'F16'|'F17'|'F18'|'F19'|'F2'|'F20'|'F21'|'F22'|'F23'|'F24'|'F3'|'F4'|'F5'|'F6'|'F7'|'F8'|'F9'|'Help'|'Home'|'Insert'|'LAlt'|'Launch_App1'|'Launch_App2'|'Launch_Mail'|'Launch_Media'|'LButton'|'LControl'|'Left'|'LShift'|'LWin'|'MButton'|'Media_Next'|'Media_Play_Pause'|'Media_Prev'|'Media_Stop'|'NumLock'|'Numpad0'|'Numpad1'|'Numpad2'|'Numpad3'|'Numpad4'|'Numpad5'|'Numpad6'|'Numpad7'|'Numpad8'|'Numpad9'|'NumpadAdd'|'NumpadClear'|'NumpadDel'|'NumpadDiv'|'NumpadDot'|'NumpadDown'|'NumpadEnd'|'NumpadEnter'|'NumpadHome'|'NumpadIns'|'NumpadLeft'|'NumpadMult'|'NumpadPgDn'|'NumpadPgUp'|'NumpadRight'|'NumpadSub'|'NumpadUp'|'Pause'|'PgDn'|'PgUp'|'PrintScreen'|'RAlt'|'RButton'|'RControl'|'Right'|'RShift'|'RWin '|'SC###'|'ScrollLock'|'Shift'|'Sleep'|'Space'|'Tab'|'Up'|'VK##'|'Volume_Down'|'Volume_Mute'|'Volume_Up'|'WheelDown'|'WheelLeft'|'WheelRight'|'WheelUp'|'XButton1'|'XButton2'} KeyName + * A key from the {@link https://www.autohotkey.com/docs/v2/KeyList.htm|Key List}. + * Or a virtual key `vkFF`, scan code `sc01D`, or combination of the two in hexadecimal format. * - * Min: Minimize operation + * GetKeyVK('Escape') => '27' + * @returns {(Integer)} + * The virtual key code of the specified key. + * 0 is returned if key is invalid or has no virtual key code. + * Convert to hexadecimal to use with AHK functions like {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} or {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|GetKeyState()}. * - * Hide: hide operation (cannot be used in combination with any of the above options) - */ -Run(Target [, WorkingDir, Options, &OutputVarPID: VarRef]) => void - -/** - * Specify a set of user credentials to be used in all subsequent Runs and RunWait. - */ -RunAs([User, Password, Domain]) => void - -/** - * Run the external program and wait for the end of the program to continue execution. - */ -RunWait(Target [, WorkingDir, Options, &OutputVarPID: VarRef]) => Integer - -/** - * Send simulated keystrokes and mouse clicks to the active window. By default, Send is equivalent to SendInput. - */ -Send(Keys) => void - -/** - * SendEvent uses the Windows keybd_event function to send keystrokes. The rate of sending keystrokes is determined by SetKeyDelay. + * Format('vk{:X}', GetKeyVK('Escape')) => 'vk1B' + * @see {@link https://www.autohotkey.com/docs/v2/lib/GetKeySC.htm|GetKeySC()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyName.htm|GetKeyName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|GetKeyState()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Format.htm|Format()} | + * {@link https://www.autohotkey.com/docs/v2/KeyList.htm|Key List} + * @example */ -SendEvent(Keys) => void - -/** - * SendInput and SendPlay use the same syntax as Send, but are generally faster and more reliable. In addition, they buffer any physical keyboard or mouse activity during the sending process, thus preventing the user's keystrokes from being scattered in the sending. - */ -SendInput(Keys) => void - -/** - * Controls whether hotkeys and hotstrings ignore simulated keyboard and mouse events. - */ -SendLevel(Level) => Integer - -/** - * Send the message to the window or control, and then wait for confirmation. - */ -SendMessage(Msg, wParam := 0, lParam := 0 [, Control, WinTitle, WinText, ExcludeTitle, ExcludeText, Timeout]) => Integer - -/** - * Make Send equal to SendEvent or SendPlay, instead of the default (SendInput). Also make Click and MouseMove/Click/Drag use specified methods. - * @param {'Event'|'Input'|'InputThenPlay'|'Play'} Mode - */ -SendMode(Mode) => String - -/** - * SendInput and SendPlay use the same syntax as Send, but are generally faster and more reliable. In addition, they buffer any physical keyboard or mouse activity during the sending process, thus preventing the user's keystrokes from being scattered in the sending. - */ -SendPlay(Keys) => void +GetKeyVK(KeyName) => Integer /** - * Similar to Send, except that all characters in Keys are interpreted literally. + * @description {@link https://www.autohotkey.com/docs/v2/lib/GetKeySC.htm|`GetKeySC()`} + * Retrieves the scan code of a key. + * @param {'Alt'|'AppsKey'|'Backspace'|'Browser_Back'|'Browser_Favorites'|'Browser_Forward'|'Browser_Home'|'Browser_Refresh'|'Browser_Search'|'Browser_Stop'|'CapsLock'|'Control'|'CtrlBreak'|'Delete'|'Down'|'End'|'Enter'|'Escape'|'F1'|'F10'|'F11'|'F12'|'F13'|'F14'|'F15'|'F16'|'F17'|'F18'|'F19'|'F2'|'F20'|'F21'|'F22'|'F23'|'F24'|'F3'|'F4'|'F5'|'F6'|'F7'|'F8'|'F9'|'Help'|'Home'|'Insert'|'LAlt'|'Launch_App1'|'Launch_App2'|'Launch_Mail'|'Launch_Media'|'LButton'|'LControl'|'Left'|'LShift'|'LWin'|'MButton'|'Media_Next'|'Media_Play_Pause'|'Media_Prev'|'Media_Stop'|'NumLock'|'Numpad0'|'Numpad1'|'Numpad2'|'Numpad3'|'Numpad4'|'Numpad5'|'Numpad6'|'Numpad7'|'Numpad8'|'Numpad9'|'NumpadAdd'|'NumpadClear'|'NumpadDel'|'NumpadDiv'|'NumpadDot'|'NumpadDown'|'NumpadEnd'|'NumpadEnter'|'NumpadHome'|'NumpadIns'|'NumpadLeft'|'NumpadMult'|'NumpadPgDn'|'NumpadPgUp'|'NumpadRight'|'NumpadSub'|'NumpadUp'|'Pause'|'PgDn'|'PgUp'|'PrintScreen'|'RAlt'|'RButton'|'RControl'|'Right'|'RShift'|'RWin '|'SC###'|'ScrollLock'|'Shift'|'Sleep'|'Space'|'Tab'|'Up'|'VK##'|'Volume_Down'|'Volume_Mute'|'Volume_Up'|'WheelDown'|'WheelLeft'|'WheelRight'|'WheelUp'|'XButton1'|'XButton2'} KeyName + * A key from the {@link https://www.autohotkey.com/docs/v2/KeyList.htm|Key List}. + * Or a virtual key `vkFF`, scan code `sc01D`, or combination of the two in hexadecimal format. + * + * GetKeySC('Escape') => '1' + * @returns {(Integer)} + * The scan code of the specified key. + * 0 is returned if key is invalid or has no scan code. + * Convert to hexadecimal to use with AHK functions like {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} or {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|GetKeyState()}. + * + * Format('sc{:03X}', GetKeySC('Escape')) => 'sc001' + * @see {@link https://www.autohotkey.com/docs/v2/lib/GetKeyVK.htm|GetKeyVK()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyName.htm|GetKeyName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|GetKeyState()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Format.htm|Format()} | + * {@link https://www.autohotkey.com/docs/v2/KeyList.htm|Key List} + * @example */ -SendText(Keys) => void +GetKeySC(KeyName) => Integer /** - * Set the state of the caps Lock key. You can also force the key to stay on or off. - * @param {'On'|'Off'|'AlwaysOn'|'AlwaysOff'} State + * @description {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|`GetKeyState()`} + * Gets the physical, logical, or toggle status of keyboard keys, mouse buttons, and controller joys. + * @param {'Alt'|'AppsKey'|'Backspace'|'Browser_Back'|'Browser_Favorites'|'Browser_Forward'|'Browser_Home'|'Browser_Refresh'|'Browser_Search'|'Browser_Stop'|'CapsLock'|'Control'|'CtrlBreak'|'Delete'|'Down'|'End'|'Enter'|'Escape'|'F1'|'F10'|'F11'|'F12'|'F13'|'F14'|'F15'|'F16'|'F17'|'F18'|'F19'|'F2'|'F20'|'F21'|'F22'|'F23'|'F24'|'F3'|'F4'|'F5'|'F6'|'F7'|'F8'|'F9'|'Help'|'Home'|'Insert'|'LAlt'|'Launch_App1'|'Launch_App2'|'Launch_Mail'|'Launch_Media'|'LButton'|'LControl'|'Left'|'LShift'|'LWin'|'MButton'|'Media_Next'|'Media_Play_Pause'|'Media_Prev'|'Media_Stop'|'NumLock'|'Numpad0'|'Numpad1'|'Numpad2'|'Numpad3'|'Numpad4'|'Numpad5'|'Numpad6'|'Numpad7'|'Numpad8'|'Numpad9'|'NumpadAdd'|'NumpadClear'|'NumpadDel'|'NumpadDiv'|'NumpadDot'|'NumpadDown'|'NumpadEnd'|'NumpadEnter'|'NumpadHome'|'NumpadIns'|'NumpadLeft'|'NumpadMult'|'NumpadPgDn'|'NumpadPgUp'|'NumpadRight'|'NumpadSub'|'NumpadUp'|'Pause'|'PgDn'|'PgUp'|'PrintScreen'|'RAlt'|'RButton'|'RControl'|'Right'|'RShift'|'RWin '|'SC###'|'ScrollLock'|'Shift'|'Sleep'|'Space'|'Tab'|'Up'|'VK##'|'Volume_Down'|'Volume_Mute'|'Volume_Up'|'WheelDown'|'WheelLeft'|'WheelRight'|'WheelUp'|'XButton1'|'XButton2'} KeyName + * A key from the {@link https://www.autohotkey.com/docs/v2/KeyList.htm|Key List}. + * Or a virtual key `vkFF`, scan code `sc01D`, or combination of the two in hexadecimal format. + * @param {'P'|'T'} [Mode] + * The type of state to get. + * Mode is ignored when getting controller status. + * - Omitted = Get logical state of the key/button. + * - `P` = Physical + * Check if key/button is physically held down. + * Keys/buttons must be hooked for this to register. + * - `T` = Toggle + * Get toggle status of `CapsLock`, `NumLock`, or `ScrollLock`. + * @returns {(Primitive)} + * - Key/button/joy: + * - `1` = Down/toggled on + * - `0` = Up/toggled off + * - Controller Axis + * - `0-100` = Percent of range depressed. + * - Controller POV `0-35900` + * - `-1` = No angle to report + * - `0` = forward POV + * - `9000` = 90 degrees POV right + * - `18000` = 180 degrees POV backward + * - `27000` = 270 degrees POV left + * - `JoyName` `JoyButtons` `JoyAxes` `JoyInfo` + * Value varies. See {@link https://www.autohotkey.com/docs/v2/KeyList.htm#Controller|Game Controllers}. + * @throws ValueError - An invalid parameter is detected. + * KeyName does not exist on the current keyboard. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GetKeyVK.htm|GetKeyVK()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeySC.htm|GetKeySC()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyName.htm|GetKeyName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyWait.htm|KeyWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyHistory.htm|KeyHistory()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InstallKeybdHook.htm|InstallKeybdHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InstallMouseHook.htm|InstallMouseHook()} + * {@link https://www.autohotkey.com/docs/v2/lib/_UseHook.htm|#UseHook} | + * {@link https://www.autohotkey.com/docs/v2/misc/RemapController.htm|Controller remapping} | + * {@link https://www.autohotkey.com/docs/v2/KeyList.htm|Key List} | + * @example + */ +GetKeyState(KeyName [,Mode]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GetMethod.htm|`GetMethod()`} + * Retrieves the implementation function of a method. + * @param {(Any)} Value + * Any value except for a {@link https://www.autohotkey.com/docs/v2/lib/ComObject.htm|ComObject}. + * @param {(String)} [Name] + * Name of the method to retrieve. + * If omitted, validation is performed on the Value param and Value is returned if successful. + * @param {(Integer)} [ParamCount] + * Number of parameters caller will be passing in. + * This value must not be less than {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#MinParams|Func.MinParams} or greater than {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#MaxParams|Func.MaxParams}. + * ParamCount should never include the hidden `this` param that all methods have. + * If omitted or ParamCount failed, a basic check for a `Call()` method is done. + * @returns {(FuncObj)} + * A function object containing a reference to the method. + * @throws MethodError - Method was not found or cannot be retrieved + * @throws ValueError|MethodError - Validation failed + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm|Objects} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasMethod.htm|HasMethod()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasBase.htm|HasBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasProp.htm|HasProp()} + * @example + */ +GetMethod(Value [,Name, ParamCount]) => Func + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GroupActivate.htm|`GroupActivate()`} + * Activates the next window in a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|Window Group}. + * @param {(String)} GroupName + * The name given to the group by {@link https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm|GroupAdd()}. + * @param {'R'} [Mode] + * Which window to activate. + * - Omit or Empty String = Activate the next window in the group. + * - `R` = Resume. If the current active window doesn't belong to the group, go back to the most recently active group window instead of going to the next. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|HWND (handle)} of the activated window is returned. + * `0` is returned if no window was found to activate or if the current active window is the only match. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm|GroupAdd()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupDeactivate.htm|GroupDeactivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupClose.htm|GroupClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/_WinActivateForce.htm|#WinActivateForce} + * @example + */ +GroupActivate(GroupName [,Mode:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm|`GroupAdd()`} + * Adds a window specification to a window group, creating the group if necessary. + * @param {(String)} GroupName + * The name of the group to add the window ID. + * The group is created if it doesn't exist and GroupName is not case-sensitive. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GroupActivate.htm|GroupActivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupDeactivate.htm|GroupDeactivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupClose.htm|GroupClose()} + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +GroupAdd(GroupName [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GroupClose.htm|`GroupClose()`} + * Close the current active group window or all group windows. + * The next window in the series is then activated. + * @param {(String)} GroupName + * The name given to the group by {@link https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm|GroupAdd()}. + * @param {'R'|'A'} [Mode] + * Which window to close. + * - Empty String = Close the active window. + * - `R` = Resume. If the current active window doesn't belong to the group, go back to the most recently active group window instead closing it. + * - `A` = All. Closes all members of a group. + * Same as: `WinClose('ahk_group GroupName')` + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GroupActivate.htm|GroupActivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupDeactivate.htm|GroupDeactivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm|GroupAdd()} + * @example + */ +GroupClose(GroupName [,Mode:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GroupDeactivate.htm|`GroupDeactivate()`} + * Activates the next window that does NOT belong to the group. + * @param {(String)} GroupName + * The name given to the group by {@link https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm|GroupAdd()}. + * @param {'R'} [Mode] + * Which window to activate. + * - Empty String = Activate the next window that doesn't belong to the group. + * - `R` = Resume. If the current active window doesn't belong to the group, go back to the most recently active group window instead of going to the next. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GroupActivate.htm|GroupActivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupClose.htm|GroupClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm|GroupAdd()} + * @example + */ +GroupDeactivate(GroupName [,Mode:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiCtrlFromHwnd.htm|`GuiCtrlFromHwnd()`} + * Gets the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl object} of a GUI control from its HWND. + * @param {(Integer)} Hwnd + * The window handle (HWND) of an AHK GUI control or a child window of such a control. + * @returns {(Gui.Control|String)} + * A GuiControl object for the specified HWND. + * An empty string is returned if HWND is invalid or isn't for a GuiControl. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GuiFromHwnd.htm|GuiFromHwnd()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm|ListView()} | + * {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm|TreeView()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|MsgBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|FileSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|Control Types} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu object} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl object} | + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|Gui object} + * @example + */ +GuiCtrlFromHwnd(Hwnd) => Gui.Control + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/GuiFromHwnd.htm|`GuiFromHwnd()`} + * Retrieves the Gui object of a GUI window associated with the specified HWND. + * @param {(Integer)} Hwnd + * The window handle (HWND) of an AHK GUI. + * If RecurseParent is true, Hwnd can be a child window of another AHK GUI. + * @param {(Boolean)} [RecurseParent] + * If true, Hwnd can be a child window which is not a GUI. + * GuiFromHwnd will search for the closest AHK GUI parent window and returns an object for it. + * @returns {(Gui|String)} + * The {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|Gui object} that belongs to Hwnd. + * An empty string is returned if HWND is invalid or isn't for a Gui. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GuiCtrlFromHwnd.htm|GuiCtrlFromHwnd()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm|ListView()} | + * {@link https://www.autohotkey.com/docs/v2/lib/TreeView.htm|TreeView()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|MsgBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|FileSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControls.htm|Control Types} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu object} | + * {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm|GuiControl object} | + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|Gui object} + * @example + */ +GuiFromHwnd(Hwnd [,RecurseParent]) => Gui + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/HasBase.htm|`HasBase()`} + * Returns a non-zero number if the specified value is derived from the specified base object. + * @param {(Any)} Value + * Any value of any type. + * @param {(Object)} BaseObj + * The object to check for in the inheritance chain of `Value`. + * @returns {(Boolean)} + * - `1` = `BaseObj` is found in the inheritance chain of `Value` + * - `0` = `BaseObj` could not be found in the inheritance chain of `Value` + * @see {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#GetBase|ObjGetBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasMethod.htm|HasMethod()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasProp.htm|HasProp()} | + * {@link https://www.autohotkey.com/docs/v2/Objects.htm|Objects} | + * {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#Base|Obj.Base} + * @example */ -SetCapsLockState([State]) => void +HasBase(Value, BaseObj) => Integer /** - * Set the delay that will occur after each control changes the function. + * @description {@link https://www.autohotkey.com/docs/v2/lib/HasMethod.htm|`HasMethod()`} + * Returns a non-zero number if the specified value has a method by the specified name. + * @param {(Any)} Value + * Any value of any type except ComObject. + * @param {(String)} [Name] + * The method name to check for. + * If omitted, `Value` is checked to see if it is callable. + * @param {(Integer)} [ParamCount] + * Number of parameters caller will be passing in. + * This value must not be less than {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#MinParams|Func.MinParams} or greater than {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#MaxParams|Func.MaxParams}. + * ParamCount should never include the hidden `this` param that all methods have. + * If omitted or ParamCount failed, a basic check for a `Call()` method is done. + * @returns {(Boolean)} + * - `1` = Method found and validated + * - `0` = Method not found or couldn't be validated + * @see {@link https://www.autohotkey.com/docs/v2/lib/HasBase.htm|HasBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetMethod.htm|GetMethod()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasProp.htm|HasProp()} | + * {@link https://www.autohotkey.com/docs/v2/Objects.htm|Objects} | + * @example + */ +HasMethod(Value [,Name:=unset, ParamCount:=unset]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/HasProp.htm|`HasProp()`} + * Returns a non-zero number if the value passed in has a property by the specified name. + * @param {(Any)} Value + * Any value of any type except ComObject. + * @param {(String)} [Name] + * The property name to check for. + * @returns {(Boolean)} + * - `1` = Object property found + * - `0` = Object property not found + * @see {@link https://www.autohotkey.com/docs/v2/lib/HasBase.htm|HasBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/HasMethod.htm|HasMethod()} | + * {@link https://www.autohotkey.com/docs/v2/Objects.htm|Objects} + * @example + */ +HasProp(Value, Name) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/HotIf.htm|`HotIf()`} + * Sets the criteria for when a subsequently created {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()}/{@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} is enabled or disabled. + * This works similarly to how {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} works with {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|`Hotkey::`}. + * All calls to Hotkey() or Hotstring() will respect the last declared HotIf(). + * @param {(String|FuncObj)} [ExpressionOrCallback] + * Something that evaluates to true or false. + * When this evaluation returns true, the hotkey or hotstring is enabled and usable. + * - **Omitted** + * Omitting this param resets any HotIf criteria and makes future hotkeys/hotstrings work globally. + * - **Expression** + * A string expression that references an existing {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} expression. + * If a `#HotIf` directive for that expression doesn't exist, a Callback should be used instead. + * - **Callback** (FuncObj) + * A {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|Function Object} that returns a true or false statement. + * The last parameter of the callback receives the hotkey/hotstring name and comes after any parameters provided by a {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc}. + * + * hotkey_callback(HotName) + * hotkey_callback(OtherParams, HotName) + * A {@link https://www.autohotkey.com/docs/v2/Variables.htm#fat-arrow|fat-arrow} callback can be used to quickly define a HotIf(): + * + * HotIf((HotName) => some_func(HotName)) + * @returns {(String)} + * An empty string is always returned. + * @throws Error - A parameter is invalid. + * No matching expression found or callback was invalid. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} | + * {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Hotkey::} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstring::} | + * {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * @example + */ +HotIf([ExpressionOrCallback]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/HotIf.htm|`HotIfWinActive()`} + * Controls when a subsequently created {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()}/{@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} is enabled or disabled based on a specific window being active. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * Omitting both params resets any HotIf criteria and makes future hotkeys/hotstrings work globally. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - A parameter is invalid. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} | + * {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Hotkey::} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstring::} | + * {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +HotIfWinActive([WinTitle:='', WinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/HotIf.htm|`HotIfWinExist()`} + * Controls when a subsequently created {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()}/{@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} is enabled or disabled based on a specific window existing. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * Omitting both params resets any HotIf criteria and makes future hotkeys/hotstrings work globally. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - A parameter is invalid. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} | + * {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Hotkey::} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstring::} | + * {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +HotIfWinExist([WinTitle:='', WinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/HotIf.htm|`HotIfWinNotActive()`} + * Controls when a subsequently created {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()}/{@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} is enabled or disabled based on a specific window not being active. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * Omitting both params resets any HotIf criteria and makes future hotkeys/hotstrings work globally. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - A parameter is invalid. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} | + * {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Hotkey::} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstring::} | + * {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +HotIfWinNotActive([WinTitle:='', WinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/HotIf.htm|`HotIfWinNotExist()`} + * Controls when a subsequently created {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()}/{@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} is enabled or disabled based on a specific window not existing. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * Omitting both params resets any HotIf criteria and makes future hotkeys/hotstrings work globally. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - A parameter is invalid. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} | + * {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Hotkey::} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstring::} | + * {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +HotIfWinNotExist([WinTitle:='', WinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|`Hotkey()`} + * Creates, modifies, enables, or disables a hotkey. + * @param {(String)} KeyName + * A {@link https://www.autohotkey.com/docs/v2/KeyList.htm|key name}, including any {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#Symbols|modifier symbols}. + * If `KeyName` is already declared, the old hotkey is replaced with the new one. + * Modifier order doesn't matter but `KeyName` must match the original spelling. `Escape` won't replace `Esc`. + * **Modifier Symbols** + * - `#` = {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Window key} + * - `!` = {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Alt key} + * - `^` = {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Control key} + * - `+` = {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Shift key} + * - `<` = Use {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#LeftRight|left side key} of a key pair + * `LAlt`, `LShift`, `LControl`, `LWin` + * - `>` = Use {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#LeftRight|right side key} of a key pair + * `RAlt`, `RShift`, `RControl`, `RWin` + * - `<^>!` = The {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#AltGr|AltGr} key. AKA: AltGraphic, AltGraph + * Windows usually sees this as `Ctrl+Alt` + * - `$` = {@link https://www.autohotkey.com/docs/v2/Hotkeys.htmprefixdollar|Hook} hotkey to prevent {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} from activating this hotkey. + * Mouse button hotkeys are automatically hooked. + * - `*` = {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#wildcard|Wildcard} allows hotkey activation even if other keys are being held + * This option hooks the hotkey + * - `~` = {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#Tilde|Send hotkey} keystroke before running the hotkey `Action` + * This option hooks the hotkey + * - `&` = Create a 2-key {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#combo|Custom Combination} + * This option hooks the hotkey + * - `Up` = Hotkey activates on release instead of on press. + * The word `Up` must be + * This option hooks the hotkey + * @param {'On'|'Off'|'Toggle'|'AltTab'|'ShiftAltTab'|'AltTabMenu'|'AltTabAndMenu'|'AltTabMenuDismiss'} [Action] + * The action to take on hotkey activation. + * This can be a callback, the name of a {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|`Hotkey::`}, or one of the following keywords: + * - `On` = The hotkey becomes enabled + * - `Off` = The hotkey becomes disabled + * - `Toggle` = The hotkey is switched between enabled and disabled + * - Special {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#alttab|AltTab} options: + * - `AltTab` = Move AltTab menu selection forward if shown, otherwise show menu + * Only works with hotkeys using two keys + * - `ShiftAltTab` = Move AltTab menu selection backward if shown, otherwise show menu + * Only works with hotkeys using two keys + * - `AltTabMenu` = Show or hide AltTab menu + * - `AltTabAndMenu` = Move AltTab menu selection forward if shown, otherwise show menu + * - `AltTabMenuDismiss` = Close the AltTab menu + * + * `Action` can be omitted when only updating a hotkey's `Options` parameter. + * @param {String|'On'|'Off'|'B'|'P'|'S'|'T'|'I'} [Options] + * Zero or more of the following options. Space separators are optional. + * - `On` = Enable hotkey + * - `Off` = Disable hotkey + * - `B` = Buffers hotkey as described in {@link https://www.autohotkey.com/docs/v2/lib/_MaxThreadsBuffer.htm|#MaxThreadsBuffer} + * Use `B0` to disable this + * - `P#` = Set Priority of hotkey where `#` is the {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread priority number} + * The default of is `P0` + * - `S` = Gives the hotkey {@link https://www.autohotkey.com/docs/v2/lib/_SuspendExempt.htm|exemption} from {@link https://www.autohotkey.com/docs/v2/lib/Suspend.htm|Suspend()} + * Use `S0` to disable exemption + * - `T#` = Set Thread number, where `#` is the max number of thread to allow + * - `I#` = Set Input level, where `#` is the hotkey's {@link https://www.autohotkey.com/docs/v2/lib/_InputLevel.htm|input level} + * @returns {(String)} + * An empty string is always returned. + * @throws ValueError - Invalid key name + * @throws ValueError - Unsupported prefix key + * @throws ValueError - AltTab hotkey must have exactly one modifier/prefix + * @throws ValueError - SltTab hotkey must specify a Left or Right side key + * @throws TargetError - Nonexistent hotkey + * @throws TargetError - Nonexistent hotkey variant + * @throws Error - Max amount of hotkeys created + * @see {@link https://www.autohotkey.com/docs/v2/lib/HotIf.htm|HotIf()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Suspend.htm|Suspend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm|Thread()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm|Critical()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm|SetTimer()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Return.htm|Return} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu object} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#ThisHotkey|A_ThisHotkey} | + * {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#Symbols|Hotkey Symbols} | + * {@link https://www.autohotkey.com/docs/v2/lib/_MaxThreadsBuffer.htm|#MaxThreadsBuffer} | + * {@link https://www.autohotkey.com/docs/v2/lib/_MaxThreadsPerHotkey.htm|#MaxThreadsPerHotkey} + * @example + */ +Hotkey(KeyName [,Action, Options]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|`Hotstring()`} + * Creates, modifies, enables, or disables a hotstring. + * The case used to type the hotstring (UPPERCASE, lowercase, Title Case) carries over to the auto-replace text. + * @param {String|'*'|'?'|'B'|'C'|'K'|'O'|'P'|'S'|'SI'|'SE'|'SP'|'T'|'R'|'X'|'Z'|'EndChards'|'MouseReset'|'Reset'} Option + * - Hotstring = An activation string and options using the {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|`::Hotstring`} format. + * This creates (or updates an already existing) hotstring. + * Options should be placed between the double colons `::` and are listed below in the `NewOptions` section + * + * ; Typing '/new' inserts #Requires and a kill switch to a new script + * Hotstring(':?*:/new', '{#}Requires AutoHotkey v2.0{+}`n*Esc::ExitApp()') + * ; Typing '!quit!' exits the script + * Hotstring(':?*X:!quit!', (*) => ExitApp()) + * - {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm#EndChars|`"EndChars"`} = Get or set the string of ending characters used by hotstrings. See `Value` param. + * - {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm#MouseReset|`"MouseReset"`} = Get or set the current setting for mouse clicks resetting the hotstring recognizer. See `Value` param. + * - {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm#Reset|`"Reset"`} = Immediately reset the hotstring recognizer. + * - NewOptions = A string of {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#Options|hotstring options} to set as the new default for future hotstrings. + * An example of each option can be found in the example section + * - `*` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#Asterisk|Wildcard}. Hotstring fires as soon as a match is made, without the need of an {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#EndChars|EndChar}. + * - `?` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#Question|Verbatim}. Hotstring fires whenever it is typed, including while inside another word + * - `B0` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#b0|Backspacing} disable. The replacement text from `Value` is sent without deleting the hotstring + * To re-enabled backspacing, use `B` + * - `C` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#C|Case-sensitive hotstring}. A hotstring must be typed exactly as defined to be activated. + * This can be disabled using `C0`. + * - `C1` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#C1|Case mirroring} disable. The {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#auto|auto-replace} text is sent **exactly** as typed. + * This overrides the default behavior where typing a hotstring in a certain case (UPPERCASE or Title Case) causes the a lowercase replacement text to conform to that case type. + * Case mirroring can be enabled using `C0`. + * - `K#` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#Kn|Key-delay}. Sets delay between {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#auto|auto-replace} keystrokes, where `#` is the time, in milliseconds, or `-1` for no delay + * This delay includes the keystrokes for backspacing the hotstring text. + * The {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#SendMode|send mode} affects Key-Delay behavior: + * - `SE` SendEvent = Sets the delay between keystrokes + * - `SP` SendPlay = Sets the {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm#dur|press duration} of each keystroke, but not the delay between them + * - `SI` SendInput = Key-delay can only affect SendInput when it's in {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInputUnavail|unavailable mode} because it defaults to SendEvent mode. + * - `O` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#O|Omit}. The {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#EndChars|EndChar} of an {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#auto|auto-replace hotstring} is omitted + * - `P#` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#Pn|Priority}. Set the {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|priority} level of the hotstring, where `#` is the level number + * This has no affect on {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#auto|auto-replace hotstring} and is rarely used. + * - `S` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#SuspendExempt|Suspend}. Makes the hotstring {@link https://www.autohotkey.com/docs/v2/lib/_SuspendExempt.htm|exempt} from {@link https://www.autohotkey.com/docs/v2/lib/Suspend.htm|Suspend()} + * Use `S1` to disable this setting, making Suspend() affect this hotstring + * - `SI` `SE` `SP` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#SendMode|Send mode}. Choose between {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInputDetail|SendInput}, {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendEvent|SendEvent}, and {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlayDetail|SendPlay} + * - `T` `R` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#T|Text} / {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#raw|Raw} mode. {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#auto|Auto-replace hotstrings} are not converted and all keystrokes are sent as typed + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape sequences} still work and must be escaped using ``` `` ``` + * [`{Text} mode`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Text) is similar to [`{RAW} mode`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Raw), but no attempt is made to translate characters (other than `` `n ``, `` `r ``, `` `t ``, and `` `b ``) + * `T0` and `R0` can be used to disable these modes. + * Text may be more reliable than Raw + * - `X` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#X|Execute}. Instead of replacement text, `Value` is treated as AHK code + * This allows hotstrings to activate code just like a hotkey + * - `Z` = {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#z|Zeroize}. When the hotstring fires, the hotstring recognizer is reset. + * All previous keystrokes are cleared, preventing them from being considered as the start of other hotstrings. + * @param {(String|FuncObj)} [Value] + * Dependent on the current `Option` being used. + * - `Hotstring` = The hotstring's replacement text or code to run (`X` option). + * This param can be omitted when working with the `Enabled` param. + * - `"EndChars"` = The string of characters to use as hotstring ending chars. + * If omitted, a string of the current `EndChars` are returned by the function. + * - `"MouseReset"` = Set `Value` to `1` to enable and `0` to disable. + * If omitted, the current `MouseReset` setting is returned by the function. + * - `NewOptions` = The `Value` param isn't with this option. + * - `"Reset"` = The `Value` param isn't with this option. + * @param {(String|Integer)} [Enabled] + * Only used with the hotstring `Option`. + * Sets the enable state of a hotstring + * - `1` = Enable hotstring + * - `0` = Disable hotstring + * - `-1` `Toggle` = Switch state between enabled and disabled. + * @returns {(String|Integer)} + * If using `"EndChars"` without the `Value` param, a string of ending characters is returned. + * If using `"MouseReset"` without a `Value` param, a `1` is returned for on, otherwise `0`. + * An empty string is returned for everything else. + * @throws Error - A parameter is invalid or memory allocation failed. + * @throws TargetError - `Option` was a hotstring that hasn't previously been declared and `Value` was omitted. + * The only time a hotstring value is omitted is when `Enabled` is being altered. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Suspend.htm|Suspend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm|Thread()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm|Critical()} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstring::} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#ThisHotkey|A_ThisHotkey} | + * {@link https://www.autohotkey.com/docs/v2/lib/_MaxThreadsPerHotkey.htm|#MaxThreadsPerHotkey} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} + * @example Option Examples + * ; * Wildcard + * ; Typing 'ahk' produces 'AutoHotkey' without needing an EndChar + * Hotstring(':*:ahk', 'AutoHotkey') + * + * ; ? Verbatim + * ; Typing 'AutoHotkey ' produces 'AutoHotstring ' + * Hotstring(':?:key', 'string') + * + * ; B0 Backspacing (disable): + * ; Typing 'for ' doesn't erase the word 'for ' + * ; 'For' is included as part of the desired replacement + * Hotstring(':B0:for', 'key, value in object') + * + * ; C Case-sensitive hotstrings + * ; Typing 'ABC ' activates hotstring but 'abc ' does not + * Hotstring(':C:ABC', 'ALL CAPS') + * + * ; C1 Case mirroring (disable) + * ; 'Case ' and 'CASE ' produce 'test ' + * ; Normally, 'Case ' and 'CASE ' would produce 'Test ' and 'TEST ' + * Hotstring(':C1:CASE', 'test') + * + * ; K# Key delay + * ; Puts a 1/2 second pause between each keystroke + * Hotstring(':SE k500:sek', 'event') + * ; Each keystroke is held down for 1/2 a second + * Hotstring(':SP k500:spk', 'play') + * ; Puts a 1/2 second pause between each keystroke when in unavailable mode + * Hotstring(':SI k500:sik', 'input') + * + * ; O Omit + * ; Typing '{esc.' produces '{Escape}', ignoring the end char + * Hotstring(':O:`{esc', '{{}Escape{}}') + * + * ; P Priority + * ; Typing '/kill' immediately exits the script + * Hotstring(':XP100?*:/kill', (*) => ExitApp()) + * + * ; S Suspend exemption + * ; Typing '/suspend' can turn suspension both on and off + * ; Without S, it could not turn off suspend as the hotstring would be suspended + * Hotstring(':SX*:/suspend', (*) => Suspend()) + * + * ; T Text Mode + * ; Typing '{esc ' produces '{Escape} ' instead of sending the Escape keystroke + * Hotstring(':T:{esc', '{Escape}') + * + * ; X Execution + * ; Typing 'greet ' calls a boundfunc + * Hotstring(':X:greet', (*) => MsgBox('Hello')) + * + * ; Z Zeroize + * ; Typing 'zzz' produces 'zz00z' instead of 'zz00z00' + * ; The recognizer is reset preventing the last z from acting as the first z of another hotstring + * Hotstring(':B0*?XZ:zz', (*) => Send('00')) + */ +Hotstring(Option [,Value, Enabled]) => String | Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL_Create|`IL_Create()`} + * Creates a new ImageList that is initially empty. + * @param {(Integer)} [InitialCount] + * The initial size of the list. Later, this can expand as needed. + * The default value is 2. + * @param {(Integer)} [GrowCount] + * The amount of additional slots to add when list expansion is needed. + * The default value is 5. + * @param {(Boolean)} [LargeIcons] + * Use large icons or small icons + * - `0` or Omitted = ImageList will contain small icons + * - `1` = ImageList will contain large icons + * @returns {(Integer)} + * On success, a unique ID for the ImageList, otherwise `0` + * @example + */ +IL_Create([InitialCount:=2, GrowCount:=5, LargeIcons:=0]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL_Add|`IL_Add()`} + * Adds an icon or picture to the specified ImageList. + * @param {(Integer)} ImageListID + * The identifying number of an image list generated by {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL_Create|IL_Create()}. + * @param {(String)} IconOrPicFile + * Filename to an icon or picture file + * - `Icon` = .ICO .CUR .ANI .EXE .DLL .CPL .SCR {@link https://www.autohotkey.com/docs/v2/misc/ImageHandles.htm|Icon Handle "HICON:"} or another icon resource + * - `Pic` = .BMP .GIF .JPG .PNG .TIF .Exif .WMF .EMF or a {@link https://www.autohotkey.com/docs/v2/misc/ImageHandles.htm|Bitmap Handle "HBITMAP:"} + * @param {(Integer)} Num + * Dependent on Icon or Picture. + * - `Icon` = Num is the icon number to use + * If this is no sign, the number indicates the icon group to use + * A negative sign indicates the number is used as a resource ID for an icon inside an executable + * Num can be omitted when using an icon and will default to `1`. + * - `Picture` = A transparency mask color in hex + * The color white `0xFFFFFF` works well for most pictures + * @param {(Boolean)} Resize + * This parameter only applies to pictures, not to icons. + * - `1` = Picture is scaled to become a single icon + * - `0` = Picture is divided into a number of icons that fit inside the given width + * @returns {(Integer)} - On success, the ImageList index position the icon was stored in is returned, otherwise `0`. + * @example + * IL_Add(ImageListID, 'C:\Path\to\application.exe', 2) + * IL_Add(ImageListID, 'C:\Path\to\image.bmp', 0xFFFFFF, ) + */ +IL_Add(ImageListID, IconOrPicFile [,Num:=1, Resize]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL_Destroy|`IL_Destroy()`} + * Deletes the specified ImageList. + * ListViews are automatically destroyed when the ListView parent window is destroyed. Rarely do they need to be manually destroyed. + * @param {(Integer)} ImageListID + * The identifying number of an image list generated by {@link https://www.autohotkey.com/docs/v2/lib/ListView.htm#IL_Create|IL_Create()}. + * @returns {(Boolean)} + * `1` on success, otherwise `0`. + * @example + * il_id := IL_Create() + * result := IL_Destroy(il_id) + * if result + * MsgBox('Image list destroyed') + * else MsgBox('Failed to destroy image list') + * */ -SetControlDelay(Delay) => Integer +IL_Destroy(ImageListID) => Integer /** - * Set the speed used when the mouse speed is not specified in click and MouseMove/click/Drag. + * @description {@link https://www.autohotkey.com/docs/v2/lib/ImageSearch.htm|`ImageSearch()`} + * Searches a region of the screen for an image. + * @param {(VarRef)} OutputVarX + * Receives the X coordinate of the upper left corner of the image match + * If no match is found, var is set to an empty string. + * @param {(VarRef)} OutputVarY + * Receives the X coordinate of the upper left corner of the image match + * If no match is found, var is set to an empty string. + * @param {(Integer)} X1 + * X coordinate of the left edge of the area to search + * @param {(Integer)} Y1 + * Y coordinate of the top edge of the area to search + * @param {(Integer)} X2 + * X coordinate of the right edge of the area to search + * @param {(Integer)} Y2 + * Y coordinate of the bottom edge of the area to search + * @param {String|'Icon'|'*'|'*Trans'|'*W'|'*H'} ImageFile + * Options followed by an image file name or path to an image file. + * If a full path isn't used, ImageFile is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * Supported formats: .ANI .BMP .CUR .EMF .Exif .GIF .ICO .JPG .PNG .TIF .WMF .EXE .DLL .CPL .SCR and other icon resources + * **Options** + * A string of zero or options separated by spaces/tabs may be added before the file path + * - `*Icon#` = Set icon group number to use, where `#` is the specific number + * - `*#` = The allowed variance in color to still match the image, where `#` is between 0 and 255 + * Default is 0 + * - `*Trans#` = Makes images easier to find by specifying a transparency color for a picture where `#` is a {@link https://www.autohotkey.com/docs/v2/misc/Colors.htm|Valid Color Name} or an RGB color with optional hex prefix. + * These are all the same: `*TransWhite`, `*TransFFFFFF`, `*Trans0xFFFFFF` + * Commonly used with .PNG .GIF and .TIF files that have some transparent area. + * `*TransWhite` works well for .GIF files while `*TransBlack` works well for .PNG and .TIF files + * - `*W#` `*H#` = Width and Height to scale the image, where `#` is the new size in pixels. + * If both are omitted, icons load to 16x16 and pictures load to their actual size. + * To preserve aspect ratio, set a width or height and use `-1` for the other: `*W300 *H-1` + * @returns {(Integer)} + * `1` if the image was found, otherwise `0` + * @throws ValueError - An invalid parameter was detected or the image could not be loaded + * @throws OSError - An OS internal function call failed + * @see {@link https://www.autohotkey.com/docs/v2/lib/PixelSearch.htm|PixelSearch()} | + * {@link https://www.autohotkey.com/docs/v2/lib/PixelGetColor.htm|PixelGetColor()} | + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|MouseGetPos()} + * @example + */ +ImageSearch(&OutputVarX, &OutputVarY, X1, Y1, X2, Y2, ImageFile) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/IniDelete.htm|`IniDelete()`} + * Deletes a value from a standard format .ini file. + * @param {(String)} FileLocation + * The file name or path to an .INI file. + * If a full path isn't used, FileLocation is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(String)} Section + * The name of a section in the .INI file. + * @param {(String)} [Key] + * The name of the key-value pair to delete. + * If omitted, all keys in the section are deleted. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure. + * Regardless of an error, {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/IniRead.htm|IniRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/IniWrite.htm|IniWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDelete.htm|RegDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDeleteKey.htm|RegDeleteKey()} + * @example ini file example. + * ; Standard INI file format: + * + * ; INI comments start with semicolons + * ; Just like AHK comments + * [Section Names Go In Square Brackets] + * Key_Name = Some saved data + * Another_Key = 0 + */ +IniDelete(FileLocation, Section [,Key]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/IniRead.htm|`IniRead()`} + * Reads a value, section or list of section names from a standard format .ini file. + * @param {(String)} FileLocation + * The file name or path to an .INI file. + * If a full path isn't used, FileLocation is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(String)} [Section] + * The name of a section in the .INI file. + * If `Section` is omitted, a newline delimited list of all sections in the file is returned. + * @param {(String)} [Key] + * The name of a key to get the value of. + * If `Key` is omitted, a newline delimited list of all keys in that section is returned. + * @param {(String)} [Default] + * If the Key name doesn't exist in the specified Section, this value is returned. + * @returns {(String)} + * The value of the specified `Key` is returned. + * If `Key` not found, the value of `Default` is returned + * If no default value was provided, an error is thrown + * If `Key` is omitted, a list of all keys from the specified section is returned + * If `Section` is omitted, a list of all sections from the specified INI file is returned + * @throws OSError - Thrown if key doesn't exist and no default was provided + * Regardless of an error, {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/IniWrite.htm|IniWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/IniDelete.htm|IniDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegRead.htm|RegRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileRead.htm|FileRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} + * @example ini file example. + * ; Standard INI file format: + * + * ; INI comments start with semicolons + * ; Just like AHK comments + * [Section Names Go In Square Brackets] + * Key_Name = Some saved data + * Another_Key = 0 + */ +IniRead(FileLocation [,Section, Key, Default]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/IniWrite.htm|`IniWrite()`} + * Writes a value or section to a standard format .ini file. + * Values longer than 65,535 characters can be written to the file, but cannot be read correctly by {@link https://www.autohotkey.com/docs/v2/lib/IniRead.htm|IniRead()}. + * INI files are created as UTF-16 with BOM. To have the INI file encoded otherwise, create it before writing to it. + * @param {(String)} Value + * Either a single value to write to a key or an entire section of key=value pair(s). + * If writing a section of key=value pairs, `key = value` format should be used for each line and there can be no blank lines. + * @param {(String)} FileLocation + * The file name or path to an .INI file. + * If a full path isn't used, FileLocation is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {(String)} Section + * The name of a section in the .INI file to write to. + * @param {(String)} Key + * The name of the key to assign `Value` to. + * Key **must** be omitted when `Value` is a section of key=value pairs. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure. + * Regardless of an error, {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/IniRead.htm|IniRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/IniDelete.htm|IniDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegWrite.htm|RegWrite()} + * @example + * ; Writing a single value to a key + * IniWrite('true', A_Desktop '\test.ini', 'Test Section', 'my_key') + * + * ; Writing multiple key=value pairs + * data := 'language = "AutoHotkey"' + * . '`nversion = "2.0.10"' + * . '`ndate = 2023-12-06' + * IniWrite(data, A_Desktop '\test.ini', 'Code Info') + * + * ; INI file format: + * ;================= + * ; INI comments start with semicolons just like AHK comments + * [Section Name Inside Square Brackets] + * Some_Key_Name = Data goes right of equal sign + * number_1000 = 1000 + */ +IniWrite(Value, FileLocation, Section, Key) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm|`InputBox()`} + * Displays a popup box to get input from the user. + * @param {(String)} [Prompt] + * Text to display to the user above the edit input control. + * If omitted, the text area remains blank. + * @param {(String)} [Title] + * A title to give to the input box GUI. + * If omitted, {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptName|A_ScriptName} is used. + * @param {String|'X'|'Y'|'W'|'H'|'T'|'Password'} [Options] + * Zero or more of the following options, separated by spaces/tabs + * - `X#` `Y#` = Set the X and/or Y coordinates of the input box's upper-left corner, where `#` is a coordinate number. + * If either is omitted, the input box will be centered on that axis. + * - `W#` `H#` = The width and height of the input box's client area, where `#` is the number of pixels. + * - `T#` = Set a timeout to occur, where `#` is the number of seconds to wait. + * If timeout occurs, the return object sets `Result` to the word `Timeout` and `Value` to whatever the user had entered. + * - `Password#` = Masks the characters of the input box to prevent others from viewing what's being typed. + * Setting `#` to a character will use that character as the symbol mask + * Using `Password*` will show a `*` each time a character is typed. + * If no character is provided after the word `Password`, a default circle is used. + * @param {(String)} [DefaultText] + * Specify any default text to show in the edit control of the input box. + * If omitted or an empty string, no text will show in the control box. + * @returns {(Object)} + * An object is returned with 2 properties. + * `obj.Value` contains the user's submitted text + * `obj.Result` contains how the input box was closed: `OK`, `Cancel`, or `Timeout` + * @see {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|MsgBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|FileSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ToolTip.htm|ToolTip()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|Gui object} | + * {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm|InputHook object} + * @example + */ +InputBox([Prompt:='', Title:=A_ScriptName, Options:='', DefaultText:='']) => $InputBoxObject + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InstallKeybdHook.htm|`InstallKeybdHook()`} + * Installs or uninstalls the keyboard hook. + * The hook monitors keystrokes hotstring activation, hotkeys not supported by Window's {@link https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey|RegisterHotkey()}, and supports {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm|InputHook}. + * The keyboard hook is automatically installed when a script has a hotstring, a hooked hotkey, the {@link https://www.autohotkey.com/docs/v2/lib/SetNumScrollCapsLockState.htm|Set[Caps/Scroll/Num]LockState()} function, or has an active InputHook. + * @param {(Boolean)} [Install] + * - `1` = Hook is required to be installed. + * - `0` = Previously set requirements by this function are removed. + * This may cause the hook to uninstall completely. + * @param {(Boolean)} [Force] + * - `1` = This depends on the `Install` param. + * If `Install` is true, the hook is uninstalled and reinstalled. + * If `Install` is false, the hook is completely uninstalled, even if needed by something else. + * A hotkey or hotstring relying on the hook is disabled until the hook is reinstalled. + * - `0` = An internal variable is changed to indicate if the hook is required by the script. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/InstallMouseHook.htm|InstallMouseHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm|InputHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyHistory.htm|KeyHistory()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|GetKeyState()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyWait.htm|KeyWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/_UseHook.htm|#UseHook} + * {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Hotkeys::} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstrings::} | + * @example + */ +InstallKeybdHook([Install:=1, Force:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InstallMouseHook.htm|`InstallMouseHook()`} + * Installs or uninstalls the mouse hook. + * The hook monitors mouse clicks for the purpose of activating mouse {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|mouse hotkeys} and {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#NoMouse|facilitating hotstrings}. + * The mouse hook is automatically installed when a script has a hotstring or a mouse hotkey. + * @param {(Boolean)} [Install] + * - `1` = Hook is required to be installed. + * - `0` = Previously set requirements by this function are removed. + * This may cause the hook to uninstall completely. + * @param {(Boolean)} [Force] + * - `1` = This depends on the `Install` param. + * If `Install` is true, the hook is uninstalled and reinstalled. + * If `Install` is false, the hook is completely uninstalled, even if needed by something else. + * A hotkey or hotstring relying on the hook is disabled until the hook is reinstalled. + * - `0` = An internal variable is changed to indicate if the hook is required by the script. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/InstallKeybdHook.htm|InstallKeybdHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm|InputHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyHistory.htm|KeyHistory()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotstring.htm|Hotstring()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|GetKeyState()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyWait.htm|KeyWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/_UseHook.htm|#UseHook} + * {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Hotkeys::} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstrings::} | + * @example + */ +InstallMouseHook([Install:=1, Force:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|`InStr()`} + * Searches inside a string for an instance of the provided string. + * The search is done from left to right but can be changed with the `StartPos` and `Occurrence` parameters. + * @param {(String)} Haystack + * The string to search inside of. + * @param {(String)} Needle + * The string to search for. + * @param {'On'|'Off'|'Locale'|Integer} [CaseSense] + * - `1` `On` = Search is case-sensitive. `A` does not match `a`. + * - `0` `Off` = Search is not case-sensitive. `A` matches `a`. + * - `Locale` = Case-sensitivity is based on the rules of the user's locale. + * This can be anywhere from x1-x8 slower than `Off`. + * @param {(Integer)} [StartPos] + * The position in the string to start the search at. + * If omitted, `1` is used. + * - Positive Number + * Starting position is counted left to right. 1 = first char, 2 = second, ... + * Search direction is set to left to right + * - Negative Number + * Starting position is counted in reverse. -1 = last char, -2 = second from last, ... + * Search direction is set right to left + * + * The `Occurrence` parameter can override these search direction settings. + * @param {(Integer)} [Occurrence] + * Get the position of the Nth occurrence. + * It's the number of times `Needle` must be found before a position is returned. + * If omitted, `1` is used. + * - Positive Number = Search is done left to right. + * - Negative Number = Search is done right to left. + * + * This setting overrides the search direction set by `StartPos`. + * @returns {(Integer)} + * The position in the string the of the first found instance. + * If `Occurrence` is set, the position reflects the position of that + * @throws ValueError - `Needle` is an empty string (zero-length) + * @throws ValueError - `CaseSense` is invalid + * @throws ValueError - `Occurrence` or `StartPos` is not a number greater than 0 + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm|RegExMatch()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} + * @example + */ +InStr(Haystack, Needle [,CaseSense:=0, StartPos:=1, Occurrence:=1]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#IsAlnum|`IsAlnum()`} + * Checks if `Value` contains only alphanumeric characters. + * Alphanumeric character is defined as: + * `abcdefghijklmnopqrstuvwxyz` + * `ABCDEFGHIJKLMNOPQRSTUVWXYZ` + * `0123456789` + * @param {(String)} Value + * A string to check. + * @param {'Locale'} [Locale] + * By default, only ASCII characters are considered. + * Specifying the word `Locale` to use the user's locale rules. + * @returns {(Boolean)} + * - `1` = Value contains only alphanumeric characters + * - `0` = Value contains non-alphanumeric characters + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example + */ +IsAlnum(Value [,Locale:=unset]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#alpha|`IsAlpha()`} + * Checks if `Value` contains only alphabetic characters. + * Alphabetic character is defined as: + * `abcdefghijklmnopqrstuvwxyz` + * `ABCDEFGHIJKLMNOPQRSTUVWXYZ` + * @param {(String)} Value + * A string to check. + * @param {'Locale'} [Locale] + * By default, only ASCII characters are considered. + * Specifying the word `Locale` to use the user's locale rules. + * @returns {(Boolean)} + * - `1` = Value contains only alphabetic characters + * - `0` = Value contains non-alphabetic characters + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example + */ +IsAlpha(Value [,Locale:=unset]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#digit|`IsDigit()`} + * Checks if `Value` contains only digits. + * Digit is defined as: + * `0123456789` + * @param {(String|Integer)} Value + * A string or integer. + * @returns {(Boolean)} + * - `1` = Value contains only numeric characters + * - `0` = Value contains non-numeric characters + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example */ -SetDefaultMouseSpeed(Speed) => Integer +IsDigit(Value) => Integer /** - * Set the delay that will occur after each keystroke sent by send and controlsend. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#float|`IsFloat()`} + * Check if `Value` is float type or a string representing a valid float. + * Spaces and tabs around the float are ignored. ` 2.1 ` + * A string float can start with a plus `+` or minus `-` sign, or a decimal `.`. `.7` + * @param {(Any)} Value + * The input to check. + * @returns {(Boolean)} + * - `1` = Value is a float number + * - `0` = Value is not a float number + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Integer.htm|Integer} | + * {@link https://www.autohotkey.com/docs/v2/lib/Float.htm|Float} | + * {@link https://www.autohotkey.com/docs/v2/lib/Number.htm|Number} | + * {@link https://www.autohotkey.com/docs/v2/lib/String.htm|String} | + * {@link https://www.autohotkey.com/docs/v2/Objects.htm#primitive|Primitive} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#values|Values} | + * {@link https://www.autohotkey.com/docs/v2/Language.htm#expressions|Expressions} + * @example */ -SetKeyDelay([Delay, PressDuration, Play: 'Play']) => void +IsFloat(Value) => Integer /** - * Set the delay that occurs after each mouse move or click. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#integer|`IsInteger()`} + * Check if `Value` is integer type or a string representing a valid integer. + * Spaces and tabs around the integer are ignored. ` 5 ` + * A string integer can start with a plus `+` or minus `-` sign. `-5` + * @param {(Any)} Value + * The input to check. + * @returns {(Boolean)} + * - `1` = Value is an integer number + * - `0` = Value is not an integer number + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Integer.htm|Integer} | + * {@link https://www.autohotkey.com/docs/v2/lib/Float.htm|Float} | + * {@link https://www.autohotkey.com/docs/v2/lib/Number.htm|Number} | + * {@link https://www.autohotkey.com/docs/v2/lib/String.htm|String} | + * {@link https://www.autohotkey.com/docs/v2/Objects.htm#primitive|Primitive} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#values|Values} | + * {@link https://www.autohotkey.com/docs/v2/Language.htm#expressions|Expressions} + * @example */ -SetMouseDelay(Delay [, Play: 'Play']) => Integer +IsInteger(Value) => Integer /** - * Set the state of the NumLock key. You can also force the key to remain open or closed. - * @param {'On'|'Off'|'AlwaysOn'|'AlwaysOff'} State + * @description {@link https://www.autohotkey.com/docs/v2/lib/IsLabel.htm|`IsLabel()`} + * Checks if `Value` is a valid {@link https://www.autohotkey.com/docs/v2/misc/Labels.htm|label} name within the current scope. + * @param {(String)} Value + * The label name to check. + * @returns {(Boolean)} + * - `1` = Value is valid label name + * - `0` = Value is not a valid label name + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Labels.htm|Labels} | + * @example */ -SetNumLockState([State]) => void +IsLabel(Value) => Integer /** - * Set RegRead, RegWrite, RegDelete, RegDeleteKey and the registry view used by the registry cycle. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#lower|`IsLower()`} + * Checks if `Value` contains only lowercase characters. + * Lowercase character is defined as: + * `abcdefghijklmnopqrstuvwxyz` + * @param {(String)} Value + * A string to check. + * @param {'Locale'} [Locale] + * By default, only ASCII characters are considered. + * Specifying the word `Locale` to use the user's locale rules. + * @returns {(Boolean)} + * - `1` = Value contains only lowercase chars. + * - `0` = Value contains chars other than lowercase chars. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example + */ +IsLower(Value [,Locale:=unset]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#number|`IsNumber()`} + * Check if `Value` is float or integer type or a string representing a valid float or integer. + * Spaces and tabs around the number are ignored. ` 7 ` + * A string number can start with a plus `+` or minus `-` sign, or a decimal `.`. `-7.5` + * @param {(Any)} Value + * The input to check. + * @returns {(Boolean)} + * - `1` = Value contains a number + * - `0` = Value contains a non-number + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Integer.htm|Integer} | + * {@link https://www.autohotkey.com/docs/v2/lib/Float.htm|Float} | + * {@link https://www.autohotkey.com/docs/v2/lib/Number.htm|Number} | + * {@link https://www.autohotkey.com/docs/v2/lib/String.htm|String} | + * {@link https://www.autohotkey.com/docs/v2/Objects.htm#primitive|Primitive} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#values|Values} | + * {@link https://www.autohotkey.com/docs/v2/Language.htm#expressions|Expressions} + * @example */ -SetRegView(RegView) => Integer +IsNumber(Value) => Integer /** - * Set the state of the scroll lock key. You can also force the key to stay on or off. - * @param {'On'|'Off'|'AlwaysOn'|'AlwaysOff'} State + * @description {@link https://www.autohotkey.com/docs/v2/lib/IsObject.htm|`IsObject()`} + * Checks if `Value` is any {@link https://www.autohotkey.com/docs/v2/Objects.htm|object} type other than a {@link https://www.autohotkey.com/docs/v2/Objects.htm#primitive|primitive}. + * @param {(Any)} Value + * The input to check. + * @returns {(Boolean)} + * - `1` = Value is an object + * - `0` = Value is not an object + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object()} | + * {@link https://www.autohotkey.com/docs/v2/Objects.htm|Objects} | + * @example */ -SetScrollLockState([State]) => void +IsObject(Value) => Integer /** - * Whether to restore the capsLock state after send. + * @description {@link https://www.autohotkey.com/docs/v2/lib/IsSet.htm|`IsSet()`} + * Checks if `Var` has been assigned a value (initialized). + * @param {(Variable)} Var + * The variable to check. + * @returns {(Boolean)} + * - `1` = Value has an assigned value and is useable + * - `0` = Value has no assigned value and cannot be used + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example */ -SetStoreCapsLockMode(State) => Integer +IsSet(Var) => Integer /** - * Automatically call the function repeatedly at the specified time interval. - * @param Callback If Callback is omitted, if any, SetTimer will run on the timer that started the current thread. For example, SetTimer, 0 can be used in a timer function to mark the timer to be deleted, while SetTimer, 1000 The Period of the current timer will be updated. - * The absolute value of @param Period Period cannot be greater than 4294967295 ms (49.7 days). - * - * If Period is greater than 0, the timer will automatically repeat until the script is explicitly disabled. - * - * If Period is less than 0, the timer will only run once. For example, specifying -100 will call the callback after 100 ms, and then delete the timer, just like using SetTimer Callback, 0. - * - * If Period is 0, the timer is marked as deleted. If the thread started by this timer is still running, then after the thread ends, the timer will be deleted (unless it is re-enabled); otherwise, it will be Delete immediately. In any case, the Period and Priority before the timer will not be retained. - * @param Priority This optional parameter is an integer (or an expression) between -2147483648 and 2147483647 to indicate the priority of the timer. + * @description {@link https://www.autohotkey.com/docs/v2/lib/IsSet.htm|`IsSetRef()`} + * Checks if referenced variable has been assigned a value (initialized). + * Same as IsSet() except using a VarRef. + * @param {(VarRef)} Ref + * The variable reference to check. + * @returns {(Boolean)} + * - `1` = Referenced value has an assigned value and is useable + * - `0` = Referenced value has no assigned value and cannot be used + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example + */ +IsSetRef(&Ref) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#IsAlnum|`IsSpace()`} + * Checks if `Value` contains only whitespace characters. + * Whitespace character is defined as: + * `` `t `` Tab + * `` `s `` Space + * `` `n `` Linefeed + * `` `r `` Carriage Return + * `` `v `` Vertical Tab + * `` `f `` Formfeed + * @param {(String)} Value + * A string to check. + * @returns {(Boolean)} + * - `1` = Value contains only whitespace characters + * - `0` = Value contains non-whitespace characters + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example */ -SetTimer(Callback?, Period := 250, Priority := 0) => void +IsSpace(Value) => Integer /** - * Set the matching behavior of WinTitle parameters in commands such as WinWait. - * @param {'Fast'|'Slow'|'RegEx'|1|2|3} MatchMode + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#IsAlnum|`IsTime()`} + * Checks if `Value` contains a valid {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS date-time stamp}. + * Any partial date-time stamp is if it follows each subsection. `20221220` is valid. + * Any year prior to 1601 will return false as the OS does not consider it valid. + * @param {(String)} Value + * A date-time stamp to check. + * @returns {(Boolean)} + * - `1` = Value contains a valid date-time stamp + * - `0` = Value does not contain a valid date-time stamp + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example */ -SetTitleMatchMode(MatchMode) => Integer | String +IsTime(Value) => Integer /** - * Set the delay after each execution of a window function (such as Winactivate). + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#upper|`IsUpper()`} + * Checks if `Value` contains only uppercase characters. + * Uppercase character is defined as: `ABCDEFGHIJKLMNOPQRSTUVWXYZ` + * @param {(String)} Value + * A string to check. + * @param {'Locale'} [Locale] + * By default, only ASCII characters are considered. + * Specifying the word `Locale` to use the user's locale rules. + * @returns {(Boolean)} + * - `1` = Value contains only uppercase chars + * - `0` = Value contains chars other than uppercase chars + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example + */ +IsUpper(Value [,Locale:=unset]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#xdigit|`IsXDigit()`} + * Checks if `Value` contains only hexadecimal digits. + * Hexadecimal digit is defined as: `0123456789abcdefABCDEF` + * A hex prefix of `0x` or `0X` is allowed. + * @param {(String|Integer)} Value + * A string or number. + * @returns {(Boolean)} + * - `1` = Value contains valid hexadecimal value + * - `0` = Value contains valid hexadecimal value + * @see {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|Type()} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|ByRef parameters} + * @example */ -SetWinDelay(Delay) => Integer +IsXDigit(Value) => Integer /** - * change the current working directory of the script. + * @description {@link https://www.autohotkey.com/docs/v2/lib/KeyHistory.htm|`KeyHistory()`} + * Displays script info and a history of the most recent key/mouse/joypad events. + * Useful for detecting scan codes, virtual keys, and exact names for any keyboard key, mouse button, or controller joy. + * {@link https://www.autohotkey.com/docs/v2/lib/InstallMouseHook.htm|Mouse}/{@link https://www.autohotkey.com/docs/v2/lib/InstallKeybdHook.htm|Keyboard} hooks must be installed to show in key history. + * @param {(Integer)} [MaxEvents] + * Specify the a maximum number of keyboard and mouse events to record. + * This number must be between `0-500` with 0 disabling key history. + * Omitting `MaxEvents` will open the script's main window and display KeyHistory view. + * Default value is 40. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/InstallKeybdHook.htm|InstallKeybdHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InstallMouseHook.htm|InstallMouseHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListHotkeys.htm|ListHotkeys()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListLines.htm|ListLines()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListVars.htm|ListVars()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|GetKeyState()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyWait.htm|KeyWait()} | + * {@link https://www.autohotkey.com/docs/v2/KeyList.htm#Controller|Controller} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#PriorKey|A_PriorKey} + * @example + */ +KeyHistory([MaxEvents:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/KeyWait.htm|`KeyWait()`} + * Waits for a key or mouse/controller button to be released or pressed down. + * @param {(String)} KeyName + * The {@link https://www.autohotkey.com/docs/v2/KeyList.htm|name of a key} to wait for. + * Controller buttons can be used but none of the others controller inputs. + * A virtual code such as `vkFF` can be used for {@link https://www.autohotkey.com/docs/v2/KeyList.htm#SpecialKeys|special cases}. + * To wait for two or more keys to be released, use KeyWait() consecutively. + * @param {String|'D'|'L'|'T'} [Options] + * - `D` = Down. Wait for key to be in the down state. + * - `L` = Logical. Checks for the logical state of the key, not the physical state. + * - `T#` = Timeout. The function stops waiting and returns 0 after `#` seconds have passed. + * A float can be used for a more precise wait time. `T0.5` = 500 ms. + * Timeout must be a decimal value. + * @returns {(Boolean)} + * - `1` = KeyWait was successful + * - `0` = Timeout occurred + * @see {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|GetKeyState()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyHistory.htm|KeyHistory()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InstallKeybdHook.htm|InstallKeybdHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InstallMouseHook.htm|InstallMouseHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ClipWait.htm|ClipWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm|InputHook} | + * {@link https://www.autohotkey.com/docs/v2/KeyList.htm|Key List} + * @example + */ +KeyWait(KeyName [,Options]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListHotkeys.htm|`ListHotkeys()`} + * Displays all hotkeys in use by the current script. + * This function opens the script's main window and switches to the Hotkeys view. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/InstallKeybdHook.htm|InstallKeybdHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InstallMouseHook.htm|InstallMouseHook()} | + * {@link https://www.autohotkey.com/docs/v2/lib/KeyHistory.htm|KeyHistory()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListLines.htm|ListLines()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListVars.htm|ListVars()} | + * {@link https://www.autohotkey.com/docs/v2/lib/A_MaxHotkeysPerInterval.htm|A_MaxHotkeysPerInterval} | + * {@link https://www.autohotkey.com/docs/v2/lib/_MaxThreadsPerHotkey.htm|#MaxThreadsPerHotkey} | + * {@link https://www.autohotkey.com/docs/v2/lib/_UseHook.htm|#UseHook} + * @example + */ +ListHotkeys() => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListLines.htm|`ListLines()`} + * Enables or disables line logging or displays the script lines most recently executed. + * The default starting value is 1. + * @param {(Boolean)} [Mode] + * - Omit = Opens the script's main window and switches to the "Lines most recently executed" view. + * - `1` = Start capturing executed lines + * - `0` = Stop capturing executed lines + * + * Only the behavior of the {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|current thread} is affected. + * @returns {(Boolean)} + * The previous setting is always returned: + * - `1` = Script was capturing executed lines + * - `0` = Script was not capturing executed lines + * @see {@link https://www.autohotkey.com/docs/v2/lib/KeyHistory.htm|KeyHistory()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListHotkeys.htm|ListHotkeys()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ListVars.htm|ListVars()} + * @example */ -SetWorkingDir(DirName) => void +ListLines([Mode]) => Integer /** - * shut down, restart or log off the system. + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListVars.htm|`ListVars()`} + * Displays the names and current contents of the script's {@link https://www.autohotkey.com/docs/v2/Variables.htm|variables}. + * This function opens the script's main window and switches to the "Variables and their contents" view. + * @returns {(String)} + * An empty string is always returned. + * @example + */ +ListVars() => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ListViewGetContent.htm|`ListViewGetContent()`} + * Returns a list of items/rows from a ListView. + * @param {String|'Selected'|'Focused'|'Col'|'Count'|'Count Selected'|'Count Focused'|'Count Col'} [Options] + * Specify what to retrieve. + * Include zero or more options separated by spaces/tabs. + * - Omit = All text in the ListView is retrieved. + * - `Selected` = Selected/highlighted row is retrieved. + * If nothing is selected, an empty string is returned. + * - `Focused` = Focused row is retrieved. + * If nothing is focused, an empty string is returned. + * - `Col#` = Retrieve the text from the specified column, where `#` is the column number. + * - `Count` = Retrieve total number of rows in the ListView. + * - `Count Selected` = Retrieve the number of selected/highlighted rows. + * - `Count Focused` = Retrieve the number of focused rows. + * - `Count Col` = Retrieve total number of columns in the ListView. + * If count cannot be determined, `-1` is returned. + * @param {(String|Integer|Object)} [Control] + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * If omitted, the main window is targeted. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String|Integer)} + * Text representing lists/columns from the ListView. + * Each column is separated by a tab `` `t `` and each row is separated by a new line `` `n ``. + * An integer is returned for `Col#`, `Count`, and `Count Col` options. + * @throws TargetError - Window or control could not be found + * @throws OSError - A message could not be sent to the control or the ListView could not be opened + * @throws ValueError - Col# specified a nonexistent column + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlGetItems.htm|ControlGetItems()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetList.htm|WinGetList()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + * ; Include a double parse loop example + * list := ListViewGetContent() + * loop parse list, '`n', '`r' { + * row_num := A_Index + * loop parse row, '`t' { + * MsgBox('Row: ' row_num + * '`nCol:' A_Index + * '`nData:' A_LoopField) + * } + * } + * @returns {string} + */ +ListViewGetContent([Options:='', Control:=unset, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String | Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoadPicture.htm|`LoadPicture()`} + * Loads a picture from file and returns a bitmap or icon handle. + * @param {(String)} Filename + * The filename or path of the picture. + * If a full path isn't used, Filename is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @param {String|'W'|'H'|'Icon'|'GDI+'} [Options] + * Zero or more of the following options, separated by spaces/tabs + * - `W#` `H#` = Load picture to specified size, where `#` is number of pixels. + * To resize and maintain aspect ratio, set `W` or `H` to the desired number and set the other to `-1`. + * Using a `0` will keep the height/width set to its original value + * - `Icon#` = Icon number to load from the icon group, where `#` is the icon number. + * Specifying `Icon1` will convert a supported image to an icon if the `OutImageType` param is used. + * - `GDI+` = Uses GDI+ to load the image, if available. + * @param {(VarRef)} [OutImageType] + * Reference to a variable that will receive the returned image type + * - `0` = IMAGE_BITMAP + * - `1` = IMAGE_ICON + * - `2` = IMAGE_CURSOR + * @returns {(Integer)} + * A {@link https://www.autohotkey.com/docs/v2/misc/ImageHandles.htm|handle to a bitmap or icon}. + * @see {@link https://www.autohotkey.com/docs/v2/misc/ImageHandles.htm|Image Handles} + * @example + */ +LoadPicture(Filename [,Options, &OutImageType]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Log|`Log()`} + * Returns the logarithm (base 10) of the specified number. + * @param {(Number)} Num + * The number to get the log of. + * @returns {(Float)} + * The logarithm of Num. + * @throws ValueError - Num is a negative number + * @example + * Log(1.2) => 0.079181 + */ +Log(Num) => Float + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Ln|`Ln()`} + * Returns the natural logarithm (base e) of the specified number. + * @param {(Number)} Num + * The number to get the natural log of. + * @returns {(Float)} + * The natural logarithm of Num. + * @throws ValueError - Num is a negative number + * @example + */ +Ln(Num) => Float + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Trim.htm|`LTrim()`} + * Trims characters from the beginning of a string. + * @param {(String)} Str + * The string to trim. + * @param {'`n'|'`r'|'`r`n'|'`t'|' '|'`n`r`t '|String} [OmitChars] + * The characters to trim off. + * These characters are case-sensitive. + * If omitted, space and tab are used. + * @returns {(String)} + * The string after being trimmed. + * @example + */ +LTrim(Str [,OmitChars:=' `t']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Max|`Max()`} + * Returns the highest number from a set of numbers. + * @param {(Number|Array)} Value1 + * The first number of the set. + * This can be an {@link https://www.autohotkey.com/docs/v2/lib/Array.htm|array} of numbers if declared {@link https://www.autohotkey.com/docs/v2/Functions.htm#Variadic|variadic*} and is the only parameter used. + * + * arr := [2, 9, 7, 1] + * Max(arr*) => 9 + * @param {(Number)} [ValueN] + * Any amount of additional numbers. + * @returns {(Number)} + * The highest number of the set is returned. + * @example + */ +Max(Value1 [,ValueN*]) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MenuFromHandle.htm|`MenuFromHandle()`} + * Retrieves the Menu or MenuBar object corresponding to a Win32 menu handle. + * @param {(Integer)} Handle + * Handle to a Win32 menu (HMENU). + * @returns {(Menu|String)} + * A {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|menu object}. + * An empty string is returned if the handle does not point to an AHK menu. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Call|Menu()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Handle|Menu.Handle} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu/MenuBar object} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Win32_Menus|Win32 Menus} + * @example */ -Shutdown(Code) => void +MenuFromHandle(Handle) => Menu /** - * Returns the sine of Number. + * @description {@link https://www.autohotkey.com/docs/v2/lib/MenuSelect.htm|`MenuSelect()`} + * Invokes a menu item from the menu bar of the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {()} MenuName + * The name or prefix of the top-level menu item. + * It can also be the listed order of the menu: `1&` is the first menu, `2&` is the second, ... + * @param {()} [SubMenu1] + * The name or position of one or more submenu item. + * Each subsequent menu should be its own property. + * In rare cases, this can be omitted if the top-level item does not contain a menu. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @throws TargetError - Does not have a standard Win32 menu + * @throws ValueError - Menu, submenu, or menu item could not be found + * @throws ValueError - The final menu parameter points to a menu item which opens a submenu + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/PostMessage.htm|PostMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +MenuSelect(WinTitle, WinText, MenuName [,SubMenuN:=unset, NoWinTitle:='', NoWinText:='', *]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Min|`Min()`} + * Returns the lowest number from a set of numbers. + * @param {(Number|Array)} Value1 + * The first number of the set. + * This can be an {@link https://www.autohotkey.com/docs/v2/lib/Array.htm|array} of numbers if declared {@link https://www.autohotkey.com/docs/v2/Functions.htm#Variadic|variadic*} and is the only parameter used. + * + * arr := [2, 9, 7, 1] + * Min(arr*) => 1 + * @param {(Number)} [ValueN] + * Any amount of additional numbers. + * @returns {(Number)} + * The lowest number of the set is returned + * @example + */ +Min(Value1 [,ValueN*]) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Mod|`Mod()` (modulo)} + * Returns the remainder of a number (dividend) divided by another number (divisor). + * @param {(Number)} Dividend + * Number to divide. + * @param {(Number)} Divisor + * Number to divide by. + * @returns {(Number)} + * Remainder after division occurs. + * Return value is integer if the dividend and divisor are both integers. + * Otherwise, return value is float. + * @throws ZeroDivisionError - Divisor was set to 0 + * @example + */ +Mod(Dividend, Divisor) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MonitorGet.htm|`MonitorGet()`} + * Checks if the specified monitor exists and optionally retrieves its bounding coordinates. + * @param {(Integer)} Num + * Monitor number to get bounding coordinates of. + * The number of monitors can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/MonitorGetCount.htm|MonitorGetCount()}. + * If omitted, the primary monitor is used. + * @param {(VarRef)} Left + * A variable to receive the coordinate of the left edge of the monitor. + * @param {(VarRef)} Top + * A variable to receive the coordinate of the top edge of the monitor. + * @param {(VarRef)} Right + * A variable to receive the coordinate of the right edge of the monitor. + * @param {(VarRef)} Bottom + * A variable to receive the coordinate of the bottom edge of the monitor. + * @returns {(Integer)} + * The monitor number used to get the provided coordinates. + * This is equal to `Num` if `Num` is provided. + * @throws Error - On failure, an exception is thrown and var refs are not modified + * @see {@link https://www.autohotkey.com/docs/v2/lib/MonitorGetWorkArea.htm|MonitorGetWorkArea()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm|SysGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Monitor.htm|Monitor functions} + * @example + */ +MonitorGet([Num, &Left, &Top, &Right, &Bottom]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MonitorGetCount.htm|`MonitorGetCount()`} + * Returns the total number of monitors. + * @returns {(Integer)} + * Total number of monitors. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm|SysGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Monitor.htm|Monitor functions} + * @example */ -Sin(Number) => Float +MonitorGetCount() => Integer /** - * Wait the specified amount of time before continuing. - * @param Delay The amount of time to pause (in milliseconds), between 0 and 2147483647 (24 days). + * @description {@link https://www.autohotkey.com/docs/v2/lib/MonitorGetName.htm|`MonitorGetName()`} + * Returns the operating system's name of the specified monitor. + * @param {(Integer)} Num + * The monitor number to get the name of. + * The number of monitors can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/MonitorGetCount.htm|MonitorGetCount()}. + * If omitted, the primary monitor is used. + * @returns {(String)} + * The operating system's name for the specified monitor. + * @throws Error - Thrown on failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm|SysGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Monitor.htm|Monitor functions} + * @example + */ +MonitorGetName([Num]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MonitorGetPrimary.htm|`MonitorGetPrimary()`} + * Returns the number of the primary monitor. + * @returns {(Integer)} + * The number of the primary monitor. + * This will always be `1` on a single monitor system. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm|SysGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Monitor.htm|Monitor functions} + * @example + */ +MonitorGetPrimary() => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MonitorGetWorkArea.htm|`MonitorGetWorkArea()`} + * Checks if the specified monitor exists and optionally retrieves the bounding coordinates of its working area. + * The working area is area not reserved or otherwise claimed by taskbars, docked windows, and docked tool bars. + * @param {(Integer)} Num + * Monitor number to get the work area bounding coordinates of. + * The number of monitors can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/MonitorGetCount.htm|MonitorGetCount()}. + * If omitted, the primary monitor is used. + * @param {(VarRef)} Left + * A variable to receive the coordinate of the left edge of the work area. + * @param {(VarRef)} Top + * A variable to receive the coordinate of the top edge of the work area. + * @param {(VarRef)} Right + * A variable to receive the coordinate of the right edge of the work area. + * @param {(VarRef)} Bottom + * A variable to receive the coordinate of the bottom edge of the work area. + * @returns {(Integer)} + * The monitor number used to get the provided coordinates. + * This is equal to `Num` if `Num` is provided. + * @throws Error - On failure, an exception is thrown and var refs are not modified + * @see {@link https://www.autohotkey.com/docs/v2/lib/MonitorGet.htm|MonitorGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm|SysGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Monitor.htm|Monitor functions} + * @example + */ +MonitorGetWorkArea([Num, &Left, &Top, &Right, &Bottom]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|`MouseClick()`} + * Clicks or holds down a mouse button, or turns the mouse wheel. Note: The Click function is generally more flexible and easier to use. + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} dictates where x0 y0 starts at + * `Client` is suggested unless working with the desktop + * If `Relative` is used, x0 y0 is the mouse cursor. + * @param {'Left'|'Right'|'Middle'|'X1'|'X2'|'WheelUp'|'WheelDown'|'WheelRight'|'WheelLeft'} [Button] + * Mouse button to click. + * If omitted, `Left` is used. + * - `Left` or `L` + * - `Right` or `R` + * - `Middle` or `M` + * - `X1` (Mouse4) + * - `X2` (Mouse5) + * - `WheelUp` or `WU` + * - `WheelDown` or `WD` + * - `WheelRight` or `WR` + * - `WheelLeft` or `WL` + * @param {(Integer)} [X] + * The X coordinate to click at. + * If omitted, the current mouse X value is used + * @param {(Integer)} [Y] + * The Y coordinate to click at + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} dictates where x0 y0 starts at + * If omitted, the current mouse Y value is used + * @param {(Integer)} [Count] + * The number of times to click + * If omitted, `1` is used + * @param {(Integer)} [Speed] + * How fast the mouse is moved to the destination click point. + * This number should be between `0` (fastest) and `100` (slowest). + * The speed setting only works when {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} is set to Event. + * @param {'D'|'U'} [State] + * Send the up state, down state, or full click. + * - Omit = A full click is sent + * - `D` = Down event. The button is logically held down. + * - `U` = Up event. The button is logically released. + * @param {'R'} [Relative] + * Include the letter `R` to click relative to the current mouse position. + * `X` and `Y` parameters are used as offsets from the current mouse position. + * In other words, the mouse cursor becomes x0 y0. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetDefaultMouseSpeed.htm|SetDefaultMouseSpeed()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|MouseGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlClick.htm|ControlClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|BlockInput()} + * @example + */ +MouseClick([Button:='L', X:=CurrentX, Y:=CurrentY, Count:=1, Speed:=2, State:=unset, Relative:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|`MouseClickDrag()`} + * Clicks and holds the specified mouse button, moves the mouse to the destination coordinates, then releases the button. + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} dictates where x0 y0 starts at + * `Client` is suggested unless working with the desktop + * If `Relative` is used, x0 y0 is the mouse cursor. + * @param {'Left'|'Right'|'Middle'|'X1'|'X2'|'WheelUp'|'WheelDown'|'WheelRight'|'WheelLeft'} [Button] + * Mouse button to click. + * If omitted, `Left` is used. + * - `Left` or `L` + * - `Right` or `R` + * - `Middle` or `M` + * - `X1` (Mouse4) + * - `X2` (Mouse5) + * - `WheelUp` or `WU` + * - `WheelDown` or `WD` + * - `WheelRight` or `WR` + * - `WheelLeft` or `WL` + * @param {(Integer)} StartX + * The X coordinate of the click hold. + * @param {(Integer)} StartY + * The Y coordinate of the click hold. + * @param {(Integer)} EndX + * The X coordinate to release the click. + * @param {(Integer)} EndY + * The Y coordinate to release the click. + * @param {(Integer)} [Speed] + * How fast the mouse is dragged between the click points. + * This number should be between `0` (fastest) and `100` (slowest). + * The speed setting only works when {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} is set to Event. + * @param {'R'} [Relative] + * Include the letter `R` to click relative to the current mouse position. + * `StartX` and `StartY` are treated as offsets from the current mouse position. + * `EndX` and `EndY` are treated as offsets of `StartX` and `StartY`, respectively. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetDefaultMouseSpeed.htm|SetDefaultMouseSpeed()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|MouseGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|BlockInput()} + * @example + */ +MouseClickDrag(Button, StartX, StartY, EndX, EndY [,Speed:=2, Relative:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|`MouseGetPos()`} + * Retrieves the current position of the mouse cursor, and optionally which window and control it is hovering over. + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} dictates where x0 y0 starts at + * `Client` is suggested unless working with the desktop + * On multi-monitor systems with different DPI settings, the returned position may be different than expected due to {@link https://www.autohotkey.com/docs/v2/misc/DPIScaling.htm|OS DPI scaling}. + * @param {(VarRef)} [OutputX] + * A variable to receive the X coordinate of the mouse cursor + * @param {(VarRef)} [OutputY] + * A variable to receive the Y coordinate of the mouse cursor + * @param {(VarRef)} [OutputWin] + * A variable to receive the handle of the window under the mouse cursor + * @param {(VarRef)} [OutputControl] + * A variable to receive the handle of the control under the mouse cursor + * @param {(Integer)} [ControlFlag] Determines how control is determined: + * - `0` = Uses the default method to determine control. + * - `1` = Use a simpler method to determine control. + * Can correctly retrieve the active/topmost child window of Multiple Document Interface (MDI) applications like SysEdit or TextPad. + * This is less accurate for other purposes, such as detecting controls inside a GroupBox. + * - `2` = `OutputControl` receives the {@link https://www.autohotkey.com/docs/v2/lib/ControlGetHwnd.htm|control's handle (HWND)} instead of the {@link https://www.autohotkey.com/docs/v2/lib/ControlGetClassNN.htm|ClassNN}. + * - `3` = Use both flags `1` and `2`. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetDefaultMouseSpeed.htm|SetDefaultMouseSpeed()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} + * @example + */ +MouseGetPos([&OutputX, &OutputY, &OutputWin, &OutputControl, ControlFlag:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|`MouseMove()`} + * Moves the mouse cursor. + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} dictates where x0 y0 starts at + * `Client` is suggested for most use cases. + * @param {(Integer)} X + * The X coordinate to move to + * @param {(Integer)} Y + * The Y coordinate to move to + * @param {(Integer)} [Speed] + * How fast the mouse is dragged to the click point. + * This number should be between `0` (fastest) and `100` (slowest). + * The speed setting only works when {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} is set to Event. + * @param {'R'} [Relative] + * Include the letter `R` to click relative to the current mouse position. + * `X` and `Y` parameters are used as offsets from the current mouse position. + * In other words, the mouse cursor becomes x0 y0. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetDefaultMouseSpeed.htm|SetDefaultMouseSpeed()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|MouseGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|BlockInput()} + * @example + */ +MouseMove(X, Y [,Speed, Relative]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|`MsgBox()`} + * Displays the specified text in a small window containing one or more customizable buttons. + * If all params are omitted, `Press OK to Continue` is used. + * @param {(String)} [Text] + * Main text to display on the message. + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape Sequences} can be used to format the text. ``Line 1`nLine 2`` + * @param {(String)} [Title] + * A title to give the window. + * If omitted, {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptName|A_ScriptName} is used. + * @param {String|'OK'|'OKCancel'|'AbortRetryIgnore'|'YesNoCancel'|'YesNo'|'RetryCancel'|'CancelTryAgainContinue'|'IconX'|'Icon?'|'Icon!'|'Iconi'|'Default2'|'Default3'|'Default4'} [Options] + * Zero or more of the following options: + * - `Owner#` = Specify a window to make {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm#Owner|owner} of the message box, where `#` is the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|window handle (HWND)} of the owner. + * - `T#` = Timeout. Max time the message box can remain open before closing, where `#` is the number of seconds. + * A float can be used for a more precise wait time. `T2.5` = 2500 ms. + * Timeout must be a decimal value. + * Return value is set to `Timeout` if a message box closes from timing out. + * - Any of the following options: + * Hex values must be added together. Otherwise, include the string value. + * + * | -Option Groups- | -Hex- | -String Value- | + * | ---: | :--: | :--- | + * | **Group #1: Button Names** | ----------- | --------------------- | + * | OK | `0x0` | `O`, `OK` | + * | OK, Cancel | `0x1` | `OC`, `O/C`, `OKCancel` | + * | Abort, Retry, Ignore | `0x2` | `ARI`, `A/R/I`, `AbortRetryIgnore` | + * | Yes, No, Cancel | `0x3` | `YNC`, `Y/N/C`, `YesNoCancel` | + * | Yes, No | `0x4` | `YN`, `Y/N`, `YesNo` | + * | Retry, Cancel | `0x5` | `RC`, `R/C`, `RetryCancel` | + * | Cancel, Try Again, Continue | `0x6` | `CTC`, `C/T/C`, `CancelTryAgainContinue` | + * | **Group #2: Icon** | ----------- | --------------------- | + * | Hand (Stop/Error) | `0x10` | `IconX` | + * | Question (?) | `0x20` | `Icon?` | + * | Exclamation (!) | `0x30` | `Icon!` | + * | Asterisk (Info) | `0x40` | `Iconi` | + * | **Group #3: Default Button** | ----------- | --------------------- | + * | Focus button 2 | `0x100` | `Default2` | + * | Focus button 3 | `0x200` | `Default3` | + * | Focus button 4({@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm#Help|Help button} required) | `0x300` | `Default4` | + * | **Group #4: Modality** | ----------- | --------------------- | + * | System Modal (Always on top) | `0x1000` | N/A | + * | Task Modal | `0x2000` | N/A | + * | System Modal (No title icon) | `0x40000` | N/A | + * | **Group #5: Other** | ----------- | --------------------- | + * | Add {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm#Help|Help button} | `0x4000` | N/A | + * | Right-justified text | `0x80000` | N/A | + * | Right-to-left text direction | `0x100000` | N/A | + * + * @returns {(String)} + * The name of the button clicked is returned: + * `OK`, `Cancel`, `Yes`, `No`, `Abort`, `Retry`, `Ignore`, `TryAgain`, `Continue`, `Timeout` + * + * Clicking `X` is dependent on: + * - `OK` button only => `OK` + * - `Cancel` button present => `Cancel` + * - `AbortRetryIgnore`, `YesNo` => `X` is disabled + * @throws Error - `Options` are invalid + * @throws Error - {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm#max|MsgBox limit} has been reached + * @throws Error - Message box could not be displayed + * @see {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm|InputBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|FileSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ToolTip.htm|ToolTip()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|Gui object} + * @example + */ +MsgBox([Text:='', Title:=A_ScriptName, Options:=0]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/NumGet.htm|`NumGet()`} + * Returns the binary number stored at the specified address and offset. + * @param {(Integer|Buffer)} Source + * A memory address or a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|buffer-like} object (any object with a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Ptr|Ptr} and {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Size|Size} property). + * @param {'Char'|'Short'|'Int'|'Int64'|'Ptr'|'UChar'|'UShort'|'UInt'|'UPtr'|'UInt64'|'Float'|'Double'|Integer} Offset_Or_DataType + * The offset, in bytes, needed to be at the start of the number to get. + * If the data starts at the beginning of `Source` with no offset needed, this parameter becomes the `DataType` parameter. + * - `Offset` = The number of additional bytes needed to be at the start of the desired data. + * The data's type must be defined in the subsequent `DataType` parameter. + * - `DataType` = The {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#types|data type} expected to be gotten from `Source`. + * Using this parameter as `DataType` assumes the offset is `0`. + * - Data types: + * | {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#Int|***Signed Integer***} | ***Bytes*** | ***Bits*** | + * | :-- | :-- | :-- | + * | `Int64` | 8 | 64 | + * | `Int` | 4 | 32 | + * | `Short` | 2 | 16 | + * | `Char` | 1 | 8 | + * | `Ptr`✝ | 8 \| 4 | 64 \| 32 | + * | {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#unsigned|***Unsigned Integer***} | ***Bytes*** | ***Bits*** | + * | `UInt64`✝✝ | NA | NA | + * | `UInt` | 4 | 32 | + * | `UShort` | 2 | 16 | + * | `UChar` | 1 | 8 | + * | `UPtr`✝ | 8 \| 4 | 64 \| 32 | + * | {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#types|***Floating Point***} | ***Bytes*** | ***Bits*** | + * | `Double` | 8 | 32 | + * | `Float` | 4 | 16 | + * + * - ✝ Pointer size is determined by the current AHK exe type. + * AHK x64 / 64-bit = 64-bit sized pointers + * AHK x86 / 32-bit = 32-bit sized pointers + * - ✝✝ {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#unsigned|Unsigned 64-bit integers are not supported} as AHK's native type is Int64. + * To work with numbers greater than or equal to `0x8000000000000000`, use `Int64` and convert the signed value. + * @param {'Char'|'Short'|'Int'|'Int64'|'Ptr'|'UChar'|'UShort'|'UInt'|'UPtr'|'UInt64'|'Float'|'Double'|Integer} [DataType] + * If the `Offset_Or_DataType` was used as a data type, this parameter should be omitted. + * Otherwise, specify the data type expected. + * - Data types: + * | {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#Int|***Signed Integer***} | ***Bytes*** | ***Bits*** | + * | :-- | :-- | :-- | + * | `Char` | 1 | 8 | + * | `Short` | 2 | 16 | + * | `Int` | 4 | 32 | + * | `Int64` | 8 | 64 | + * | `Ptr`✝ | 8 \| 4 | 64 \| 32 | + * | {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#unsigned|***Unsigned Integer***} | ***Bytes*** | ***Bits*** | + * | `UChar` | 1 | 8 | + * | `UShort` | 2 | 16 | + * | `UInt` | 4 | 32 | + * | `UPtr`✝ | 8 \| 4 | 64 \| 32 | + * | `UInt64` | ✝✝ | ✝✝ | + * | {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#types|***Floating Point***} | ***Bytes*** | ***Bits*** | + * | `Float` | 4 | 16 | + * | `Double` | 8 | 32 | + * + * - ✝ Pointer size is determined by the current AHK exe type. + * AHK x64 (64-bit) = 8 byte sized pointers + * AHK x86 (32-bit) = 4 byte sized pointers + * - ✝✝ {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#unsigned|Unsigned 64-bit integers are not supported} as AHK's native type is Int64. + * To work with numbers greater than or equal to `0x8000000000000000`, use `Int64` and convert the signed value. + * @returns {(Number)} + * The number that was retrieved from the specified address and offset. + * @throws Error - The `Source` address was not valid + * Using a buffer object can help ensure memory addresses are always valid. + * @see {@link https://www.autohotkey.com/docs/v2/lib/NumPut.htm|NumPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/VarSetStrCapacity.htm|VarSetStrCapacity()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer object} + * @example Using NumPut() and NumGet() with a buffer object. + * ; Assigning a number to a buffer. + * buff := Buffer(4) + * NumPut('Int', 123, buff) + * MsgBox('The number stored in buff is: ' NumGet(buff, 'Int')) + * + * ; Assigning multiple numbers to a buffer. + * rect := Buffer(16, 0) + * NumPut('Int', 100, 'Int', 0, 'Int', 255, 'Int', 50, rect) + * MsgBox('The 3rd integer stored in rect is: ' NumGet(rect, 8, 'Int')) + * + * ; Assigning 4 points from an array to a RECT struct. + * rect := Buffer(16, 0) + * data := [0, 0, 255, 75] + * address := rect.Ptr + * for num in data + * address := NumPut('Int', num, address) + * MsgBox('The 4th integer stored in rect is: ' NumGet(rect, 12, 'Int')) + */ +NumGet(Source, Offset_Or_DataType [,DataType:=unset]) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/NumPut.htm|`NumPut()`} + * Stores one or more numbers in binary format at the specified address and offset. + * Multiple numbers can be assigned as long as type and then number is provided. + * @param {'Char'|'Short'|'Int'|'Int64'|'Ptr'|'UChar'|'UShort'|'UInt'|'UPtr'|'UInt64'|'Float'|'Double'|Integer} DataTypeN + * The type of the number being written to `Target`. + * - Data types: + * | {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#Int|***Signed Integer***} | ***Bytes*** | ***Bits*** | + * | :-- | :-- | :-- | + * | `Char` | 1 | 8 | + * | `Short` | 2 | 16 | + * | `Int` | 4 | 32 | + * | `Int64` | 8 | 64 | + * | `Ptr`✝ | 8 \| 4 | 64 \| 32 | + * | {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#unsigned|***Unsigned Integer***} | ***Bytes*** | ***Bits*** | + * | `UChar` | 1 | 8 | + * | `UShort` | 2 | 16 | + * | `UInt` | 4 | 32 | + * | `UPtr`✝ | 8 \| 4 | 64 \| 32 | + * | `UInt64`✝✝ | NA | NA | + * | {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#types|***Floating Point***} | ***Bytes*** | ***Bits*** | + * | `Float` | 4 | 16 | + * | `Double` | 8 | 32 | + * + * - ✝ Pointer size is determined by the current AHK exe type. + * AHK x64 (64-bit) = 8 byte sized pointers + * AHK x86 (32-bit) = 4 byte sized pointers + * - ✝✝ {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#unsigned|Unsigned 64-bit integers are not supported} as AHK's native type is Int64. + * To work with numbers greater than or equal to `0x8000000000000000`, use `Int64` and convert the signed value. + * + * More than one `DataType`-`Num` pair can be used to add multiple contiguous numbers at once. + * + * NumPut(NumType1, Num1, NumType2, Num2, NumType3, Num3, target [,offset]) + * @param {(Number)} NumN + * The number to write to the Target. + * More than one DataType/Num pair can be used in a call to add multiple contiguous numbers. + * + * NumPut(NumType1, Num1, NumType2, Num2, NumType3, Num3, target [,offset]) + * @param {(Integer|Buffer)} Target + * A memory address or a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|buffer-like} object (any object with a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Ptr|Ptr} and {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Size|Size} property). + * @param {(Integer)} [Offset] + * The number of bytes to offset from `Target` memory's starting address. + * If omitted, 0 is used. + * @returns {(Integer)} + * The memory address immediately following the data that was just written is returned. + * This address can be used as the next target when calling NumPut() multiple times, such as when looping through values. See example code. + * If the data is contiguous and the code permits, it's better to use multiple DataType-Num pairs in one call. + * @throws Error - The `Target` address was not valid + * Using a buffer object can help ensure memory addresses are always valid. + * @see {@link https://www.autohotkey.com/docs/v2/lib/NumGet.htm|NumGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/VarSetStrCapacity.htm|VarSetStrCapacity()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer object} + * @example Using NumPut() and NumGet() with a buffer object. + * ; Assigning a number to a buffer. + * buff := Buffer(4) + * NumPut('Int', 123, buff) + * MsgBox('The number stored in buff is: ' NumGet(buff, 'Int')) + * + * ; Assigning multiple numbers to a buffer. + * rect := Buffer(16, 0) + * NumPut('Int', 100, 'Int', 0, 'Int', 255, 'Int', 50, rect) + * MsgBox('The 3rd integer stored in rect is: ' NumGet(rect, 8, 'Int')) + * + * ; Assigning 4 points from an array to a RECT struct. + * rect := Buffer(16, 0) + * data := [0, 0, 255, 75] + * address := rect.Ptr + * for num in data + * address := NumPut('Int', num, address) + * MsgBox('The 4th integer stored in rect is: ' NumGet(rect, 12, 'Int')) + */ +NumPut(DataTypeN, NumN, Target [,Offset:=0], *) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ObjAddRef.htm|`ObjAddRef()`} + * Increments an object's {@link https://www.autohotkey.com/docs/v2/Objects.htm#Reference_Counting|reference count}. + * @param {(Integer)} Ptr + * An unmanaged object pointer of COM interface pointer. + * @returns {(Integer)} + * The new reference count. + * This value should only be used for debugging. + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm#Reference_Counting|Reference Counting} + * @example */ -Sleep(Delay) => void +ObjAddRef(Ptr) => Integer /** - * Arrange the contents of the variables in alphabetical, numeric or random order (you can choose whether to remove duplicates). - * @param Options A string consisting of zero or more of the following letters (in any order, the letters can be separated by spaces): - * - * C: Case-sensitive sorting (if there is an N option, this option is ignored). If both C and CL are omitted, the uppercase letters A-Z are considered equivalent to their corresponding lowercase forms in the sorting. - * - * CL: Case-insensitive sorting based on the current user locale. For example, most English and Western European regions equate the letters AZ and ANSI letters (such as Ä and Ü) to their lowercase forms. This method also uses " Word sorting", it handles hyphens and apostrophes in this way (words like "coop" and "co-op" are kept together). According to the content of the sorted item, its execution performance is indistinguishable than the default The method is 1 to 8 times worse. - * - * Dx: Specify x as the delimiter, which determines the start and end position of each item. If this option does not exist, x defaults to a newline character (`n), so when the string is lined with LF (`n) Or CR+LF(`r`n) can be sorted correctly at the end. - * - * N: Number sorting: each item is assumed to be sorted as a number instead of a string (for example, if this option does not exist, the string 233 is considered to be less than the string 40 according to the alphabetical order). Decimal and hexadecimal Strings (such as 0xF1) are considered to be numbers. Strings that do not start with a number are treated as zeros in sorting. The number is treated as a 64-bit floating point value, so that each digit in the fractional part ( If there is). - * - * Pn: Sort items according to character position n (not using hexadecimal n) (each item is compared from the nth character). If this option is not used, n defaults to 1, which is the first The position of the character. Sorting will start from the nth character to compare each string with other strings. If n is greater than the length of any string, the string will be treated as blank when sorting. When with the option When N (number sort) is used together, the character position of the string will be used, which is not necessarily the same as the number position of the number. + * @description {@link https://www.autohotkey.com/docs/v2/lib/ObjBindMethod.htm|`ObjBindMethod()`} + * Creates a {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc object} which calls a method of an object. + * @param {(Object)} Obj + * Any object. + * @param {(String)} [Method] + * The name of a method. + * If omitted, the object itself is called. Meaning: `Obj.Call()` + * @param {(Any)} [Params] + * Zero or more parameters to pass to the specified `Method`. + * Each param needs to be separated by a comma. * - * R: Reverse sorting (alphabetical or numerical sorting according to other options). - * - * Random: Random sorting. This option will cause other options except D, Z and U to be ignored (Nevertheless, N, C and CL will still affect the detection of duplicates). - * - * U: Remove duplicate items in the list so that each item is unique. If the C option is valid, the case of the items must match to be considered equivalent. If the N option is valid, then items like 2 Will be considered as a duplicate of 2.0. If the Pn or \(backslash) option is valid, the entire item must be the same to be regarded as a duplicate, not just a substring used for sorting. If the Random option or custom sorting Effective, the duplicates will be deleted only when there are adjacent duplicates in the sorting result. For example, when "A|B|A" is sorted randomly, the result may contain one or two A's. - * - * Z: To understand this option, please consider the variable whose content is RED`nGREEN`nBLUE`n. If the Z option does not exist, the last newline character (`n) will be considered as part of the last item, so the variable There are only three items. But if option Z is specified, the last `n (if it exists) will be considered to separate the last empty item in the list, so there are four items in the variable (the last one is empty). - * - * \: Sort according to the substring after the last backslash in each item. If the item does not contain a backslash, the entire item is used as the sorted substring. This option can be used to sort individual file names (I.e. does not include the path) - * @param Callback The function must accept three parameters: `MyFunction(first, second, offset)` - * - * When the function thinks that the first parameter is greater than the second parameter, it should return a positive integer; when the two parameters are judged to be equal, it should return 0, "", or empty; otherwise, it should return a negative integer. If it returns If there is a decimal part in the value, the part is ignored (i.e. 0.8 is equivalent to 0). - * - * If present, the third parameter receives the offset (in characters) of the second item from the first item, as seen in the original/unsorted list (see example). - * - * This function uses the same global (or thread-specific) settings as the sorting function that called it. - * - * `Note:` When there is a Callback, all options except D, Z and U will be ignored (although N, C and CL will still affect the detection of duplicates). + * ObjBindMethod(this, 'SomeMethod', 'a', 'b', 'c') + * @returns {(BoundFunc)} + * A {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc object} that can be used as a callback. + * @see {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm#BoundFunc|BoundFunc} + * @example */ -Sort(String, Options? [, Callback]) => String +ObjBindMethod(Obj [,Method, Params*]) => BoundFunc /** - * Sound is emitted from the PC speaker. - * @param Frequency The frequency of the sound. It should be a number between 37 and 32767. - * @param Duration The duration of the sound, in milliseconds. + * @description {@link https://www.autohotkey.com/docs/v2/Objects.htm#ObjFromPtr|`ObjFromPtr()`} + * Create an object reference from an object's memory address. + * @param {(Integer)} Address - The memory address of an object. + * @returns {(Object)} A reference to the object at that address. + * @example */ -SoundBeep(Frequency := 523, Duration := 150) => void +ObjFromPtr(Address) => Object /** - * Retrieve the native COM interface of a sound device or component. - * @param Component The display name and/or index of the component. For example, 1, "Line in" or "Line in: 2". If omitted or left blank, the interface implemented by the device itself will be retrieved. - * @param Device The display name and/or index of the device. For example, 1, "Speakers", "Speakers:2" or "Speakers (Example HD Audio)". - * If this parameter is omitted, it will default to the system's default playback device (not necessarily device 1). + * @description {@link https://www.autohotkey.com/docs/v2/Objects.htm#ObjFromPtr|`ObjFromPtrAddRef()`} + * Creates an object from a pointer and adds that object reference to the reference count. + * @param {()} Address - The memory address of an object. + * @returns {(Object)} A reference to the object at that address. + * @example These two lines are equal. + * ObjAddRef(address), myObject := ObjFromPtr(address) + * myObject := ObjFromPtrAddRef(address) */ -SoundGetInterface(IID [, Component, Device]) => ComObject +ObjFromPtrAddRef(Address) => Object /** - * Retrieve the mute setting from the sound device. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#HasOwnProp|`ObjHasOwnProp()`} + * Checks if an object has a property of the specified name. + * This function is equivalent to the built-in {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object} method `Obj.HasOwnProp()`. + * It is recommended to use the object's method instead of this function. + * @param {(Object)} Obj + * The object to check. + * @param {(String)} Name + * The property name to check for. + * @returns {(Boolean)} + * - `1` = Object has property + * - `0` = Object property does not exist + * @example */ -SoundGetMute([Component, Device]) => Integer +ObjHasOwnProp(Obj, Name) => Integer /** - * Retrieve the name of the sound device or component. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#GetBase|`ObjGetBase()`} + * Retrieves an object's {@link https://www.autohotkey.com/docs/v2/Objects.htm#delegation|base object}. + * @param {(Any)} Value + * Any value. + * @returns {(Prototype)} + * The base of the object. + * An empty string is returned if no base exists. + * Only the {@link https://www.autohotkey.com/docs/v2/lib/Any.htm|`Any`} prototype has no base. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#SetBase|ObjSetBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#Base|Base} | + * {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#Base|Obj.Base} + * @example + * obj := Array() + * obj_b := ObjGetBase(obj) + * if (obj_b = Array.Prototype) + * MsgBox('obj`'s base was derived from the Array class.') + */ +ObjGetBase(Value) => Prototype + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#GetCapacity|`ObjGetCapacity()`} + * Returns the current capacity of the object's internal array of properties. + * @param {(Object)} Obj + * The object to check. + * @returns {(Integer)} + * The max capacity of the object. + * @throws TypeError - Exception is thrown if `Obj` is incorrect type. + * @example + * obj1 := {} + * obj2 := {a:1, b:2, c:3, d:4, e:5} + * MsgBox(ObjGetCapacity(obj1) ' ' ObjGetCapacity(obj2)) */ -SoundGetName([Component, Device]) => String +ObjGetCapacity(Obj) => Integer /** - * Retrieve the volume setting from the sound device. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#OwnPropCount|`ObjOwnPropCount()`} + * Returns the number of properties owned by an object. + * @param {(Object)} Obj + * The object to check. + * @returns {(Integer)} + * The number of properties owned by an object. + * @example + * obj := {a:1, b:2, c:3, d:4, e:5} + * MsgBox(ObjGetCapacity(obj) '`n' ObjOwnPropCount(obj)) + * obj.DeleteProp('c') + * MsgBox(ObjGetCapacity(obj) '`n' ObjOwnPropCount(obj)) */ -SoundGetVolume([Component, Device]) => Integer +ObjOwnPropCount(Obj) => Integer /** - * Play audio, video or other supported file types. - * @param FileName The name of the file to be played, if the absolute path is not specified, it is assumed to be in A_WorkingDir. - * To make a standard system sound, please specify an asterisk followed by a number, as shown below. Note: In this mode, the Wait parameter has no effect. - * - * •*-1 = Simple beep. If the sound card is not available, the speaker will be used to generate this sound. - * - * •*16 = hand type (stop/error sound) - * - * •*32 = Question mark sound + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#OwnProps|`ObjOwnProps()`} + * Returns an enumerator for an object's own properties. + * This function is equivalent to the built-in {@link https://www.autohotkey.com/docs/v2/lib/Object.htm|Object} method `Obj.OwnProp()`. + * This is normally used with a {@link https://www.autohotkey.com/docs/v2/lib/For.htm|for-loop} to iterate through the the object's properties. + * It is usually recommended to use the corresponding method instead. + * @param {(Object)} Obj + * The object to enumerate. + * @returns {(Enumerator)} + * An {@link https://www.autohotkey.com/docs/v2/lib/Enumerator.htm|Enumerator} for the object's properties. + * @example Enumerating through an object's properties. + * obj := {a:'Alpha', b:'Bravo', c:'Charlie'} + * for key, value in ObjOwnProps(obj) + * MsgBox('key: ' key '`nvalue: ' value) * - * •*48 = exclamation - * - * •*64 = Asterisk (message sound) - * - * `Known limitations:` Due to Windows system limitations, WAV files with a path exceeding 127 characters will not be played. To solve this problem, you can use other file types such as MP3 (the path length can be up to 255 characters) or Use 8.3 short paths (see A_LoopFileShortPath for how to retrieve these paths). + * ; Identical to ObjOwnProps() method + * obj := {a:'Alpha', b:'Bravo', c:'Charlie'} + * for key, value in obj.ObjOwnProps() + * MsgBox('key: ' key '`nvalue: ' value) */ -SoundPlay(FileName: $FilePath, Wait := false) => void +ObjOwnProps(obj) => Enumerator /** - * Change the mute setting of the sound device. + * @description {@link https://www.autohotkey.com/docs/v2/Objects.htm#ObjPtr|`ObjPtr()`} + * Retrieve the memory address of an object. + * @param {(Object)} Obj - An object to get the memory address of. + * @returns {(Integer)} The pointer address of the object. + * @example */ -SoundSetMute(NewSetting [, Component, Device]) => void +ObjPtr(Obj) => Integer /** - * Change the volume setting of the sound device. + * @description {@link https://www.autohotkey.com/docs/v2/Objects.htm#ObjPtr|`ObjPtrAddRef()`} + * Increments an object's {@link https://www.autohotkey.com/docs/v2/Objects.htm#Reference_Counting|reference count}. + * @param {(Object)} Obj + * An unmanaged object pointer of COM interface pointer. + * @returns {(Integer)} + * The memory address of the object. + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm#Reference_Counting|Reference Counting} + * @example */ -SoundSetVolume(NewSetting [, Component, Device]) => void +ObjPtrAddRef(Obj) => Integer /** - * Break the file name (path) or URL into its name, directory, extension and drive. + * @description {@link https://www.autohotkey.com/docs/v2/lib/ObjAddRef.htm|`ObjRelease()`} + * Decrements an object's {@link https://www.autohotkey.com/docs/v2/Objects.htm#Reference_Counting|reference count}. + * @param {(Integer)} Ptr + * An unmanaged object pointer of COM interface pointer. + * @returns {(Integer)} + * The new reference count. + * This value should only be used for debugging. + * @see {@link https://www.autohotkey.com/docs/v2/Objects.htm#Reference_Counting|Reference Counting} + * @example + */ +ObjRelease(ptr) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#SetBase|`ObjSetBase()`} + * Sets an object's {@link https://www.autohotkey.com/docs/v2/Objects.htm#delegation|base object}. + * @param {(Object)} Obj + * The object to assign the new base to. + * @param {(Prototype)} BaseObj + * The prototype of another object. + * @returns {(String)} + * An empty string is always returned. + * @throws TypeError - `Obj` or `BaseObj` is of an incorrect type. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Any.htm#GetBase|ObjGetBase()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#Base|Base property} + * @example + */ +ObjSetBase(Obj, BaseObj) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Object.htm#SetCapacity|`ObjSetCapacity()`} + * Sets the current capacity of the object's internal array of own properties. + * @param {(Object)} Obj + * The object to set the capacity of. + * @param {(Integer)} MaxProps + * The new capacity. + * If `MaxProps` is less than the total amount of properties, capacity is set to the total properties. + * @returns {(Integer)} + * The new capacity amount. + * @throws TypeError - `Obj` is of an incorrect type. + * @example + */ +ObjSetCapacity(Obj, MaxProps) => ReturnValue + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/OnClipboardChange.htm|`OnClipboardChange()`} + * Registers a {@link https://www.autohotkey.com/docs/v2/Functions.htm|function} to be called automatically whenever the clipboard's content changes. + * @param {(FuncObj)} Callback + * The {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} to call on clipboard change. + * The callback must be able to accept one parameter for data type. + * Possible DataType values: + * - `0` = Clipboard is empty. + * - `1` = Clipboard contains text. + * - `2` = Clipboard Contains binary data (such as a picture). + * + * clipboard_func(DataType) ; Expected callback format + * @param {(Integer)} [AddRemove] + * - `1` = Callback after any previously registered callbacks. + * - `-1` = Callback before any previously registered callbacks. + * - `0` = Do not call the callback. + * + * If a callback returns a non-zero integer, all subsequent callbacks are skipped. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/OnExit.htm|OnExit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm|OnMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm|CallbackCreate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/A_Clipboard.htm|A_Clipboard} + * @example + */ +OnClipboardChange(Callback [,AddRemove:=1]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|`OnError()`} + * Registers a {@link https://www.autohotkey.com/docs/v2/Functions.htm|function} to be called automatically whenever an unhandled error occurs. + * @param {(FuncObj)} Callback + * The {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} to call on error. + * The callback must be able to accept two parameters. + * - `ThrownValue` = The value that was thrown, usually an {@link https://www.autohotkey.com/docs/v2/lib/Error.htm|Error object}. + * - `ErrorMode` + * - {@link https://www.autohotkey.com/docs/v2/lib/Return.htm|`Return`} + * The thrown value is a continuable runtime error. + * The thread continues if the callback returns -1; otherwise the thread exits. + * - {@link https://www.autohotkey.com/docs/v2/lib/Exit.htm|`Exit`} + * The thrown value is a non-continuable runtime error or a value {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|thrown} by the script. + * The thread will exit. + * - {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|`ExitApp`} + * The thrown value is a critical runtime error, such as corruption detected by DllCall. + * The program will exit. + * + * clipboard_func(ThrownValue, ErrorMode) ; Callback format + * + * The callback can return one of the following values: + * - `0` Omit ` ` (Space) = Allow error handling to proceed as normal. + * - `1` = Suppress the default error dialog and any remaining error callbacks. + * - `-1` = If `ErrorMode` was `Return`, execution of the current thread continues. + * @param {(Integer)} [AddRemove] + * - `1` = Callback after any previously registered callbacks. + * - `-1` = Callback before any previously registered callbacks. + * - `0` = Do not call the callback. + * + * If a callback returns a non-zero integer, all subsequent callbacks are skipped. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/OnExit.htm|OnExit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try} | + * {@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} | + * {@link https://www.autohotkey.com/docs/v2/lib/Throw.htm|Throw} + * @example + */ +OnError(Callback [,AddRemove:=1]) => ReturnValue + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/OnExit.htm|`OnExit()`} + * Registers a function to be called automatically whenever the script exits. + * @param {(FuncObj)} Callback + * The {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} to call on script exit. + * The callback must be able to accept two parameters. + * - {@link https://www.autohotkey.com/docs/v2/lib/OnExit.htm#ExitReason|`ExitReason`} = The reason for exiting: + * - `Logoff` = The user is logging off. + * - `Shutdown` = The system is being shut down or restarted. + * - `Close` = The script was sent a WM_CLOSE or WM_QUIT message, had a critical error, or is being closed in some other way. + * - `Error` = A runtime error occurred in a script that is not persistent. + * - `Menu` = The user selected Exit from the main window's menu or from the standard tray menu. + * - `Exit` = Exit or ExitApp was used (includes custom menu items). + * - `Reload` = The script is being reloaded via the Reload function or menu item. + * - `Single` = The script is being replaced by a new instance of itself as a result of #SingleInstance. + * - `ExitCode` = The code that was passed to {@link https://www.autohotkey.com/docs/v2/lib/Exit.htm|Exit()} or {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|ExitApp()} + * + * OnExit(ExitReason, ExitCode) ; Callback format + * + * The callback can return a non-zero integer to prevent the script from exiting and calling more callbacks. + * Otherwise, the script exits after all registered callbacks are called. + * @param {(Integer)} [AddRemove] + * - `1` = Callback after any previously registered callbacks. + * - `-1` = Callback before any previously registered callbacks. + * - `0` = Do not call the callback. + * + * If a callback returns a non-zero integer, all subsequent callbacks are skipped. + * @see {@link https://www.autohotkey.com/docs/v2/lib/OnError.htm|OnError()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm|OnMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm|CallbackCreate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnClipboardChange.htm|OnClipboardChange()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|ExitApp()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Shutdown.htm|Shutdown()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Persistent.htm|Persistent()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/Return.htm|Return} + * @example + */ +OnExit(Callback [,AddRemove:=1]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm|`OnMessage()`} + * Registers a {@link https://www.autohotkey.com/docs/v2/Functions.htm|function} to be called automatically whenever the script receives the specified message. + * @param {(Integer)} MsgNumber + * The message number to monitor or query. + * This should be between 0-4294967295 (0x0-0xFFFFFFFF). + * If not monitoring a system message (messages below 1024/0x0400), use a number greater than 4096/0x1000 to avoid any conflicts with internal messages used by AHK. + * @param {(FuncObj)} Callback + * The {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} to call when a message is received. + * The callback must be able to accept four parameters. + * - `WPARAM` = Word Param. This is used to send additional data about the message to the callback. + * The W stands for Word, because it used to be 16-bits. Both PARAMs are now 32 or 64 bits, depending on architecture. + * - `LPARAM` = Long Param. This is used to send additional data about the message to the callback. + * The L stands for Word, because it used to be 32-bits. Both PARAMs are now 32 or 64 bits, depending on architecture. + * - `Msg` = The message number. + * List of common {@link https://www.autohotkey.com/docs/v2/misc/SendMessageList.htm|WM_ Windows Messages}. + * - `Hwnd` = A handle to the window + * + * wm_callback(Wparam, Lparam, Msg, Hwnd) ; Callback format + * @param {(Integer)} [MaxThreads] + * The maximum {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|threads} the Message can call. + * The default is `1` which is desireable. This prevents messages from processing out of chronological order. + * Specify `0` to unregister a previously registered callback. + * An alternative to changing MaxThreads is to {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm#Critical|use critical}. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm|CallbackCreate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnExit.htm|OnExit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnClipboardChange.htm|OnClipboardChange()} | + * {@link https://www.autohotkey.com/docs/v2/lib/PostMessage.htm|PostMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm|Critical()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm|Thread()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/Functions.htm|Functions} | + * {@link https://www.autohotkey.com/docs/v2/misc/SendMessageList.htm|Message List} | + * {@link https://www.autohotkey.com/docs/v2/misc/SendMessage.htm|Message Tutorial} | + * @example Move a GUI with click and drag. + * goo := Gui() + * goo.AddText(, 'Click and drag gui.') + * goo.Show('w300 h300') + * OnMessage(0x200, move_gui) + * + * move_gui(Wparam, Lparam, Msg, Hwnd) { + * WM_NCLBUTTONDOWN := 0xA1 + * if (Wparam = 1) + * SendMessage(WM_NCLBUTTONDOWN,2,,,'A') + * } + */ +OnMessage(MsgNumber, Callback [,MaxThreads:=1]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Ord.htm|`Ord()`} + * Returns the ordinal value (numeric character code) of the first character in the specified string. + * @param {(String)} Str + * The string to retrieve the ordinal value for. + * @returns {(Integer)} + * If ANSI, an integer between 0 and 255 is returned. + * If Unicode, an integer between 0x0 to 0xFFFF is returned. + * If `Str` begins with a {@link https://learn.microsoft.com/en-us/windows/win32/intl/surrogates-and-supplementary-characters|Unicode supplementary character}, the corresponding Unicode char is sent (between 0x10000 and 0x10FFFF) + * If the string is empty, `0` is returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Chr.htm|Chr()} | + * {@link https://raw.githubusercontent.com/GroggyOtter/GroggyRepo/master/AHK/Groggy's%20ASCII%20Tables.txt|ASCII Table} + * @example + * Ord("t") => 116 + * Ord("test") => 116 + */ +Ord(Str) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/OutputDebug.htm|`OutputDebug()`} + * Sends a string to the debugger (if any) for display. + * @param {(String)} Text + * The text to send to the debugger. + * This can include newlines `` `n ``. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/Scripts.htm#debug|Other Debugging Methods} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileAppend.htm|FileAppend()} | + * {@link https://www.autohotkey.com/docs/v2/Scripts.htm#continuation|Continuation sections} + * @example + */ +OutputDebug(Text) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Pause.htm|`Pause()`} + * Pauses the script's current thread. + * This is different from {@link https://www.autohotkey.com/docs/v2/lib/Suspend.htm|Suspend()}, which prevents the script's hotkeys and hotstring from firing. + * @param {(Integer)} NewState + * - Omit = The {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|current thread} is paused. + * - `1` = Mark the thread beneath the current one as paused. + * When the current thread finishes, the prior thread will finish its function call then go into a paused state. + * - `0` = Unpauses and underlying thread. + * - `-1` = Toggles the pauses state of the underlying thread. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Suspend.htm|Suspend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|ExitApp()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm|SetTimer()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu object} + * @example + */ +Pause([NewState:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Persistent.htm|`Persistent()`} + * Prevents the script from exiting automatically when the last thread completes, allowing a script to stay running in an idle state. + * This setting is automatically set to `1` if the script has any {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|hotkeys}, {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|hotstrings}, visible {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|GUIs}, active {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm|timers}, {@link https://www.autohotkey.com/docs/v2/lib/OnClipboardChange.htm|clipboard monitoring}, or {@link https://www.autohotkey.com/docs/v2/lib/InputHook.htm|Inputhooks}. + * @param {(Boolean)} Enable + * Turns on script persistence. + * If omitted, `1` is used. + * - `1` = Persistence is enabled and keeps the script running even if there's not an active thread. + * - `0` = Persistence is disabled and the script will close when the last active thread ends. + * @returns {(Boolean)} + * The previous setting is always returned: + * - `1` = Script was persistent + * - `0` = Script was not persistent + * @see {@link https://www.autohotkey.com/docs/v2/lib/Exit.htm|Exit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|ExitApp()} + * @example + */ +Persistent([Enable:=1]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/PixelGetColor.htm|`PixelGetColor()`} + * Retrieves the color of the pixel at the specified X and Y coordinates. + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} dictates where x0 y0 starts at + * `Client` is suggested for most use cases. + * @param {(Integer)} X + * The X coordinate of the pixel + * @param {(Integer)} Y + * The Y coordinate of the pixel + * @param {'Alt'|'Slow'} [Mode] + * Set the color retrieval method: + * - Omit = Normal method is used to retrieve pixel color. + * - `Alt` = The alt method should be used if the normal method produces inaccurate colors. + * This method runs about 10% slower. + * - `Slow` = Use a more elaborate method to get pixel color. + * This method is about 200% slower than the normal method. + * @returns {(String)} + * A string in 6-digit RGB hex format: `0xFFAA55` + * FF = Red, AA = Green, 55 = Blue + * @throws OSError - Thrown on failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/PixelSearch.htm|PixelSearch()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ImageSearch.htm|ImageSearch()} | + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|MouseGetPos()} + * @example Actively show color of pixel under mouse. + * SetTimer(active_color_checker, 50) + * + * active_color_checker() { + * if (A_CoordModePixel != 'Screen') + * A_CoordModePixel := 'Screen' + * MouseGetPos(&x, &y) + * color := PixelGetColor(x, y) + * Tooltip('Red: 0x' SubStr(color, 3, 2) + * '`nGreen: 0x' SubStr(color, 5, 2) + * '`nBlue: 0x' SubStr(color, 7, 2)) + * } + */ +PixelGetColor(X, Y [,Mode]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/PixelSearch.htm|`PixelSearch()`} + * Searches a region of the screen for a pixel of the specified color. + * @param {(VarRef)} OutputX + * A variable to receive the X coordinate of the found pixel. + * If a match is not made, this var receives an empty string. + * @param {(VarRef)} OutputY + * A variable to receive the Y coordinate of the found pixel. + * If a match is not made, this var receives an empty string. + * @param {(Integer)} X1 + * The left edge of the search area. + * @param {(Integer)} Y1 + * The top edge of the search area. + * @param {(Integer)} X2 + * The right edge of the search area. + * @param {(Integer)} Y2 + * The bottom edge of the search area. + * @param {(Integer)} ColorID + * The color ID to search for. + * This can be a hexadecimal or decimal number in RGB format. + * `0xFFFF00` is the same as `16776960`. + * Color ID can be gotten with Window Spy or by using {@link https://www.autohotkey.com/docs/v2/lib/PixelGetColor.htm|PixelGetColor()} + * @param {(Integer)} [Variation] + * Sets the amount of color variation allowed to match a color. + * This should be a number between `0`-`255` (`0x0`-`0xFF`). + * If looking for `0x20C0B0` with a `0x10` variation, the colors `0x10B0A0` to `0x30D0C0` will cause a positive match. + * @returns {(Boolean)} + * - `1` Color found + * - `0` Color not found + * @throws OSError - The function was unable to conduct the search. + * @see {@link https://www.autohotkey.com/docs/v2/lib/PixelGetColor.htm|PixelGetColor()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ImageSearch.htm|ImageSearch()} | + * {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos.htm|MouseGetPos()} + * @example + */ +PixelSearch(&OutputX, &OutputY, X1, Y1, X2, Y2, ColorID [,Variation:=0]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/PostMessage.htm|`PostMessage()`} + * Places a message in the message queue of a window or control. + * Unlike {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage()}, PostMessage() does not wait for acknowledgement. + * @param {(Integer)} MsgNumber + * The {@link https://www.autohotkey.com/docs/v2/misc/SendMessageList.htm|message number} to send. + * @param {(Integer)} [wParam] + * Word Param. Used to pass message-specific information and must be an integer. + * If omitted, defaults to `0`. + * @param {(Integer)} [lParam] + * Long Param. Also used to pass message-specific information and must be an integer. + * If omitted, defaults to `0`. + * @param {(String|Integer|Object)} [Control] + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * If omitted, the target window is used instead of a control. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @throws OSError - Message could not be posted + * @see {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm|OnMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MenuSelect.htm|MenuSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage()} | + * {@link https://www.autohotkey.com/docs/v2/misc/SendMessageList.htm|Message List} | + * {@link https://www.autohotkey.com/docs/v2/misc/SendMessage.htm|Message Tutorial} | + * {@link https://www.autohotkey.com/docs/v2/misc/Winamp.htm|Automating Winamp} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +PostMessage(MsgNumber [,wParam:=0, lParam:=0, Control:=TargetWindow, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ProcessClose.htm|`ProcessClose()`} + * Forces the first matching process to close. + * @param {(String|Integer)} NameOrPID + * The process name or process ID to close. + * - `Name` = The name of the process without a path: `Notepad.exe` + * If there are multiple processes with that name, the first match is used. + * Names are not case-sensitive. + * - `PID` = The Process ID number of a process. This is not a static value and changes each time the process is launched. + * A PID can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()}, {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|ProcessExist()}, and with {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} using the `&OutputPID` parameter. + * This is different from a Window ID (HWND) that uniquely identifies a Window or control. + * @returns {(Integer)} + * The Process ID of the specified process. + * `0` if a matching process was not found. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinClose.htm|WinClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinKill.htm|WinKill()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} + * @example + */ +ProcessClose(NameOrPID) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|`ProcessExist()`} + * Checks if the specified process exists. + * @param {(String|Integer)} [NameOrPID] + * The process name or process ID to check existence of. + * If omitted, the script's own process ID is used. + * - `Name` = The name of the process without a path: `Notepad.exe` + * If there are multiple processes with that name, the first match is used. + * Names are not case-sensitive. + * - `PID` = The Process ID number of a process. This is not a static value and changes each time the process is launched. + * A PID can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()}, {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|ProcessExist()}, and with {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} using the `&OutputPID` parameter. + * This is different from a Window ID (HWND) that uniquely identifies a Window or control. + * @returns {(Integer)} + * The Process ID of the specified process. + * `0` if a matching process was not found. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} + * @example + */ +ProcessExist([NameOrPID:=unset]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ProcessGetName.htm|`ProcessGetName()`} + * Returns the name of the specified process. + * @param {(String|Integer)} [NameOrPID] + * The process name or process ID to get the name of. + * If omitted, the script's own process ID is used. + * - `Name` = The name of the process without a path: `Notepad.exe` + * If there are multiple processes with that name, the first match is used. + * Names are not case-sensitive. + * - `PID` = The Process ID number of a process. This is not a static value and changes each time the process is launched. + * A PID can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()}, {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|ProcessExist()}, and with {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} using the `&OutputPID` parameter. + * This is different from a Window ID (HWND) that uniquely identifies a Window or control. + * @returns {(String)} + * The name of the specified process. `notepad.exe` + * @throws TargetError - The process could not be found + * @throws OSError - The name could not be retrieved + * @see {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} + * @example + */ +ProcessGetName([NameOrPID:=unset]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ProcessGetParent.htm|`ProcessGetParent()`} + * Returns the process ID (PID) of the process which created the specified process. + * A parent process is a process that launches another process. + * @param {(String|Integer)} [NameOrPID] + * The process name or process ID to get the parent of. + * If omitted, the script's own process ID is used. + * - `Name` = The name of the process without a path: `Notepad.exe` + * If there are multiple processes with that name, the first match is used. + * Names are not case-sensitive. + * - `PID` = The Process ID number of a process. This is not a static value and changes each time the process is launched. + * A PID can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()}, {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|ProcessExist()}, and with {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} using the `&OutputPID` parameter. + * This is different from a Window ID (HWND) that uniquely identifies a Window or control. + * @returns {(Integer)} + * The parent process ID that created the specified process. + * @throws TargetError - The process could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} + * @example + */ +ProcessGetParent([NameOrPID]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ProcessGetName.htm|`ProcessGetPath()`} + * Returns the path of the specified process. + * @param {(String|Integer)} [NameOrPID] + * The process name or process ID to get the full path of. + * If omitted, the script's own process ID is used. + * - `Name` = The name of the process without a path: `Notepad.exe` + * If there are multiple processes with that name, the first match is used. + * Names are not case-sensitive. + * - `PID` = The Process ID number of a process. This is not a static value and changes each time the process is launched. + * A PID can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()}, {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|ProcessExist()}, and with {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} using the `&OutputPID` parameter. + * This is different from a Window ID (HWND) that uniquely identifies a Window or control. + * @returns {(String)} + * The full process path of the specified process. `C:\Windows\notepad.exe` + * @throws TargetError - The process could not be found + * @throws OSError - The path could not be retrieved + * @see {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} + * @example + */ +ProcessGetPath([NameOrPID]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ProcessSetPriority.htm|`ProcessSetPriority()`} + * Changes the priority level of the first matching process. + * @param {'L'|'B'|'N'|'A'|'H'|'R'} Level + * Specify a priority level name or its first letter: + * - `L` `Low` + * - `B` `BelowNormal` + * - `N` `Normal` + * - `A` `AboveNormal` + * - `H` `High` + * - `R` `Realtime` + * @param {(String|Integer)} [NameOrPID] + * The process name or process ID to set the priority of. + * If omitted, the script's own process ID is used. + * - `Name` = The name of the process without a path: `Notepad.exe` + * If there are multiple processes with that name, the first match is used. + * Names are not case-sensitive. + * - `PID` = The Process ID number of a process. This is not a static value and changes each time the process is launched. + * A PID can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()}, {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|ProcessExist()}, and with {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} using the `&OutputPID` parameter. + * This is different from a Window ID (HWND) that uniquely identifies a Window or control. + * @returns {(Integer)} + * The Process ID of the specified process. + * `0` if the process cannot be found or altered. + * @throws TargetError - The process could not be found + * @throws OSError - The path could not be retrieved + * @see {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} + * @example + */ +ProcessSetPriority(Level [,PIDOrName]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ProcessWait.htm|`ProcessWait()`} + * Waits for the specified process to exist. + * @param {(String|Integer)} [NameOrPID] + * The process name or process ID to set the priority of. + * If omitted, the script's own process ID is used. + * - `Name` = The name of the process without a path: `Notepad.exe` + * If there are multiple processes with that name, the first match is used. + * Names are not case-sensitive. + * - `PID` = The Process ID number of a process. This is not a static value and changes each time the process is launched. + * A PID can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()}, {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|ProcessExist()}, and with {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} using the `&OutputPID` parameter. + * This is different from a Window ID (HWND) that uniquely identifies a Window or control. + * @param {(Number)} Timeout + * The number of seconds to wait for the process to exist. + * This number can be a float for higher precision. + * If omitted, the function waits indefinitely. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|Process ID} when the process is detected. + * `0` if the function times out. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ProcessWaitClose.htm|ProcessWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} + * @example + */ +ProcessWait(PIDOrName [,Timeout]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ProcessWaitClose.htm|`ProcessWaitClose()`} + * Waits for all matching processes to close. + * @param {(String|Integer)} [NameOrPID] + * The process names or process ID to wait for closure. + * If omitted, the script's own process ID is used. + * - `Name` = The name of the process without a path: `Notepad.exe` + * If there are multiple processes with that name, the first match is used. + * Names are not case-sensitive. + * - `PID` = The Process ID number of a process. This is not a static value and changes each time the process is launched. + * A PID can be gotten with {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()}, {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|ProcessExist()}, and with {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} using the `&OutputPID` parameter. + * This is different from a Window ID (HWND) that uniquely identifies a Window or control. + * @param {(Number)} Timeout + * The number of seconds to wait for all specified processes to be closed. + * This number can be a float for higher precision. + * If omitted, the function waits indefinitely. + * @returns {(Integer)} + * `0` if all matching processes are closed. + * If a timed out, the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|Process ID} of the first detected remaining process is returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ProcessWait.htm|ProcessWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} + * @example + */ +ProcessWaitClose(PIDOrName [,Timeout]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Random.htm|`Random()`} + * Generates a pseudo-random number. + * @param {(Number)} [Num1] + * Any number. Can be the high or low number. + * If omitted, defaults to `0.0` + * @param {(Number)} [Num2] + * Any number. Can be the high or low number. + * If omitted and `Num1` omitted, this defaults to `1.0`. + * If omitted and `Num1` is a number, this defaults to `0.0`. + * @returns {(Number)} + * A random number that falls between the two given number. + * If `Num1` and `Num2` are integers, an integer is returned. + * Otherwise, a float is returned. + * @example + */ +Random([Num1:=0.0, Num2:1.0]) => Number + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm|`RegExMatch()`} + * Determines whether a string contains a pattern (regular expression). + * @param {(String)} Haystack + * The string to search through. This can contain binary zero. + * @param {(String)} RegExNeedle + * A RegEx pattern with options. + * To use {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#Options|Options}, include them before the pattern: `options)pattern` + * @param {(VarRef)} [MatchObj] + * A variable reference to receive a {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm#MatchObject|RegExMatchInfo object}. + * This object contains the position, length, and values of the full match and all subpattern matches. + * @param {(Integer)} [StartPos] + * The character position number in the string to start the RegEx matching. + * A negative number is considered an offset from the end of string. -1 = last char, -2 = second from last, ... + * `0` starts the RegEx at the very end of the string. + * @returns {(Integer)} + * The position in the string where the first match was found. + * `0` if pattern could not be found. + * @throws Error - Pattern contains a syntax error + * Error format: *Compile error [PCRE ERROR NUMBER] at offset [ERROR POSITION]: description* + * @throws Error - An error occurred during RegEx execution + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegExReplace.htm|RegExReplace()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|SubStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm#RegEx|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/RegExCallout.htm|Regular Expression Callouts} | + * {@link https://www.autohotkey.com/forum/topic16164.html|Global matching/Grep (forum link)} | + * {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm|AHK RegEx Quick Reference} | + * {@link https://regex101.com/|RegEx101.com Tester and Reference Guide} | + * {@link https://www.rexegg.com/regex-quickstart.html/|RegEx Cheat Sheet} | + * {@link https://www.regular-expressions.info/refflavors.html|In-depth RegEx Info} + * - ### RegEx Options: + * Include before the RegEx: `options)RgxPattern` + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_i|`i`} = Case-insensitive matching. a-z = A-Z + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#Multiline|`m`} = Multiline. Evaluate each line individually instead of as one long string. Affects the meaning of `^` and `$` anchors. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_s|`s`} = DotAll. The any character dot `.` matches all characters including newlines and carriage returns. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_x|`x`} = Ignore whitespace except when escaped `\t` or inside a character class `[ ]`. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_A|`A`} = Forces the pattern to be anchored. Similar to forcing `^` + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_D|`D`} = Force dollar-sign ($) to match at end of Haystack, even if Haystack's last item is a newline. + * This is overridden by `m`. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_J|`J`} = Allows duplicate named subpatterns. If multiple matches are found, the leftmost one is stored. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_U|`U`} = Ungreedy (forces `?`). `*`, `?`, `+`, and `{#,#}` consume the least amount of characters. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_extra|`X`} = PCRE_EXTRA. Enables PCRE features. + * With this option, escaped characters that do not **need** to be escaped throw an errors. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#Study|`S`} = Studies the pattern to tries to improve its performance. The more complex the regex pattern, the more beneficial this becomes. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_Callout|`C`} = Enables the auto-callout mode. See {@link https://www.autohotkey.com/docs/v2/misc/RegExCallout.htm#auto|`Regular Expression Callouts`} for more info. + * - `` `n `` {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_esc_n|Esc n} = Causes a solitary linefeed (`n) to be the only recognized newline marker. + * - `` `a `` {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#NEWLINE_ANY|NewlineAny} = Enables recognition of additional newline markers. + * - `` `r `` {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_esc_r|Esc r} = Causes a solitary carriage return (`r) to be the only recognized newline marker. + * + * - ### RegEx Cheat Sheet + * **Meta Sequence** + * - `.` = Any char but newline = `[^\n]` + * - `\s` = White space = `[\r\n\t\f\v ]` + * - `\S` = Not white space = `[^\s]` + * - `\d` = Digit = `[0-9]` + * - `\D` = Not digit = `[^\d]` + * - `\w` = Word = `[a-zA-Z0-9_]` + * - `\W` = Not word = `[^\w]` + * - `\N` = Non-newline char = `[^\n]` + * - `\v` = Vertical whitespace = `[\n\r\f\x0B\x85\x{2028}\x{2029}]` + * - `\V` = Not vertical whitespace = `[^\v]` + * - `\h` = Horizontal whitespace = `[ \t\xA0\x{1680}\x{180E}\x{2000}-\x{200A}\x{202F}\x{205F}\x{3000}]` + * - `\H` = Not horizontal whitespace = `[^\h]` + * - `\X` = Unicode chars = All chars are unicode + * - `\R` = All line break types = `[\r\n|\n|\r|\f|\x0b|\x85]` + * - `\#` = Backreference = Use a capture group number `#` as the next match + * + * **Common** = **Characters** + * - `\n` = Newline = `[\x0A]` + * - `\r` = Carriage return = `[\x0D]` + * - `\t` = Tab = `[\x09]` + * - `\v` = Vertical tab = `[\x0B]` + * - `\f` = Form feed = `[\x0C]` + * - `\b` = Backspace = `[\x08]` + * - `\###` = Octal char, where `#` is a digit + * - `\x##` = Hex ASCII range, where `#` is a digit + * - `\x{####}` = Hex Unicode range, where `#` is a digit + * + * **Quantifiers** = + * - `*` = Matches 0 or more + * - `+` = Matches 1 or more + * - `?` = Matches 0 or 1 + * - `{3}` = Match exactly 3 + * - `{3,}` = Match at least 3 + * - `{0,3}` = Match 0-3 chars + * - Quantifier`?` = Match minimum chars for this quantifier + * - Quantifier`+` = Match maximum chars for this quantifier + * + * **Anchors and Boundaries** + * - `\A` = Start of string + * - `\Z` = End of string + * - `^` = Start of line = Equal to `\A` if no `m` option + * - `$` = End of line = Equal to `\Z` if no `m` option + * - `\b` = Word boundary. Must not be a word class. = `(?=\W)` + * - `\B` = Not word boundary. Must be a word class. = `(?=\w)` + * - `\G` = Start of string or last match + * - `\K` = Drop all matched chars up to this point + + * **Escape Sequence** + * - `\` = Next character is literal + * - `\Q` ... `\E` = All chars between are treated as literal + * + * **Group Constructs** + * - `(?#)` = Comment only = Does not affect matching + * - `()` = Capturing group + * - `(?:)` = Match but do not capture + * - `(?'name')` = Named capturing group + * - `(?)` = Named capturing group + * - `(?P)` = Named capturing group + * - `(this`|`that)` = Capture this OR that + * - `(?>)` = Atomic group = Non-capturing, non-backtracking + * - `(?=)` = Positive lookahead - Verify next matches but do not capture or consume + * - `(?!)` = Negative lookahead - Verify next does not match and do not capture or consume + * - `(?<=)` = Positive lookbehind - Verify previous matches but do not capture or consume + * - `(??@[\]^_{`|`}~]` + * - `[:space:]` = Blank characters = `[ \t\r\n\v\f]` + * - `[:upper:]` = Upper case letters = `[A-Z]` + * - `[:word:]` = Digits, letters, underscore = `[a-zA-Z0-9_]` + * - `[:xdigit:]` = Hexadecimal digits = `[0-9a-fA-F]` + * + * **Replacement** + * - `$$` = Literal dollar sign = Prevent capture group + * - `$#` = Use a captured group number. `$0` = entire match + * - `${name}` - Use a named capture group. + * @example + */ +RegExMatch(Haystack, RegExNeedle [,&MatchObj, StartPos]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegExReplace.htm|`RegExReplace()`} + * Replaces occurrences of a pattern (regular expression) inside a string. + * @param {(String)} Haystack + * The string to search through. This can contain binary zero. + * @param {(String)} RegExNeedle + * A RegEx pattern with options. + * To use {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#Options|Options}, include them before the pattern: `options)pattern` + * @param {(String)} [Replacement] + * The text to replace the matched text with. + * If omitted or an empty string, the match is deleted. + * Back references such as `$1`, `${10}`, and `${SubPatName}` can be used in the replacement text to insert captured subpatterns. + * Subpattern case can be altered by including `U/L/T` (UPPER/lower/Title Case) between the `$` and identifier: `$U1`, `$T{Name}` + * To create a literal dollar sign, use `$$`. + * @param {(VarRef)} [OutputReplaceTotal] + * A variable reference to receive the total number of replacements made. + * `0` if no replacements were made. + * @param {(Integer)} [ReplaceLimit] + * Total amount of replacements to make before stopping. + * If omitted or `-1`, are replacements are made. + * Characters right of the replacement will remain unchanged. + * @param {(Integer)} [StartPos] + * The character position number in the string to start the RegEx matching. + * A negative number is considered an offset from the end of string. -1 = last char, -2 = second from last, ... + * `0` starts the RegEx at the very end of the string. + * @returns {(String)} + * A string containing the updated text from `Haystack`. + * If no replacements are made, the string is identical to `Haystack`. + * @throws Error - Pattern contains a syntax error + * Error format: *Compile error [PCRE ERROR NUMBER] at offset [ERROR POSITION]: description* + * @throws Error - An error occurred during RegEx execution + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm|RegExMatch()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|SubStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm#RegEx|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/RegExCallout.htm|Regular Expression Callouts} | + * {@link https://www.autohotkey.com/forum/topic16164.html|Global matching/Grep (forum link)} | + * {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm|AHK RegEx Quick Reference} | + * {@link https://regex101.com/|RegEx101.com Tester and Reference Guide} | + * {@link https://www.rexegg.com/regex-quickstart.html/|RegEx Cheat Sheet} + * {@link https://www.regular-expressions.info/refflavors.html|In-depth RegEx Info} + * - ## RegEx Options: + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_i|`i`} = Case-insensitive matching. a-z = A-Z + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#Multiline|`m`} = Multiline. Evaluate each line individually instead of as one long string. Affects the meaning of `^` and `$` anchors. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_s|`s`} = DotAll. The any character dot `.` matches all characters including newlines and carriage returns. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_x|`x`} = Ignore whitespace except when escaped `\t` or inside a character class `[ ]`. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_A|`A`} = Forces the pattern to be anchored. Similar to forcing `^` + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_D|`D`} = Force dollar-sign ($) to match at end of Haystack, even if Haystack's last item is a newline. + * This is overridden by `m`. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_J|`J`} = Allows duplicate named subpatterns. If multiple matches are found, the leftmost one is stored. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_U|`U`} = Ungreedy (forces `?`). `*`, `?`, `+`, and `{#,#}` consume the least amount of characters. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_extra|`X`} = PCRE_EXTRA. Enables PCRE features. + * With this option, escaped characters that do not **need** to be escaped throw an errors. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#Study|`S`} = Studies the pattern to tries to improve its performance. The more complex the regex pattern, the more beneficial this becomes. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_Callout|`C`} = Enables the auto-callout mode. See {@link https://www.autohotkey.com/docs/v2/misc/RegExCallout.htm#auto|Regular Expression Callouts} for more info. + * - `` `n `` {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_esc_n|Esc n} = Causes a solitary linefeed (`n) to be the only recognized newline marker. + * - `` `a `` {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#NEWLINE_ANY|NewlineAny} = Enables recognition of additional newline markers. + * - `` `r `` {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm#opt_esc_r|Esc r} = Causes a solitary carriage return (`r) to be the only recognized newline marker. + * - ## RegEx Reference: + * | Token/Construct | Description and equivalent | + * | ---: | :--- | + * | **Meta Sequences** | Unicode past \xFF omitted | + * | `.` | Any character but newlines **[^\n]** | + * | `\s` | White space **[\r\n\t\f\v ]** | + * | `\S` | Not white space **[^\s]** | + * | `\d` | Digit **[0-9]** | + * | `\D` | Not digit **[^\d]** | + * | `\w` | Word **[a-zA-z0-9_]** | + * | `\W` | Not word **[^\w]** | + * | `\N` | Non-newline characters **[^\n]** | + * | `\v` | Vertical whitespace **[\n\r\f\x0B\x85]** | + * | `\V` | Not vertical whitespace **[^\v]** | + * | `\h` | Horizontal whitespace **[ \t\xA0]** | + * | `\H` | Not horizontal whitespace **[^\h]** | + * | `\X` | Unicode characters **[.\n]** | + * | `\R` | All line break types **[\r\n|\r|\n|\f]** | + * | `\#` | Backreference | + * | `\{Name}` | Named backreference | + * | | | + * | **Characters** | | + * | `\n` | Newline | + * | `\r` | Carriage return | + * | `\t` | Tab | + * | `\v` | Vertical tab | + * | `\f` | Form feed | + * | `\###` | Octal char | + * | `\x##` | Hex ASCII range | + * | `\x{########}` | Hex Unicode range | + * | | | + * | **Quantifiers** | | + * | `*` | Match 0 or more | + * | `+` | Match 1 or more | + * | `?` | Match 0 or 1 | + * | `{3}` | Match Exactly 3 | + * | `{3,}` | Match 3 or more | + * | `{0,3}` | Match Between 0 and 3 | + * | Quantifier`?` | Match minimum amount (Lazy) | + * | Quantifier`+` | Match minimum amount (Greedy) | + * | | | + * | **Anchors/Boundaries** | | + * | `\A` | Start of string | + * | `\Z` | End of string | + * | `^` | Start of line | + * | `$` | End of line | + * | `\b` | Word boundary | + * | `\B` | Not word boundary | + * | `\G` | Start or last match | + * | `\K` | Drop all matches up to here | + * | | | + * | **Escape Sequence** | | + * | `\` | Next character is literal | + * | `\Q` ... `\E` | Literal sequence start and end | + * | | | + * | **Group Constructs** | | + * | `()` | Capturing group | + * | `(?:)` | Match but do not capture | + * | `(this`|`that)` | Capture this or that | + * | `(?'name')` | Named capturing group | + * | `(?)` | Named capturing group | + * | `(?P)` | Named capturing group | + * | `(?>)` | Atomic group | + * | `(?=)` | Positive lookahead | + * | `(?!)` | Negative lookahead | + * | `(?<=)` | Positive lookbehind | + * | `(??@[\]^_`{|}~]** | + * | `[:space:]` | Blank characters **[ \t\r\n\v\f]** | + * | `[:upper:]` | Upper case letters **[A-Z]** | + * | `[:word:]` | Word characters **[0-9_a-zA-Z]** | + * | `[:xdigit:]` | Hexadecimal digits **[0-9a-fA-F]** | + * | | | + * | **Replacement** | | + * | `$$` | Literal dollar sign | + * | `$n` | nth capture group | + * | `${#:1:0}` | Conditional group replace | + * @example + */ +RegExReplace(Haystack, RegExNeedle [,Replacement:='', &OutputReplaceTotal, ReplaceLimit:=-1, StartPos:=1]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegCreateKey.htm|`RegCreateKey()`} + * Creates a registry key without writing a value. + * @param {'HKEY_CLASSES_ROOT'|'HKEY_CURRENT_USER'|'HKEY_LOCAL_MACHINE'|'HKEY_USERS'|'HKEY_CURRENT_CONFIG'|'HKCR'|'HKCU'|'HKLM'|'HKU'|'HKCC'} [KeyName] + * Full name of a registry key. + * Must start with: + * - `HKCR` or `HKEY_CLASSES_ROOT` + * - `HKCU` or `HKEY_CURRENT_USER` + * - `HKLM` or `HKEY_LOCAL_MACHINE` + * - `HKU` or `HKEY_USERS` + * - `HKCC` or `HKEY_CURRENT_CONFIG` + * + * A remote registry can be accessed by prefixing the remote name: + * `\\workstation01\HKLM` + * + * KeyName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry}. The current loop item will be used as the KeyName. + * + * Use {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} to set 32-bit or 64-bit mode when working with the registry. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the operating system's {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()} function + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegDelete.htm|RegDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDeleteKey.htm|RegDeleteKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegRead.htm|RegRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegWrite.htm|RegWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry} + * @example + */ +RegCreateKey([KeyName]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegDelete.htm|`RegDelete()`} + * Deletes a value from the registry. + * @param {'HKEY_CLASSES_ROOT'|'HKEY_CURRENT_USER'|'HKEY_LOCAL_MACHINE'|'HKEY_USERS'|'HKEY_CURRENT_CONFIG'|'HKCR'|'HKCU'|'HKLM'|'HKU'|'HKCC'} [KeyName] + * Full name of a registry key. + * Must start with: + * - `HKCR` or `HKEY_CLASSES_ROOT` + * - `HKCU` or `HKEY_CURRENT_USER` + * - `HKLM` or `HKEY_LOCAL_MACHINE` + * - `HKU` or `HKEY_USERS` + * - `HKCC` or `HKEY_CURRENT_CONFIG` + * + * A remote registry can be accessed by prefixing the remote name: + * `\\workstation01\HKLM` + * + * KeyName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry}. The current loop item will be used as the KeyName. + * + * Use {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} to set 32-bit or 64-bit mode when working with the registry. + * @param {(String)} [ValueName] + * Specify the name of the value to delete. + * If omitted, the key's `(Default)` value will be deleted. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the operating system's {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()} function + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegCreateKey.htm|RegCreateKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDeleteKey.htm|RegDeleteKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegRead.htm|RegRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegWrite.htm|RegWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} | + * {@link https://www.autohotkey.com/docs/v2/lib/IniDelete.htm|IniDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry} + * @example + */ +RegDelete([KeyName, K]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegDeleteKey.htm|`RegDeleteKey()`} + * Deletes a subkey from the registry. + * @param {'HKEY_CLASSES_ROOT'|'HKEY_CURRENT_USER'|'HKEY_LOCAL_MACHINE'|'HKEY_USERS'|'HKEY_CURRENT_CONFIG'|'HKCR'|'HKCU'|'HKLM'|'HKU'|'HKCC'} [KeyName] + * Full name of a registry key. + * Must start with: + * - `HKCR` or `HKEY_CLASSES_ROOT` + * - `HKCU` or `HKEY_CURRENT_USER` + * - `HKLM` or `HKEY_LOCAL_MACHINE` + * - `HKU` or `HKEY_USERS` + * - `HKCC` or `HKEY_CURRENT_CONFIG` + * + * A remote registry can be accessed by prefixing the remote name: + * `\\workstation01\HKLM` + * + * KeyName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry}. The current loop item will be used as the KeyName. + * + * Use {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} to set 32-bit or 64-bit mode when working with the registry. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the operating system's {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()} function + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegCreateKey.htm|RegCreateKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDelete.htm|RegDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegRead.htm|RegRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegWrite.htm|RegWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} | + * {@link https://www.autohotkey.com/docs/v2/lib/IniDelete.htm|IniDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry} + * @example + */ +RegDeleteKey([KeyName]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegRead.htm|`RegRead()`} + * Reads a value from the registry. + * @param {'HKEY_CLASSES_ROOT'|'HKEY_CURRENT_USER'|'HKEY_LOCAL_MACHINE'|'HKEY_USERS'|'HKEY_CURRENT_CONFIG'|'HKCR'|'HKCU'|'HKLM'|'HKU'|'HKCC'} [KeyName] + * Full name of a registry key. + * Must start with: + * - `HKCR` or `HKEY_CLASSES_ROOT` + * - `HKCU` or `HKEY_CURRENT_USER` + * - `HKLM` or `HKEY_LOCAL_MACHINE` + * - `HKU` or `HKEY_USERS` + * - `HKCC` or `HKEY_CURRENT_CONFIG` + * + * A remote registry can be accessed by prefixing the remote name: + * `\\workstation01\HKLM` + * + * KeyName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry}. The current loop item will be used as the KeyName. + * + * Use {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} to set 32-bit or 64-bit mode when working with the registry. + * @param {(String)} [ValueName] + * Specify the name of the value to delete. + * If omitted, the key's `(Default)` value will be deleted. + * @param {(Any)} [Default] + * The value to return if a specified key or value doesn't exist. + * If omitted, the script will throw an {@link https://www.autohotkey.com/docs/v2/lib/Error.htm#OSError|OSError}. + * @returns {(Primitive)} + * The value retrieved from the registry key. + * @throws OSError - Thrown on failure such as a permission error + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} is set to the result of the operating system's {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()} function + * @throws OSError - Key does not exist + * @throws OSError - Key's value does not exist and no `Default` parameter was provided + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegCreateKey.htm|RegCreateKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDelete.htm|RegDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDeleteKey.htm|RegDeleteKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegWrite.htm|RegWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} | + * {@link https://www.autohotkey.com/docs/v2/lib/IniRead.htm|IniRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry} + * @example + */ +RegRead([KeyName, ValueName, Default]) => Primitive + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RegWrite.htm|`RegWrite()`} + * Writes a value to the registry. + * @param {(String|Integer)} Value + * The value to be written. + * @param {'REG_SZ'|'REG_DWORD'|'REG_BINARY'|'REG_EXPAND_SZ'|'REG_MULTI_SZ'} [ValueType] + * A registry value type: + * - `REG_SZ` = A null-terminated unicode or ANSI string + * - `REG_DWORD` = A 32-bit number + * - `REG_BINARY` = Binary data + * - `REG_EXPAND_SZ` = A null-terminated unicode or ANSI string that contains unexpanded references to environment variables + * - `REG_MULTI_SZ` = A sequence of null-terminated strings, ending with an empty string + * + * Can be omitted if `KeyName` is omitted (inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry}) + * @param {'HKEY_CLASSES_ROOT'|'HKEY_CURRENT_USER'|'HKEY_LOCAL_MACHINE'|'HKEY_USERS'|'HKEY_CURRENT_CONFIG'|'HKCR'|'HKCU'|'HKLM'|'HKU'|'HKCC'} [KeyName] + * Full name of a registry key. + * Must start with: + * - `HKCR` or `HKEY_CLASSES_ROOT` + * - `HKCU` or `HKEY_CURRENT_USER` + * - `HKLM` or `HKEY_LOCAL_MACHINE` + * - `HKU` or `HKEY_USERS` + * - `HKCC` or `HKEY_CURRENT_CONFIG` + * + * A remote registry can be accessed by prefixing the remote name: + * `\\workstation01\HKLM` + * + * KeyName can be omitted if inside a {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry}. The current loop item will be used as the KeyName. + * + * Use {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} to set 32-bit or 64-bit mode when working with the registry. + * @param {(String)} [ValueName] + * Specify the name of the value to write. + * If omitted, the key's `(Default)` value will be used. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegCreateKey.htm|RegCreateKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDelete.htm|RegDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDeleteKey.htm|RegDeleteKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegRead.htm|RegRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} | + * {@link https://www.autohotkey.com/docs/v2/lib/IniWrite.htm|IniWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry} + * @example + */ +RegWrite(Value [,ValueType, KeyName, ValueName]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Reload.htm|`Reload()`} + * Closes the currently running instance of the script and launches a new instance. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Edit.htm|Edit()} + * @example + */ +Reload() => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Round|`Round()`} + * Returns the specified number rounded to N decimal places. + * @param {(Number)} Num + * The number to round. + * @param {(Integer)} [Precision] + * The amount of places to round + * - Positive = Number of decimal places to round to + * + * Round(42.454545, 3) => '42.455' + * - Negative = Number of integer places to round to + * + * Round(42.454545, -1) => 40 + * - Omit = Round to nearest integer + * + * Round(42.454545) => 42 + * @returns {(Integer|String)} + * Rounded value is a String if rounding to a certain amount of decimal places. + * Otherwise, the value is an integer. + * @example + */ +Round(Num [,Precision]) => Primitive + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Trim.htm|`RTrim()`} + * Trims characters from the end of a string. + * @param {(String)} Str + * The string to trim. + * @param {'`n'|'`r'|'`r`n'|'`t'|' '|'`n`r`t '|String} [OmitChars] + * The characters to trim off. + * These characters are case-sensitive. + * If omitted, space and tab are used. + * @returns {(String)} + * The string after being trimmed. + * @example + */ +RTrim(Str [,OmitChars:=' `t']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|`Run()`} + * Runs an external program. + * @param {(String)} Target + * The file, executable, URL, or other item to run along with any optional switches or parameters. + * @param {(String)} [WorkingDir] + * The initial working directory to be used by the new process. + * If blank or omitted, {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir} is used. + * @param {'Max'|'Min'|'Hide'} [LaunchOpt] + * - Omitted or Empty String = Launch normally + * - `Max` = Launch in maximized state + * - `Min` = Launch in minimized state + * - `Hide` = Launch with window hidden + * @param {(VarRef)} [OutputPID] + * A variable reference to receive the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|Process ID} of the launched executable. + * An empty string is used if the PID can't be determined. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - Target cannot be launched. + * Use a {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try}/{@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} to prevent this. + * @see {@link https://www.autohotkey.com/docs/v2/lib/RunAs.htm|RunAs()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Exit.htm|Exit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/misc/CLSID-List.htm|CLSID List} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} + * @example + */ +Run(Target [,WorkingDir:=A_WorkingDir, LaunchOpt:='', &OutputPID]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/RunAs.htm|`RunAs()`} + * Specifies a set of user credentials to use for all subsequent {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} and {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|RunWait()} functions. + * Omit all parameters to disable RunAs() credentials. + * @param {(String)} [User] + * The username used to create the new process. + * @param {(String)} [Password] + * The password for User. + * If omitted, an empty string is used. + * @param {(String)} [Domain] + * The User's domain. + * `@ComputerName` may also work. + * If omitted or an empty string, local count will be used. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|`Run()`} | + * {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|`RunWait()`} + * @example + */ +RunAs([User, Password, Domain]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|`RunWait()`} + * Runs an external program and waits until it finishes. + * @param {(String)} Target + * The file, executable, URL, or other item to run along with any optional switches or parameters. + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#ComSpec|ComSpec} can be used as a shortcut to the command line (cmd.exe). + * System verbs can be used to open files. These are similar to what's found in a file's right click menu. + * - `*verb` = System defined verbs, such as {@link https://www.autohotkey.com/docs/v2/lib/Run.htm#RunAs|*RunAs}. + * + * Run('*RunAs notepad.exe') + * - `properties` = Display the item's {@link https://i.imgur.com/E6botq0.png|"Properties" window}. + * + * Run('Properties notepad.exe') + * - `find` = Open an {@link https://i.imgur.com/ybcIkAb.png|Explorer search window} at the specified path. + * + * Run('find D:\') + * - `explore` = Open an instance of Explorer at the specified path. + * + * Run('explore D:\Scripts') + * - `edit` = Open a file using the assigned program in the file's edit registry key. + * + * Run('edit test_script.ahk') + * - `open` = Opens the specified target. This is the default verb for most file types. + * + * Run('open notepad.exe) + * - `print` = Prints the indicated file with the associated application. + * + * Run('print D:\receipts\amazon20231210.pdf') + * @param {(String)} [WorkingDir] + * The initial working directory to be used by the new process. + * If blank or omitted, {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir} is used. + * @param {'Max'|'Min'|'Hide'} [LaunchOpt] + * - Omit or Empty String = Launch normally + * - `Max` = Launch in maximized state + * - `Min` = Launch in minimized state + * - `Hide` = Launch with window hidden + * @param {(VarRef)} [OutputPID] + * A variable reference to receive the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|Process ID} of the launched executable. + * An empty string is used if the PID can't be determined. + * @returns {(Integer)} + * The program's exit code. + * Some programs will immediately launch another process and then close. + * This will cause RunWait() to return even though the program is still running. + * @throws Error - Target cannot be launched. + * Use a {@link https://www.autohotkey.com/docs/v2/lib/Try.htm|Try}/{@link https://www.autohotkey.com/docs/v2/lib/Catch.htm|Catch} to prevent this. + * @see {@link https://www.autohotkey.com/docs/v2/lib/RunAs.htm|RunAs()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Exit.htm|Exit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/misc/CLSID-List.htm|CLSID List} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} + * @example + */ +RunWait(Target [,WorkingDir:=A_WorkingDir, LaunchOpt:='', &OutputPID]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|`Send()`} + * Transmits keystrokes to the system. + * Send is an alias for {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInputDetail|SendInput()} by default. + * It can be changed to {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendEvent|SendEvent()} or {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlayDetail|SendPlay()} by using {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()}. + * @param {String|'{Raw}'|'{Text}'|'{Blind}'|'{!}'|'{#}'|'{+}'|'{^}'|'{{}'|'{}}'|'{Alt}'|'{AppsKey}'|'{Backspace}'|'{Browser_Back}'|'{Browser_Favorites}'|'{Browser_Forward}'|'{Browser_Home}'|'{Browser_Refresh}'|'{Browser_Search}'|'{Browser_Stop}'|'{CapsLock}'|'{Click}'|'{Control}'|'{Ctrl}'|'{CtrlBreak}'|'{Delete}'|'{Down}'|'{End}'|'{Enter}'|'{Escape}'|'{F1}'|'{F10}'|'{F11}'|'{F12}'|'{F13}'|'{F14}'|'{F15}'|'{F16}'|'{F17}'|'{F18}'|'{F19}'|'{F2}'|'{F20}'|'{F21}'|'{F22}'|'{F23}'|'{F24}'|'{F3}'|'{F4}'|'{F5}'|'{F6}'|'{F7}'|'{F8}'|'{F9}'|'{Help}'|'{Home}'|'{Insert}'|'{LAlt}'|'{Launch_App1}'|'{Launch_App2}'|'{Launch_Mail}'|'{Launch_Media}'|'{LButton}'|'{LControl}'|'{LCtrl}'|'{Left}'|'{LShift}'|'{LWin}'|'{MButton}'|'{Media_Next}'|'{Media_Play_Pause}'|'{Media_Prev}'|'{Media_Stop}'|'{NumLock}'|'{Numpad0}'|'{Numpad1}'|'{Numpad2}'|'{Numpad3}'|'{Numpad4}'|'{Numpad5}'|'{Numpad6}'|'{Numpad7}'|'{Numpad8}'|'{Numpad9}'|'{NumpadAdd}'|'{NumpadClear}'|'{NumpadDel}'|'{NumpadDiv}'|'{NumpadDot}'|'{NumpadDown}'|'{NumpadEnd}'|'{NumpadEnter}'|'{NumpadHome}'|'{NumpadIns}'|'{NumpadLeft}'|'{NumpadMult}'|'{NumpadPgDn}'|'{NumpadPgUp}'|'{NumpadRight}'|'{NumpadSub}'|'{NumpadUp}'|'{Pause}'|'{PgDn}'|'{PgUp}'|'{PrintScreen}'|'{RAlt}'|'{RButton}'|'{RControl}'|'{RCtrl}'|'{Right}'|'{RShift}'|'{RWin }'|'{SC###}'|'{ScrollLock}'|'{Shift}'|'{Sleep}'|'{Space}'|'{Tab}'|'{U+####}'|'{ASC+####}'|'{Up}'|'{VK##}'|'{VK##SC###}'|'{Volume_Down}'|'{Volume_Mute}'|'{Volume_Up}'|'{WheelDown}'|'{WheelLeft}'|'{WheelRight}'|'{WheelUp}'|'{XButton1}'|'{XButton2}'} KeySend + * Sequence of keys to send. + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#keynames|Key names}, literal {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|modifier symbols}, and literal curly braces must be wrapped in curly braces: `{!} {#} {+} {^} {{} {}}` + * Using braces forces the key to be sent by virtual keycode, even if the character does not exist on the current keyboard layout. + * Single character keys do not need to be wrapped and will be sent regardless of keyboard layout. + * + * Send('AHK{!}') + * - {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|**Modifier Key Symbols**}: Modifier is included with next key + * - `!` = Alt: `Send('!{F4}')` ; 'Alt+F4 - Close Window' + * - `^` = Control: `Send('^c')` ; 'Ctrl+c Copy' + * - `+` = Shift: `Send('+a')` ; 'Shift+a Select all' + * - `#` = Windows key: `Send('#d')` ; 'Win+d Show Desktop' + * + * - {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|**Escape Sequences**} `` ` ``: + * - ``` `` ``` = Literal grave accent. + * - `` `; `` = Literal semicolon (prevents comment). + * - `` `n `` = Newline + * - `` `r `` = Carriage Return + * - `` `t `` = Tab + * - `` `s `` = Space + * - `` `' ``|`` `" `` = Literal quotes (prevents end of string) + * + * - {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Special_modes|**Special modes**}: Must be the first part of the string + * - [`{Blind}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Blind) + * Modifier key release is not done if key is not in the down state. + * Physically held modifier keys are included with the keys. + * Blind can be used with Raw and Text modes + * {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|SetStoreCapsLockMode()} is ignored and {@link https://www.autohotkey.com/docs/v2/lib/A_MenuMaskKey.htm|menu masking} is disabled. + * - [`{Raw}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Raw) + * Special characters such as `^+!#{}` are all sent as literal characters instead of their special meaning. + * Raw does not affect {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|escape sequences}. + * + * Send('{Raw}+{Enter}') => '+{Enter}' ; Instead of Shift+Enter + * - [`{Text}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Text) is similar to {Raw} except characters don't get translated to key codes, other than the ones listed below: + * - `` `r ``, `` `n ``, and `` `r`n `` = `Enter` keystroke + * - `` `t `` = `Tab` keystroke + * - `` `b `` = `Backspace` keystroke + * + * ### {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Repeating_or_Holding_Down_a_Key|**Hold, Release, and Repeat**} + * - `{Key Down}`/`{Key Up}` = Puts key in a logical down (held) or up (released) state. + * + * Send('{Shift Down}s{Shift Up}') => 'shift+s' + * = `{Key #}` = The number of times to send the key. + * + * Send('{z 3}') => 'zzz' + * - `{ModKey DownTemp}` = Same as `Down` state. + * However, modifier keys being held by this will be released at the next {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|Send function} call. + * - `{ModKey DownR}` = Works the same as `DownTemp`. + * However, the modifier key resumes being held after the {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|Send function} call. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|SetStoreCapsLockMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|BlockInput()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|WinActivate()} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstrings::} | + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape sequences} + * @example + */ +Send(KeySend) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendEvent|`SendEvent()`} + * Transmits keystrokes to the system via the {@link https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-keybd_event|keybd_event function}. + * While {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInputDetail|SendInput()} and {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlayDetail|SendPlay()} are generally faster and more reliable, SendEvent() has some unique benefits. + * There are situations where SendEvent() will work when SendInput()/SendPlay() fail. + * SendEvent() can make use of {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} to define key press duration and delay between keystrokes, eliminating the need to add Sleep() between keystroke events. + * @param {String|'{Raw}'|'{Text}'|'{Blind}'|'{!}'|'{#}'|'{+}'|'{^}'|'{{}'|'{}}'|'{Alt}'|'{AppsKey}'|'{Backspace}'|'{Browser_Back}'|'{Browser_Favorites}'|'{Browser_Forward}'|'{Browser_Home}'|'{Browser_Refresh}'|'{Browser_Search}'|'{Browser_Stop}'|'{CapsLock}'|'{Click}'|'{Control}'|'{Ctrl}'|'{CtrlBreak}'|'{Delete}'|'{Down}'|'{End}'|'{Enter}'|'{Escape}'|'{F1}'|'{F10}'|'{F11}'|'{F12}'|'{F13}'|'{F14}'|'{F15}'|'{F16}'|'{F17}'|'{F18}'|'{F19}'|'{F2}'|'{F20}'|'{F21}'|'{F22}'|'{F23}'|'{F24}'|'{F3}'|'{F4}'|'{F5}'|'{F6}'|'{F7}'|'{F8}'|'{F9}'|'{Help}'|'{Home}'|'{Insert}'|'{LAlt}'|'{Launch_App1}'|'{Launch_App2}'|'{Launch_Mail}'|'{Launch_Media}'|'{LButton}'|'{LControl}'|'{LCtrl}'|'{Left}'|'{LShift}'|'{LWin}'|'{MButton}'|'{Media_Next}'|'{Media_Play_Pause}'|'{Media_Prev}'|'{Media_Stop}'|'{NumLock}'|'{Numpad0}'|'{Numpad1}'|'{Numpad2}'|'{Numpad3}'|'{Numpad4}'|'{Numpad5}'|'{Numpad6}'|'{Numpad7}'|'{Numpad8}'|'{Numpad9}'|'{NumpadAdd}'|'{NumpadClear}'|'{NumpadDel}'|'{NumpadDiv}'|'{NumpadDot}'|'{NumpadDown}'|'{NumpadEnd}'|'{NumpadEnter}'|'{NumpadHome}'|'{NumpadIns}'|'{NumpadLeft}'|'{NumpadMult}'|'{NumpadPgDn}'|'{NumpadPgUp}'|'{NumpadRight}'|'{NumpadSub}'|'{NumpadUp}'|'{Pause}'|'{PgDn}'|'{PgUp}'|'{PrintScreen}'|'{RAlt}'|'{RButton}'|'{RControl}'|'{RCtrl}'|'{Right}'|'{RShift}'|'{RWin }'|'{SC###}'|'{ScrollLock}'|'{Shift}'|'{Sleep}'|'{Space}'|'{Tab}'|'{U+####}'|'{ASC+####}'|'{Up}'|'{VK##}'|'{VK##SC###}'|'{Volume_Down}'|'{Volume_Mute}'|'{Volume_Up}'|'{WheelDown}'|'{WheelLeft}'|'{WheelRight}'|'{WheelUp}'|'{XButton1}'|'{XButton2}'} KeySend + * Sequence of keys to send. + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#keynames|Key names}, literal {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|modifier symbols}, and literal curly braces must be wrapped in curly braces: `{!} {#} {+} {^} {{} {}}` + * Using braces forces the key to be sent by virtual keycode, even if the character does not exist on the current keyboard layout. + * Single character keys do not need to be wrapped and will be sent regardless of keyboard layout. + * + * Send('AHK{!}') + * - {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|**Modifier Key Symbols**}: Modifier is included with next key + * - `!` = Alt: `Send('!{F4}')` ; 'Alt+F4 - Close Window' + * - `^` = Control: `Send('^c')` ; 'Ctrl+c Copy' + * - `+` = Shift: `Send('+a')` ; 'Shift+a Select all' + * - `#` = Windows key: `Send('#d')` ; 'Win+d Show Desktop' + * + * - {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|**Escape Sequences**} `` ` ``: + * - ``` `` ``` = Literal grave accent. + * - `` `; `` = Literal semicolon (prevents comment). + * - `` `n `` = Newline + * - `` `r `` = Carriage Return + * - `` `t `` = Tab + * - `` `s `` = Space + * - `` `' ``|`` `" `` = Literal quotes (prevents end of string) + * + * - {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Special_modes|**Special modes**}: Must be the first part of the string + * - [`{Raw}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Raw) + * Special characters such as `^+!#{}` are all sent as literal characters instead of their special meaning. + * Raw does not affect {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|escape sequences}. + * + * Send('{Raw}+{Enter}') => '+{Enter}' ; Instead of Shift+Enter + * - [`{Text}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Text) is similar to {Raw} except characters don't get translated to key codes, other than the ones listed below: + * - `` `r ``, `` `n ``, and `` `r`n `` = `Enter` keystroke + * - `` `t `` = `Tab` keystroke + * - `` `b `` = `Backspace` keystroke + * + * ### {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Repeating_or_Holding_Down_a_Key|**Hold, Release, and Repeat**} + * - `{Key Down}`/`{Key Up}` = Puts key in a logical down (held) or up (released) state. + * + * Send('{Shift Down}s{Shift Up}') => 'shift+s' + * = `{Key #}` = The number of times to send the key. + * + * Send('{z 3}') => 'zzz' + * - `{ModKey DownTemp}` = Same as `Down` state. + * However, modifier keys being held by this will be released at the next {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|Send function} call. + * - `{ModKey DownR}` = Works the same as `DownTemp`. + * However, the modifier key resumes being held after the {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|Send function} call. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|SetStoreCapsLockMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|BlockInput()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|WinActivate()} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstrings::} | + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape sequences} + * @example + */ +SendEvent(KeySend) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInput|`SendInput()`} + * Is the preferred method to transmit keystrokes to the system. + * Unlike {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendEvent|SendEvent()}, SendInput() buffers (stores) keyboard and mouse actions until sending finishes, preventing interruption during the send. + * All buffered key strokes and mouse actions are sent after SendInput() finishes. + * SendInput() has a limit of roughly ~5000 characters per send. + * @param {String|'{Raw}'|'{Text}'|'{Blind}'|'{!}'|'{#}'|'{+}'|'{^}'|'{{}'|'{}}'|'{Alt}'|'{AppsKey}'|'{Backspace}'|'{Browser_Back}'|'{Browser_Favorites}'|'{Browser_Forward}'|'{Browser_Home}'|'{Browser_Refresh}'|'{Browser_Search}'|'{Browser_Stop}'|'{CapsLock}'|'{Click}'|'{Control}'|'{Ctrl}'|'{CtrlBreak}'|'{Delete}'|'{Down}'|'{End}'|'{Enter}'|'{Escape}'|'{F1}'|'{F10}'|'{F11}'|'{F12}'|'{F13}'|'{F14}'|'{F15}'|'{F16}'|'{F17}'|'{F18}'|'{F19}'|'{F2}'|'{F20}'|'{F21}'|'{F22}'|'{F23}'|'{F24}'|'{F3}'|'{F4}'|'{F5}'|'{F6}'|'{F7}'|'{F8}'|'{F9}'|'{Help}'|'{Home}'|'{Insert}'|'{LAlt}'|'{Launch_App1}'|'{Launch_App2}'|'{Launch_Mail}'|'{Launch_Media}'|'{LButton}'|'{LControl}'|'{LCtrl}'|'{Left}'|'{LShift}'|'{LWin}'|'{MButton}'|'{Media_Next}'|'{Media_Play_Pause}'|'{Media_Prev}'|'{Media_Stop}'|'{NumLock}'|'{Numpad0}'|'{Numpad1}'|'{Numpad2}'|'{Numpad3}'|'{Numpad4}'|'{Numpad5}'|'{Numpad6}'|'{Numpad7}'|'{Numpad8}'|'{Numpad9}'|'{NumpadAdd}'|'{NumpadClear}'|'{NumpadDel}'|'{NumpadDiv}'|'{NumpadDot}'|'{NumpadDown}'|'{NumpadEnd}'|'{NumpadEnter}'|'{NumpadHome}'|'{NumpadIns}'|'{NumpadLeft}'|'{NumpadMult}'|'{NumpadPgDn}'|'{NumpadPgUp}'|'{NumpadRight}'|'{NumpadSub}'|'{NumpadUp}'|'{Pause}'|'{PgDn}'|'{PgUp}'|'{PrintScreen}'|'{RAlt}'|'{RButton}'|'{RControl}'|'{RCtrl}'|'{Right}'|'{RShift}'|'{RWin }'|'{SC###}'|'{ScrollLock}'|'{Shift}'|'{Sleep}'|'{Space}'|'{Tab}'|'{U+####}'|'{ASC+####}'|'{Up}'|'{VK##}'|'{VK##SC###}'|'{Volume_Down}'|'{Volume_Mute}'|'{Volume_Up}'|'{WheelDown}'|'{WheelLeft}'|'{WheelRight}'|'{WheelUp}'|'{XButton1}'|'{XButton2}'} KeySend + * Sequence of keys to send. + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#keynames|Key names}, literal {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|modifier symbols}, and literal curly braces must be wrapped in curly braces: `{!} {#} {+} {^} {{} {}}` + * Using braces forces the key to be sent by virtual keycode, even if the character does not exist on the current keyboard layout. + * Single character keys do not need to be wrapped and will be sent regardless of keyboard layout. + * + * Send('AHK{!}') + * - {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|**Modifier Key Symbols**}: Modifier is included with next key + * - `!` = Alt: `Send('!{F4}')` ; 'Alt+F4 - Close Window' + * - `^` = Control: `Send('^c')` ; 'Ctrl+c Copy' + * - `+` = Shift: `Send('+a')` ; 'Shift+a Select all' + * - `#` = Windows key: `Send('#d')` ; 'Win+d Show Desktop' + * + * - {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|**Escape Sequences**} `` ` ``: + * - ``` `` ``` = Literal grave accent. + * - `` `; `` = Literal semicolon (prevents comment). + * - `` `n `` = Newline + * - `` `r `` = Carriage Return + * - `` `t `` = Tab + * - `` `s `` = Space + * - `` `' ``|`` `" `` = Literal quotes (prevents end of string) + * + * - {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Special_modes|**Special modes**}: Must be the first part of the string + * - [`{Raw}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Raw) + * Special characters such as `^+!#{}` are all sent as literal characters instead of their special meaning. + * Raw does not affect {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|escape sequences}. + * + * Send('{Raw}+{Enter}') => '+{Enter}' ; Instead of Shift+Enter + * - [`{Text}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Text) is similar to {Raw} except characters don't get translated to key codes, other than the ones listed below: + * - `` `r ``, `` `n ``, and `` `r`n `` = `Enter` keystroke + * - `` `t `` = `Tab` keystroke + * - `` `b `` = `Backspace` keystroke + * + * ### {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Repeating_or_Holding_Down_a_Key|**Hold, Release, and Repeat**} + * - `{Key Down}`/`{Key Up}` = Puts key in a logical down (held) or up (released) state. + * + * Send('{Shift Down}s{Shift Up}') => 'shift+s' + * = `{Key #}` = The number of times to send the key. + * + * Send('{z 3}') => 'zzz' + * - `{ModKey DownTemp}` = Same as `Down` state. + * However, modifier keys being held by this will be released at the next {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|Send function} call. + * - `{ModKey DownR}` = Works the same as `DownTemp`. + * However, the modifier key resumes being held after the {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|Send function} call. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|SetStoreCapsLockMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|BlockInput()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|WinActivate()} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstrings::} | + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape sequences} + * @example + */ +SendInput(KeySend) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlay|`SendPlay()`} + * Transmits keystrokes to the system in a "play back" manner. + * There are times when SendPlay() works where other send types fail, especially in video games. + * SendPlay() sends keystroke events (messages) directly to the active window, similar to a low level {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} for a Window. + * @param {String|'{Raw}'|'{Text}'|'{Blind}'|'{!}'|'{#}'|'{+}'|'{^}'|'{{}'|'{}}'|'{Alt}'|'{AppsKey}'|'{Backspace}'|'{Browser_Back}'|'{Browser_Favorites}'|'{Browser_Forward}'|'{Browser_Home}'|'{Browser_Refresh}'|'{Browser_Search}'|'{Browser_Stop}'|'{CapsLock}'|'{Click}'|'{Control}'|'{Ctrl}'|'{CtrlBreak}'|'{Delete}'|'{Down}'|'{End}'|'{Enter}'|'{Escape}'|'{F1}'|'{F10}'|'{F11}'|'{F12}'|'{F13}'|'{F14}'|'{F15}'|'{F16}'|'{F17}'|'{F18}'|'{F19}'|'{F2}'|'{F20}'|'{F21}'|'{F22}'|'{F23}'|'{F24}'|'{F3}'|'{F4}'|'{F5}'|'{F6}'|'{F7}'|'{F8}'|'{F9}'|'{Help}'|'{Home}'|'{Insert}'|'{LAlt}'|'{Launch_App1}'|'{Launch_App2}'|'{Launch_Mail}'|'{Launch_Media}'|'{LButton}'|'{LControl}'|'{LCtrl}'|'{Left}'|'{LShift}'|'{LWin}'|'{MButton}'|'{Media_Next}'|'{Media_Play_Pause}'|'{Media_Prev}'|'{Media_Stop}'|'{NumLock}'|'{Numpad0}'|'{Numpad1}'|'{Numpad2}'|'{Numpad3}'|'{Numpad4}'|'{Numpad5}'|'{Numpad6}'|'{Numpad7}'|'{Numpad8}'|'{Numpad9}'|'{NumpadAdd}'|'{NumpadClear}'|'{NumpadDel}'|'{NumpadDiv}'|'{NumpadDot}'|'{NumpadDown}'|'{NumpadEnd}'|'{NumpadEnter}'|'{NumpadHome}'|'{NumpadIns}'|'{NumpadLeft}'|'{NumpadMult}'|'{NumpadPgDn}'|'{NumpadPgUp}'|'{NumpadRight}'|'{NumpadSub}'|'{NumpadUp}'|'{Pause}'|'{PgDn}'|'{PgUp}'|'{PrintScreen}'|'{RAlt}'|'{RButton}'|'{RControl}'|'{RCtrl}'|'{Right}'|'{RShift}'|'{RWin }'|'{SC###}'|'{ScrollLock}'|'{Shift}'|'{Sleep}'|'{Space}'|'{Tab}'|'{U+####}'|'{ASC+####}'|'{Up}'|'{VK##}'|'{VK##SC###}'|'{Volume_Down}'|'{Volume_Mute}'|'{Volume_Up}'|'{WheelDown}'|'{WheelLeft}'|'{WheelRight}'|'{WheelUp}'|'{XButton1}'|'{XButton2}'} KeySend + * Sequence of keys to send. + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#keynames|Key names}, literal {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|modifier symbols}, and literal curly braces must be wrapped in curly braces: `{!} {#} {+} {^} {{} {}}` + * Using braces forces the key to be sent by virtual keycode, even if the character does not exist on the current keyboard layout. + * Single character keys do not need to be wrapped and will be sent regardless of keyboard layout. + * + * Send('AHK{!}') + * - {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|**Modifier Key Symbols**}: Modifier is included with next key + * - `!` = Alt: `Send('!{F4}')` ; 'Alt+F4 Close' + * - `^` = Control: `Send('^c')` ; 'Ctrl+c Copy' + * - `+` = Shift: `Send('+a')` ; 'Shift+a Capitalize' + * - `#` = Windows key: `Send('#d')` ; 'Win+d Show Desktop' + * + * - {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|**Escape Sequences**} `` ` ``: + * - ``` `` ``` = Literal grave accent. + * - `` `; `` = Literal semicolon (prevents comment). + * - `` `n `` = Newline + * - `` `r `` = Carriage Return + * - `` `t `` = Tab + * - `` `s `` = Space + * - `` `' ``|`` `" `` = Literal quotes (prevents end of string) + * + * - {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Special_modes|**Special modes**}: Must be the first part of the string + * - [`{Raw}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Raw) + * Special characters such as `^+!#{}` are all sent as literal characters instead of their special meaning. + * Raw does not affect {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|escape sequences}. + * + * Send('{Raw}+{Enter}') => '+{Enter}' ; Instead of Shift+Enter + * - [`{Text}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Text) is similar to {Raw} except characters don't get translated to key codes, other than the ones listed below: + * - `` `r ``, `` `n ``, and `` `r`n `` = `Enter` keystroke + * - `` `t `` = `Tab` keystroke + * - `` `b `` = `Backspace` keystroke + * + * ### {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Repeating_or_Holding_Down_a_Key|**Hold, Release, and Repeat**} + * - `{Key Down}`/`{Key Up}` = Puts key in a logical down (held) or up (released) state. + * + * Send('{Shift Down}s{Shift Up}') => 'shift+s' + * = `{Key #}` = The number of times to send the key. + * + * Send('{z 3}') => 'zzz' + * - `{ModKey DownTemp}` = Same as `Down` state. + * However, modifier keys being held by this will be released at the next {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|Send function} call. + * - `{ModKey DownR}` = Works the same as `DownTemp`. + * However, the modifier key resumes being held after the {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#modifierkeys|Send function} call. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|SetStoreCapsLockMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|BlockInput()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|WinActivate()} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstrings::} | + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape sequences} + * @example + */ +SendPlay(KeySend) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendText|`SendText()`} + * Transmits keys to the system using [`{Text}` mode](https://www.autohotkey.com/docs/v2/lib/Send.htm#Text). + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape Sequences} are respected. + * @param {(String)} KeySend + * Sequence of keys to send. + * - {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|**Escape Sequences**} `` ` ``: + * - ``` `` ``` = Literal grave accent. + * - `` `; `` = Literal semicolon (prevents comment). + * - `` `n `` = Newline + * - `` `r `` = Carriage Return + * - `` `t `` = Tab + * - `` `s `` = Space + * - `` `' `` `` `" `` = Literal quotes (prevents end of string) + * + * - {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Special_modes|**Special modes**}: Must be the first part of the string + * - [`{Blind}`](https://www.autohotkey.com/docs/v2/lib/Send.htm#Blind) + * Modifier key release is not done if key is not in the down state. + * Physically held modifier keys are included with the keys. + * {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|SetStoreCapsLockMode()} is ignored and {@link https://www.autohotkey.com/docs/v2/lib/A_MenuMaskKey.htm|menu masking} is disabled. + * + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|SetStoreCapsLockMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/BlockInput.htm|BlockInput()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|WinActivate()} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstrings::} | + * {@link https://www.autohotkey.com/docs/v2/misc/EscapeChar.htm|Escape sequences} + * @example + */ +SendText(KeySend) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SendLevel.htm|`SendLevel()`} + * Controls which artificial keyboard and mouse events are ignored by hotkeys and hotstrings. + * @param {(Integer)} Level + * A number `0` and `100`. + * Default is `0`. + * @returns {(Integer)} + * The previous level is returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()} | + * {@link https://www.autohotkey.com/docs/v2/lib/_InputLevel.htm|#InputLevel} + * @example */ -SplitPath(Path [, &OutFileName: VarRef, &OutDir: VarRef, &OutExtension: VarRef, &OutNameNoExt: VarRef, &OutDrive: VarRef]) => void +SendLevel(Level) => Integer /** - * Returns the square root of Number. + * @description {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|`SendMessage()`} + * Sends a message to a window or control and waits for acknowledgement. + * @param {(Integer)} MsgNumber + * The {@link https://www.autohotkey.com/docs/v2/misc/SendMessageList.htm|message number} to send. + * @param {(Integer)} [wParam] + * Word Param. Used to pass message-specific information and must be an integer. + * If omitted, defaults to `0`. + * @param {(Integer)} [lParam] + * Long Param. Also used to pass message-specific information and must be an integer. + * If omitted, defaults to `0`. + * @param {(String|Integer|Object)} [Control] + * A control's ClassNN, Text, HWND (handle), or an object with an HWND property. See {@link https://www.autohotkey.com/docs/v2/lib/Control.htm#Parameter|Control Parameter}. + * If omitted, the target window is used instead of a control. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @param {(Integer)} [Timeout] + * Specify the maximum time, in milliseconds, to wait for the message to be processed. + * Defaults to `5000`. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window or control could not be found + * @throws TimeoutError - Message was not processed in the specified time + * @throws OSError - Message could not be posted + * @see {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm|OnMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MenuSelect.htm|MenuSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage()} | + * {@link https://www.autohotkey.com/docs/v2/misc/SendMessageList.htm|Message List} | + * {@link https://www.autohotkey.com/docs/v2/misc/SendMessage.htm|Message Tutorial} | + * {@link https://www.autohotkey.com/docs/v2/misc/Winamp.htm|Automating Winamp} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +SendMessage(MsgNumber [,wParam:=0, lParam:=0, Control:=TargetWindow, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='', Timeout:=5000]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|`SendMode()`} + * Changes the send type used by {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()}. + * Also affects {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()}, {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()}, {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()}, and {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()}. + * The default type is {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInputDetail|SendInput()}. + * @param {'Event'|'Input'|'Play'|'InputThenPlay'} Mode + * - `Event` = Use SendEvent() for sending. + * - `Input` = Use SendInput() for sending. + * - `Play` = Use SendPlay() for sending. + * - `InputThenPlay` = Same as `Input` but uses `Play` as the {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInputUnavail|unavailable fallback method} instead of `Event`. + * @returns {(String)} + * The previous setting: + * - `Event` + * - `Input` + * - `Play` + * - `InputThenPlay` + * @see {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()} + * @example */ -Sqrt(Number) => Float +SendMode(Mode) => String /** - * Get the text of the standard status bar control. + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetNumScrollCapsLockState.htm|`SetCapsLockState()`} + * Sets the toggle state of CapsLock. + * Can also permanently enable or disable the key state. + * @param {'On'|'Off'|'AlwaysOn'|'AlwaysOff'} [State] + * - Omit or Empty String = Disables the `AlwaysOn` and `AlwaysOff` options. + * - `1` `On` = Set CapsLock toggle to on and disable `AlwaysOn` and `AlwaysOff` options. + * - `0` `Off` = Set CapsLock toggle to off and disables `AlwaysOn` and `AlwaysOff` options. + * - `AlwaysOn` = Set CapsLock toggle to on and prevents it from being turned off. + * - `AlwaysOff` = Set CapsLock toggle to off and prevents it from being turned on. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|`SetStoreCapsLockMode()`} | + * {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|`GetKeyState()`} + * @example + */ +SetCapsLockState([State]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|`SetControlDelay()`} + * Sets the amount of time to wait after each control-modifying function. + * @param {(Integer)} Delay + * - Number = Time to wait, in milliseconds. + * - `0` = Minimum possible delay. + * - `-1` = No delay. + * @returns {(Integer)} + * The previous delay is returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetWinDelay.htm|SetWinDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} + * @example */ -StatusBarGetText(Part := 1 [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => String +SetControlDelay(Delay) => Integer /** - * Wait until the status bar of the window contains the specified string. + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetDefaultMouseSpeed.htm|`SetDefaultMouseSpeed()`} + * Sets the mouse speed that will be used if unspecified in Click, MouseMove, MouseClick, and MouseClickDrag. + * @param {(Integer)} Speed + * The speed to set mouse movement. + * Speed should be between `0` (instant) and `100` (slowest). + * Default is 2. + * @returns {(Integer)} + * The previous speed is returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetWinDelay.htm|SetWinDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} + * @example */ -StatusBarWait([BarText, Timeout, Part, WinTitle, WinText, Interval, ExcludeTitle, ExcludeText]) => Integer +SetDefaultMouseSpeed(Speed) => Integer /** - * Compare two strings in alphabetical order. - * @param CaseSense One of the following values (if omitted, the default is 0): - * - * "On" or 1(True): The comparison is case sensitive. - * - * "Off" or 0(False): The letters A-Z are considered the same as their lowercase letters. - * - * "Locale": According to the current user's locale rules, the comparison is case-insensitive. For example, in most English and Western European regions, not only AZ is considered equivalent to their lowercase form, but also non-ASCII letters (Such as Ä and Ü) are considered equivalent. Depending on the nature of the string being compared, Locale is 1 to 8 times slower than Off. - * - * "Logical": Similar to Locale, but the numbers in the string are treated as digital content, not text. For example, "A2" is considered smaller than "A10". However, if the two numbers differ only by the presence of leading zeros , Then a string with leading zeros may be considered smaller than another string. The exact behavior may vary in different operating system versions. + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|`SetKeyDelay()`} + * Sets the hold time and delay between keystrokes for {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} and {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} keystrokes. + * @param {(Integer)} [KeyDelay] + * The amount of time between each keystroke. + * Default is 10 for SendEvent() and -1 for SendPlay(). + * - Omit = KeyDelay is not changed. + * - Number = Time before next keystroke is sent, in milliseconds. + * - `-1` = No delay before sending. + * - `0` = Smallest possible delay before sending. + * + * Due to the granularity of the OS time-keeping system, KeyDelay might be rounded to the nearest multiple of 10 or 15. + * @param {(Integer)} [HoldTime] + * The amount of time the keystroke is held down. + * Default is -1 for both SendEvent() and SendPlay(). + * - Omit = HoldTime is not changed. + * - Number = Time, in milliseconds, to hold key down before releasing. + * - `-1` = No delay before releasing. + * - `0` = Smallest possible delay before releasing. + * + * Due to the granularity of the OS time-keeping system, HoldTime might be rounded to the nearest multiple of 10 or 15. + * @param {'Play'} [Play] + * - `Play` = Settings apply to {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlayDetail|SendPlay() mode}. + * - Omit or Empty String = Settings apply to {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendEvent() mode}. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetWinDelay.htm|SetWinDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} + * @example + */ +SetKeyDelay([KeyDelay:=unset, HoldTime:=unset, Play:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|`SetMouseDelay()`} + * Sets the delay that will occur after each mouse movement or click. + * @param {(Integer)} [Delay] + * The amount of time between each mouse event. + * Default is 10 for SendEvent() and -1 for SendPlay(). + * - Omit = KeyDelay is not changed. + * - Number = Time, in milliseconds, before the next keystroke is sent. + * - `-1` = No delay before sending. + * - `0` = Smallest possible delay before sending. + * If `Play` parameter is set, 0 is the same as -1. + * + * Due to the granularity of the OS time-keeping system, Delay might be rounded to the nearest multiple of 10 or 15. + * @param {'Play'} [Play] + * - `Play` = Settings apply to {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlayDetail|SendPlay() mode}. + * - Omit or Empty String = Settings apply to {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendEvent() mode}. + * @returns {(Integer)} + * The previous Delay is returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetDefaultMouseSpeed.htm|SetDefaultMouseSpeed()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseClickDrag()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetWinDelay.htm|SetWinDelay()} | + * @example + */ +SetMouseDelay(Delay [,Play]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetNumScrollCapsLockState.htm|`SetNumLockState()`} + * Sets the toggle state of NumLock. + * Can also permanently enable or disable the key state. + * @param {'On'|'Off'|'AlwaysOn'|'AlwaysOff'|Integer} [State] + * - Omit or Empty String = Disables the `AlwaysOn` and `AlwaysOff` options. + * - `1` `On` = Set NumLock toggle to on and disable `AlwaysOn` and `AlwaysOff` options. + * - `0` `Off` = Set NumLock toggle to off and disables `AlwaysOn` and `AlwaysOff` options. + * - `AlwaysOn` = Set NumLock toggle to on and prevents it from being turned off. + * - `AlwaysOff` = Set NumLock toggle to off and prevents it from being turned on. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|`GetKeyState()`} + * @example + */ +SetNumLockState([State]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetNumScrollCapsLockState.htm|`SetScrollLockState()`} + * Sets the toggle state of ScrollLock. + * Can also permanently enable or disable the key state. + * @param {'On'|'Off'|'AlwaysOn'|'AlwaysOff'|Integer} [State] + * - Omit or Empty String = Disables the `AlwaysOn` and `AlwaysOff` options. + * - `1` `On` = Set ScrollLock toggle to on and disable `AlwaysOn` and `AlwaysOff` options. + * - `0` `Off` = Set ScrollLock toggle to off and disables `AlwaysOn` and `AlwaysOff` options. + * - `AlwaysOn` = Set ScrollLock toggle to on and prevents it from being turned off. + * - `AlwaysOff` = Set ScrollLock toggle to off and prevents it from being turned on. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/GetKeyState.htm|`GetKeyState()`} + * @example + */ +SetScrollLockState([State]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|`SetRegView()`} + * Sets the registry view used by {@link https://www.autohotkey.com/docs/v2/lib/RegRead.htm|RegRead()}, {@link https://www.autohotkey.com/docs/v2/lib/RegWrite.htm|RegWrite()}, {@link https://www.autohotkey.com/docs/v2/lib/RegDelete.htm|RegDelete()}, {@link https://www.autohotkey.com/docs/v2/lib/RegDeleteKey.htm|RegDeleteKey()} and {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry}. + * Sets 32-bit or 64-bit registry view. {@link https://www.autohotkey.com/docs/v1/Variables.htm#RegView|A_RegView} stores the current view type. + * @param {'Default'|Integer} RegView + * View type + * - `32` = Access registry as a 32-bit program. + * - `64` = Access registry as a 64-bit program. + * - `Default` = Restore to normal view type. + * @returns {(String)} + * The previous setting is returned + * - `32` + * - `64` + * - `Default` + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegRead.htm|RegRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegWrite.htm|RegWrite()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegCreateKey.htm|RegCreateKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDelete.htm|RegDelete()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegDeleteKey.htm|RegDeleteKey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm|Loop-Registry} + * @example + * last := SetRegView(32) + * MsgBox('Value: ' last) + */ +SetRegView(RegView) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|`SetStoreCapsLockMode()`} + * Sets whether CapsLock's state is restored after a {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send function}. + * This allows the sending of the CapsLock keystroke to alter the CapsLock state. + * {@link https://www.autohotkey.com/docs/v1/Variables.htm#StoreCapsLockMode|A_StoreCapsLockMode} stores the current SetStoreCapsLockMode setting. + * @param {(Boolean)} Mode + * - `1` = CapsLock state is set to whatever it was prior to the send. + * - `0` = CapsLock state stays at it's current state when send finishes. + * @returns {(Boolean)} + * The previous setting is always returned: `1` or `0` + * @see {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSend.htm|ControlSend()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetNumScrollCapsLockState.htm|Set[Caps/Num/Scroll]LockState()} + * @example + */ +SetStoreCapsLockMode(Mode) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm|`SetTimer()`} + * Causes a function or callback to be activated on a set timer, either once or repeatedly. + * @param {(FuncObj)} [Callback] + * The {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|function object} to call. + * A {@link https://www.autohotkey.com/docs/v2/Concepts.htm#references-to-objects|reference} to the function object is kept until the timer is deleted. + * This prevents the function object from being freed prematurely. + * If omitted, all SetTimer() changes are applied to the timer that launched the thread (if any). + * @param {(Integer)} [Period] + * The time interval, in milliseconds, used by SetTimer. + * - `#` = A positive SetTimer() period runs repeatedly, waiting `#` milliseconds between each activation. + * - `-#` = A negative SetTimer() period waits `#` milliseconds, runs once, and then is deleted. + * - `0` = The specified timer is deleted. This is done automatically with run-once timers. + * - Omit = If timer already exists, it is {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm#reset|reset} to its former period. + * Otherwise, a new timer defaults to `250`. + * + * A period cannot exceed 4294967295 ms (49.7 days). + * @param {(Integer)} [Priority] + * Specify an integer or {@link https://www.autohotkey.com/docs/v2/Variables.htm#Expressions|expression} between `-2147483648` and `2147483647` to indicate {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm#Priority|thread priority level}. + * `Period` can be omitted when only updating a timer's priority. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm|Thread()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm|Critical()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Functor.htm|Function Objects} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} + * @example + */ +SetTimer([Callback:=unset, Period:=250, Priority:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|`SetTitleMatchMode()`} + * Sets the matching behavior of the WinTitle parameter in built-in functions such as WinWait. + * @param {'1'|'2'|'3'|'RegEx'|'Fast'|'Slow'|Integer} ModeOrSpeed + * - **Mode:** How the title uses the provided text. + * The current value is stored in {@link https://www.autohotkey.com/docs/v2/Variables.htm#TitleMatchMode|A_TitleMatchMode} + * - `1` = Title must start with specified text. + * - `2` = Title must contain the specified text. + * - `3` = Title must exactly match specified text. + * - `RegEx` = Title is treated as a RegEx pattern. + * The window matches if the RegEx evaluates true. + * + * - **Speed:** Method to use when evaluating Window text parameters. + * The current value is stored in {@link https://www.autohotkey.com/docs/v2/Variables.htm#TitleMatchModeSpeed|A_TitleMatchModeSpeed} + * This defaults to `Fast` + * - `Fast` = Can perform much faster than `Slow` but certain controls cannot be detected. + * - `Slow` = Can perform slower but works with all controls that respond to {@link https://learn.microsoft.com/windows/win32/winmsg/wm-gettext|WM_GETTEXT}. + * @returns {(Integer|String)} + * The previous value of the last changed type. + * `Mode` change: + * - `1` + * - `2` + * - `3` + * - `RegEx` + * + * `Speed` change: + * - `Fast` + * - `Slow` + * @see {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle and LastFoundWindow} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetWinDelay.htm|SetWinDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|WinActivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm|RegExMatch()} | + * @example + */ +SetTitleMatchMode(ModeOrSpeed) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetWinDelay.htm|`SetWinDelay()`} + * Sets the delay that will occur after each {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|window function}. + * {@link https://www.autohotkey.com/docs/v1/Variables.htm#WinDelay|A_WinDelay} stores the current SetWinDelay() setting. + * @param {(Integer)} Delay + * Default is `100` + * - Number = Time to wait, in milliseconds. + * - `0` = Smallest possible delay. + * - `-1` = No delay. + * @returns {(Integer)} + * The previous setting is returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} + * @example */ -StrCompare(String1, String2, CaseSense := false) => Integer +SetWinDelay(Delay) => Integer /** - * Copy a string from a memory address or buffer, optionally convert it from a given code page. - * @overload StrGet(Source, Encoding?) => String - * @param Source contains the buffer-like object of the string, or the memory address of the string. If the buffer-like object is provided, or the Length parameter is specified, the string does not need to end with a null terminator. - * @param Length The maximum number of characters to be read. If the string ends with a null terminator, it can be omitted. - * By default, only the first binary zero is copied. If Length is negative, its absolute value indicates the exact number of characters to be converted, including any binary zeros that the string may contain-in other words, the result is always with String of that length. - * @param Encoding "UTF-8", "UTF-16" or "CP936". For numeric identifiers, the prefix "CP" can be omitted only when Length is specified. Specify an empty string or "CP0" to use the system The default ANSI code page. + * @description {@link https://www.autohotkey.com/docs/v2/lib/SetWorkingDir.htm|`SetWorkingDir()`} + * Changes the script's current working directory. + * @param {(String)} DirName + * the name of the new working directory. + * If a full path isn't used, DirName is assumed to be a subfolder of the current {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#InitialWorkingDir|A_InitialWorkingDir} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptDir|A_ScriptDir} + * @example + */ +SetWorkingDir(DirName) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Shutdown.htm|`Shutdown()`} + * Shuts down, restarts, or logs off the system. + * @param {(Integer)} Flag + * A sum of the following options: + * - `0` = Logoff. Current user is logged off. + * - `1` = Shutdown. Operating + * - `2` = Reboot. Operating system is shut down then turned back on. + * - `4` = Force close. Forcefully closes all applications. + * This can cause data loss in some situations. + * - `8` = Power down. Shuts down the system and turns power off. + * + * Shutdown(6) ; Reboot system (2) and force close everything (4) + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|ExitApp()} | + * {@link https://www.autohotkey.com/docs/v2/lib/OnExit.htm|OnExit()} + * @example + */ +Shutdown(Flag) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Sin|`Sin()`} + * Returns the trigonometric sine of the number. + * Convert radians to degrees: `Value * 180/pi` (180/pi = ~57.29578) + * Convert degrees to radians: `Value * pi/180` (pi/180 = ~0.01745329252) + * @param {(Number)} Num + * The number to get the sine value of. + * Must be expressed in radians. + * @returns {(Float)} + * Sine of `Num`. + * @example + * Sin(1.2) => 0.932039 + */ +Sin(Num) => Float + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Sleep.htm|`Sleep()`} + * Waits the specified amount of time before continuing. + * @param {(Integer)} Delay + * Amount of time, in milliseconds, to wait before continuing the thread. + * Number must be between `0` and `2147483647` (24 days). + * `-1` causes no sleep and instead makes the script check its message queue, allowing for interrupts to occur. + * Due to the granularity of the OS time-keeping system, Delay might be rounded to the nearest multiple of 10 or 15. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetWinDelay.htm|SetWinDelay()} + * @example + */ +Sleep(Delay) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Sort.htm|`Sort()`} + * Arranges a variable's contents in alphabetical, numerical, or random order (optionally removing duplicates). + * @param {(String)} Text + * The string to sort. + * @param {String|'C'|'CL'|'CLogical'|'D'|'N'|'P'|'R'|'Random'|'U'|'Z'|'\:'} [Options] + * Zero or more of the following {@link https://www.autohotkey.com/docs/v2/lib/Sort.htm#Options|options}: + * - `C` `C1` `COn`: Case-sensitive sort. Uppercase comes before lowercase. + * The `N` option overrides this setting. + * - `C0` `COff`: Case-insensitive sort. Uppercase and lowercase are considered equals. + * - `CL` `CLocale`: Case-insensitive sort based on the current user's locale. + * - `CLogical`: Same as `CLocale`, but digits in each item are treated as numerical group values rather than individual key code. + * `A10,A2` would sort as `A2,A10` because 2 is less than 10 numerically, even though the key codes A1 come before A2. + * - `D#`: Delimiter character, where `#` is the specific character that separates each item to sort. + * Delimiter is always case-sensitive and the default value is newline `` `n ``. + * - `N`: Numeric sort. Numbers inside the string are sorted by their value rather than their individual key codes. + * `100,5` would sort to `5,100` because the value 5 is less than 100 even though first character `5` comes after `1`. + * - `P#`: Sorting starts at the specified position for each item, where `#` is the decimal position to start at. + * Everything before that position is ignored in the sort. + * Default is `1`. + * + * Sort('x 2`nz 1`ny 3', 'P3') => 'z 1`nx 2`ny 3' + * ; z 1 + * ; x 2 + * ; y 3 + * ; ^--Sort starts at 3rd character + * - `R`: Reverse sort. Uses descending order. + * - `Random`: Randomizes order of items. + * Overrides all options except `D`, `Z`, and `U`. + * The `N`, `C`, and `CL` options will still apply to how duplicates are detected. + * - `U`: Unique. Enforces a unique list by removing duplicates. + * - If `C` is in effect, the case of the list items must be identical. + * - If `N` is in effect, numerical values are considered duplicates. `2`, `2.0`, and `02` are the same. + * - If `P` or `\` is in effect, the entire item must still be a duplicate, not just the substring or portion. + * - If `Random` or custom sorting is in effect, duplicates are only removed if adjacent to each other. + * - `Z`: If a string ends with a delimiting character, the blank area after it is considered an item to sort. + * Without `Z`, the last ending delimiter is considered part of the last item to sort. + * - `\:` Path sorting. Items are sorted by the characters that come after the last backslash `\` in the string. + * If no backslash is present, the whole item is used. This option is useful for sorting bare filenames (i.e. excluding their paths), such as the example below, in which the AAA.txt line is sorted above the BBB.txt line because their directories are ignored for the purpose of the sort: + * `C:\bb\aa.txt` would come first, `C:\aa\bb.txt` second, and `cc.txt` last. + * @param {(FuncObj)} [Callback] + * A callback to perform custom user-implemented sorting. + * If omitted, no special sorting is performed. + * Callback requires 3 parameters: + * - `item1` = First value to compare. + * - `item2` = Second value to compare. + * - `offset` = Number of characters between the start position of each item, including delimiter. + * Callback return values: + * - `Positive integer` = item1 is greater than item2 + * - `Negative integer` = item2 is greater than item1 + * - `0` Empty String = item1 and item2 are equal + * + * sort_callback(item1, item2, offset) + * + * Having a callback overrides all options except `D`, `Z`, and `U`. + * The `N`, `C`, and `CL` options will still apply to how duplicates are detected. + * @returns {(String)} + * The sorted version of `Text`. + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileRead.htm|FileRead()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrSplit.htm|StrSplit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/CallbackCreate.htm|CallbackCreate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/A_Clipboard.htm|A_Clipboard} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopParse.htm|Loop-Parse} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm|Loop-Files} + * @example + */ +Sort(Text [,Options:='C0', Callback:=unset]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SoundBeep.htm|`SoundBeep()`} + * Emits a tone from the PC speaker. + * This function will wait for the sound to finish before continuing. + * To produce system sounds instead of speaker beeping, see {@link https://www.autohotkey.com/docs/v2/lib/SoundPlay.htm|SoundPlay()}. + * @param {(Integer)} [Frequency] + * The frequency of the beep, between `37` and `32767` + * @param {(Integer)} [Duration] + * The duration of the beep in milliseconds. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SoundPlay.htm|SoundPlay()} + * @example + */ +SoundBeep([Frequency:=523, Duration:=150]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SoundGetInterface.htm|`SoundGetInterface()`} + * Retrieves a native COM interface of a sound device or component. + * @param {(String)} IID + * An interface identifier (GUID). + * GUID format: `{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}` + * @param {(String|Integer)} [Component] + * Specify the component's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#component|Component (Sound Functions)}. + * If omitted or empty string, the interface implemented by the drive is retrieved. + * @param {(String|Integer)} [Device] + * Specify the device's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#device|Device (Sound Functions)}. + * If omitted or empty string, the system's default device is retrieved. + * @returns {(Integer)} + * `0` if interface is not supported, otherwise an interface pointer is returned. + * @throws OSError - Thrown on failure other than TargetError. + * @throws TargetError - Device or component could not be found. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm|Sound Functions} | + * {@link https://learn.microsoft.com/windows/win32/coreaudio/devicetopology-api|DeviceTopology API} + * @example + */ +SoundGetInterface(IID [,Component:='', Device:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SoundGetName.htm|`SoundGetMute()`} + * Retrieves a mute setting of a sound device. + * @param {(String|Integer)} [Component] + * Specify the component's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#component|Component (Sound Functions)}. + * If omitted or empty string, the master mute setting is used. + * @param {(String|Integer)} [Device] + * Specify the device's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#device|Device (Sound Functions)}. + * If omitted or empty string, the system's default device is retrieved. + * @returns {(Boolean)} + * - `1` = Muted + * - `0` = Unmuted + * @throws OSError - Thrown on failure other than TargetError. + * @throws TargetError - Device or component could not be found or component does not support this control type. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SoundSetMute.htm|SoundSetMute()} + * {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm|Sound Functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#ExSoundcard|Soundcard Analysis Script} + * @example + */ +SoundGetMute([Component:='', Device:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SoundGetName.htm|`SoundGetName()`} + * Retrieves the name of a sound device or component. + * @param {(String|Integer)} [Component] + * Specify the component's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#component|Component (Sound Functions)}. + * If omitted or empty string, the name of the device itself will be retrieved. + * @param {(String|Integer)} [Device] + * Specify the device's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#device|Device (Sound Functions)}. + * If omitted or empty string, the system's default device is retrieved. + * @returns {(String)} + * The name of the device or component. + * This value can be a blank string. + * @throws OSError - Thrown on failure other than TargetError. + * @throws TargetError - Device or component could not be found. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm|Sound Functions} | + * @example + */ +SoundGetName([Component:='', Device:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SoundGetVolume.htm|`SoundGetVolume()`} + * Retrieves a volume setting of a sound device. + * @param {(String|Integer)} [Component] + * Specify the component's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#component|Component (Sound Functions)}. + * If omitted or empty string, it defaults to the master volume setting. + * @param {(String|Integer)} [Device] + * Specify the device's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#device|Device (Sound Functions)}. + * If omitted or empty string, the system's default device is retrieved. + * @returns {(Float)} + * The current volume between `0.0` and `100.0` + * @throws OSError - Thrown on failure other than TargetError. + * @throws TargetError - Device or component could not be found or component does not support this control type. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SoundSetVolume.htm|SoundSetVolume()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm|Sound Functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#ExSoundcard|Soundcard Analysis Script} + * @example + */ +SoundGetVolume([Component:='', Device:='']) => Float + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SoundPlay.htm|`SoundPlay()`} + * Plays a sound, video, or other supported file type. + * @param {'*-1'|'*16'|'*32'|'*48'|'*64'|String} Filename + * Path of the file to be played. + * If a full path isn't used, Filename is assumed to start in {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir}. + * To produce system standard sounds, specify one of the following: + * - `*-1` = Simple beep. + * The internal speaker will beep if no sound card is found. + * - `*16` = Hand (Stop/Error) sound + * - `*32` = Question sound + * - `*48` = Exclamation sound + * - `*64` = Information (Info) sound + * @param {'1'|'0'|'Wait'} [Wait] + * - `1`, `Wait` = The current thread waits until the file has finished playing. + * - `0` = The current thread immediately continues. + * @returns {(String)} + * An empty string is always returned. + * @throws Error - Thrown on failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/SoundBeep.htm|SoundBeep()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|MsgBox()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm|Sound Functions} + * @example + */ +SoundPlay(Filename [,Wait:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SoundSetMute.htm|`SoundSetMute()`} + * Changes a mute setting of a sound device. + * @param {(Integer)} NewSetting + * - `1` = Enable mute. + * - `0` = Disable mute. + * - `-1` = Toggle between current setting. Mute <-> Unmute. + * @param {(String|Integer)} [Component] + * Specify the component's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#component|Component (Sound Functions)}. + * If omitted or empty string, it defaults to the master mute setting. + * @param {(String|Integer)} [Device] + * Specify the device's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#device|Device (Sound Functions)}. + * If omitted or empty string, the system's default device is retrieved. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure other than TargetError. + * @throws TargetError - Device or component could not be found or component does not support this control type. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm|Sound Functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/SoundGetMute.htm|SoundGetMute()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#ExSoundcard|Soundcard Analysis Script} + * @example + */ +SoundSetMute(NewSetting [,Component:='', Device:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SoundSetVolume.htm|`SoundSetVolume()`} + * Changes a volume setting of a sound device. + * @param {(Primitive)} NewSetting + * - A number prefixed with a `+` increases the current volume by that amount. This must be a string. + * - A number prefixed with a `-` decreases the current volume by that amount. + * - A positive number sets the current volume to that number. + * If over 100, 100 is used. + * @param {(String|Integer)} [Component] + * Specify the component's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#component|Component (Sound Functions)}. + * If omitted or empty string, it defaults to the master volume setting. + * @param {(String|Integer)} [Device] + * Specify the device's display name and/or index number. + * See {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#device|Device (Sound Functions)}. + * If omitted or empty string, the system's default device is retrieved. + * @returns {(String)} + * An empty string is always returned. + * @throws OSError - Thrown on failure other than TargetError. + * @throws TargetError - Device or component could not be found or component does not support this control type. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm|Sound Functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/SoundGetMute.htm|SoundGetMute()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Sound.htm#ExSoundcard|Soundcard Analysis Script} + * @example + */ +SoundSetVolume(NewSetting [,Component:='', Device:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SplitPath.htm|`SplitPath()`} + * Splits up a file name or URL into its component parts. + * @param {(String)} Path + * A filename or URL to process. + * Filenames should use `\` path separators while URLs use `/`. + * If the path points to a subdirectory, that subdirectory becomes the "file" of the path. + * @param {(VarRef)} [OutName] + * A variable reference to receive the file name. + * For a URL, this is the file name or the last subdirectory if URL doesn't contain a file. + * @param {(VarRef)} [OutDir] + * A variable reference to receive the directory containing `OutName`. + * For a URL, this is the address up until the file or last subdirectory. + * @param {(VarRef)} [OutExt] + * A variable reference to receive the file's extension type. + * This is blank of the file lacks a defined extension. + * @param {(VarRef)} [OutNameNoExt] + * A variable reference to receive the Filename without the extension. + * @param {(VarRef)} [OutDrive] + * A variable reference to receive the drive of the file. + * For a URL, this is main domain without any included subdirectories. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/StrSplit.htm|StrSplit()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|SubStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|FileSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileExt|A_LoopFileExt} + * @example Path and URL examples. + * url := 'https://www.autohotkey.com/download/2.0/AutoHotkey_2.0.10.zip' + * SplitPath(url, &OutName, &OutDir, &OutExt, &OutNameNoX, &OutDrive) + * MsgBox('OutName: ' OutName ; AutoHotkey_2.0.10.zip + * '`nOutDir: ' OutDir ; https://www.autohotkey.com/download/2.0 + * '`nOutExt: ' OutExt ; zip + * '`nOutNameNoX: ' OutNameNoX ; AutoHotkey_2.0.10 + * '`nOutDrive: ' OutDrive ; https://www.autohotkey.com + * ) + * + * Path := 'C:\Program Files\AutoHotkey\UX\launcher.ahk' + * SplitPath(path, &OutName, &OutDir, &OutExt, &OutNameNoX, &OutDrive) + * MsgBox('OutName: ' OutName ; launcher.ahk + * '`nOutDir: ' OutDir ; C:\Program Files\AutoHotkey\UX + * '`nOutExt: ' OutExt ; ahk + * '`nOutNameNoX: ' OutNameNoX ; launcher + * '`nOutDrive: ' OutDrive ; C: + * ) + */ +SplitPath(Path [,&OutName, &OutDir, &OutExt, &OutNameNoExt, &OutDrive]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Sqrt|`Sqrt()`} + * Returns the square root of the specified number. + * @param {(Number)} Num + * A positive number. + * @returns {(Float)} + * The square root of `Num`. + * @throws ValueError - Number is negative + * @example Square Root Examples. + * x := Sqrt(9) + * MsgBox('value: ' x) ; 3.0 + * + * ; Square root of a negative: + * num := -144 + * if (num < 0) + * ans := Sqrt(Abs(num)) 'i', + * else ans := Sqrt(num) + * MsgBox(ans) ; 12.0i + */ +Sqrt(Num) => Float + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StatusBarGetText.htm|`StatusBarGetText()`} + * Retrieves the text from a standard status bar control. + * @param {(Integer)} [Section] + * The section number if status bar to get the text of. + * If omitted, it defaults to 1. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The text of the specified section. + * @throws TargetError - Target window could not be found or does not contain a standard status bar. + * @throws OSError - There was a problem sending SB_GETPARTS message + * @throws OSError - No reply was received within 2000 ms + * @throws OSError - Memory could not be allocated within the process that owns the status bar + * @see {@link https://www.autohotkey.com/docs/v2/lib/StatusBarWait.htm|StatusBarWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetText.htm|WinGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetText.htm|ControlGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +StatusBarGetText([Section:=1, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StatusBarWait.htm|`StatusBarWait()`} + * Waits until a window's status bar contains the specified string. + * @param {(String)} [BarText] + * Text to wait for in the specified section. + * If omitted or empty string, the function waits for the section to be blank. + * @param {(Number)} [Timeout] + * The max amount of seconds to wait. + * This number can be a float for higher precision. + * If omitted, the function waits indefinitely. + * @param {(Integer)} [Section] + * The section number if status bar to get the text of. + * If omitted, it defaults to 1. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(Integer)} [Interval] + * How often the status bar should be checked, in milliseconds. + * If omitted, it defaults to 50. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @throws TargetError - Target window could not be found or does not contain a standard status bar. + * @throws OSError - There was a problem sending SB_GETPARTS message + * @throws OSError - No reply was received within 2000 ms + * @throws OSError - Memory could not be allocated within the process that owns the status bar + * @see {@link https://www.autohotkey.com/docs/v2/lib/StatusBarGetText.htm|StatusBarGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetText.htm|WinGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetText.htm|ControlGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +StatusBarWait([BarText:='', Timeout:=unset, Section:=1, WinTitle:='', WinText:='', Interval:=50, NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrCompare.htm|`StrCompare()`} + * Compares two strings alphabetically. + * @param {(String)} String1 + * First string to compare. + * @param {(String)} String2 + * Second string to compare. + * @param {'On'|'Off'|'Locale'|'Logical'|'A2'|'1'|'0'|Integer} [CaseSense] + * - `1` `On` = Case-sensitivity enabled. + * - `0` `Off` = Case-sensitivity disabled. + * - `Locale` = Comparison is case-sensitive based on current user's locale. + * This can be anywhere from x1-x8 slower than `Off`. + * - `Logical` = Same as Locale, but digits are treated as numerical values rather than individual characters. + * `A2` is considered less than `A10` because 2 is numerically less than 10. + * @returns {(Integer)} + * A number indicating how the two strings compared: + * Negative = Str1 comes before Str2 in lexicographical order. + * `0` = Str1 and Str2 are equal. + * Positive = Str2 comes before Str1 in lexicographical order. + * + * No other assumptions should be made from the returned value. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Sort.htm|Sort()} | + * {@link https://www.autohotkey.com/docs/v2/lib/VerCompare.htm|VerCompare()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Sort.htm#callback|Sort callbacks} + * @example + * str1 := 'a2', str2 := 'a10' + * ans1 := StrCompare(str1, str2) ; 1 + * ans2 := StrCompare(str1, str2, 'Logical') ; -1 + * MsgBox('Normal: ' ans1 '`nLogical: ' ans2) + */ +StrCompare(String1, String2 [,CaseSense]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrGet.htm|`StrGet()`} + * Copies a string from a memory address or buffer, optionally converting it from a given code page. + * @param {(Integer|Buffer)} Source + * A memory address or a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|buffer-like} object (any object with a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Ptr|Ptr} and {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Size|Size} property). + * @param {(Integer|String)} [Length] + * Specify the maximum number of {@link https://www.autohotkey.com/docs/v2/Concepts.htm#character|characters} to read. + * If omitted or if encoding is passed to the `Length` parameter, the string's full length is used. + * @param {'CP0'|'UTF-8'|'UTF-8-RAW'|'UTF-16'|'UTF-16-RAW'|'CPnnn'|'RAW'|'`n'|String|Integer} [Encoding] + * Specify the source encoding. + * If omitted, the string is copied without any conversion. + * Otherwise, any of the {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm#Parameters|FileEncoding()} names. + * - `CP0`: The system default ANSI code page. + * - `UTF-8`: Unicode UTF-8 (equivalent to CP65001). + * - `UTF-8-RAW`: UTF-8 but no byte order mark is written when a new file is created. + * - `UTF-16`: Unicode UTF-16 with little endian byte order (CP1200). + * - `UTF-16-RAW`: UTF-16 but no byte order mark is written when a new file is created. + * - `CPnnn`: A code page with numeric identifier nnn. See {@link https://learn.microsoft.com/windows/win32/intl/code-page-identifiers|Code Page Identifiers}. + * - `nnn`: A numeric code page identifier. + * + * Encoding can be passed to the `Length` parameter and the string's full length will be used for `Length`. + * @returns {(String)} + * The string retrieved from `Source`. + * @throws ValueError - An invalid parameter is detected + * @throws OSError - Conversion could not be performed + * @see {@link https://www.autohotkey.com/docs/v2/lib/StrPut.htm|StrPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm|FileEncoding()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/VarSetStrCapacity.htm|VarSetStrCapacity()} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#string-encoding|String Encoding} | + * {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer object} | + * {@link https://www.autohotkey.com/docs/v2/Compat.htm|Binary Compatibility} + * @example + */ +StrGet(Source [,Length:=unset, Encoding:=unset]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrLen.htm|`StrLen()`} + * Retrieves the count of how many characters are in a string. + * @param {(String)} Str + * String to get the length of. + * @returns {(Integer)} + * The number of characters in the string. + * @see {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|SubStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Trim.htm|Trim()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLower.htm|StrLower()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLower.htm|StrUpper()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrPut.htm|StrPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrGet.htm|StrGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrReplace.htm|StrReplace()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrSplit.htm|StrSplit()} + * @example + */ +StrLen(Str) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrLower.htm|`StrLower()`} + * Converts a string to lowercase. + * @param {(String)} Str + * The string to convert. + * @returns {(String)} + * A string converted to lowercase. + * @see {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|SubStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLen.htm|StrLen()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrReplace.htm|StrReplace()} + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#upper|IsUpper()} + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#lower|IsLower()} + * @example + */ +StrLower(Str) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrPtr.htm|`StrPtr()`} + * Returns the current memory address of a string. + * @param {(String)} Str + * A variable containing a string. + * @returns {(Integer)} + * The current memory address of the string. + * @see {@link https://www.autohotkey.com/docs/v2/lib/VarSetStrCapacity.htm|VarSetStrCapacity()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage()} | + * {@link https://www.autohotkey.com/docs/v2/lib/NumPut.htm|NumPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/NumGet.htm|NumGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer object} + * @example + */ +StrPtr(Str) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrPut.htm|`StrPut()`} + * Copy a string to a memory address and can convert encoding. + * This function can also be used to calculate the required buffer size for a string. + * @param {(String)} Str + * Any string. If a number is given, its converted to a string first. + * The string is assumed to be in {@link https://www.autohotkey.com/docs/v2/Concepts.htm#string-encoding|native encoding}. + * @param {(Integer|Buffer)} Target + * A memory address or a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|buffer-like} object (any object with a {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Ptr|Ptr} and {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm#Size|Size} property). + * If omitted, this parameter can be the string's encoding type and will return the required buffer size for `Str`. + * @param {(Integer)} [Length] + * The maximum number of {@link https://www.autohotkey.com/docs/v2/Concepts.htm#character|characters} to write, including the {@link https://www.autohotkey.com/docs/v2/Concepts.htm#null-termination|null-terminator} if required. + * Length should be the size of the buffer in characters, not the length of `Str` or a substring. + * @param {'CP0'|'UTF-8'|'UTF-8-RAW'|'UTF-16'|'UTF-16-RAW'|'CPnnn'|'RAW'|'`n'|String|Integer} [Encoding] + * Specify the encoding type. + * If omitted, the string is not converted before being copied to `Target` or measured for size. + * Otherwise, any of the {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm#Parameters|FileEncoding()} names. + * - `CP0`: The system default ANSI code page. + * - `UTF-8`: Unicode UTF-8 (equivalent to CP65001). + * - `UTF-8-RAW`: UTF-8 but no byte order mark is written when a new file is created. + * - `UTF-16`: Unicode UTF-16 with little endian byte order (CP1200). + * - `UTF-16-RAW`: UTF-16 but no byte order mark is written when a new file is created. + * - `CPnnn`: A code page with numeric identifier nnn. See {@link https://learn.microsoft.com/windows/win32/intl/code-page-identifiers|Code Page Identifiers}. + * - `nnn`: A numeric code page identifier. + * @returns {(Integer)} + * If `Target` is used, the function returns number of bytes written. + * A null terminator is written if there is space to add it. + * If `Target` is omitted, the function returns the bytes requires to make a buffer for `Str`. + * @throws Error - Length is zero or length is smaller than required size after conversion + * @throws Error - Length is larger than buffer size, even if string would fit in the buffer + * @throws ValueError - An invalid parameter is detected + * @throws OSError - Conversion could not be performed + * @see {@link https://www.autohotkey.com/docs/v2/lib/StrGet.htm|StrGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm|FileEncoding()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/VarSetStrCapacity.htm|VarSetStrCapacity()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer object} | + * {@link https://www.autohotkey.com/docs/v2/Compat.htm|Binary Compatibility} | + * {@link https://www.autohotkey.com/docs/v2/Concepts.htm#string-encoding|String Encoding} + * @example + */ +StrPut(Str [,Target, Length, Encoding]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrReplace.htm|`StrReplace()`} + * Replaces the specified substring with a new string. + * StrReplace() should be whenever possible over RegEx as it performs **much** faster. + * @param {(String)} Haystack + * The string with contents to be replaced + * @param {(String)} Needle + * The specific string to find inside the `Haystack` + * @param {(String)} [ReplaceText] + * The replacement text for the found `Needle`. + * If this parameter is omitted or is an empty string, the found text is removed. + * @param {'On'|'Off'|'Locale'|'1'|'0'} [CaseSense] + * The case-sensitivity setting for this replacement. + * - `1` `On` = The search is case-sensitive. `a` does not equal `A` + * - `0` `Off` = The search is not case-sensitive. `a` and `A` are equal. + * - `Locale` = Case-sensitivity follows the current user's locale. + * This can be anywhere from x1-x8 slower than `Off`. + * @param {(VarRef)} [OutputVarCount] + * A variable reference to receive the number of replacements modes. + * `0` if no replacements were made. + * @param {(Integer)} [Limit] + * The max amount of replacements to make before stopping. All remaining text remains unchanged. + * If omitted `-1` is used. `-1` sets replacement to 'All'. + * @returns {(String)} + * The `Haystack` after replacements are made. + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegExReplace.htm|RegExReplace()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|SubStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLen.htm|StrLen()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLower.htm|StrLower()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLower.htm|StrUpper()} + * @example + */ +StrReplace(Haystack, Needle [,ReplaceText:='', CaseSense:=0, &OutputVarCount, Limit:=-1]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrSplit.htm|`StrSplit()`} + * Separates a string into an array of substrings using the specified delimiters. + * @param {(String)} Str + * The string to split up. + * @param {(String|Array)} [Delimiters] + * The character that identifies where each split is to occur. + * If omitted, the string is split up into each individual character. + * If an array of characters is passed in, each character is used a delimiter once. + * When the first delimiter is reached, the substring is saved and the delimiter is updated to the next character in the array. + * When the last array character is reached, it restarts at the beginning of the array. + * @param {(String)} [OmitChars] + * Specify a list of characters to trim from the beginning and end of each substring. + * If `Delimiters` is an empty string or omitted, `OmitChars` removes all matching characters from the returned array. + * If omitted or an empty string, no characters are excluded. + * Common uses for this parameter: + * - Trimming whitespace from around each substring: + * + * StrSplit(str, ',', ' `t') ; Removes surrounding tabs and spaces + * - Dealing with the uncertainty of `` `r`n `` when the delimiter is newline `` `n ``. + * + * StrSplit(str, '`n', '`r') ; Split by newline and remove carriage returns + * @param {(Integer)} [MaxArrSize] + * Specify the maximum size of the return array + * If a non-zero number is used, the string continues to be split until the last element is reached. + * At that point, any remaining text is put in the last element of the array. + * If omitted, `-1` is used indicating no array size limit. + * @returns {(Array)} + * An array of the substrings from splitting `Str`. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Sort.htm|Sort()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SplitPath.htm|SplitPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|SubStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLen.htm|StrLen()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLower.htm|StrLower()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLower.htm|StrUpper()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrReplace.htm|StrReplace()} | + * {@link https://www.autohotkey.com/docs/v2/lib/LoopParse.htm|Loop-Parse} + * @example Splitting a string up. + * txt := '1 2!3 4?5 6.7 8!9 10?11 12' + * arr := ['!','?','.'] + * str := '' + * for i, v in StrSplit(txt, arr) + * str .= 'Group ' i ': ' v '`n' + * MsgBox(str) + */ +StrSplit(Str [,Delimiters:='', OmitChars:='', MaxArrSize:=-1]) => Array + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrLower.htm|`StrTitle()`} + * Converts a string to Title Case. + * The First Letter Of Each Word Is Capitalized. + * @param {(String)} Str + * The string to convert. + * @returns {(String)} + * A string converted to Title Case. + * @see {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|SubStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLen.htm|StrLen()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrReplace.htm|StrReplace()} + * @example Convert text to title case. + * str := 'title case conversion.' + * MsgBox(str) + * str := StrTitle(str) + * MsgBox(str) + */ +StrTitle(Str) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/StrLower.htm|`StrUpper()`} + * Converts a string to UPPERCASE. + * @param {(String)} Str + * The string to convert. + * @returns {(String)} + * A string converted to UPPERCASE. + * @see {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|SubStr()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrLen.htm|StrLen()} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrReplace.htm|StrReplace()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#upper|IsUpper()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm#lower|IsLower()} + * @example Convert text to uppercase. + * str := 'title case conversion.' + * MsgBox(str) + * str := StrUpper(str) + * MsgBox(str) + */ +StrUpper(Str) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SubStr.htm|`SubStr()`} + * Retrieves one or more characters from the specified position in a string. + * @param {(String)} Str + * The string to get a portion of. + * @param {(Integer)} StartPos + * The character position in the string to start the search at. + * - Positive Number = Left to right. 1 = first char, 2 = second, ... + * If the number exceeds the length of `Str`, the match starts after the last char. + * This will result in an empty substring being returned. + * - Negative Number = Right to left. -1 = last char, -2 = second from last, ... + * If a negative number exceeds the length of `Str`, the first char is used. + * @param {(Integer)} [Length] + * If positive, this is the number of characters to capture after `StartPos`. + * If negative, that's the number of characters from the end to stop capturing at. This can be though of trimming characters from the end. + * If omitted, all characters from `StartPos` to the end are captured. + * @returns {(String)} + * The captured substring. + * If `Length` is a negative number equal to or greater than the substring's length, an empty string is returned. + * If position is `0` or greater than string length, an empty string is returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/RegExMatch.htm|RegExMatch()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InStr.htm|InStr()} + * @example + */ +SubStr(Str, StartPos [,Length:=unset]) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Suspend.htm|`Suspend()`} + * Disables or enables all or selected hotkeys and hotstrings. + * @param {(Integer)} [NewState] New suspend state. + * - `1` = Suspend all hotkeys and hotstrings. + * - `0` = Enable all hotkeys and hotstrings. + * - `-1` = Toggles suspend state. On <-> Off + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Pause.htm|Pause()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ExitApp.htm|ExitApp()} | + * {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm|Hotkeys::} | + * {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm|::Hotstrings::} | + * {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} | + * {@link https://www.autohotkey.com/docs/v2/lib/_SuspendExempt.htm|#SuspendExempt} + * @example + */ +Suspend([NewState:=-1]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm|`SysGet()`} + * Retrieves dimensions of system objects, and other system properties. + * @param {(Integer)} Property + * A {@link https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics|system property}. + * **{@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm#Commonly_Used|Common Properties}** + * - `56` = SM_ARRANGE: + * Flags specifying how the system arranged minimized windows. + * - `67` = SM_CLEANBOOT: + * Specifies how the system was started: + * - `0` = Normal boot + * - `1` = Fail-safe boot + * - `2` = Fail-safe with network boot + * - `5` `6` = SM_CXBORDER, SM_CYBORDER: + * Width and height of a window border, in pixels. + * - `13` `14` = SM_CXCURSOR, SM_CYCURSOR: + * Width and height of a cursor, in pixels. The system cannot create cursors of other sizes. + * - `36` `37` = SM_CXDOUBLECLK, SM_CYDOUBLECLK: + * Width and height of the rectangle, in pixels, that defines the area a double-click can happen in. + * - `68` `69` = SM_CXDRAG, SM_CYDRAG: + * Width and height of a rectangle, in pixels, that allows for limited mouse movement before a drag operation begins. + * - `45` `46` = SM_CXEDGE, SM_CYEDGE: + * Dimensions of a 3-D border, in pixels. + * These are the 3-D counterparts of SM_CXBORDER and SM_CYBORDER. + * - `7` `8 = SM_CXFIXEDFRAME, SM_CYFIXEDFRAME: + * Thickness, in pixels, of the frame around a window that has the caption style but is not sizable. + * - `83` `84 = SM_CXFOCUSBORDER, SM_CYFOCUSBORDER: + * Width of the left and right edges and height of the top and bottom edges of a control's focus rectangle. In pixels. + * - `21` `3 = SM_CXHSCROLL, SM_CYHSCROLL: + * Width of the arrow bitmap on a horizontal scroll bar and height of a horizontal scroll bar. In pixels. + * - `10` = SM_CXHTHUMB: + * Width of the thumb box in a horizontal scroll bar, in pixels. + * - `11` `12` = SM_CXICON, SM_CYICON: + * Default width and height of an icon, in pixels. + * - `38` `39` = SM_CXICONSPACING, SM_CYICONSPACING: + * Dimensions of a grid cell for items in large icon view, in pixels. + * - `71` `72` = SM_CXMENUCHECK, SM_CYMENUCHECK: + * Dimensions of the default menu check-mark bitmap, in pixels. + * - `54` `55` = SM_CXMENUSIZE, SM_CYMENUSIZE: + * Dimensions of menu bar buttons in pixels. + * - `47` `48` = SM_CXMINSPACING, SM_CYMINSPACING: + * Dimensions of a grid cell for a minimized window, in pixels. + * Each minimized window fits into a rectangle this size when arranged. + * - `30` `31` = SM_CXSIZE, SM_CYSIZE: + * Width and height of a button in a window's caption or title bar, in pixels. + * - `32` `33` = SM_CXSIZEFRAME, SM_CYSIZEFRAME: + * Thickness of the sizing border around the perimeter of a window that can be resized, in pixels. + * - `49` `50` = SM_CXSMICON, SM_CYSMICON: + * Recommended dimensions of a small icon, in pixels. + * - `52` `53` = SM_CXSMSIZE, SM_CYSMSIZE: + * Dimensions of small caption buttons, in pixels. + * - `2` `20` = SM_CXVSCROLL, SM_CYVSCROLL: + * Width of a vertical scroll bar and height of the arrow bitmap on a vertical scroll bar, in pixels. + * - `4` = SM_CYCAPTION: + * Height of a caption area, in pixels. + * - `18` = SM_CYKANJIWINDOW: + * For double byte character set versions of the system, this is the height of the Kanji window at the bottom of the screen, in pixels. + * - `15` = SM_CYMENU: + * Height of a single-line menu bar, in pixels. + * - `51` = SM_CYSMCAPTION: + * Height of a small caption, in pixels. + * - `9` = SM_CYVTHUMB: + * Height of the thumb box in a vertical scroll bar, in pixels. + * - `42` = SM_DBCSENABLED: + * Nonzero if User32.dll supports DBCS; zero otherwise. + * - `22` = SM_DEBUG: + * Nonzero if the debug version of User.exe is installed; zero otherwise. + * - `82` = SM_IMMENABLED: + * Nonzero if Input Method Manager/Input Method Editor features are enabled; zero otherwise. + * - `40` = SM_MENUDROPALIGNMENT: + * Nonzero if drop-down menus are right-aligned with the corresponding menu-bar item; zero if the menus are left-aligned. + * - `74` = SM_MIDEASTENABLED: + * Nonzero if the system is enabled for Hebrew and Arabic languages, zero if not. + * - `41` = SM_PENWINDOWS: + * Nonzero if the Microsoft Windows for Pen computing extensions are installed; zero otherwise. + * - `44` = SM_SECURE: + * Nonzero if security is present; zero otherwise. + * - `81` = SM_SAMEDISPLAYFORMAT: + * Nonzero if all the display monitors have the same color format, zero otherwise. + * + * Also {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm#Not_Commonly_Used|Uncommon properties}. + * @returns {(Integer)} + * The value gotten from the specified Property. + * @see {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Monitor.htm|Monitor functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm#Commonly_Used|Common Properties} | + * {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm#Not_Commonly_Used|Uncommon properties} + * @example */ -StrGet(Source [, Length, Encoding]) => String +SysGet(Property) => Integer /** - * Retrieve the number of characters in a string. + * @description {@link https://www.autohotkey.com/docs/v2/lib/SysGetIPAddresses.htm|`SysGetIPAddresses()`} + * Returns an array of the system's IPv4 addresses. + * Currently, IPv6 is not supported. + * @returns {(Array)} + * An array where each index is an IPv4 address. + * @see {@link https://www.autohotkey.com/docs/v2/Variables.htm#ComputerName|A_ComputerName} + * @example */ -StrLen(String) => Integer +SysGetIPAddresses() => Array /** - * Convert the string to lowercase. + * @description {@link https://www.autohotkey.com/docs/v2/lib/Math.htm#Tan|`Tan()`} + * Returns the trigonometric tangent of the number. + * Convert radians to degrees: `Value * 180/pi` (180/pi = ~57.29578) + * Convert degrees to radians: `Value * pi/180` (pi/180 = ~0.01745329252) + * @param {(Number)} Num + * The number to get the tangent value of. + * Must be expressed in radians. + * @returns {(Float)} + * Tangent of `Num`. + * @example Tangent Example. + * Tan(1.2) => 2.572152 + */ +Tan(Num) => Float + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm|`Thread()`} + * Sets the priority or interruptibility of threads. It can also temporarily disable all timers. + * @param {'NoTimers'|'Priority'|'Interrupt'} Option + * A thread option to adjust: + * - {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm#NoTimers|NoTimers} = Sets when a thread can be interruptible by a {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm|timer}. + * By default, this is setting is false. + * Timers become interruptible when: + * - The {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|current thread} ends + * - `Thread('NoTimers', false)` is called + * - It is interrupted by another thread that allows timers. + * + * - {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm#Priority|Priority} = Change the priority level of the current thread. + * The function {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm|Critical()} is generally preferred over this due to its ability to buffer events. + * Calling this only affects the current thread. + * - {@link https://www.autohotkey.com/docs/v2/lib/Thread.htm#Interrupt|Interrupt} = Change the duration of the interruptibility for newly launched threads. + * By default, every new launched thread is uninterruptible for 15 milliseconds or 1000 lines of the script have executed (whichever comes first). + * This is a global setting and calling this affects all subsequent threads. + * @param {(Integer)} [NewSetting] + * Dependent on the option in use: + * - `NoTimers`: + * - `1`, Omitted = Timers cannot interrupt this thread. + * - `0` = Timers can interrupt this thread. + * - `Priority`: + * Set the priority level to a number between `-2147483648` and `2147483647`. + * This does not affect other threads. + * - `Interrupt`: + * Set the duration of the interruptibility in milliseconds. + * Default is 15. + * - `0` = Newly launched thread is immediately interruptible. + * - `-1` = The thread cannot be interrupted. + * - Number = The number of milliseconds the thread is uninterruptible. + * - Omit = Setting is not changed. Used when setting LineCount only. + * @param {(Integer)} [LineCount] + * Only useable with the `Interrupt` option. + * - `0` = Newly launched thread is immediately interruptible. + * - `-1` = The thread cannot be interrupted. + * - Number = Set the amount of lines that can execute before the thread is interruptible. + * - Omit = Setting is not changed. Used when setting `NewSetting` duration only. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm|Critical()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Hotkey.htm|Hotkey()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm|SetTimer()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|Threads} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu object} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} + * @example + */ +Thread(Option [,NewSetting, LineCount]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/ToolTip.htm|`ToolTip()`} + * Shows an always-on-top window anywhere on the screen. + * @param {(String)} [Text] + * The text to display in the tooltip. + * If omitted, the tooltip is hidden. + * @param {(Integer)} [X] + * The X offset of the tooltip relative to the mouse cursor. + * @param {(Integer)} [Y] + * The Y offset of the tooltip relative to the mouse cursor. + * @param {(Integer)} [ID] + * The ID of the tooltip to work with. + * This can be `1` through `20` and defaults to `1` if omitted. + * @returns {(Integer)} + * If the tooltip is being shown or updated, the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|window handle (HWND)} is returned. + * This handle can be used to move the tooltip as well as use {@link https://learn.microsoft.com/windows/win32/controls/bumper-tooltip-control-reference-messages|tooltip control messages}. + * `0` is returned when the tooltip his destroyed. + * This happens when `Text` is an empty string or ToolTip() is called wth no parameters. + * @see {@link https://www.autohotkey.com/docs/v2/lib/CoordMode.htm|CoordMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/TrayTip.htm|TrayTip()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|MsgBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm|InputBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|FileSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|GUI} | + * {@link https://learn.microsoft.com/windows/win32/controls/bumper-tooltip-control-reference-messages|Tooltip control messages} + * @example + */ +ToolTip([Text:='', X:=0, Y:=0, ID:=1]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/TraySetIcon.htm|`TraySetIcon()`} + * Changes the script's {@link https://www.autohotkey.com/docs/v2/Program.htm#tray-icon|tray icon} (also used by {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|GUI} and dialog windows). + * @param {(String)} [FileName] + * The path to an icon or image. A {@link https://www.autohotkey.com/docs/v2/misc/ImageHandles.htm|bitmap or icon handle} can be used. + * `*` restores the script's default icon. + * If omitted, the current tray icon is used. Only applicable when working with `Freeze`. + * Supported types: `ICO`, `CUR`, `ANI`, `EXE`, `DLL`, `CPL`, `SCR`, and `Other icon resources` + * @param {(Integer)} [IconNumber] + * Specify the number of the icon group to use. + * If negative, the number is used as a resource ID for an icon inside an executable. + * If `FileName` is omitted, `IconNumber` is ignored. + * @param {(Boolean)} [Freeze] + * Set tray icon's freeze state. + * - `1` = Icon is frozen. Things like {@link https://www.autohotkey.com/docs/v2/lib/Pause.htm|Pause()} and {@link https://www.autohotkey.com/docs/v2/lib/Suspend.htm|Suspend()} will not change the icon. + * - `0` = Icon is unfrozen and can be changed. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/TrayTip.htm|TrayTip()} | + * {@link https://www.autohotkey.com/docs/v2/lib/_NoTrayIcon.htm|#NoTrayIcon} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu object} + * @example + */ +TraySetIcon([FileName:=unset, IconNumber:=1, Freeze:=unset]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/TrayTip.htm|`TrayTip()`} + * Shows a toast notification near the {@link https://www.autohotkey.com/docs/v2/Program.htm#tray-icon|tray icon}. For pre-Windows 10, this is a balloon notification. + * @param {(String)} [Text] + * The message to display. There is a display limit of 256 characters. + * Linefeed `` `n `` and carriage return `` `r `` can be used to make new lines. + * If omitted or an empty string, no text is shown and the tray tip becomes shorter. + * @param {(String)} [Title] + * The title of the TrayTip. There is a display limit of 75 characters. + * If omitted or an empty string, no text is shown and the tray tip becomes shorter. + * @param {String|'IconI'|'Icon!'|'IconX'|'Mute'|String|Integer} [Options] + * Zero or more of the following options. + * If the string version is used, separate items with a space or tab. + * If a dec or hex is used, use the sum of the numbers for multiple options. + * Icons will not show if a TrayTip lacks a title. + * Defaults to `0`. + * | -Function- | -Dec- | -Hex- | -String- | + * | ---: | :--: | :--: | :--- | + * | `No icon` | `0` | `0x0` | `N/A` | + * | `Info icon` | `1` | `0x1` | `IconI` | + * | `Warning icon` | `2` | `0x2` | `Icon!` | + * | `Error icon` | `3` | `0x3` | `IconX` | + * | `Tray icon` | `4` | `0x4` | `N/A` | + * | `No notify sound` | `16` | `0x10` | `Mute` | + * | `Use large icon` | `32` | `0x20` | `N/A` | + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ToolTip.htm|ToolTip()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTimer.htm|SetTimer()} | + * {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|MsgBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm|InputBox()} | + * {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|FileSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu object} | + * {@link https://www.autohotkey.com/docs/v2/Scripts.htm#continuation|Continuation Section} + * @example + */ +TrayTip([Text:='', Title:='', Options:=0]) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Trim.htm|`Trim()`} + * Trims characters from the beginning and end of a string. + * @param {(String)} Str + * The string to trim. + * @param {'`n'|'`r'|'`r`n'|'`t'|' '|'`n`r`t '|String} [OmitChars] + * The characters to trim off. + * These characters are case-sensitive. + * If omitted, space and tab are used. + * @returns {(String)} + * The string after being trimmed. + * @example + */ +Trim(Str [,OmitChars:=' `t']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/Type.htm|`Type()`} + * Returns the class name of a value. + * @param {(Any)} Value + * The value to check. + * @returns {(String)} + * The class type of the given value. + * @see {@link https://www.autohotkey.com/docs/v2/Concepts.htm#values|Values} | + * {@link https://www.autohotkey.com/docs/v2/Language.htm#expressions|Expressions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Integer.htm|Integer} | + * {@link https://www.autohotkey.com/docs/v2/lib/Float.htm|Float} | + * {@link https://www.autohotkey.com/docs/v2/lib/String.htm|String} | + * {@link https://www.autohotkey.com/docs/v2/lib/Is.htm|Is functions} + * @example */ -StrLower(String) => String +Type(Value) => String /** - * Returns the current memory address of the string. + * @description {@link https://www.autohotkey.com/docs/v2/lib/VarSetStrCapacity.htm|`VarSetStrCapacity()`} + * Enlarges a variable's holding capacity or frees its memory. + * This is not normally needed, but may be used with {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()}, {@link https://www.autohotkey.com/docs/v2/lib/SendMessage.htm|SendMessage()}, or to optimize repeated concatenation. + * @param {(VarRef)} TargetVar + * A variable reference to a string to set the capacity of. + * This is not limited to string variables. Dynamic variables like `arr%i%` and {@link https://www.autohotkey.com/docs/v2/Functions.htm#ByRef|function ByRef parameters} can be used. + * @param {(Integer)} [Capacity] + * Specify the number of characters the variable should be able to hold, not including the null terminator. + * For performance reasons, variables are not shrunk in size when `Capacity` is less than the current variable size. + * - `0` = Frees the memory of the variable + * - `-1` = Update the variable's internal string length based on its current contents. + * Useful when something outside of AHK alters the string's contents. + * @returns {(Integer)} + * The number of characters that `TargetVar` can now hold. + * This number may return greater than the `RequestedCapacity`. + * If no `Capacity` is provided, the current capacity of `TargetVar` is returned. + * @throws TargetError - `TargetVar` is not a valid variable reference + * @throws ValueError - `Capacity` is less than `-1` + * @throws ValueError - `Capacity` is greater than the available memory + * @throws MemoryError - The requested capacity is too large to fit within any single contiguous memory block + * @see {@link https://www.autohotkey.com/docs/v2/lib/NumGet.htm|NumGet()} | + * {@link https://www.autohotkey.com/docs/v2/lib/NumPut.htm|NumPut()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm|DllCall()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Buffer.htm|Buffer object} + * @example + */ +VarSetStrCapacity(&TargetVar [,Capacity:=unset]) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/VerCompare.htm|`VerCompare()`} + * Compares two version strings. + * Each version is delimited into groups by the version dots. + * Each group is compared numerically, not by character codes: `v1.01` = `v1.1` + * A missing group is `0`: `1.37.0.0` = `1.37` + * Pre-releases are considered lower than standard versions: `2.0` > `2.0-alpha.1` + * @param {'<'|'<='|'>'|'>='|'='} VersionA + * A string containing a version. + * Can optionally start with one of these operators: `<` `<=` `>` `>=` `=` + * These operators do not affect the comparison: `2.0` = `>2.0` = `<2.0` + * @param {'<'|'<='|'>'|'>='|'='} VersionB + * A string containing a version to compare against `VersionA` + * Can optionally start with one of these operators: `<` `<=` `>` `>=` `=` + * These operators do not affect the comparison: `2.0` = `>2.0` = `<2.0` + * @returns {(Integer)} + * An integer representing the relationship between the two versions: + * - Positive Integer = `VersionA` is greater than `VersionB` + * - `0` = Both versions are considered equals + * - Negative Integer = `VersionB` is greater than `VersionA` + * @see {@link https://www.autohotkey.com/docs/v2/lib/Sort.htm#callback|Sort() callbacks} | + * {@link https://www.autohotkey.com/docs/v2/lib/StrCompare.htm|StrCompare()} | + * {@link https://www.autohotkey.com/docs/v2/lib/_Requires.htm|#Requires} + * @example */ -StrPtr(Value) => Integer +VerCompare(VersionA, VersionB) => Integer /** - * Copy the string to the memory address, you can choose to convert it to the given code page. - * If Target, Length, and Encoding are omitted, this function returns the required buffer size in bytes, including space for the null-terminator. - * @overload StrPut(String, Encoding := 'UTF-16') => Integer - * @param Target class buffer object or memory address, the string will be written into it. - * @param Length The maximum number of characters to be written, including the null terminator when necessary. - * - * If Length is 0 or less than the planned length after conversion (or the length of the source string when conversion is not required), an exception is thrown. - * - * Unless the buffer size is known to be large enough, Length cannot be omitted, for example, if the buffer is allocated based on StrPut that was previously called with the same Source and Encoding. - * @param Encoding "UTF-8", "UTF-16" or "CP936". For numeric identifiers, the prefix "CP" can be omitted only when Length is specified. Specify an empty string or "CP0" to use the system The default ANSI code. - * @returns returns the number of bytes written. If Target is not specified, it returns the necessary buffer size in bytes. If Length is exactly equal to the length of the source string, then the string does not contain the null terminator; otherwise it returns The size includes the null terminator. + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|`WinActivate()`} + * Activates the specified window. + * This will automatically restore a minimized window before activating it. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinActivateBottom.htm|WinActivateBottom()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|WinActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitActive.htm|WinWaitActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinClose.htm|WinClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupActivate.htm|GroupActivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/_WinActivateForce.htm|#WinActivateForce} + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinActivate([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinActivateBottom.htm|`WinActivateBottom()`} + * Activates the bottommost matching window rather than the topmost. + * Similar to {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|WinActivate()}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|WinActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitActive.htm|WinWaitActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupActivate.htm|GroupActivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} | + * {@link https://www.autohotkey.com/docs/v2/lib/_WinActivateForce.htm|#WinActivateForce} + * @example + */ +WinActivateBottom([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|`WinActive()`} + * Checks if the specified window is active and returns its unique ID (HWND). + * On success, this function sets {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|unique ID (HWND)} if the active window matches the specified criteria, otherwise `0`. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|WinActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitActive.htm|WinWaitActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} | + * {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} + * @example + * ; Quickly get active window's ID + * id := WinActive('A') + */ +WinActive([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinClose.htm|`WinClose()`} + * Closes the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [SecToWait] + * The number of seconds to wait for the window to close. + * If omitted, the function does not wait. + * When the wait time is up, the script continues regardless of successful closing. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * No exception is thrown when a window is found but cannot be closed + * Use {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} or {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinKill.htm|WinKill()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ProcessClose.htm|ProcessClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|WinActivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|WinActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitActive.htm|WinWaitActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupActivate.htm|GroupActivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinClose([WinTitle:='', WinText:='', SecToWait:=unset, NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|`WinExist()`} + * Checks if the specified window exists and returns the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|unique ID (HWND)} of the first matching window. + * On success, this function sets {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|unique ID (HWND)} of the first matching window, otherwise `0`. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|WinActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ProcessExist.htm|ProcessExist()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinActivate.htm|WinActivate()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitActive.htm|WinWaitActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/_HotIf.htm|#HotIf} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinExist([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|`WinGetClass()`} + * Retrieves the specified window's class name. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|class name} of the specified window. + * @throws TargetError - Window could not be found + * @throws OSError - The class name could not be retrieved + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetClass([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetClientPos.htm|`WinGetClientPos()`} + * Retrieves the position and size of the specified window's client area. + * Systems with multiple screens with different DPI settings may return different sizes/positions than expected due to {@link https://www.autohotkey.com/docs/v2/misc/DPIScaling.htm|OS DPI scaling}. + * @param {(VarRef)} [OutX] + * A reference to a variable to receive the X coordinate of the window. + * The point references the upper left corner of the client window. + * The client area is the main part of the application and excludes the title bar and window border. + * @param {(VarRef)} [OutY] + * A reference to a variable to receive the Y coordinate of the window. + * The point references the upper left corner of the client window. + * The client area is the main part of the application and excludes the title bar and window border. + * @param {(VarRef)} [OutWidth] + * A reference to a variable to receive the Width of the client area in pixels. + * @param {(VarRef)} [OutHeight] + * A reference to a variable to receive the Height of the client area in pixels. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetPos.htm|WinGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMove.htm|WinMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetPos.htm|ControlGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetText.htm|WinGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetText.htm|ControlGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetClientPos([&OutX, &OutY, &OutWidth, &OutHeight, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetControls.htm|`WinGetControls()`} + * Returns the control names for all controls in the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Array)} + * An array containing the {@link https://www.autohotkey.com/docs/v2/lib/GuiControl.htm#ClassNN|ClassNN} of every control. + * The order is based on the control's z-order which is usually the order they're declared and the order of focus when tabbing. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetControlsHwnd.htm|WinGetControlsHwnd()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetControls([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Array + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetControlsHwnd.htm|`WinGetControlsHwnd()`} + * Returns the unique ID numbers for all controls in the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Array)} + * An array containing the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|window handle (HWND)} of every control. + * The order is based on the control's z-order which is usually the order they're declared and the order of focus when tabbing. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetControls.htm|WinGetControls()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetControlsHwnd([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Array + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetCount.htm|`WinGetCount()`} + * Returns the number of existing windows that match the specified criteria. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The number of existing windows that match the specified criteria, otherwise `0`. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetList.htm|WinGetList()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetCount([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|`WinGetID()`} + * Returns the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|unique ID number} of the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|window handle (HWND)} of the specified window. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetIDLast.htm|WinGetIDLast()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetHwnd.htm|ControlGetHwnd()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Hwnd|Gui.Hwnd} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetID([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetIDLast.htm|`WinGetIDLast()`} + * Returns the unique ID number of the last/bottommost window if there is more than one match. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|window handle (HWND)} of the bottommost (last) window. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetHwnd.htm|ControlGetHwnd()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#Hwnd|Gui.Hwnd} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetIDLast([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetList.htm|`WinGetList()`} + * Returns the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|unique ID numbers} of all existing windows that match the specified criteria. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * A Window title is optional and must come before any `ahk_` criteria. + * If `A` is used, the active window is used. + * If all params are omitted, all windows on the system will be retrieved. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Array)} + * An array containing the {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|window handle (HWND)} of every existing window. + * The order of windows is from topmost to bottommost (z-order). + * If no windows are matched, the array is empty. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetCount.htm|WinGetCount()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetList([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Array + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetMinMax.htm|`WinGetMinMax()`} + * Returns the state whether the specified window is maximized or minimized. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * A number indicating the state of the window: + * - `1` = Window is maximized + * Use {@link https://www.autohotkey.com/docs/v2/lib/WinRestore.htm|WinRestore()} to revert from maximize. + * - `-1` = Window is minimized + * Use {@link https://www.autohotkey.com/docs/v2/lib/WinRestore.htm|WinRestore()} to revert from minimize. + * - `0` = Window is normal (not minimized or maximized) + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMaximize.htm|WinMaximize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMinimize.htm|WinMinimize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetMinMax([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|`WinGetPID()`} + * Returns the Process ID number of the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|Process ID (PID)} of the specified window. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetPID([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetPos.htm|`WinGetPos()`} + * Retrieves the position and size of the specified window. + * Systems with multiple screens with different DPI settings may return different sizes/positions than expected due to {@link https://www.autohotkey.com/docs/v2/misc/DPIScaling.htm|OS DPI scaling}. + * @param {(VarRef)} [OutX] + * A reference to a variable to receive the X coordinate of the window. + * The point references the upper left corner of the window. + * @param {(VarRef)} [OutY] + * A reference to a variable to receive the Y coordinate of the window. + * The point references the upper left corner of the window. + * @param {(VarRef)} [OutWidth] + * A reference to a variable to receive the Width of the window in pixels. + * @param {(VarRef)} [OutHeight] + * A reference to a variable to receive the Height of the window in pixels. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMove.htm|WinMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClientPos.htm|WinGetClientPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetPos.htm|ControlGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetText.htm|WinGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetText.htm|ControlGetText()} + * @example + */ +WinGetPos([&OutX, &OutY, &OutWidth, &OutHeight, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|`WinGetProcessName()`} + * Returns the name of the process that owns the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The process name that owns the specified window. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetProcessName([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|`WinGetProcessPath()`} + * Returns the full path and name of the process that owns the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @returns {(String)} + * The full path of the process that owns the specified window. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Process.htm|Process functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetProcessPath([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|`WinGetStyle()`} + * Returns the style of the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|style} of the specified window. + * @throws TargetError - Window could not be found + * @throws OSError - The class name could not be retrieved + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinSetStyle.htm|WinSetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinSetStyle.htm|WinSetExStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetStyle.htm|ControlGetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetStyle.htm|ControlGetExStyle()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Styles table} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetStyle([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|`WinGetExStyle()`} + * Returns the extended style of the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|extended style} of the specified window. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinSetStyle.htm|WinSetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinSetStyle.htm|WinSetExStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetStyle.htm|ControlGetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetStyle.htm|ControlGetExStyle()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Styles table} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetExStyle([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetText.htm|`WinGetText()`} + * Retrieves the text from the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The text of the specified window. + * @throws TargetError - Window could not be found + * @throws OSError - There was a problem retrieving the window's text + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlGetText.htm|ControlGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPos.htm|WinGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetText([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|`WinGetTitle()`} + * Retrieves the title of the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The title of the specified window. + * An empty string is returned if no matching window is found. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinSetTitle.htm|WinSetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetText.htm|WinGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetText.htm|ControlGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPos.htm|WinGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetTitle([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetTransColor.htm|`WinGetTransColor()`} + * Returns the color that is marked transparent in the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * The six-digit RGB color marked as transparent by the target window. + * The number includes a hex prefix: `0x0099FF` + * An empty string is returned if: + * - No window matches + * - No transparency is set + * - A window has been altered (minimized/resized/restored) since being made transparent + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransColor.htm|WinSetTransColor()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTransparent.htm|WinGetTransparent()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetTransColor([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinGetTransparent.htm|`WinGetTransparent()`} + * Returns the degree of transparency of the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer|String)} + * The level of window transparency from `0` (invisible) to `255` (opaque). + * An empty string is returned if: + * - No window matches + * - No transparency is set + * - A window has been altered (minimized/resized/restored) since being made transparent + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransparent.htm|WinSetTransparent()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTransColor.htm|WinGetTransColor()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinGetTransparent([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinHide.htm|`WinHide()`} + * Hides the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * This does not apply when using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|window group}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinShow.htm|WinShow()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinHide([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinKill.htm|`WinKill()`} + * Forces the specified window to close. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * This does not apply when using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|window group}. + * No exception is thrown when a window is found but cannot be closed + * Use {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} or {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} + * @see {@link https://www.autohotkey.com/docs/v2/lib/ProcessClose.htm|ProcessClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinClose.htm|WinClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinKill([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinMaximize.htm|`WinMaximize()`} + * Enlarges the specified window to its maximum size. + * {@link https://www.autohotkey.com/docs/v2/lib/WinRestore.htm|WinRestore()} can remove the maximize state and return it to prior size and position. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * This does not apply when using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|window group}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinRestore.htm|WinRestore()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMinimize.htm|WinMinimize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinMaximize([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinMinimize.htm|`WinMinimize()`} + * Collapses the specified window into a button on the task bar. + * {@link https://www.autohotkey.com/docs/v2/lib/WinRestore.htm|WinRestore()} can remove the maximize state and return it to prior size and position. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * This does not apply when using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|window group}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinRestore.htm|WinRestore()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMaximize.htm|WinMaximize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMinimizeAll.htm|WinMinimizeAll()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinMinimize([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinMinimizeAll.htm|`WinMinimizeAll()`} + * Minimizes all windows. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMinimize.htm|WinMinimize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm|GroupAdd()} + * @example + * WinMinimizeAll() + * Sleep(1000) + * WinMinimizeAllUndo() + */ +WinMinimizeAll() => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinMinimizeAll.htm|`WinMinimizeAllUndo()`} + * Un-minimizes all windows. + * @returns {(String)} + * An empty string is always returned. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMinimize.htm|WinMinimize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm|GroupAdd()} + * @example + * WinMinimizeAll() + * Sleep(1000) + * WinMinimizeAllUndo() + */ +WinMinimizeAllUndo() => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinMove.htm|`WinMove()`} + * Changes the position and/or size of the specified window. + * Systems with multiple screens with different DPI settings may return different sizes/positions than expected due to {@link https://www.autohotkey.com/docs/v2/misc/DPIScaling.htm|OS DPI scaling}. + * @param {(Integer)} [X] + * The new x coordinate of the window. + * This marks the window's upper left corner. + * If omitted, nothing changes and the original value is used. + * @param {(Integer)} [Y] + * The new y coordinate of the window. + * This marks the window's upper left corner. + * If omitted, nothing changes and the original value is used. + * @param {(Integer)} [Width] + * New window width in pixels. + * If omitted, nothing changes and the original value is used. + * @param {(Integer)} [Height] + * New window height in pixels. + * If omitted, nothing changes and the original value is used. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - An internal function reported a failure. + * Success may be reported even if the window doesn't move, such as it being restricted from moving by its own rules. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlMove.htm|ControlMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPos.htm|WinGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinHide.htm|WinHide()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMinimize.htm|WinMinimize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMaximize.htm|WinMaximize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessPath.htm|WinGetProcessPath()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetProcessName.htm|WinGetProcessName()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetClass.htm|WinGetClass()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetID.htm|WinGetID()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPID.htm|WinGetPID()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinMove([X, Y, Width, Height, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinMoveBottom.htm|`WinMoveBottom()`} + * Sends the specified window to the bottom of stack; that is, beneath all other windows. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - May be thrown on error + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMoveTop.htm|WinMoveTop()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinSetAlwaysOnTop.htm|WinSetAlwaysOnTop()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinMoveBottom([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinMoveTop.htm|`WinMoveTop()`} + * Brings the specified window to the top of the stack without explicitly activating it. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - May be thrown on error + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMoveBottom.htm|WinMoveBottom()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinSetAlwaysOnTop.htm|WinSetAlwaysOnTop()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinMoveTop([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinRedraw.htm|`WinRedraw()`} + * Redraws the specified window. + * If redraw doesn't work, try {@link https://www.autohotkey.com/docs/v2/lib/WinMove.htm|WinMove()} or try {@link https://www.autohotkey.com/docs/v2/lib/WinHide.htm|WinHide()} then {@link https://www.autohotkey.com/docs/v2/lib/WinShow.htm|WinShow()}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMoveBottom.htm|WinMoveBottom()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinSetAlwaysOnTop.htm|WinSetAlwaysOnTop()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinRedraw([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinRestore.htm|`WinRestore()`} + * Restore a specified window from a minimized or maximized state to its original position and size. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * This does not apply when using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|window group}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMinimize.htm|WinMinimize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMaximize.htm|WinMaximize()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinRestore([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinSetAlwaysOnTop.htm|`WinSetAlwaysOnTop()`} + * Makes the specified window stay on top of all other windows (except other always-on-top windows). + * @param {(Integer)} [NewSetting] + * - `1` = Set to on. + * - `0` = Set to off. + * - `-1` = Toggle between current state. on <-> off + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - May be thrown on failure. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMoveTop.htm|WinMoveTop()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinMoveBottom.htm|WinMoveBottom()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinSetAlwaysOnTop([NewSetting:=1, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinSetEnabled.htm|`WinSetEnabled()`} + * Enables or disables the specified window. + * @param {(Integer)} [NewSetting] + * - `1` = Set to enabled. + * - `0` = Set to disabled. + * - `-1` = Toggle between current state. enabled <-> disabled + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - The change could not be applied + * @see {@link https://www.autohotkey.com/docs/v2/lib/ControlSetEnabled.htm|ControlSetEnabled()} + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinSetEnabled([NewSetting:=1, WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinSetRegion.htm|`WinSetRegion()`} + * Changes the shape of the specified window to be the specified rectangle, ellipse, or polygon. + * @param {String|'W'|'H'|'X-Y'|'E'|'R'|'Polygons'|'Wind'} [Options] + * Zero or more of the following, separated by spaces: + * - Omit - Restores window to original/default display area. + * - `W#` `H#` = Set the width of the rectangle or ellipse in pixels: `w100 h450` + * - `X-Y` = An x-y coordinate pair set: `300-400` + * These coordinate pairs can be used multiple times when making a polygon. + * - `E` = Sets region shape to ellipse instead of rectangle. + * The `W` and `H` options must be present. + * - `R#-#` = Creates rounded corners on a rectangular region. + * The `#-#` represents the width-height of the ellipse used to round the corners. + * The `W` and `H` options must be present. + * - Polygons = If `W` and `H` are omitted, the new display area is a polygon. + * Multiple `X-Y` sets can be used to define the shape of the polygon. + * - `Wind` = Use the winding method instead of the alternating method to determine the polygon region. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws ValueError - One or more options are invalid + * @throws OSError - The specified region is invalid + * @throws OSError - The specified region could not be applied to the target window + * @see {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinSetRegion([Options:='', WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinSetStyle.htm|`WinSetStyle()`} + * Changes the style of the specified window. + * @param {(String|Integer)} Value + * The {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|style} to add, remove, or toggle from the current style. + * | -Operation- | -Example- | -Formula- | + * | :--- | :--: | :--- | + * | `+` Add | `+0x80` | NewStyle := CurrentStyle | Value | + * | `-` Remove | `-0x80` | NewStyle := CurrentStyle & ~Value | + * | `^` Toggle | `^0x80` | NewStyle := CurrentStyle ^ Value | + * + * If `Value` is a number, `'+'` and `'^'` can be prefixed as a string: `'+' new_style` + * The current style can be retrieved with {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|WinGetStyle()}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - The change could not be applied + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|WinGetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSetStyle.htm|ControlSetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Styles table} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinSetStyle(Value [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinSetStyle.htm|`WinSetExStyle()`} + * Changes the extended style of the specified window. + * @param {(String|Integer)} Value + * The {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|extended style} to add, remove, or toggle from the current style. + * | -Operation- | -Example- | -Formula- | + * | :--- | :--: | :--- | + * | `+` Add | `+0x80` | NewExStyle := CurrentExStyle | Value | + * | `-` Remove | `-0x80` | NewExStyle := CurrentExStyle & ~Value | + * | `^` Toggle | `^0x80` | NewExStyle := CurrentExStyle ^ Value | + * + * If `Value` is a number, `'+'` and `'^'` can be prefixed as a string: `'+' newExStyle` + * The current extended style can be retrieved with {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|WinGetExStyle()}. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - The change could not be applied + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinGetStyle.htm|WinGetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlSetStyle.htm|ControlSetStyle()} | + * {@link https://www.autohotkey.com/docs/v2/misc/Styles.htm|Styles table} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinSetExStyle(Value [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinSetTitle.htm|`WinSetTitle()`} + * Changes the title of the specified window. + * @param {(String)} NewTitle + * The window's new title. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - The change could not be applied + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinMove.htm|WinMove()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetTitle.htm|WinGetTitle()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetText.htm|WinGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ControlGetText.htm|ControlGetText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinGetPos.htm|WinGetPos()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinSetTitle(NewTitle [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransColor.htm|`WinSetTransColor()`} + * Makes all pixels of the chosen color invisible inside the specified window. + * @param {(String|Integer)} ColorAndTrans + * An RGB hex value and/or a transparency. + * Color must be a 6-digit RGB hex value: `00FFbb` + * Alpha must come after the color and have a space before it: `FFcc88 128` + * To adjust only transparency, use alpha prefixed by a space: ` 255` + * `Off` or an empty string transparency and performs better than using `255`. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - The change could not be applied + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransparent.htm|WinSetTransparent()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinSetTransColor(Color [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransparent.htm|`WinSetTransparent()`} + * Makes the specified window semi-transparent. + * @param {(String|Integer)} NewSetting + * Specify a transparency number or disable it. + * `0`-`255` = Enable transparency for window. `0` is invisible, `255` is opaque. + * `Off` or Empty String = Disables transparency and performs better than using `255`. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * @throws OSError - The change could not be applied + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinSetTransColor.htm|WinSetTransColor()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinSetTransparent(NewSetting [,WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinShow.htm|`WinShow()`} + * Unhides the specified window. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(String)} + * An empty string is always returned. + * @throws TargetError - Window could not be found + * This does not apply when using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|window group}. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinHide.htm|WinHide()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinShow([WinTitle:='', WinText:='', NoWinTitle:='', NoWinText:='']) => EmptyString + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|`WinWait()`} + * Waits until the specified window exists. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(Number)} [Timeout] + * The max amount of seconds to wait. + * This number can be a float for higher precision. + * If omitted, the function waits indefinitely. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|`unique ID (HWND)`} if a matching window is found, otherwise `0`. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinWaitActive.htm|WinWaitActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|WinActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/ProcessWait.htm|ProcessWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinWait([WinTitle:='', WinText:='', Timeout:=unset, NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinWaitActive.htm|`WinWaitActive()`} + * Waits until the specified window is active. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(Number)} [Timeout] + * The max amount of seconds to wait. + * This number can be a float for higher precision. + * If omitted, the function waits indefinitely. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * The {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|`unique ID (HWND)`} if a matching window is found, otherwise `0`. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|WinActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinWaitActive([WinTitle:='', WinText:='', Timeout:=unset, NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinWaitActive.htm|`WinWaitNotActive()`} + * Waits until the specified window is not active. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(Number)} [Timeout] + * The max amount of seconds to wait. + * This number can be a float for higher precision. + * If omitted, the function waits indefinitely. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * `1` if the active window does not match the criteria, otherwise `0` if the function timed out. + * @see {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|WinWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|WinActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinWaitNotActive([WinTitle:='', WinText:='', Timeout:=unset, NoWinTitle:='', NoWinText:='']) => Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/lib/WinWaitClose.htm|`WinWaitClose()`} + * Waits until no matching windows can be found. + * @param {'ahk_exe '|'ahk_class '|'ahk_id '|'ahk_pid '|'ahk_group '} [WinTitle] + * A string using a {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle} to match a window. + * Types: {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_exe|ahk_exe}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_class|ahk_class}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_id|ahk_id}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_pid|ahk_pid}, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_group|ahk_group} + * Window title is optional and must come before any `ahk_` criteria. + * If WinTitle is the letter `A`, the active window is used. + * If all `Win` params are omitted, {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} is used. + * @param {(String)} [WinText] + * Text that must be found in the window. + * WindowSpy, found in the AHK install folder, can be used to see window text. + * @param {(Number)} [Timeout] + * The max amount of seconds to wait. + * This number can be a float for higher precision. + * If omitted, the function waits indefinitely. + * @param {(String)} [NoWinTitle] + * Window title does not contain this text. + * @param {(String)} [NoWinText] + * Text that must not appear in the window. + * Use WindowSpy to view window text. + * @returns {(Integer)} + * `1` if the window closed, otherwise `0` if the function timed out. + * @see {@link https://www.autohotkey.com/docs/v2/lib/ProcessWaitClose.htm|ProcessWaitClose()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinClose.htm|WinClose()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinWait.htm|WinWait()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinWaitActive.htm|WinWaitActive()} + * {@link https://www.autohotkey.com/docs/v2/lib/WinExist.htm|WinExist()} | + * {@link https://www.autohotkey.com/docs/v2/lib/WinActive.htm|WinActive()} | + * {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Win functions} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} | + * {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} | + * {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitle Window Matching} | + * {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#LastFoundWindow|Last Found Window} + * @example + */ +WinWaitClose([WinTitle:='', WinText:='', Timeout:=unset, NoWinTitle:='', NoWinText:='']) => Integer +;@endregion + +;@region vars +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#AhkPath|A_AhkPath} + * - If embedded or not compiled: + * The full path and name of the AutoHotkey file that is running the current script. + * Example: `C:\Program Files\AutoHotkey\AutoHotkey.exe` + * - If compiled .exe file: + * Contains the full path of the compiled script. + * This can be used in combination with {@link https://www.autohotkey.com/docs/v2/Scripts.htm#SlashScript|/script} to execute external scripts. + * - If compiled .bin file: + * The installation path recorded in the registry for AutoHotkey is used and `\AutoHotkey.exe` is appended. + * If AutoHotkey is not found in the registry, this variable will be an empty string. + * @type String + * @example + * MsgBox('The current AHK path is: ' A_AhkPath) + * + * ; Running a file using the AHK interpreter that's running the current script: + * Run(AhkPath ' /script "C:\Some\Path\my_script.ahk"') + * + * ; This is the code used for determining the path for a compiled file: + * InstallDir := RegRead('HKLM\SOFTWARE\AutoHotkey', 'InstallDir', '') + * AhkPath := InstallDir ? InstallDir '\AutoHotkey.exe' : '' */ -StrPut(String [, Target [, Length]], Encoding := 'UTF-16') => Integer +A_AhkPath: String /** - * Replace the specified substring with a new string. - * @param CaseSense One of the following values (if omitted, the default is 0): - * - * "On" or 1 (True): Search is case sensitive. - * - * "Off" or 0 (False): The letters A-Z are considered the same as their lowercase letters. - * - * "Locale": According to the current user's locale rules, the search is not case sensitive. For example, in most English and Western European regions, not only treats AZ as equivalent to their lowercase form, but also treats non-ASCII letters ( Such as Ä and Ü) are considered equivalent. Depending on the nature of the string being compared, Locale is 1 to 8 times slower than Off. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#AhkVersion|A_AhkVersion} + * Contains the version of AutoHotkey that is running the script. + * v2 uses {@link https://semver.org/|semantic versioning}: `2.0.11` + * Compiled scripts will report the version of AHK bundled with the exe. + * Version comparison is allowed: `(A_AhkVersion >= '2.0.1')` + * Remember that this is a string, not a number. + * @type String + * @see {@link https://www.autohotkey.com/docs/v2/lib/_Requires.htm|#Requires} | + * {@link https://www.autohotkey.com/docs/v2/lib/VerCompare.htm|VerCompare} + * @example + * ; Showing the current version + * MsgBox('This script is being ran by version: ' A_AhkVersion) + * + * ; Comparing the current version + * if VerCompare(A_AhkVersion, '<2.0.11') + * MsgBox('You probably need to update you AHK.') + * else MsgBox('Your AHK version is at least 2.0.11') */ -StrReplace(Haystack, SearchText, ReplaceText?, CaseSense := false, &OutputVarCount?: VarRef, Limit := -1) => String +A_AhkVersion: String /** - * Use the specified delimiter to divide the string into an array of substrings. - * @param Delimiters If this parameter is empty or omitted, each character in the input string will be parsed as a separate substring. - * Delimiters can be a single string or an array of strings, and each delimiter is used to determine where the boundary between substrings appears. - * - * Using `[A_Tab, A_Space]` as a separator will create a new array element every time a space or tab is encountered in the input string. - * @param OmitChars Optional list of characters (case sensitive), used to remove these characters from the beginning and end of each array element. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#AllowMainWindow|A_AllowMainWindow} + * Used to get or set whether the {@link https://www.autohotkey.com/docs/v2/Program.htm#main-window|script's main window} can be opened with the script's {@link https://www.autohotkey.com/docs/v2/Program.htm#tray-icon|tray icon}. + * This variable can be set to the following values: + * - `1` = Tray icon can activate main window. + * - `0` = Tray icon can no longer open the main window. + * This removes the "Open" option from the tray menu as well as the ability to double click the tray icon to launch the main window. + * The default value is `0`. + * If the script is {@link https://www.autohotkey.com/docs/v2/Program.htm#embedded-scripts|embedded} or {@link https://www.autohotkey.com/docs/v2/Scripts.htm#ahk2exe|compiled}, the default value is `1`. + * @type Integer + * @example + * MsgBox('Try right clicking the tray icon. Notice the "Open" option.' + * '`nAlso, double click the icon to launch the main window.' + * '`n`nClick OK to set A_AllowMainWindow to false.') + * A_AllowMainWindow := 0 + * MsgBox('Try right clicking the tray icon. "Open" no longer exists.' + * '`nDouble clicking no longer launches the main window.') */ -StrSplit(String, Delimiters?, OmitChars?, MaxParts := -1) => Array +A_AllowMainWindow: Integer /** - * @since v2.1-alpha.9 + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#AppData|A_AppData} + * This variable contains the path to the user's application data folder. + * Typically, this contains: `C:\Users\\AppData\Roaming` + * @type String + * @example + * MsgBox('Path to user`'s application data folder: ' A_AppData) */ -StructFromPtr(StructClass, Address) => Object +A_AppData: String /** - * Convert the string to uppercase. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#AppDataCommon|A_AppDataCommon} + * This variable contains the path to the common/all-user application data folder. + * Typically, this contains: `C:\ProgramData` + * @type String + * @example + * MsgBox('Path to the common application data folder: ' A_AppDataCommon) */ -StrUpper(String) => String +A_AppDataCommon: String /** - * Retrieve one or more characters from the specified position in the string. - * @param String - * @param StartingPos specifies that 1 starts from the first character, 2 starts from the second, and so on (if StartingPos is 0 or exceeds the length of the String, an empty string is returned). + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Args|A_Args} + * Contains an {@link https://www.autohotkey.com/docs/v2/Objects.htm#Usage_Simple_Arrays|array} of command line parameters. + * For details, see {@link https://www.autohotkey.com/docs/v2/Scripts.htm#cmd|Passing Command Line Parameters to a Script}. + * @type Array + * @example Showing a /restart arg + * ; If the script has no args. + * if !A_Args.Length + * ; Restart the script with some args. + * Run(A_ScriptFullPath ' /restart "Hello World"') * - * Specify a negative StartingPos to start from the right position. For example, -1 extracts the last character, and -2 extracts the last two characters (however, if StartingPos tries to exceed the left end of the string, the extraction will start from the first character Start). - * @param Length If this parameter is omitted, the default is "all characters". In other cases, it is the maximum number of characters to be extracted (when the remaining part of the string is too short, the number of extracted characters will be less than the maximum). You can still Specify a negative Length to omit this number of characters at the end of the returned string (if all or too many characters are omitted, an empty string is returned). + * ; Show all the args that were passed in. + * for value in A_Args + * MsgBox(value) */ -SubStr(String, StartingPos [, Length]) => String +A_Args: Array /** - * Disable or enable all or selected hotkeys and hotstrings. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Clipboard|A_Clipboard} + * This variable gives access to the operating system's clipboard. + * This is what's used when you use copy and paste methods such as ctrl+c and ctrl+v. + * Pasting text can be much faster than using the Send() method. + * @type String + * {@link https://www.autohotkey.com/docs/v2/lib/A_Clipboard.htm|A_Clipboard info} + * @example */ -Suspend(Mode := -1) => void +A_Clipboard: String /** - * Convert string to title case. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ComSpec|A_ComSpec} + * This variable contains the path to Window's cmd.exe (command prompt). + * Typically, this contains: `C:\Windows\system32\cmd.exe` + * This is normally used with {@link https://www.autohotkey.com/docs/v2/lib/Run.htm|Run()/RunWait()}. + * @type String + * @example + * ; A ping tester activated by typing: /pingtest + * :*?:/pingtest:: { + * ; This will ping Google's DNS server until stopped + * Run(A_ComSpec ' /c ping -t 8.8.8.8') + * ToolTip('Press control+c to stop the pinging or close the window.') + * } */ -StrTitle(String) => String +A_ComSpec: String /** - * Get the size and other system properties of the system object. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ComputerName|A_ComputerName} + * The assigned name of the computer as seen on the network. + * @type String + * @example + * MsgBox('Computer name: ' A_ComputerName) */ -SysGet(Property) => Integer +A_ComputerName: String /** - * Return the system's IPv4 address array. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ControlDelay|A_ControlDelay} + * Used to get or set the delay, in milliseconds, that occurs after {@link https://www.autohotkey.com/docs/v2/lib/Control.htm|Control functions} are used. + * This variable can be set to the following values: + * - Positive value = The amount of time to wait, in ms. + * - `0` = Use the smallest possible delay. + * - `-1` = Use no delay. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetControlDelay.htm|SetControlDelay()} + * @example + * ; This will cause a 0.5 second delay between + * ; window activation and sending the keystrokes. + * A_WinDelay := 500 + * WinActivate('ahk_exe SomeProgram.exe') + * Send('Hello, world!') */ -SysGetIPAddresses() => Array +A_ControlDelay: Integer /** - * Returns the tangent of Number. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#CoordModeCaret|A_CoordModeCaret} + * Gets or sets the coordinate mode used by {@link https://www.autohotkey.com/docs/v2/lib/CaretGetPos.htm|CaretGetPos( relative to everything else)}. + * Coordinate mode determines where x0 y0 starts. + * This variable can be set to the following values: + * - `Screen` = x0 y0 starts at the upper left corner of the main monitor. + * Though this is the default value, it's not normally the best choice. + * - `Window` = x0 y0 starts at the upper left corner of the active window. + * This includes the window's title bar and border. + * - `Client` = x0 y0 starts at the upper left corner of the client portion of the window. + * The client portion is the main part of the window and does not include the title bar and border Window's adds. + * Generally, client is the best mode to use. + * @type String + * @example + * ; Launch an instance of notepad and get its caret position + * Run('notepad.exe') + * WinWaitActive('ahk_exe notepad.exe') + * get_cursor_positions() + * + * get_cursor_positions() { + * str := '' + * ; Loop through all 3 coord mode types + * ; and save to string + * loop parse 'Screen,Window,Client', 'csv' + * A_CoordModeCaret := A_LoopField + * ,CaretGetPos(&x, &y) + * ,str .= A_LoopField ':' + * . '`nx: ' x + * . '`ny: ' y + * . '`n`n' + * ; Show the different coord mode coordinates + * MsgBox(str) + * } + */ +A_CoordModeCaret: String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#CoordModeMenu|A_CoordModeMenu} + * Gets or sets the coordinate mode used by {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm#Show|Menu.Show()}. + * Coordinate mode determines where x0 y0 starts relative to everything else. + * This variable can be set to the following values: + * - `Screen` = x0 y0 starts at the upper left corner of the main monitor. + * Though this is the default value, it's not normally the best choice. + * - `Window` = x0 y0 starts at the upper left corner of the active window. + * This includes the window's title bar and border. + * - `Client` = x0 y0 starts at the upper left corner of the client portion of the window. + * The client portion is the main part of the window and does not include the title bar and border Window's adds. + * Generally, client is the best mode to use. + * @type String + * @example + * #Requires AutoHotkey v2.0.11+ + * + * ; Use notepad so there's a window in the middle of the screen. + * Run('notepad.exe') + * WinWaitActive('ahk_exe notepad.exe') + * WinMove(A_ScreenWidth/2, A_ScreenHeight/2, A_ScreenWidth/2, A_ScreenHeight/2, 'A') + * + * ; Create a generic menu + * main_menu := Menu() + * main_menu.Add('1: Click to continue', void) + * main_menu.Add('2: Click to continue', void) + * main_menu.Add('3: Click to continue', void) + * + * ; A function for the menu items to use tha does nothing. + * void(*) => '' + * + * ; Open menu using the different coordinate modes types. + * for value in ['Screen', 'Window', 'Client'] + * MsgBox("Press OK to move mouse to the " value "'s x0 y0 position.") + * ,A_CoordModeMenu := value + * ,main_menu.Show(0,0) + */ +A_CoordModeMenu: String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#CoordModeMouse|A_CoordModeMouse} + * Gets or sets the coordinate mode used by {@link https://www.autohotkey.com/docs/v2/lib/MouseGetPos|MouseGetPos()}, {@link https://www.autohotkey.com/docs/v2/lib/Click|Click()}, {@link https://www.autohotkey.com/docs/v2/lib/MouseMove|MouseMove()}, {@link https://www.autohotkey.com/docs/v2/lib/MouseClick|MouseClick()}, and {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag|MouseClickDrag()}. + * Coordinate mode determines where x0 y0 starts relative to everything else. + * This variable can be set to the following values: + * - `Screen` = x0 y0 starts at the upper left corner of the main monitor. + * Though this is the default value, it's not normally the best choice. + * - `Window` = x0 y0 starts at the upper left corner of the active window. + * This includes the window's title bar and border. + * - `Client` = x0 y0 starts at the upper left corner of the client portion of the window. + * The client portion is the main part of the window and does not include the title bar and border Window's adds. + * Generally, client is the best mode to use. + * @type String + * @example + * ; Use notepad so there's a window in the middle of the screen. + * Run('notepad.exe') + * WinWaitActive('ahk_exe notepad.exe') + * WinMove(500, 200, A_ScreenWidth/2, A_ScreenHeight/2, 'A') + * + * ; Move the mouse to the x0 y0 position of each coordinate mode type. + * A_DefaultMouseSpeed := 10 + * for value in ['Screen', 'Window', 'Client'] + * MsgBox("Press OK to move mouse to the " value "'s x0 y0 position.") + * ,A_CoordModeMouse := value + * ,Click(0, 0, 0) + */ +A_CoordModeMouse: String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#CoordModePixel|A_CoordModePixel} + * Gets or sets the coordinate mode used by {@link https://www.autohotkey.com/docs/v2/lib/PixelGetColor.htm|PixelGetColor()}, {@link https://www.autohotkey.com/docs/v2/lib/PixelSearch.htm|PixelSearch()}, and {@link https://www.autohotkey.com/docs/v2/lib/ImageSearch.htm|ImageSearch()}. + * Coordinate mode determines where x0 y0 starts relative to everything else. + * This variable can be set to the following values: + * - `Screen` = x0 y0 starts at the upper left corner of the main monitor. + * Though this is the default value, it's not normally the best choice. + * - `Window` = x0 y0 starts at the upper left corner of the active window. + * This includes the window's title bar and border. + * - `Client` = x0 y0 starts at the upper left corner of the client portion of the window. + * The client portion is the main part of the window and does not include the title bar and border Window's adds. + * Generally, client is the best mode to use. + * @type String + * @example + * ; Use notepad so there's a window in the middle of the screen. + * Run('notepad.exe') + * WinWaitActive('ahk_exe notepad.exe') + * WinMove(500, 200, A_ScreenWidth/2, A_ScreenHeight/2, 'A') + * + * ; Get the x0 y0 pixel color of each coordinate type. + * ; Mouse moves to each pixel being checked. + * A_DefaultMouseSpeed := 10 + * for value in ['Screen', 'Window', 'Client'] + * A_CoordModeMouse := value + * ,A_CoordModePixel := value + * ,Click(0, 0, 0) + * ,color := PixelGetColor(0, 0) + * ,MsgBox('Color at ' value ' x0 y0: ' color) + */ +A_CoordModePixel: String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#CoordModeToolTip|A_CoordModeToolTip} + * Gets or sets the coordinate mode used by . + * Coordinate mode determines where x0 y0 starts relative to everything else. + * This variable can be set to the following values: + * - `Screen` = x0 y0 starts at the upper left corner of the main monitor. + * Though this is the default value, it's not normally the best choice. + * - `Window` = x0 y0 starts at the upper left corner of the active window. + * This includes the window's title bar and border. + * - `Client` = x0 y0 starts at the upper left corner of the client portion of the window. + * The client portion is the main part of the window and does not include the title bar and border Window's adds. + * Generally, client is the best mode to use. + * @type String + * @example + * ; Use notepad so there's a window in the middle of the screen. + * Run('notepad.exe') + * WinWaitActive('ahk_exe notepad.exe') + * WinMove(500, 200, A_ScreenWidth/2, A_ScreenHeight/2, 'A') + * + * ; Loop through each coordinate mode type + * for value in ['Screen', 'Window', 'Client'] + * A_CoordModeToolTip := value + * ,show_tt() + * + * ; Show tooltip for 4 seconds + * show_tt() { + * start := A_TickCount + * loop + * remain := 4000 - (A_TickCount - start) + * ,ToolTip('This tooltip is at x0 y0 using coordinate mode ' value '.' + * '`nTooltip remaining time: ' Round(remain / 1000) ' seconds' + * , 0, 0) + * ,Sleep(50) + * until (remain < 0) + * } + */ +A_CoordModeToolTip: String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Cursor|A_Cursor} + * The type of mouse cursor currently being displayed. + * It will be one of the following: + * | Cursor Name | Description | + * | :-- | :-- | + * | `AppStarting` | Arrow & hour glass | + * | `Arrow` | Arrow | + * | `Cross` | Cross | + * | `Help` | Arrow & question mark | + * | `IBeam` | I-beam shape | + * | `Icon` | Custom icon | + * | `No` | Circle with slash | + * | `Size` | 4-Point arrow | + * | `SizeAll` | 4-Point arrow | + * | `SizeNESW` | Double arrow, NE/SW | + * | `SizeNS` | Double arrow, N/S | + * | `SizeNWSE` | Double arrow, NW/SE | + * | `SizeWE` | Double arrow, E/W | + * | `UpArrow` | Vertical arrow | + * | `Wait` | Arrow & hour glass | + * | `Wait` | Rotating circle | + * | `Unknown` | Any unknown icon | + * @type String + * @see {@link https://learn.microsoft.com/en-us/windows/win32/menurc/about-cursors|MSDN Cursor Info} + * @example + * monitor_cursor() + * ; Constantly monitor the current cursor + * monitor_cursor() { + * ; Show current cursor + * ToolTip(A_Cursor) + * ; Run this function one more time in 50 ms + * SetTimer(monitor_cursor, -50) + * } */ -Tan(Number) => Float +A_Cursor: String /** - * Set the thread priority or whether it can be interrupted. It can also temporarily disable all timers. - * @overload Thread('NoTimers', TrueOrFalse) - * @overload Thread('Priority', Level) - * @overload Thread('Interrupt' [, Duration, LineCount]) - * @param {'NoTimers'|'Priority'|'Interrupt'} SubFunction + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#DD|A_DD} + * The current date in two-digit format: `00`-`31` + * This is synonymous with A_MDay. + * @type String + * @example + * MsgBox('Today`'s date is: ' A_MMMM ' ' A_DD) */ -Thread(SubFunction [, Value1, Value2]) => void +A_DD: String /** - * @since v2.1-alpha.3 + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#DDD|A_DDD} + * The abbreviated name of the current day of the week: `Sun`-`Sat` + * @type String + * @example + * MsgBox('The current day is : ' A_DDD) */ -Throw(Value*) => void +A_DDD: String /** - * Create a top window anywhere on the screen. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#DDDD|A_DDDD} + * The full name of the current day of the week: `Sunday`-`Saturday` + * @type String + * @example + * MsgBox('The current day is : ' A_DDDD) */ -ToolTip([Text, X, Y, WhichToolTip]) => Integer +A_DDDD: String /** - * Change the tray icon of the script. - * @param FileName The path of the icon or picture. For a list of supported formats, see Picture Control. - * - * Specify an asterisk (*) to restore the script to its default icon. - * @param IconNumber To use an icon group other than the first group of icons in the file, please specify its number in IconNumber (if omitted, it defaults to 1). For example, 2 will load the default icon in the second group of icons . If IconNumber is negative, it is assumed that its absolute value represents the resource ID of the icon in the executable file. - * @param Freeze Specify 1 (true) to freeze the icon, or 0 (false) to unfreeze it (or leave it blank to keep the frozen/thawed state unchanged). When the icon is frozen, Pause and Suspend will not change it. Note : To freeze or unfreeze the current icon, please use 1 (true) or 0 (false), as shown in the following example: TraySetIcon(,, 1). + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#DefaultMouseSpeed|A_DefaultMouseSpeed} + * Used to get or set the speed the mouse is moved by mouse functions. + * This value should be set between `0` (fastest) and `100` (slowest). + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetDefaultMouseSpeed.htm|SetDefaultMouseSpeed()} + * @example + * ; Set start position + * Click(0, 0, 0) + * ; Slow movement down + * A_DefaultMouseSpeed := 20 + * Click(100, 500, 0) + * ; Slow movement down even more + * A_DefaultMouseSpeed := 50 + * MouseMove(A_ScreenWidth, A_ScreenHeight) + * ; Set movement speed to instant + * A_DefaultMouseSpeed := 0 + * MouseClick('L', A_ScreenWidth/2, A_ScreenHeight/2) */ -TraySetIcon(FileName?: $FilePath, IconNumber := 1, Freeze := false) => void +A_DefaultMouseSpeed: Integer /** - * Create a balloon prompt window near the tray icon. In Windows 10, a toast notification may be displayed instead. - * @param Text The message to be displayed. Only the first 265 characters are displayed. You can use carriage return (`r) or line feed (`n) to create multiple lines of text. For example: Line1`nLine2. - * @param Title The title of the window. Only the first 73 characters are displayed. - * @param Options information icon 0x1 - * - * Warning icon 0x2 - * - * Error icon 0x3 - * - * Tray icon 0x4 - * - * Do not play notification sound. 0x10 - * - * Use large icons. 0x20 + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Desktop|A_Desktop} + * This variable contains the path to the user's Desktop folder. + * Typically, this contains: `C:\Users\\Desktop` + * @type String + * @example + * MsgBox('Path to user`'s Desktop folder: ' A_Desktop) */ -TrayTip(Text?, Title?, Options := 0) => void +A_Desktop: String /** - * Trim characters from the beginning and end of the string. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#DesktopCommon|A_DesktopCommon} + * This variable contains the path to the common/all-user Desktop folder. + * Typically, this contains: `C:\Users\Public\Desktop` + * @type String + * @example + * MsgBox('Path to the common Desktop folder: ' A_DesktopCommon) */ -Trim(String, OmitChars := ' `t') => String +A_DesktopCommon: String /** - * The exact type of the return value. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#|A_DetectHiddenText} + * Used to get or set the whether hidden text is detected. + * This variable can be set to the following values: + * - `1` = Hidden text is detected. This is the default value. + * - `0` = Hidden text is not detected. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenText.htm|DetectHiddenText()} + * @example + * WinHide(A_ScriptHwnd) + * MsgBox('Script window exist: ' WinExist(A_ScriptHwnd)) + * A_DetectHiddenWindows := 1 + * MsgBox('After enabling DetectHiddenWindows: ' WinExist(A_ScriptHwnd)) */ -Type(Value) => String +A_DetectHiddenText: Integer /** - * Increase the capacity of the variable or release its memory. Generally not needed, but it can be used with DllCall or SendMessage, or to optimize repeated connections. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#DetectHiddenWindows|A_DetectHiddenWindows} + * Used to get or set the whether hidden windows are detected. + * This variable can be set to the following values: + * - `1` = Hidden windows are detected. + * - `0` = Hidden windows are not detected, except by the {@link https://www.autohotkey.com/docs/v2/lib/WinShow.htm|WinShow()} function. This is the default value. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/DetectHiddenWindows.htm|DetectHiddenWindows()} + * @example + * WinHide(A_ScriptHwnd) + * MsgBox('Script window exist: ' WinExist(A_ScriptHwnd)) + * A_DetectHiddenWindows := 1 + * MsgBox('After enabling DetectHiddenWindows: ' WinExist(A_ScriptHwnd)) */ -VarSetStrCapacity(&TargetVar [, RequestedCapacity]) => Integer +A_DetectHiddenWindows: Integer /** - * Compare two version strings. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#EndChar|A_EndChar} + * Contains the {@link https://www.autohotkey.com/docs/v2/Hotstrings.htm#EndChars|ending character} used to trigger the most recent non-auto-replace hotstring (A hotstring that uses the `x` option). + * If the wildcard `*` option is being used, there is no end char and this variable will contain an empty string. + * @type String + * @example + * ; Try triggering this hotkey with different end chars. + * ; Type ahk followed by a space, tab, or enter. + * :?x:ahk:: { + * Send('AutoHotkey') + * MsgBox('The end char used to trigger the hotkey is: ' + * '`n' GetKeyName(A_EndChar)) + * } */ -VerCompare(VersionA, VersionB) => Integer +A_EndChar: String /** - * Activate the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#EventInfo|A_EventInfo} + * Contains additional information about the following events: + * - {@link https://www.autohotkey.com/docs/v2/Hotkeys.htm#Wheel|Mouse wheel hotkeys}: + * Stores the number of times the wheel was turned, which is typically 120. + * - {@link https://www.autohotkey.com/docs/v2/lib/OnMessage.htm|OnMessage()}: + * Contains a `0` if SendMessage() was used, otherwise contains the {@link https://www.autohotkey.com/docs/v2/Variables.htm#TickCount|tick count} since PostMessage() was posted. + * - {@link https://www.autohotkey.com/docs/v2/misc/RegExCallout.htm|Regular Expression Callouts}: + * Contains additional information from the pcre_callout_block structure. + * This is binary data and can be retrieved using {@link https://www.autohotkey.com/docs/v2/lib/NumGet.htm|NumGet()} + * + * Unlike most variables, each {@link |thread} retains its own A_EventInfo. Starting a new thread does not alter the prior threads A_EventInfo. + * @type Integer + * @example + * + * ; Monitoring the amount the mouse wheel is turned. + * A_MaxHotkeysPerInterval := 1000 + * ~WheelDown:: + * ~WheelUp:: { + * ToolTip A_EventInfo + * } + * + * + * ; Getting information from a RegEx Callout: + * text := 'Hello, world!' + * RegExMatch(text, 'C)Hello(.*?)') + * + * ; Function that's called whenever the C) RegEx option is used + * ; To change the function name, use this in the RegExPattern: + * ; (?CalloutNumber:FuncName) + * pcre_callout(RegExMatchInfoObject, CalloutNumber, FoundPos, Haystack, NeedleRegEx) { + * str := '' + * pad := A_PtrSize = 8 ? 4 : 0 + * version := NumGet(A_EventInfo, 0 , 'Int') + * str .= 'version: ' version + * str .= '`ncallout_number: ' NumGet(A_EventInfo, 4 , 'Int') + * str .= '`noffset_vector: ' NumGet(A_EventInfo, 8 , 'Ptr') + * str .= '`nsubject: ' NumGet(A_EventInfo, 8 + A_PtrSize , 'Ptr') + * str .= '`nsubject_length: ' NumGet(A_EventInfo, 8 + A_PtrSize*2 , 'Int') + * str .= '`nstart_match: ' NumGet(A_EventInfo, 12 + A_PtrSize*2 , 'Int') + * str .= '`ncurrent_position: ' NumGet(A_EventInfo, 16 + A_PtrSize*2 , 'Int') + * str .= '`ncapture_top: ' NumGet(A_EventInfo, 20 + A_PtrSize*2 , 'Int') + * str .= '`ncapture_last: ' NumGet(A_EventInfo, 24 + A_PtrSize*2 , 'Int') + * str .= '`ncallout_data: ' NumGet(A_EventInfo, 28 + pad + A_PtrSize*2, 'Ptr') + * str .= '`npattern_position: ' NumGet(A_EventInfo, 28 + pad + A_PtrSize*3, 'Int') + * str .= '`nnext_item_length: ' NumGet(A_EventInfo, 32 + pad + A_PtrSize*3, 'Int') + * if (version >= 2) + * str .= '`nmark: ' NumGet(A_EventInfo, 36 + pad + A_PtrSize*3, 'Int') + * + * MsgBox(str) + * } */ -WinActivate([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_EventInfo: Integer /** - * Same as WinActivate, except that this function activates the bottom matching window instead of the top. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#FileEncoding|A_FileEncoding} + * Used to get or set the default encoding of various built-in functions. + * This variable can be set to the following values: + * - `CP0` or Empty String: The system default ANSI code page. See remarks below. + * - `UTF-8` = Unicode UTF-8. Equivalent to `CP65001`. + * - `UTF-8-RAW` = UTF-8 with no {@link https://www.w3.org/International/questions/qa-byte-order-mark|byte order mark} is written when a new file is created. + * - `UTF-16` = Unicode UTF-16 with little endian byte order, equivalent to CP1200. + * - `UTF-16-RAW` = As above, but no {@link https://www.w3.org/International/questions/qa-byte-order-mark|byte order mark} is written when a new file is created. + * - `CP###` = A code page where `###` is a numeric identifier. See {@link https://learn.microsoft.com/windows/win32/intl/code-page-identifiers|Code Page Identifiers}. + * - `###` = A numeric code page identifier. + * @type String + * @see {@link https://www.autohotkey.com/docs/v2/lib/FileEncoding.htm|FileEncoding()} */ -WinActivateBottom([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_FileEncoding: String /** - * Check if the specified window exists and is currently active (at the forefront). + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#HotkeyInterval|A_HotkeyInterval} + * Used to get or set the time interval, in milliseconds, that's used by {@link https://www.autohotkey.com/docs/v2/Variables.htm#MaxHotkeysPerInterval|A_MaxHotkeysPerInterval}. + * When a script activates more hotkeys than the value of A_MaxHotkeysPerInterval within this time interval, the script throws up a warning. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/A_MaxHotkeysPerInterval.htm|A_MaxHotkeysPerInterval / A_HotkeyInterval info} */ -WinActive([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_HotkeyInterval: Integer /** - * Close the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#HotkeyModifierTimeout|A_HotkeyModifierTimeout} + * Used to get or set the time, in milliseconds, that a hotkey will assume modifier keys (ctrl/alt/win/shift) are still being held when using {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|SendEvent()}. + * Hotkeys release all modifiers when sending keys so they don't affect the keystrokes being sent. + * If a hotkey finishes sending in less time than this timeout, the initial modifiers are automatically returned to their down state. + * This timeout only applies to unhooked hotkeys that are using the Send Event mode. + * The variable can be set to the following values: + * - Positive number = The number of milliseconds to wait. Default is 50. + * - `0` = Always timeout. Modifier keys are never set back to their initial state. + * - `-1` = Never timeout. Modifier keys always set back to their initial state. + * @type Integer */ -WinClose([WinTitle, WinText, SecondsToWait, ExcludeTitle, ExcludeText]) => void +A_HotkeyModifierTimeout: Integer /** - * Check if the specified window exists. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Hour|A_Hour} + * Current 2-digit hour in 24-hour time: `00`-`23` + * To get 12-hour time, use: `FormatTime(, 'h:mm:ss tt')` + * @type String + * @example + * MsgBox('The current hour is: ' A_Hour + * '`nOr in 12-hour format: ' FormatTime(, 'h tt')) */ -WinExist([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_Hour: String /** - * Returns true if the specified window is always-on-top, otherwise false. - * @since v2.1-alpha.1 + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#IconFile|A_IconFile} + * Contains the full path of the custom icon file that's been applied to the script's tray icon. + * If no custom image has been applied, this variable contains an empty string. + * @type String + * @see {@link https://www.autohotkey.com/docs/v2/lib/TraySetIcon.htm|TraySetIcon()} + * @example + * ; Image to get. + * url := 'https://i.imgur.com/DlSIhRC.png' + * ; Path to store the file. + * path := A_AppData '\AhkV2CustomTrayIcon.png' + * ; Download the image. + * Download(url, path) + * ; Set the downloaded image as the tray icon + * TraySetIcon(path) + * ; Showing that A_IconFile is equal to the path we've used + * MsgBox('The path of the current tray icon file is: ' A_IconFile + * '`nPress OK to delete downloaded image.') + * ; File clean up + * FileDelete(path) + * ExitApp() */ -WinGetAlwaysOnTop([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_IconFile: String /** - * Get the class name of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#|A_IconHidden} + * Used to get or set the visibility of the tray icon. + * This variable can be set to the following values: + * - `0` = Tray icon is set to visible. + * - `1` = Tray icon is set to hidden. + * @type Integer + * @example + * ; Create a gui with 2 radio buttons to show/hide tray icon. + * goo := Gui() + * con := goo.AddRadio('xm ym Checked vShow', 'Show Icon') + * con.OnEvent('Click', switch_icon) + * con := goo.AddRadio('x+m vHide', 'Hide Icon') + * con.OnEvent('Click', switch_icon) + * goo.Show() + * + * switch_icon(radio, info) { + * if radio.name = 'Show' + * A_IconHidden := 0 + * else A_IconHidden := 1 + * } */ -WinGetClass([WinTitle, WinText, ExcludeTitle, ExcludeText]) => String +A_IconHidden: Integer /** - * Retrieve the location and size of the workspace of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#IconNumber|A_IconNumber} + * Contains the number of the icon being used with the script's current Tray Icon. + * If `A_IconFile` is an empty string, this variable will also contain an empty string. + * @type Primitive + * @see {@link https://www.autohotkey.com/docs/v2/Variables.htm#IconFile|A_IconFile} */ -WinGetClientPos([&X: VarRef, &Y: VarRef, &Width: VarRef, &Height: VarRef, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_IconNumber: Primitive /** - * Return the names of all controls in the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#IconTip|A_IconTip} + * Used to get or set the text displayed when hovering over the script's tray icon. + * To create multiple lines of text, use the linefeed character: `` `n `` + * The max characters that can be displayed is 127. Characters past that are truncated. + * If there is a tab character `` `t ``, all characters past the tab are truncated. + * @type String + * @example + * A_IconTip := 'Custom message shown on hover!' + * . '`nAdditional line of text!' + * . '`tThis line will not show up because of the tab.' + * MsgBox('Hover your mouse over the AHK script icon in the system tray.') */ -WinGetControls([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Array +A_IconTip: String /** - * Return the unique ID numbers of all controls in the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Index|A_Index} + * A built-in variable available to all loop types, including for-loops and while-loops. + * This contains the current iteration number of the loop. + * If there are nested loops, this variable contains the inner-most loop's current iteration. + * To access an outer-loop's A_Index, save it to a variable. + * Assigning a number + * @type Integer + * @example + * ; === Showing each iteration of a basic loop + * loop 3 + * MsgBox(A_Index) + * + * ; === Assigning a value to A_Index + * ; Track actual iteration number + * i := 0 + * ; Loop 5 times + * loop 5 { + * ; Increment i by 1 + * i++ + * ; On the 3rd iteration + * If (A_index = 3) + * ; Set A_Index to 5 + * A_Index := 5 + * ; Show actual iteration and A_Index + * MsgBox('iteration: ' i + * '`nA_Index: ' A_Index) + * } + * + * ; === Make copy+paste hotkeys using numpad + * ; A class that turns the Numpad into a multi-clipboard. + * ; Use ctrl+Numpad# to save data to that "slot number". + * ; Use alt+Numpad# to paste data from that "slot number". + * class multi_clip { + * ; Object to store all clipboard info. + * static data := Map() + * + * ; Runs automatically when the script starts. + * static __New() { + * ; Create the numpad0-numpad9 hotkeys. + * loop 10 { + * ; Use A_Index to create each number. + * num := A_Index - 1 + * ; Clear data from that number slot. + * this.data[num] := '' + * ; Create callback to run when hotkey is pressed. + * callback := ObjBindMethod(this, 'copy', num) + * ; Create copy hotkeys (ctrl+numpad). + * Hotkey('$^Numpad' num, callback) + * ; Create paste hotkeys (alt+numpad). + * callback := ObjBindMethod(this, 'paste', num) + * Hotkey('$!Numpad' num, callback) + * } + * } + * + * ; Method that runs for copy hotkeys. + * static copy(num, *) { + * ; Clear clipboard and copy. + * A_Clipboard := '' + * Send('^c') + * ; Wait up to 1 second for something + * ; to appear on clipboard. + * if ClipWait(1, 1) + * ; Save clipboard data to slot. + * this.data[num] := A_Clipboard + * ; Otherwise, inform user data could not be gotten. + * else TrayTip('No data showed up on clipboard.') + * } + * + * ; Method that runs for paste hotkeys. + * static paste(num, *) { + * ; Backup current clipboard data. + * clipbackup := ClipboardAll() + * ; Assign stored data to clipboard + * A_Clipboard := this.data[num] + * ; Paste data + * Send('^v') + * + * loop + * ; Wait 100ms + * Sleep(100) + * ; Break if clipboard window no longer open + * ; or if too many tries (20) have been made + * until !DllCall('GetOpenClipboardWindow', 'Ptr') + * || (A_Index > 20) + * ; Finally, restore original clipboard contents + * A_Clipboard := clipbackup + * } + * } */ -WinGetControlsHwnd([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Array +A_Index: Integer /** - * Returns the number of existing windows that meet the specified conditions. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#InitialWorkingDir|A_InitialWorkingDir} + * The script's initial working directory, which is determined by how it was launched. + * This is not the same as {@link https://www.autohotkey.com/docs/v2/Variables.htm#BuiltIn#WorkingDir|A_WorkingDir}. + * @type String + * @example */ -WinGetCount([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_InitialWorkingDir: String /** - * Returns true if the specified window is enabled, otherwise false. - * @since v2.1-alpha.1 + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Is64bitOS|A_Is64bitOS} + * Contains a `1` if the OS is 64-bit or `0` if it's 32-bit. + * @type Integer + * @example + * MsgBox('The current OS is ' (A_Is64bitOS ? '64-bit' : '32-bit')) */ -WinGetEnabled([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_Is64bitOS: Integer /** - * Return the style or extended style of the specified window respectively. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#IsAdmin|A_IsAdmin} + * This variable is set to `1` if script has administrative rights, otherwise `0`. + * A script can be restarted with admin privileges using {@link https://www.autohotkey.com/docs/v2/lib/Run.htm#RunAs|Run('*RunAs')}. + * @type Integer + * @example + * MsgBox('Script running with admin privileges: ' (A_IsAdmin ? 'Yes' : 'No')) + * + * ; Function that attempts to run script as admin + * run_as_admin() + * + * run_as_admin() { + * if (!A_IsAdmin && !InStr(DllCall("GetCommandLine", "str"), ' /restart')) + * try + * if A_IsCompiled + * Run('*RunAs "' A_ScriptFullPath '" /restart') + * else Run('*RunAs "' A_AhkPath '" /restart "' A_ScriptFullPath '"') + * Finally ExitApp() + * TrayTip('Script Running as Admin: ' (A_IsAdmin ? 'True' : 'False')) + * } */ -WinGetExStyle([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_IsAdmin: Integer /** - * Return the unique ID number of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#IsCompiled|A_IsCompiled} + * Contains 1 if the script is running as a compiled EXE, otherwise it is set to 0. + * @type Integer + * @example + * if A_IsCompiled + * MsgBox('Script is compiled.') + * else MsgBox('Script is not compiled.') */ -WinGetID([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_IsCompiled: Integer /** - * If multiple matching windows are found, the unique ID number of the last/bottom window will be returned. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#IsCritical|A_IsCritical} + * This is set to `0` if {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm|critical} is off for the {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|current thread}. + * Otherwise, this variable is to a positive number, namely the {@link https://www.autohotkey.com/docs/v2/lib/Critical.htm#Interval|message-check interval} being used by Critical. + * @type Integer + * @example + * if A_IsCritical + * state := 'Enabled' + * else state := 'Disabled' + * MsgBox('The current thread`'s critical state is: ' state) */ -WinGetIDLast([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_IsCritical: Integer /** - * Return the unique ID numbers of all existing windows that match the specified conditions. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#IsPaused|A_IsPaused} + * This is set to `1` if the {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|thread} immediately under the current thread is {@link |paused}, otherwise it's set to `0`. + * @type Integer + * @example + * if A_IsPaused + * MsgBox('Prior thread is paused.') + * else MsgBox('Prior thread is not paused.') */ -WinGetList([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Array +A_IsPaused: Integer /** - * Returns whether the specified window is maximized or minimized. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#IsSuspended|A_IsSuspended} + * This is set to `1` when script is in the {@link https://www.autohotkey.com/docs/v2/lib/Suspend.htm|suspended state}, otherwise it's set to `0`. + * @type Integer + * @example + * if A_IsSuspended + * MsgBox('Script is suspended.') + * else MsgBox('Script is not suspended.') */ -WinGetMinMax([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_IsSuspended: Integer /** - * Returns the process ID of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#KeyDelay|A_KeyDelay} + * Used to get or set the the key delay duration used by {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} events. + * This is the amount of time, in milliseconds, between the sending of each keystroke. + * It has no affect on SendInput() events. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} + * @example + * ; There will be a 0.5 second pause between each character sent. + * A_KeyDelay := 500 + * SendEvent('AHK') */ -WinGetPID([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_KeyDelay: Integer /** - * Get the position and size of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#KeyDelayPlay|A_KeyDelayPlay} + * Used to get or set the the key delay duration used by {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlayDetail|SendPlay()} events. + * This is the amount of time, in milliseconds, between the sending of each keystroke. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} + * @example + * ; There will be a 0.5 second pause between each character sent. + * A_KeyDelayPlay := 500 + * SendPlay('AHK') */ -WinGetPos([&X: VarRef, &Y: VarRef, &Width: VarRef, &Height: VarRef, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_KeyDelayPlay: Integer /** - * Returns the name of the process of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#KeyDelay|A_KeyDuration} + * Used to get or set the the key hold duration used by {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} events. + * This is the amount of time, in milliseconds, a key is held down before being released. + * It has no affect on SendInput() events. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} + * @example + * ; During sending, each key is held down for 100ms before being released + * A_KeyDuration := 100 + * SendEvent('AHK') */ -WinGetProcessName([WinTitle, WinText, ExcludeTitle, ExcludeText]) => String +A_KeyDuration: Integer /** - * Returns the full path and name of the process that owns the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#KeyDelayPlay|A_KeyDurationPlay} + * Used to get or set the the key hold duration used by {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlayDetail|SendPlay()} events. + * This is the amount of time, in milliseconds, a key is held down before being released. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm|SetKeyDelay()} + * @example + * ; During sending, each key is held down for 100ms before being released + * A_KeyDurationPlay := 100 + * SendPlay('AHK') */ -WinGetProcessPath([WinTitle, WinText, ExcludeTitle, ExcludeText]) => String +A_KeyDurationPlay: Integer /** - * Return the style or extended style of the specified window respectively. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Language|A_Language} + * The {@link https://www.autohotkey.com/docs/v2/misc/Languages.htm|4-digit language code} number of the system's default language. + * Examples: + * English (US): `0409` + * French (France): `040C` + * Chinese (Simplified, China): `0804` + * @type String + * @example + * MsgBox('Current system language code: ' A_Language) */ -WinGetStyle([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_Language: String /** - * Retrieve text from the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#LastError|A_LastError} + * Usually contains the results from the operating system's {@link https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror|GetLastError()} and is a decimal number between `0` and `4294967295`. + * A `0` indicates success and a positive number indicates some kind of error. + * Unlike most built-in variables, this value is stored per-thread. Interruptions from other {@link https://www.autohotkey.com/docs/v2/misc/Threads.htm|threads} do not change it. + * @type Integer + * @see {@link https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-|List of OS error codes} + * @example + * error_example() + * + * error_example() { + * error_list := Map( + * 0, 'ERROR_SUCCESS', + * 1, 'ERROR_INVALID_FUNCTION', + * 2, 'ERROR_FILE_NOT_FOUND', + * 3, 'ERROR_PATH_NOT_FOUND', + * 4, 'ERROR_TOO_MANY_OPEN_FILES', + * 5, 'ERROR_ACCESS_DENIED', + * 6, 'ERROR_INVALID_HANDLE', + * 7, 'ERROR_ARENA_TRASHED', + * 8, 'ERROR_NOT_ENOUGH_MEMORY', + * 9, 'ERROR_INVALID_BLOCK' + * ) + * ; Make a faulty system function call + * DllCall('GetHandleInformation') + * ; Error is set to 6 + * MsgBox('System error number: ' A_LastError + * '`nError message: ' error_list[A_LastError]) + * } */ -WinGetText([WinTitle, WinText, ExcludeTitle, ExcludeText]) => String +A_LastError: Integer /** - * Retrieve the title of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#LineFile|A_LineFile} + * The full path and name of the file to which {@link https://www.autohotkey.com/docs/v2/Variables.htm#LineNumber|A_LineNumber} belongs. + * If loaded from an external file, this is the same as {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptFullPath|A_ScriptFullPath}. + * If the code belongs to an {@link https://www.autohotkey.com/docs/v2/lib/_Include.htm|#Include} file, that file's name is used. + * If the script is {@link https://www.autohotkey.com/docs/v2/Scripts.htm#ahk2exe|compiled} or a {@link https://www.autohotkey.com/docs/v2/Scripts.htm#ahk2exe-base|.bin file}, this is the full path and name of the executable file. + * If the script is {@link https://www.autohotkey.com/docs/v2/Program.htm#embedded-scripts|embedded}, A_LineFile will contain an asterisk (*) followed by the resource name: `*#1` + * @type String + * @example + * MsgBox('This line of code resides on line: ' A_LineNumber + * '`nand is found in the file: ' A_LineFile) */ -WinGetTitle([WinTitle, WinText, ExcludeTitle, ExcludeText]) => String +A_LineFile: String /** - * Returns the color marked as transparent in the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#LineNumber|A_LineNumber} + * The number of the currently executing line. This can be within the main script or a script from an {@link https://www.autohotkey.com/docs/v2/lib/_Include.htm|#Include} file. + * This line number match the one found in {@link https://www.autohotkey.com/docs/v2/lib/ListLines.htm|ListLines()} + * @type Integer + * @example + * ; This comment is on line one + * var := 'This variable is on line 2' + * MsgBox('This should show as line 3:`nLine ' A_LineNumber) */ -WinGetTransColor([WinTitle, WinText, ExcludeTitle, ExcludeText]) => String +A_LineNumber: Integer /** - * Returns the transparency level of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ListLines|A_ListLines} + * Used to get or set whether a script should log executed lines to the {@link https://www.autohotkey.com/docs/v2/Program.htm#main-window|main AHK window}. + * This variable can be set to the following values: + * - `1` = Logging lines is enabled. This is the default value. + * - `0` = Logging lines is disabled. + * Lines can be viewed using {@link https://www.autohotkey.com/docs/v2/lib/ListLines.htm|ListLines()} + * @type Integer + * @example + * x := 0 + * y := 'The next line will be the last line logged.' + * A_ListLines := 0 + * if x + * z := 123 + * else z := 'abc' + * ListLines() */ -WinGetTransparent([WinTitle, WinText, ExcludeTitle, ExcludeText]) => Integer +A_ListLines: Integer /** - * Hide the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopParse.htm#LoopField|A_LoopField} + * Used by all parse-loops, this built-in variable contains the current substring of the parse. + * If there are nested parse-loops, this variable contains the inner-most loop's current substring. + * To access an outer-loop's A_LoopField, save it to a variable prior to the inner-parse-loop. + * @type String + * @example + * ; Get current script's text. + * text := FileRead(A_ScriptFullPath) + * + * ; Parse through each line of the script. + * loop parse text, '`n', '`r' { + * ; Save the current line. + * line := A_LoopField + * ; Parse through each word of the line. + * loop parse line, ' ' + * ; Show line and current word. + * MsgBox('Script line:`n' line + * '`n`nCurrent word`n: ' A_LoopField) + * } */ -WinHide([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopField: String /** - * Forcibly close the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileAttrib|A_LoopFileAttrib} + * The {@link https://www.autohotkey.com/docs/v2/lib/FileGetAttrib.htm|attributes} of the file currently retrieved. + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinKill([WinTitle, WinText, SecondsToWait, ExcludeTitle, ExcludeText]) => void +A_LoopFileAttrib: String /** - * Enlarge the specified window to the maximum size (maximize the specified window). + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileDir|A_LoopFileDir} + * The directory path of the current file of the loop. + * If the loop's {@link {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#Parameters|FilePattern} is relative, this path will also be relative. + * Root directories will not contain a trailing backslash: `C:` instead of `C:\` + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinMaximize([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileDir: String /** - * Minimize the specified window to a button on the taskbar (minimize the specified window). + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileExt|A_LoopFileExt} + * The current file's extension without the period separator. + * Examples: `txt`, `docx`, `exe`, `ahk` + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinMinimize([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileExt: String /** - * Minimizes all windows. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileFullPath|A_LoopFileFullPath} + * The path and name of the file/folder currently retrieved. + * This always contains the absolute path of the file, even if the loop's {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#Parameters|FilePattern} contains a relative path. + * Character case is converted to match the exact characters used in the path. This is helpful when renaming. + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinMinimizeAll() => void +A_LoopFileFullPath: String /** - * Unminimizes all windows. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileName|A_LoopFileName} + * The name of the file or folder currently retrieved. + * This does not contain the file's path. + * @type + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinMinimizeAllUndo() => void +A_LoopFileName: String /** - * Change the position and/or size of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFilePath|A_LoopFilePath} + * The path and name of the file/folder currently retrieved. + * If FilePattern contains a relative path instead of an absolute path, the path here will also be relative. + * @type + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinMove([X, Y, Width, Height, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFilePath: String /** - * Send the specified window to the bottom of the stack; that is, below all other windows. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileShortName|A_LoopFileShortName} + * The short name or alternate name of the file in 8.3 format. + * A_LoopFileName is used if the if the file doesn't have a short format. + * This might be due to the long name being shorter than 8.3 or because NTFS is being used and short-name generation is disabled. + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinMoveBottom([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileShortName: String /** - * Move the specified window to the top of the stack without explicitly activating it. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileShortPath|A_LoopFileShortPath} + * Contains the short path and name of the file/folder currently retrieved in 8.3 format. + * Example: `C:\MYDOCU~1\ADDRES~1.txt` + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinMoveTop([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileShortPath: String /** - * Redraw the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileSize|A_LoopFileSize} + * The current file's size, in bytes, rounded down to the nearest integer. + * Files larger than 4 GB are supported. + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinRedraw([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileSize: Integer /** - * If the specified window is minimized or maximized, restore it. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileSizeKB|A_LoopFileSizeKB} + * The current file's size, in KB, rounded down to the nearest integer. + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinRestore([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileSizeKB: Integer /** - * Make the specified window stay on top of all other windows (except for other windows that are always on top (top)). + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileSizeMB|A_LoopFileSizeMB} + * The current file's size, in MB, rounded down to the nearest integer. + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinSetAlwaysOnTop([Value, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileSizeMB: Integer /** - * Enable or disable the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileTimeAccessed|A_LoopFileTimeAccessed} + * The time the file was last accessed. + * This time is returned in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|YYYYMMDDHH24MISS format}. + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinSetEnabled(Value [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileTimeAccessed: String /** - * Change the style and extended style of the specified window respectively. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileTimeCreated|A_LoopFileTimeCreated} + * The time the file was created. + * This time is returned in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|YYYYMMDDHH24MISS format}. + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinSetExStyle(Value [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileTimeCreated: String /** - * Change the shape of the specified window to the specified rectangle, ellipse or polygon. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopFiles.htm#LoopFileTimeModified|A_LoopFileTimeModified} + * The time the file was last accessed. + * This time is returned in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|YYYYMMDDHH24MISS format}. + * @type String + * @example + * loop files A_ScriptDir '\*', 'F' { + * var_list := [ + * 'A_LoopFileName' + * ,'A_LoopFileExt' + * ,'A_LoopFilePath' + * ,'A_LoopFileFullPath' + * ,'A_LoopFileShortPath' + * ,'A_LoopFileShortName' + * ,'A_LoopFileDir' + * ,'A_LoopFileAttrib' + * ,'A_LoopFileSize' + * ,'A_LoopFileSizeKB' + * ,'A_LoopFileSizeMB' + * ,'A_LoopFileTimeModified' + * ,'A_LoopFileTimeCreated' + * ,'A_LoopFileTimeAccessed' + * ] + * + * str := '' + * for var in var_list + * str .= var ':`n' %var% '`n`n' + * + * MsgBox(str, 'Files from: ' A_ScriptDir) + * } */ -WinSetRegion([Options, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopFileTimeModified: String /** - * Change the style and extended style of the specified window respectively. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopRead.htm#LoopReadLine|A_LoopReadLine} + * Used by all file read-loops, this built-in variable contains the current line of the file, excluding the end of line character: `` `n `` or `` `r`n `` + * If there are nested file read-loops, this variable contains the inner-most loop's current line. + * To access an outer-loop's A_LoopReadLine, save it to a variable prior to the inner-parse-loop. + * @type String + * @example + * ; Showing each line of the current script. + * loop read A_ScriptFullPath + * MsgBox('Line ' A_Index '`n' A_LoopReadLine) */ -WinSetStyle(Value [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopReadLine: String /** - * Change the title of the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm#vars|A_LoopRegKey} + * Name of the currently retrieved item, which can be either a subkey name or a value. + * Value names displayed by Windows RegEdit as `(Default)` will be retrieved if a value has been assigned to them, but A_LoopRegName will be blank. + * @type String */ -WinSetTitle(NewTitle [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopRegKey: String /** - * Make all pixels of the selected color invisible in the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm#vars|A_LoopRegName} + * The full name of the key which contains the current loop item. + * For remote registry access, this value will not include the computer name. + * @type String */ -WinSetTransColor(Color [, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopRegName: String /** - * Make the specified window semi-transparent. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm#vars|A_LoopRegTimeModified} + * The time the current subkey or any of its values was last modified. + * This time is returned in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm|YYYYMMDDHH24MISS} format. + * If the currently retrieved item is not a subkey, this variable will be empty. + * @type String */ -WinSetTransparent([N, WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopRegTimeModified: String /** - * Display the specified window. + * @description {@link https://www.autohotkey.com/docs/v2/lib/LoopReg.htm#vars|A_LoopRegType} + * The type of the currently retrieved item. + * Values can be: + * - `REG_SZ` = A null-terminated string. Can be either Unicode or ANSI. + * - `REG_EXPAND_SZ` = A null-terminated string that contains unexpanded references to environment variables. + * Example: `%PATH%` + * - `REG_MULTI_SZ` = A sequence of null-terminated strings, terminated by an empty string `\0`. + * Example: `String1\0String2\0String3\0LastString\0\0` + * - `REG_DWORD` = A 32-bit number. + * - `REG_QWORD` = A 64-bit number. + * - `REG_BINARY` = Binary data. + * - `REG_LINK` = A null-terminated Unicode string that contains the target path of a symbolic link that was created by calling the {@link https://learn.microsoft.com/en-us/windows/win32/api/Winreg/nf-winreg-regcreatekeyexa|RegCreateKeyEx} function with REG_OPTION_CREATE_LINK. + * - `REG_RESOURCE_LIST` = A device driver's list of hardware resources, used by the driver or one of the physical devices it controls, in the \ResourceMap tree. + * - `REG_FULL_RESOURCE_DESCRIPTOR` = A list of hardware resources that a physical device is using, detected and written into the \HardwareDescription tree by the system. + * - `REG_RESOURCE_REQUIREMENTS_LIST` = A device driver's list of possible hardware resources it or one of the physical devices it controls can use, from which the system writes a subset into the \ResourceMap tree. + * - `REG_DWORD_BIG_ENDIAN` = A 32-bit number in {@link https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types#byte-formats|big-endian format}. + * - Empty String - The currently retrieved item is of an unknown type. + * @type String */ -WinShow([WinTitle, WinText, ExcludeTitle, ExcludeText]) => void +A_LoopRegType: String /** - * Wait until the specified window exists. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#MaxHotkeysPerInterval|A_MaxHotkeysPerInterval} + * Used to get or set the maximum number of hotkeys that can be activated within the interval time period. + * This interval can be gotten or changed with the {@link https://www.autohotkey.com/docs/v2/Variables.htm#HotkeyInterval|A_HotkeyInterval} variable. + * When a script activates more hotkeys than this number within A_HotkeyInterval's time frame, the script throws up a warning. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/A_MaxHotkeysPerInterval.htm|A_MaxHotkeysPerInterval / A_HotkeyInterval info} */ -WinWait([WinTitle, WinText, Timeout, ExcludeTitle, ExcludeText]) => Integer +A_MaxHotkeysPerInterval: Integer /** - * Wait until the specified window is active. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#DD|A_MDay} + * The current date in two-digit format: `00`-`31`. + * This is synonymous with A_DD. + * @type String + * @example + * MsgBox('Today`'s date is: ' A_MMMM ' ' A_DD) */ -WinWaitActive([WinTitle, WinText, Seconds, ExcludeTitle, ExcludeText]) => Integer +A_MDay: String /** - * Wait until no matching window is found. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#MenuMaskKey|A_MenuMaskKey} + * Used to get or set the key used to mask Win and Alt up events. + * This is used to prevent the start menu and other alt-up menus from activating when using a hotkey containing alt or win keys. + * This value needs to be a `vk###` (virtual key), `sc###` (scan code), or both `vk###sc###`. + * If set to an empty string, masking is disabled. + * The default mask key is: `vk11sc01D`, the left Ctrl key. + * @type String + * @see {@link https://www.autohotkey.com/docs/v2/lib/A_MenuMaskKey.htm|A_MenuMaskKey info} + * @example + * ; Reset the menu mask to it's original value + * A_MenuMaskKey := 'vk11sc01D' */ -WinWaitClose([WinTitle, WinText, Timeout, ExcludeTitle, ExcludeText]) => Integer +A_MenuMaskKey: String /** - * Wait until the specified window is inactive. + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Min|A_Min} + * The current minute in 2-digit format: `00`-`59` + * @type String + * @example + * MsgBox('The current minutes is: ' A_Min) */ -WinWaitNotActive([WinTitle, WinText, Seconds, ExcludeTitle, ExcludeText]) => Integer -;@endregion - -;@region class -class Any { - /** - * The implementation function of the retrieval method. - */ - GetMethod(Name) => Func - - /** - * If BaseObj is in Value's base object chain, it returns true, otherwise it returns false. - */ - HasBase(BaseObj) => Integer - - /** - * If the value has a method using this name, it returns true, otherwise it returns false. - */ - HasMethod(Name) => Integer - - /** - * If the value has an attribute with this name, it returns true, otherwise it returns false. - */ - HasProp(Name) => Integer - - __Class: String - - __Init() => void - - /** - * The base object to retrieve the value. - */ - Base { - get => Object | void - set => void - } -} - -class Array extends Object { - /** - * An array object contains a list or sequence of values. - */ - __New(Values*) => void - - /** - * Enumerates array elements. - */ - __Enum(NumberOfVars?) => Enumerator | Enumerator - - /** - * Retrieves or sets the value of an array element. - */ - __Item[Index] { - get => T - set => void - } - - /** - * Return a shallow copy of the object. - */ - Clone() => this - - /** - * Defines the default value returned when an element with no value is requested. - */ - Default?: T - - /** - * Delete the value of the array element so that the index does not contain a value. - */ - Delete(Index) => T - - /** - * Returns the value at a given index, or a default value. - */ - Get(Index [, Default]) => T - - /** - * If Index is valid and there is a value at that position, it returns true, otherwise it returns false. - */ - Has(Index) => Integer - - /** - * Insert one or more values to the given position. - */ - InsertAt(Index, Values*) => void - - /** - * Delete and return the last array element. - */ - Pop() => T - - /** - * Append the value to the end of the array. - */ - Push(Values*) => void - - /** - * Removes items from the array. - */ - RemoveAt(Index, Length := 1) => T - - /** - * Retrieve or set the length of the array. - */ - Length { - get => Integer - set => void - } - - /** - * Retrieve or set the current capacity of the array. - */ - Capacity { - get => Integer - set => void - } -} - -class BoundFunc extends Func { -} - -class Buffer extends Object { - /** - * Allocate a memory block and return it to the buffer object. - * @param ByteCount The number of bytes to be allocated. Corresponds to Buffer.Size. - * @param FillByte specifies a number between 0 and 255 to set each byte in the buffer to that number. - * In the case of direct writing without first reading the buffer, it should usually be omitted, because its time overhead is proportional to the number of bytes. - * If omitted, the buffered memory is not initialized; the value of each byte is arbitrary. - */ - __New([ByteCount, FillByte]) => void - - /** - * Retrieve the current memory address of the buffer. - */ - Ptr => Integer - - /** - * Retrieve or set the size of the buffer, in bytes. - */ - Size { - get => Integer - set => void - } -} - -class Class extends Object { - /** - * @param Name If specified, assign the class name to `ClassObj.Prototype.__Class`. - * @param BaseClass `ClassObj.Base` is set to this, while `ClassObj.Prototype.Base` is set to `BaseClass.Prototype`. - * @param Args If specified, any other parameters are passed to `static __New`, as in `ClassObj.__New(Args*)`. - * @since v2.1-alpha.3 - */ - static Call([Name,] BaseClass?, Args*) => this - - /** - * Retrieve or set the object on which all instances of the class are based. - */ - Prototype: Prototype -} - -class ClipboardAll extends Buffer { - /** - * Create an object (such as pictures and formats) that contains all the content on the clipboard. - */ - __New([Data, Size]) => void -} - -class Closure extends Func { -} - -class ComObjArray extends ComValue { - /** - * Create a safe array for COM. - * @param VarType The base type of the array (the VARTYPE of each element in the array). VARTYPE is restricted to a subset of the variant type. - * Cannot be set to VT_ARRAY or VT_BYREF flags. VT_EMPTY and VT_NULL are not valid base types for arrays. All other types are legal. - * @param Counts* The size of each dimension. Supports arrays of up to 8 dimensions. - */ - static Call(VarType, Counts*) => ComObjArray - - /** - * Enumerates array elements. - */ - __Enum(NumberOfVars?) => Enumerator - - MaxIndex(n) => Integer - - MinIndex(n) => Integer - - Clone() => ComObjArray -} - -class ComObject extends ComValue { - /** - * Create a COM object. - * @param CLSID The CLSID or readable Prog ID of the COM object to be created. - * @param IID The identifier of the interface to be returned. In most cases, it is omitted; if omitted, it defaults to IID_IDispatch - */ - static Call(CLSID, IID := '{00020400-0000-0000-C000-000000000046}') => ComObject | ComValue -} - -class ComValue extends Any { - /** - * Wrap a value, safe array or COM object for use by scripts or pass to COM methods. - * @param VarType represents an integer of value type. See ComObjType for the list of types. - * @param Value The value to be wrapped. Currently only integer and pointer values are supported. - * @param Flags Flags that affect the behavior of the wrapper object; for details, see ComObjFlags. - */ - static Call(VarType, Value [, Flags]) => ComValue | ComObject | ComObjArray - - Ptr?: Integer -} - -class ComValueRef extends ComValue { -} - -class Enumerator extends Func { - /** - * Retrieves the next item or items in an enumeration. - */ - Call(&OutputVar1?: VarRef, &OutputVar2?: VarRef, *) => Integer -} - -class Error extends Object { - /** - * An error message. - */ - Message: String - - /** - * What threw the exception. This is usually the name of a function, but is blank for exceptions thrown due to an error in an expression (such as using a math operator on a non-numeric value). - */ - What: String - - /** - * A string value relating to the error, if available. If this value can be converted to a non-empty string, the standard error dialog displays a line with "Specifically:" followed by this string. - */ - Extra: String - - /** - * The full path of the script file which contains the line at which the error occurred, or at which the Error object was constructed. - */ - File: String - - /** - * The line number at which the error occurred, or at which the Error object was constructed. - */ - Line: Integer - - /** - * A string representing the call stack at the time the Error object was constructed. - */ - Stack: String - - /** - * Create an Error object. - */ - __New([Message, What, Extra]) => void -} - -class File extends Object { - static Call() => throw - - /** - * Retrieve or set the position of the file pointer. - */ - Pos { - get => Integer - set => void - } - - /** - * Retrieve or set the size of the file. - */ - Length { - get => Integer - set => void - } - - /** - * Retrieve a non-zero value if the file pointer has reached the end of the file. - */ - AtEOF => Integer - - /** - * Retrieve or set the text encoding used by this file object. - */ - Encoding { - get => String - set => void - } - - /** - * Retrieve system file handles intended for use with DllCall. - */ - Handle => Integer - - /** - * Read the string from the file and move the file pointer forward. - */ - Read([Characters]) => String - - /** - * Write a string to the file and move the file pointer forward. - */ - Write(String) => Integer - - /** - * Read the original binary data from the file to the memory and move the file pointer forward. - */ - RawRead(Buffer [, Bytes]) => Integer - - /** - * Write the original binary data to the file and move the file pointer forward. - */ - RawWrite(Data [, Bytes]) => Integer - - /** - * Read a line of text from the file and move the file pointer forward. - */ - ReadLine() => String - - /** - * According to the flag used when opening the file, write the string followed by `n or `r`n. Move the file pointer forward. - */ - WriteLine([String]) => Integer - - /** - * Read the specified type of data from the file and move the file pointer forward. - */ - ReadChar() => Integer - - /** - * Read Double type data from the file and move the file pointer forward. - */ - ReadDouble() => Float - - /** - * Read Float type data from the file and move the file pointer forward. - */ - ReadFloat() => Float - - /** - * Read Int type data from the file and move the file pointer forward. - */ - ReadInt() => Integer - - /** - * Read Int64 type data from the file and move the file pointer forward. - */ - ReadInt64() => Integer - - /** - * Read Short type data from the file and move the file pointer forward. - */ - ReadShort() => Integer - - /** - * Read UChar type data from the file and move the file pointer forward. - */ - ReadUChar() => Integer - - /** - * Read UInt type data from the file and move the file pointer forward. - */ - ReadUInt() => Integer - - /** - * Read UShort type data from the file and move the file pointer forward. - */ - ReadUShort() => Integer - - /** - * Write Char type data to the file and move the file pointer forward. - */ - WriteChar(Num) => Integer - - /** - * Write Double type data to the file and move the file pointer forward. - */ - WriteDouble(Num) => Integer - - /** - * Write Float type data to the file and move the file pointer forward. - */ - WriteFloat(Num) => Integer - - /** - * Write Int type data to the file and move the file pointer forward. - */ - WriteInt(Num) => Integer - - /** - * Write Int64 type data to the file and move the file pointer forward. - */ - WriteInt64(Num) => Integer - - /** - * Write Short type data to the file and move the file pointer forward. - */ - WriteShort(Num) => Integer - - /** - * Write UChar type data to the file and move the file pointer forward. - */ - WriteUChar(Num) => Integer - - /** - * Write UInt type data to the file and move the file pointer forward. - */ - WriteUInt(Num) => Integer - - /** - * Write UShort type data to the file and move the file pointer forward. - */ - WriteUShort(Num) => Integer - - /** - * Move the file pointer. If Origin is omitted, when the Distance is negative, Origin defaults to SEEK_END, and otherwise it is SEEK_SET.. - */ - Seek(Distance [, Origin]) => Integer - - /** - * Close the file, write all the data in the cache to disk and release the shared lock. - */ - Close() => void -} - -class Float extends Number { - /** - * Convert a numeric string or numerical to a floating point number. - */ - static Call(Value) => Float -} - -class Func extends Object { - static Call() => throw - - /** - * Returns the name of the function. - */ - Name => String - - /** - * The built-in function returns true, otherwise it returns false. - */ - IsBuiltIn => Integer - - /** - * When the function is a variable parameter, it returns true, otherwise it returns false. - */ - IsVariadic => Integer - - /** - * Return the number of required parameters. - */ - MinParams => Integer - - /** - * For user-defined functions, return the number of officially declared parameters, for built-in functions, return the maximum number of parameters. - */ - MaxParams => Integer - - /** - * call function. - */ - Call(Params*) => Any - - /** - * Bind parameters to the function and return the bound function object. - */ - Bind(Params*) => BoundFunc - - /** - * Determine whether the parameter is of the ByRef type (if the parameter is omitted, it means whether the function contains a ByRef parameter). - */ - IsByRef(ParameterVar) => Integer - - /** - * Determine whether the parameter is optional (if the parameter is omitted, it means whether the function contains optional parameters). - */ - IsOptional([ParamIndex]) => Integer -} - -class Gui extends Object { - /** - * Retrieve or set the background color of the window. - */ - BackColor { - get => String - set => void - } - - /** - * Retrieve the GuiControl object of the focus control of the GUI. - */ - FocusedCtrl => ControlType - - /** - * Retrieve the window handle (HWND) of the GUI window. - */ - Hwnd => Integer - - /** - * Retrieve or set the size of the horizontal margin between the two sides and the subsequently created control. - */ - MarginX { - get => Integer - set => void - } - - /** - * Retrieve or set the size of the vertical margin between the two sides and the subsequently created control. - */ - MarginY { - get => Integer - set => void - } - - /** - * Retrieve or set the menu bar of the window. - */ - MenuBar { - get => MenuBar - set => void - } - - /** - * Retrieve or set the custom name of the GUI window. - */ - Name { - get => String - set => void - } - - /** - * Retrieve or set the title of the GUI. - */ - Title { - get => String - set => void - } - - /** - * Create a new Gui object. - * @param Options AlwaysOnTop Border Caption Disabled -DPIScale LastFound - * MaximizeBox MinimizeBox MinSize600x600 MaxSize800x800 Resize - * OwnDialogs '+Owner' OtherGui.hwnd +Parent - * SysMenu Theme ToolWindow - * @param Title The window title. If omitted, it defaults to the current value of A_ScriptName. - * @param EventObj OnEvent, OnNotify and OnCommand can be used to register methods of EventObj to be called when an event is raised - */ - __New(Options := '', Title := A_ScriptName, EventObj?) => void - - /** - * Enumerates the GUI's controls. - */ - __Enum(NumberOfVars?) => Enumerator | Enumerator - - /** - * Create controls such as text, buttons or checkboxes, and return a GuiControl object. - * @param {'ActiveX'|'Button'|'Checkbox'|'ComboBox'|'Custom'|'DateTime'|'DDL'|'DropDownList'|'Edit'|'GroupBox'|'Hotkey'|'Link'|'ListBox'|'ListView'|'MonthCal'|'Pic'|'Picture'|'Progress'|'Radio'|'Slider'|'StatusBar'|'Tab'|'Tab2'|'Tab3'|'Text'|'TreeView'|'UpDown'} ControlType - * @param Options V: Sets the control's Name. - * Pos: xn yn wn hn rn Right Left Center Section - * VScroll HScroll -Tabstop -Wrap - * BackgroundColor Border Theme Disabled Hidden - */ - Add(ControlType [, Options, Text]) => ControlType - - /** - * Create a text control that the user cannot edit. Often used to label other controls. - * @param Options V: Sets the control's Name. - * Pos: xn yn wn hn rn Right Left Center Section - * VScroll HScroll -Tabstop -Wrap - * BackgroundColor BackgroundTrans - * Border Theme Disabled Hidden - * @param Text The text - */ - AddText([Options, Text]) => Gui.Text - - /** - * Create controls such as text, buttons or checkboxes, and return a GuiControl object. - * @param Options Limit Lowercase Multi Number Password ReadOnly - * Tn Uppercase WantCtrlA WantReturn WantTab - * V: Sets the control's Name. - * Pos: xn yn wn hn rn Right Left Center Section - * VScroll HScroll -Tabstop -Wrap - * BackgroundColor Border Theme Disabled Hidden - * @param Text The text in the Edit - */ - AddEdit([Options, Text]) => Gui.Edit - - /** - * Create UpDown control and return a GuiControl object. - */ - AddUpDown([Options, Text]) => Gui.UpDown - - /** - * Create Picture control and return a GuiControl object. - */ - AddPicture([Options, FileName: $FilePath<'bmp|jpg|png|gif|ico'>]) => Gui.Pic - /** @see {@link Gui#AddPicture} */ - AddPic([Options, FileName: $FilePath<'bmp|jpg|png|gif|ico'>]) => Gui.Pic - - /** - * Adds a Button control and returns a GuiControl object. - * @param Options Positioning and Sizing of Controls - * V: Sets the control's Name. - * Positioning: xn yn wn hn rn Right Left Center Section -Tabstop -Wrap - * BackgroundColor Border Theme Disabled Hidden - * @param Text The text of the button - */ - AddButton([Options, Text]) => Gui.Button - - /** - * Create Checkbox and return a GuiControl object. - * GuiCtrl.Value returns the number 1 for checked, 0 for unchecked, and -1 for gray/indeterminate. - * @param Options V: Sets the control's Name. - * Checked: Start off checked - * Check3: Enable a third "indeterminate" state that displays a gray checkmark - * CheckedGray: Start off checked or indeterminate - * CheckedN: Set state: 0, 1 or -1 - * Pos: xn yn wn Right Left Center Section - * VScroll HScroll -Tabstop -Wrap - * BackgroundColor BackgroundTrans - * Border Theme Disabled Hidden - * @param Text The text of the Checkbox - */ - AddCheckbox([Options, Text]) => Gui.Checkbox - - /** - * Create Radio control and return a GuiControl object. - * GuiCtrl.Value returns the number 1 for checked, 0 for unchecked, and -1 for gray/indeterminate. - * Events: DoubleClick, Focus & LoseFocus - * @param Options V: Sets the control's Name. - * Checked: Start off checked - * CheckedN: Set state: 0 or 1 - * Group: Start a new group - * Pos: xn yn wn Right Left Center Section - * VScroll HScroll -Tabstop -Wrap - * BackgroundColor BackgroundTrans - * Border Theme Disabled Hidden - * @param Text The text of the Checkbox - */ - AddRadio([Options, Text]) => Gui.Radio - - /** - * Create DropDownList control and return a GuiControl object. - */ - AddDropDownList([Options, Items]) => Gui.DDL - /** @see {@link Gui#AddDropDownList} */ - AddDDL([Options, Items]) => Gui.DDL - - /** - * Create ComboBox control and return a GuiControl object. - */ - AddComboBox([Options, Items]) => Gui.ComboBox - - /** - * Create ListBox control and return a GuiControl object. - */ - AddListBox([Options, Items]) => Gui.ListBox - - /** - * Create ListView control and return a GuiControl object. - */ - AddListView([Options, Titles]) => Gui.ListView - - /** - * Create TreeView control and return a GuiControl object. - */ - AddTreeView([Options, Text]) => Gui.TreeView - - /** - * Create Link control and return a GuiControl object. - */ - AddLink([Options, Text]) => Gui.Link - - /** - * Create Hotkey control and return a GuiControl object. - */ - AddHotkey([Options, Text]) => Gui.Hotkey - - /** - * Create DateTime control and return a GuiControl object. - */ - AddDateTime([Options, DateTime]) => Gui.DateTime - - /** - * Create MonthCal control and return a GuiControl object. - */ - AddMonthCal([Options, YYYYMMDD]) => Gui.MonthCal - - /** - * Create Slider control and return a GuiControl object. - */ - AddSlider([Options, Value]) => Gui.Slider - - /** - * Create Progress control and return a GuiControl object. - */ - AddProgress([Options, Value]) => Gui.Progress - - /** - * Create GroupBox control and return a GuiControl object. - */ - AddGroupBox([Options, Text]) => Gui.GroupBox - - /** - * Create Tab control and return a GuiControl object. - */ - AddTab([Options, Pages]) => Gui.Tab - - /** - * Create Tab2 control and return a GuiControl object. - */ - AddTab2([Options, Pages]) => Gui.Tab - - /** - * Create Tab3 control and return a GuiControl object. - */ - AddTab3([Options, Pages]) => Gui.Tab - - /** - * Create StatusBar control and return a GuiControl object. - */ - AddStatusBar([Options, Text]) => Gui.StatusBar - - /** - * Create ActiveX control and return a GuiControl object. - */ - AddActiveX([Options, Component]) => Gui.ActiveX - - /** - * Create Custom controls and return a GuiControl object. - */ - AddCustom([Win32Class, Text]) => Gui.Custom - - /** - * Delete window. - */ - Destroy() => void - - /** - * Flashing windows and their taskbar buttons. - */ - Flash(false) => void - - /** - * Retrieve the position and size of the working area of the window. - */ - GetClientPos([&X: VarRef, &Y: VarRef, &Width: VarRef, &Height: VarRef]) => void - - /** - * Retrieve the position and size of the window. - */ - GetPos([&X: VarRef, &Y: VarRef, &Width: VarRef, &Height: VarRef]) => void - - /** - * Hide window. - */ - Hide() => void - - /** - * Hide window. - */ - Cancel() => void - - /** - * Open and maximize the window. - */ - Maximize() => void - - /** - * Open and minimize the window. - */ - Minimize() => void - - /** - * Move/resize the GUI window. - */ - Move([X, Y, Width, Height]) => void - - /** - * Registers a function or method to be called when the given event is raised by a GUI window. - * @param {'Close'|'ContextMenu'|'DropFiles'|'Escape'|'Size'} EventName - * @param Callback The function, method or object to call when the event is raised. - * If the GUI has an event sink (that is, if Gui()'s EventObj parameter was specified), this parameter may be the name of a method belonging to the event sink. - * Otherwise, this parameter must be a function object. - * - Close(GuiObj) => Integer - * - ContextMenu(GuiObj, GuiCtrlObj, Item, IsRightClick, X, Y) => Integer - * - DropFiles(GuiObj, GuiCtrlObj, FileArray, X, Y) => Integer - * - Escape(GuiObj) => Integer - * - Size(GuiObj, MinMax, Width, Height) => Integer - */ - OnEvent(EventName, Callback, AddRemove := 1) => void - - /** - * Registers a function or method to be called whenever the Gui receives the specified message. - * @param {Integer} Msg The number of the message to monitor, which should be between 0 and 4294967295 (0xFFFFFFFF). - * @param {String|(GuiObj, wParam, lParam, Msg) => Integer} Callback The function, method or object to call when the event is raised. - * If the GUI has an event sink (that is, if Gui()'s EventObj parameter was specified), this parameter may be the name of a method belonging to the event sink. - * Otherwise, this parameter must be a function object. (**ahk_h 2.0**)The function may also consult the built-in variable `A_EventInfo`, which contains 0 if the message was sent via SendMessage. - * If sent via PostMessage, it contains the tick-count time the message was posted. - * @param {Integer} AddRemove If omitted, it defaults to 1 (call the callback after any previously registered callbacks). Otherwise, specify one of the following numbers: - * - 1 = Call the callback after any previously registered callbacks. - * - -1 = Call the callback before any previously registered callbacks. - * - 0 = Do not call the callback. - * @since 2.1-alpha.1 or ahk_h 2.0 - */ - OnMessage(Msg, Callback [, AddRemove]) => void - - /** - * Set various options and styles for the appearance and behavior of the window. - * @param Options AlwaysOnTop Border Caption Disabled -DPIScale LastFound - * MaximizeBox MinimizeBox MinSize600x600 MaxSize800x800 Resize - * OwnDialogs '+Owner' OtherGui.hwnd '+Parent' OtherGui.hwnd - * SysMenu Theme ToolWindow - */ - Opt(Options) => void - - /** - * Unhides the window (if necessary) and restores it, if it was minimized or maximized beforehand. - */ - Restore() => void - - /** - * Set the font, size, style, and text color of the subsequently created control. - * @param Options Bold italic strike underlin norm - * cColor : Color name or RBG, color names are also accepted - * Sn : Wize in points - * Wn : Weight (boldness) - * Qn : Rendering quality - * @param FontName MS sans serif - * Arial Calibri Courier - * Verdana Consolas Terminal - * Times New Roman - * ... - */ - SetFont([Options, FontName]) => void - - /** - * Display window. It can also minimize, maximize or move the window. - * @param Options Positioning: Xn Yn Wn Hn Center xCenter yCenter AutoSize - * Minimize Maximize Restore NoActivate NA Hide - */ - Show([Options]) => void - - /** - * Collect values from named controls and combine them into an object, optionally hiding the window. - */ - Submit(Hide := true) => void - - class ActiveX extends Gui.Control { - } - - class Button extends Gui.Control { - } - - class CheckBox extends Gui.Control { - } - - class ComboBox extends Gui.List { - } - - class Control extends Object { - static Call() => throw - - /** - * Retrieve the ClassNN of the control. - */ - ClassNN => String - - /** - * Retrieve the current interactive state of the control, or enable or disable (gray) the control. - */ - Enabled { - get => Integer - set => void - } - - /** - * Retrieve the current focus state of the control. - */ - Focused => Integer - - /** - * Retrieve the Gui parent control of the control. - */ - Gui => Gui - - /** - * Retrieve the HWND of the control. - */ - Hwnd => Integer - - /** - * Retrieve or set the explicit name of the control. - */ - Name { - get => String - set => void - } - - /** - * Retrieve or set the text/title of the control. - */ - Text { - get => String - set => void - } - - /** - * Retrieve the type of control. - */ - Type => String - - /** - * Retrieve new content or set it as a valuable control. - */ - Value { - get => Float | Integer | String - set => void - } - - /** - * Retrieve the current visible state of the control, or show or hide it. - */ - Visible { - get => Integer - set => void - } - - /** - * Set the keyboard focus to the control. - */ - Focus() => void - - /** - * Retrieve the position and size of the control. - */ - GetPos([&X: VarRef, &Y: VarRef, &Width: VarRef, &Height: VarRef]) => void - - /** - * Move/resize controls. - */ - Move([X, Y, Width, Height]) => void - - /** - * Registers a function or method to be called when a control notification is received via the WM_COMMAND message. - * @param Callback The function, method or object to call when the event is raised. - * If the GUI has an event sink (that is, if Gui()'s EventObj parameter was specified), this parameter may be the name of a method belonging to the event sink. - * Otherwise, this parameter must be a function object. - * - Command(GuiControl) - */ - OnCommand(NotifyCode, Callback, AddRemove := 1) => void - - /** - * Registers a function or method to be called when the given event is raised. - * @param {'Change'|'Click'|'DoubleClick'|'ColClick'|'ContextMenu'|'Focus'|'LoseFocus'|'ItemCheck'|'ItemEdit'|'ItemExpand'|'ItemFocus'|'ItemSelect'} EventName - * @param Callback The function, method or object to call when the event is raised. - * If the GUI has an event sink (that is, if Gui()'s EventObj parameter was specified), this parameter may be the name of a method belonging to the event sink. - * Otherwise, this parameter must be a function object. - * - Change(GuiCtrlObj, Info) - * - Click(GuiCtrlObj, Info, Href?) - * - DoubleClick(GuiCtrlObj, Info) - * - ColClick(GuiCtrlObj, Info) - * - ContextMenu(GuiCtrlObj, Item, IsRightClick, X, Y) - * - Focus(GuiCtrlObj, Info) - * - LoseFocus(GuiCtrlObj, Info) - * - ItemCheck(GuiCtrlObj, Item, Checked) - * - ItemEdit(GuiCtrlObj, Item) - * - ItemExpand(GuiCtrlObj, Item, Expanded) - * - ItemFocus(GuiCtrlObj, Item) - * - ItemSelect(GuiCtrlObj, Item, Selected?) - */ - OnEvent(EventName, Callback, AddRemove := 1) => void - - /** - * Registers a function or method to be called whenever the GuiControl receives the specified message. - * @param {Integer} Msg The number of the message to monitor, which should be between 0 and 4294967295 (0xFFFFFFFF). - * @param {String|(GuiCtrlObj, wParam, lParam, Msg) => Integer} Callback The function, method or object to call when the event is raised. - * If the GUI has an event sink (that is, if Gui()'s EventObj parameter was specified), this parameter may be the name of a method belonging to the event sink. - * Otherwise, this parameter must be a function object. The function may also consult the built-in variable `A_EventInfo`, which contains 0 if the message was sent via SendMessage. - * If sent via PostMessage, it contains the tick-count time the message was posted. - * @param {Integer} AddRemove If omitted, it defaults to 1 (call the callback after any previously registered callbacks). Otherwise, specify one of the following numbers: - * - 1 = Call the callback after any previously registered callbacks. - * - -1 = Call the callback before any previously registered callbacks. - * - 0 = Do not call the callback. - * @since 2.1-alpha.7 or ahk_h 2.0 - */ - OnMessage(Msg, Callback [, AddRemove]) => void - - /** - * Registers a function or method to be called when a control notification is received via the WM_NOTIFY message. - * @param Callback The function, method or object to call when the event is raised. - * If the GUI has an event sink (that is, if Gui()'s EventObj parameter was specified), this parameter may be the name of a method belonging to the event sink. - * Otherwise, this parameter must be a function object. - * - Notify(GuiControl, lParam) - */ - OnNotify(NotifyCode, Callback, AddRemove := 1) => void - - /** - * Set various options and styles for the appearance and behavior of the control. - */ - Opt(Options) => void - - /** - * Redraw the GUI window area occupied by the control. - */ - Redraw() => void - - /** - * Set the font, size, style and/or color of the control. - */ - SetFont([Options, FontName]) => void - - /** - * Set the display format of the DateTime control. - */ - SetFormat([TimeFormat]) => void - } - - class Custom extends Gui.Control { - } - - class DateTime extends Gui.Control { - } - - class DDL extends Gui.List { - } - - class Edit extends Gui.Control { - } - - class GroupBox extends Gui.Control { - } - - class Hotkey extends Gui.Control { - } - - class Link extends Gui.Control { - } +A_Min: String - class List extends Gui.Control { - /** - * Add the specified item to the current list of the list box, drop-down list, combo box or tab control. - */ - Add(Items*) => void - - /** - * Set the selection in the ListBox, DropDownList, ComboBox or Tab control to the specified value. - */ - Choose(Value) => void - - /** - * Delete the specified item or all items of ListBox, DropDownList, ComboBox or Tab control. - */ - Delete([Index]) => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#MM|A_MM} + * The current month in 2-digit format: `01`-`12`. + * Synonymous with `A_Mon`. + * @type String + * @example + * MsgBox('The current month number is: ' A_MM) + */ +A_MM: String - class ListBox extends Gui.List { - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#MMM|A_MMM} + * The 3 letter abbreviation for the current month: `Jan`-`Dec` + * @type String + * @example + * MsgBox('The current month is: ' A_MMM) + */ +A_MMM: String - class ListView extends Gui.Control { - /** - * Add a new row to the bottom of the list and return the new row number. If the ListView has a Sort or SortDesc style, it may not be the last row. - */ - Add([Options, Cols*]) => void - - /** - * Delete the specified row, return 1 on success, and return 0 on failure. - */ - Delete([RowNumber]) => Integer - - /** - * Delete the specified column and all the content under it, and return 1 on success and 0 on failure. - */ - DeleteCol(ColumnNumber) => Integer - - /** - * Returns the number of rows or columns in the control. - */ - GetCount([Mode]) => Integer - - /** - * Return the line number of the next selected, selected or focused line, otherwise it returns zero. - */ - GetNext([StartingRowNumber, RowType]) => Integer - - /** - * Retrieve the text of the specified row number and column number. - */ - GetText(RowNumber [, ColumnNumber]) => String - - /** - * Insert a new line at the specified line number, and return the new line number. - */ - Insert(RowNumber [, Options, Cols*]) => Integer - - /** - * Insert a new column at the specified column number, and return the position number of the new column. - */ - InsertCol(ColumnNumber [, Options, ColumnTitle]) => Integer - - /** - * Modify the attributes/text of the row and return 1 on success and 0 on failure. - */ - Modify(RowNumber [, Options, NewCols*]) => Integer - - /** - * Modify the attribute/text of the specified column and its title, and return 1 on success and 0 on failure. - */ - ModifyCol([ColumnNumber, Options, ColumnTitle]) => Integer - - /** - * Set or replace ImageList, and return the ImageListID previously associated with this control (if not, return 0). - */ - SetImageList(ImageListID [, IconType]) => Integer - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#MMMM|A_MMMM} + * The full name of the current month: `January`-`December` + * @type String + * @example + * MsgBox('The current month is: ' A_MMMM) + */ +A_MMMM: String - class MonthCal extends Gui.Control { - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#A_MM|A_Mon} + * The current month in 2-digit format: `01`-`12`. + * Synonymous with `A_MM`. + * @type String + * @example + * MsgBox('The current month number is: ' A_MM) + */ +A_Mon: String - class Pic extends Gui.Control { - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#MouseDelay|A_MouseDelay} + * Used to get or set the delay, in milliseconds, that occurs after SendEvent-based mouse movements or clicks. + * This variable can be set to the following values: + * - Positive value = The amount of time to wait, in ms. + * - `0` = Use the smallest possible delay. + * - `-1` = Use no delay. + * SendPlay mode has its own delay setting. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#MouseDelayPlay|A_MouseDelayPlay} + * @example + * SendMode('Event') + * A_MouseDelay := 200 + * ; Each click will have 200ms between them + * Click(3) + */ +A_MouseDelay: Integer - class Progress extends Gui.Control { - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#MouseDelayPlay|A_MouseDelayPlay} + * Used to get or set the delay, in milliseconds, that occurs after SendPlay-based mouse movements or clicks. + * This variable can be set to the following values: + * - Positive value = The amount of time to wait, in ms. + * - `0` or `-1` = Use no delay. + * SendEvent mode has its own delay setting. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetMouseDelay.htm|SetMouseDelay()} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#MouseDelay|A_MouseDelay} + */ +A_MouseDelayPlay: Integer - class Radio extends Gui.Control { - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#MSec|A_MSec} + * The current millisecond in 3-digit format: `000`-`999` + * @type String + * @example + * MsgBox('Current milliseconds: ' A_MSec) + */ +A_MSec: String - class Slider extends Gui.Control { - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#A_MyDocuments|A_MyDocuments} + * This variable contains the path to the user's Documents (My Documents) folder. + * Typically, this contains: `C:\Users\\Documents` + * Unlike most other path variables, the following `\` is not included with root directories: `D:` instead of `D:\` + * @type String + * @example + * MsgBox('Path to user`'s Documents folder:`n' A_MyDocuments) + */ +A_MyDocuments: String - class StatusBar extends Gui.Control { - /** - * Display a small icon on the left side of the text in the specified part, and return the handle of the icon. - */ - SetIcon(FileName: $FilePath, IconNumber := 1, PartNumber := 1) => Integer - - /** - * Divide the bar into multiple parts according to the specified width (in pixels), and return a non-zero value (HWND of the status bar). - */ - SetParts(Widths*) => Integer - - /** - * Display NewText in the specified part of the status bar, return 1 if successful, and return 0 if failed. - */ - SetText(NewText, PartNumber := 1, Style := 0) => Integer - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Now|A_Now} + * @type String + * The current local time in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS format}. + * Date and time math can be performed with {@link https://www.autohotkey.com/docs/v2/lib/DateAdd.htm|DateAdd()} and {@link https://www.autohotkey.com/docs/v2/lib/DateDiff.htm|DateDiff()}. + * Time formatting can be done with {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|FormatTime()}. + * @example + * current := A_Now + * formatted := FormatTime(current, 'dddd, MMMM dd, yyyy @ hh:mm:ss tt') + * past := DateAdd(current, -7, 'D') + * time_until := DateDiff(current, 21000101000000, 'D') + * MsgBox('Current DTS: ' + * '`n' current + * '`nCurrent time formatted: ' + * '`n' formatted + * '`n1 week ago: ' + * '`n' past + * '`nTime until the year 2100: ' + * '`n' Abs(time_until) ' Days') + */ +A_Now: String - class Tab extends Gui.List { - /** - * Causes the subsequently added control to belong to the specified tab of the tab control. - * The @param Value parameter is 1 for the first entry, 2 for the second, and so on. If Value is not an integer, the previous part of the tag that matches Value will be used. The search is not case sensitive. For example, if a control Contains the "UNIX Text" tag, specify the word unix (lowercase) to use it. If Value is 0, it is a blank string or is omitted, the subsequent controls will be added to the Tab control. - * @param ExactMatch If this parameter is true, Value must match exactly, but it is not case sensitive. - */ - UseTab(Value := 0, ExactMatch := false) => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#NowUTC|A_NowUTC} + * The current UTC (Coordinated Universal Time) time in {@link https://www.autohotkey.com/docs/v2/lib/FileSetTime.htm#YYYYMMDD|YYYYMMDDHH24MISS format}. + * This is also known as Zulu time. + * Date and time math can be performed with {@link https://www.autohotkey.com/docs/v2/lib/DateAdd.htm|DateAdd()} and {@link https://www.autohotkey.com/docs/v2/lib/DateDiff.htm|DateDiff()}. + * Time formatting can be done with {@link https://www.autohotkey.com/docs/v2/lib/FormatTime.htm|FormatTime()}. + * Bonus info: It's called UTC as a compromise between the English abbreviation CUT (Coordinated Universal Time) and the French version TUC (Temps Universel Coordonné). + * @type String + * @example + * current := A_NowUTC + * formatted := FormatTime(current, 'dddd, MMMM dd, yyyy @ hh:mm:ss tt') + * past := DateAdd(current, -7, 'D') + * time_until := DateDiff(current, 21000101000000, 'D') + * MsgBox('Current UTC time: ' + * '`n' current + * '`nCurrent UTC time formatted: ' + * '`n' formatted + * '`n1 week ago: ' + * '`n' past + * '`nTime until the year 2100: ' + * '`n' Abs(time_until) ' Days') + */ +A_NowUTC: String - class Text extends Gui.Control { - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#OSVersion|A_OSVersion} + * The current operating system version in `Major`.`Minor`.`Patch` format. + * Example: `10.0.19045` + * @type String + * @example + * MsgBox('Current OS Version: ' A_OSVersion) + */ +A_OSVersion: String - class TreeView extends Gui.Control { - /** - * Add a new item to the TreeView, and return its unique item ID number. - */ - Add(Name [, ParentItemID, Options]) => Integer - - /** - * Delete the specified item, return 1 if successful, and return 0 if failed. - */ - Delete([ItemID]) => Integer - - /** - * If the specified item has the specified attribute, a non-zero value (item ID) is returned. - * @param ItemID selected item. - * @param Attribute specify "E", "Expand" or "Expanded" to determine whether this item is currently expanded (that is, its sub-items are displayed); specify "C", "Check" or "Checked" to determine Whether this item contains a check mark; or specify "B" or "Bold" to determine whether this item is currently bold. - */ - Get(ItemID, Attribute) => Integer - - /** - * Return the ID number of the first/top child item of the specified item (if there is none, return 0). - */ - GetChild(ParentItemID) => Integer - - /** - * Returns the total number of items in the control. - */ - GetCount() => Integer - - /** - * Return the ID number of the next item below the specified item (if there is none, return 0). - */ - GetNext([ItemID, ItemType]) => Integer - - /** - * Return the parent item of the specified item as the item ID. - */ - GetParent(ItemID) => Integer - - /** - * Return the ID number of the previous item above the specified item (if there is none, return 0). - */ - GetPrev(ItemID) => Integer - - /** - * Return the ID number of the selected item. - */ - GetSelection() => Integer - - /** - * Retrieve the text/name of the specified item. - */ - GetText(ItemID) => String - - /** - * Modify the project's attributes/name, and return the project's own ID. - */ - Modify(ItemID [, Options, NewName]) => Integer - - /** - * Set or replace ImageList, and return the ImageListID previously associated with this control (if not, return 0). - */ - SetImageList(ImageListID [, IconType]) => Integer - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#PriorHotkey|A_PriorHotkey} + * Contains the text of the hotkey or non-auto-replacing hotstring (a hotstring that uses the `x` option) that was executed prior to the last hotkey. + * This is a useful variable when writing code that activates on a double tap or to otherwise track prior key sequences. + * @type String + * @example + * ; Creating code that activates on double tap + * *Space:: { + * ; Initially, A_TimeSincePriorHotkey and A_PriorHotkey are empty strings. + * ; Using an empty string in a comparison is an error. + * ; Try prevents this initial inevitable error. + * try + * ; Check if it's been 400 ms or less since the prior hotkey was fired + * ; And check if the current fired hotkey matches the prior hotkey. + * if (A_TimeSincePriorHotkey < 400 && A_ThisHotkey = A_PriorHotkey) + * MsgBox('Double tap detected!') + * else Send(' ') + * catch + * Send(' ') + * } + */ +A_PriorHotkey: String - class UpDown extends Gui.Control { - } -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#PriorKey|A_PriorKey} + * Contains the text of the last key press since the most most recent key down or key up event. + * @type String + * @example + * last_key_checker() + * + * last_key_checker() { + * if (A_PriorKey = '') + * ToolTip('Prior key: ' A_PriorKey) + * else ToolTip(A_PriorKey) + * SetTimer(%A_ThisFunc%, -50) + * } + * + * MsgBox('Type to see A_PriorKey being tracked.') + */ +A_PriorKey: String -class IndexError extends ValueError { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ProgramFiles|A_ProgramFiles} + * This variable contains the path to the user's Program Files folder. + * Typically, this contains: `C:\Program Files` or `C:\Program Files (x86)` + * This is usually the same as the ProgramFiles {@link https://www.autohotkey.com/docs/v2/Concepts.htm#environment-variables|environment variable}. + * @type String + * @example + * MsgBox('The system`'s Program Files path:`n' A_ProgramFiles) + */ +A_ProgramFiles: String -class InputHook extends Object { - /** - * Returns the name of the end construction that was pressed when the Input was terminated. - */ - EndKey => String - - /** - * Returns the string that is logically the modifier key that was pressed when Input was terminated. - */ - EndMods => String - - /** - * Returns the EndReason string, which indicates how the Input is terminated. - */ - EndReason => String - - /** - * If the input is in progress, it returns true, otherwise it returns false. - */ - InProgress => Integer - - /** - * Returns any text collected since the last time Input was started. - */ - Input => String - - /** - * Return the MatchList item that caused the Input to terminate. - */ - Match => String - - /** - * Retrieve or set the function object called when Input is terminated. - */ - OnEnd { - get => Func | void - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Programs|A_Programs} + * This variable contains the path to the user's Start menu's Programs folder. + * Typically, this contains: `C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs` + * @type String + * @example + * MsgBox('Start menu`'s Programs folder path: ' A_Programs) + */ +A_Programs: String - /** - * Retrieve or set a function object, which will be called after characters are added to the input buffer. - */ - OnChar { - get => Func | void - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ProgramsCommon|A_ProgramsCommon} + * This variable contains the path to the common/all-user Start menu's Programs folder. + * Typically, this contains: `C:\ProgramData\Microsoft\Windows\Start Menu\Programs` + * @type String + * @example + * MsgBox('The common Start menu`'s Programs folder path: ' A_ProgramsCommon) + */ +A_ProgramsCommon: String - /** - * Retrieve or set the function object, which will be called when the button that enables notification is pressed. - */ - OnKeyDown { - get => Func | void - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#PtrSize|A_PtrSize} + * The size of the pointer, in bytes, based on the system architecture type. + * This is `8` if a 64-bit system and `4` if a 32-bit system. + * @type Integer + * @example + * MsgBox('Pointers are ' A_PtrSize ' bytes on this system.') + */ +A_PtrSize: Integer - /** - * Retrieve or set the function object, which will be called when the enable notification button is released. - */ - OnKeyUp { - get => Func | void - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#RegView|A_RegView} + * Used to get or set which Registry view, 32-bit or 64-bit, is used. + * This variable can be set to the following values: + * - `32` = View registry as a 32-bit app. + * - `64` = View registry as a 64-bit app. + * - `Default` = Restore to normal view. + * @type String + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetRegView.htm|SetRegView()} + */ +A_RegView: String - /** - * Control whether Backspace deletes the most recently pressed character from the end of the input buffer. - */ - BackspaceIsUndo { - get => Integer - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScreenDPI|A_ScreenDPI} + * The number of pixels per logical inch of screen width. + * On most systems, this is 96. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm#DPIScale|Gui DPIScale} + * @example + * MsgBox('This computer`'s screen DPI is set to ' A_ScreenDPI) + */ +A_ScreenDPI: Integer - /** - * Control whether MatchList is case sensitive. - */ - CaseSensitive { - get => Integer - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScreenHeight|A_ScreenHeight} + * The height of the primary monitor, in pixels. + * To get the height of other monitors, use {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm|SysGet()} or one of the {@link https://www.autohotkey.com/docs/v2/lib/Monitor.htm|monitor functions} such as {@link https://www.autohotkey.com/docs/v2/lib/MonitorGet.htm|MonitorGet()}. + * @type Integer + * @example Open Notepad 4 times and arrange in 2x2 grid. + * ; Array to store each notepad PID. + * win_list := [] + * ; Do everything 4 times. + * loop 4 { + * ; Run notepad and add PID to list. + * Run('notepad.exe',,, &pid) + * win_list.Push(pid) + * notepad := 'ahk_pid ' pid + * ; Assign 1/2 width and height. + * w := A_ScreenWidth / 2 + * h := A_ScreenHeight / 2 + * ; Assign x/y based on each iteration. + * switch A_Index { + * ; Upper left window + * case 1: x := 0, y := 0 + * ; Upper right window + * case 2: x := w, y := 0 + * ; Lower left window + * case 3: x := 0, y := h + * ; Lower right window + * case 4: x := w, y := h + * } + * ; Wait to make sure the window has fully launched. + * WinWait(notepad) + * ; Move window to its correct position and size. + * WinMove(x, y, w, h, notepad) + * } + * + * MsgBox('Click OK to close the notepad instances.') + * for pid in win_list + * WinClose('ahk_pid ' pid) + */ +A_ScreenHeight: Integer - /** - * Control whether each match can be a substring of the input text. - */ - FindAnywhere { - get => Integer - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScreenWidth|A_ScreenWidth} + * The width of the primary monitor, in pixels. + * To get the width of other monitors, use {@link https://www.autohotkey.com/docs/v2/lib/SysGet.htm|SysGet()} or one of the {@link https://www.autohotkey.com/docs/v2/lib/Monitor.htm|monitor functions} such as {@link https://www.autohotkey.com/docs/v2/lib/MonitorGet.htm|MonitorGet()}. + * @type Integer + * @example Open Notepad 4 times and arrange in 2x2 grid. + * ; Array to store each notepad PID. + * win_list := [] + * ; Do everything 4 times. + * loop 4 { + * ; Run notepad and add PID to list. + * Run('notepad.exe',,, &pid) + * win_list.Push(pid) + * notepad := 'ahk_pid ' pid + * ; Assign 1/2 width and height. + * w := A_ScreenWidth / 2 + * h := A_ScreenHeight / 2 + * ; Assign x/y based on each iteration. + * switch A_Index { + * ; Upper left window + * case 1: x := 0, y := 0 + * ; Upper right window + * case 2: x := w, y := 0 + * ; Lower left window + * case 3: x := 0, y := h + * ; Lower right window + * case 4: x := w, y := h + * } + * ; Wait to make sure the window has fully launched. + * WinWait(notepad) + * ; Move window to its correct position and size. + * WinMove(x, y, w, h, notepad) + * } + * + * MsgBox('Click OK to close the notepad instances.') + * for pid in win_list + * WinClose('ahk_pid ' pid) + */ +A_ScreenWidth: Integer - /** - * Retrieve or set the minimum sending level of the input to be collected. - */ - MinSendLevel { - get => Integer - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptDir|A_ScriptDir} + * The full directory path of the current script. + * The final backslash is omitted. This includes for root directories. + * If the script text is {@link https://www.autohotkey.com/docs/v2/Scripts.htm#stdin|read from stdin} rather than from file, this variable contains the {@link https://www.autohotkey.com/docs/v2/Variables.htm#InitialWorkingDir|initial working directory.}. + * @type String + * @example + * ; Open the current script's directory. + * Run(A_ScriptDir) + */ +A_ScriptDir: String - /** - * Control whether the OnKeyDown and OnKeyUp callbacks are called when a non-text key is pressed. - */ - NotifyNonText { - get => Integer - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptFullPath|A_ScriptFullPath} + * The full path of the current script. Directory and file name: `C:\Scripts\My Script.ahk` + * If the script text is {@link https://www.autohotkey.com/docs/v2/Scripts.htm#stdin|read from stdin} rather than from file, this variable contains an asterisk (*). + * If the script is {@link https://www.autohotkey.com/docs/v2/Scripts.htm#ahk2exe|compiled} or {@link https://www.autohotkey.com/docs/v2/Program.htm#embedded-scripts|embedded}, the file's exe is used. + * @type String + */ +A_ScriptFullPath: String - /** - * Retrieve or set the timeout value (in seconds). - */ - Timeout { - get => Integer - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptHwnd|A_ScriptHwnd} + * The unique ID (HWND/handle) of the script's hidden {@link https://www.autohotkey.com/docs/v2/Program.htm#main-window|main window}. + * @type Integer + * @example + * ; A hotkey that maximizes the script's main window. + * $F1::WinMaximize(A_ScriptHwnd) + */ +A_ScriptHwnd: Integer - /** - * Control whether keys or key combinations that do not produce text are visible (not blocked). - */ - VisibleNonText { - get => Integer - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptName|A_ScriptName} + * Used to get or set the default title used when calling {@link https://www.autohotkey.com/docs/v2/lib/MsgBox.htm|MsgBox()}, {@link https://www.autohotkey.com/docs/v2/lib/InputBox.htm|InputBox()}, {@link https://www.autohotkey.com/docs/v2/lib/FileSelect.htm|FileSelect()}, {@link https://www.autohotkey.com/docs/v2/lib/DirSelect.htm|DirSelect()}, and {@link https://www.autohotkey.com/docs/v2/lib/Gui.htm|Gui()}. + * The default value is the script's name, including extension: `my_script.ahk` + * If the script text is {@link https://www.autohotkey.com/docs/v2/Scripts.htm#stdin|read from stdin} rather than from file, this variable contains an asterisk (*). + * If the script is {@link https://www.autohotkey.com/docs/v2/Scripts.htm#ahk2exe|compiled} or {@link https://www.autohotkey.com/docs/v2/Program.htm#embedded-scripts|embedded}, the file's exe is used. + * @type String + * @example + * ; Notice the text and title are the same. + * MsgBox(A_ScriptName) + * ; Set to new name. + * A_ScriptName := 'Customized A_ScriptName!' + * ; Now the title is + * MsgBox(A_ScriptName) + */ +A_ScriptName: String - /** - * Control whether the key or key combination that generates the text is visible (not blocked). - */ - VisibleText { - get => Integer - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Sec|A_Sec} + * The current seconds in 2-digit format: `00`-`59` + * @type String + * @example + * MsgBox('Current seconds: ' A_Sec) + */ +A_Sec: String - /** - * Create an object that can be used to collect or intercept keyboard input. - * @param Options A string consisting of zero or more of the following letters (in any order, with optional spaces in between): - * - * B: Set BackspaceIsUndo to false, which will cause Backspace to be ignored. - * - * C: Set CaseSensitive to true to make MatchList case sensitive. - * - * I: Set MinSendLevel to 1 or a given value, so that any input with an input level lower than this value is ignored. For example, I2 will ignore any input with level 0 (default) or 1, but will capture any input with level 2 enter. - * - * L: Length limit (such as L5). The maximum allowable length of the input. When the text reaches this length, the input is terminated and EndReason is set to the word Max (unless the text matches a phrase in the MatchList, in which case EndReason is Set to the word Match). If not specified, the length is limited to 1023. - * - * Specify L0 to disable the collection of text and the length limit, but it does not affect the statistics of the text generated by the key (see VisibleText). This can be used in combination with OnChar, OnKeyDown, KeyOpt or EndKeys. - * - * M: Recognize and transcribe modifier keystrokes corresponding to real ASCII characters (such as Ctrl+A to Ctrl+Z). Refer to this example, it recognizes Ctrl+C: - * - * T: Set Timeout (e.g. T3 or T2.5). - * - * V: Set VisibleText and VisibleNonText to true. Normally, user input is blocked (hidden from the system). Use this option to send the user's keystrokes to the active window. - * - * ·*: Wildcard. Set FindAnywhere to true to allow matches to be found anywhere the user types. - * - * E: Handling single-character end keys by character code instead of key code. If the keyboard layout of the active window is different from that of the script, it can provide more consistent results. It also prevents the given end character from actually being generated The key combination to end Input; for example, if @ is the end key, Shift+2 will trigger it on the American keyboard, but Ctrl+Shift+2 will not trigger (when using the E option). If you also use C Option, the ending character is case sensitive. - * @param EndKeys A list of zero or more keys, where any key terminates input when pressed (the end key itself will not be written into the input buffer). When Input is terminated in this way, EndReason is set to The word EndKey, EndKey properties are set to the name of the key. - * - * The EndKeys list uses a format similar to the Send function. For example, specifying {Enter}.{Esc} will cause either Enter,. Or Esc to terminate the Input. Using the brace itself as the end key, specify {{} and /or{}}. - * - * To use Ctrl, Alt or Shift as the end key, please specify the left and/or right version of the key instead of the neutral version. For example, specify {LControl}{RControl} instead of (Control). - * - * Although modifier keys such as Alt+C(!c) are not supported, instead of alphanumeric characters (such as?!:@&()) by default, the Shift key is required to be pressed or not, depending on the normal input of characters Method. If there is an E option, a single character key name is interpreted as a character. In this case, the modifier key must be in the correct state to generate the character. When the E and M options are used at the same time, by including in EndKeys Corresponding ASCII control characters to support Ctrl+A to Ctrl+Z. - * - * You can also specify a clear virtual key code, such as {vkFF} or {sc001}. This is very useful in rare cases where the key has no name and does not produce visible characters when pressed. Its virtual key code can be found at the bottom of the key list page The steps to determine. - * @param MatchList is a comma-separated list of keywords, any of which will cause the input to be terminated (in this case, EndReason will be set to the word Match). The content entered by the user must exactly match a certain phrase in the match list (Unless there is an * option). In addition, any spaces or tabs around the delimiter comma are meaningful, which means they are part of the matching string. For example, if MatchList is ABC, XYZ, then the user must Type a space after ABC or before XYZ to form a match. - * - * Two consecutive commas produce a single literal comma. For example, the following match list will produce a single literal comma at the end of string1: string1,,,string2. Similarly, the following match list contains only one literal comma Single item: single,,item. - * - * Because the items in MatchList are not treated as separate parameters, the list can be completely contained in a variable. In fact, if the length of this list exceeds 16383, then all or part of the list must be contained in the variable because of this length Is the maximum length of any script line. For example, MatchList may consist of List1 "," List2 "," List3 - each of these variables contains a sublist of matching phrases. - */ - __New(Options?, EndKeys?, MatchList?) => void - - /** - * Set the options of the key or key list. - * @param Keys key list. Braces are used to enclose key names, virtual key codes or scan codes, similar to the Send function. For example, {Enter}.{{} will be applied to Enter,. and {. By name, press {vkNN} or pressing the designated key of {scNNN} may produce three different results; for details, see below. - * - * Separately specify the string (All) (not case sensitive) to apply KeyOptions to all VKs and all SCs. Then you can call KeyOpt again to delete options from a specific key. - * @param KeyOptions One or more of the following single-character options (spaces and tabs). - * - * -(Minus sign): Remove any options after-until the next +. - * - * + (Plus sign): cancel any previous -, otherwise invalid. - * - * E: End key. If enabled, press the key to terminate Input, set EndReason to the word EndKey, and set the EndKey property to the standard name of the key. Unlike the EndKeys parameter, the state of the Shift key will be ignored. For example, @ and 2 Both are equivalent to {vk32} in the American keyboard layout. - * - * I: Ignore text. Normally any text generated by the key will be ignored, and the key will be treated as a non-text key (see VisibleNonText). If the key normally does not produce text, it has no effect. - * - * N: Notification. OnKeyDown and OnKeyUp callbacks are called every time a key is pressed. - * - * S: Suppress (block) the key press after processing it. This will overwrite VisibleText or VisibleNonText until -S is used. +S means -V. - * - * V: Visible. Prevents key presses from being suppressed (blocked). This will override VisibleText or VisibleNonText until -V is used. +V means -S. - */ - KeyOpt(Keys, KeyOptions) => void - - /** - * Start collecting input. - */ - Start() => void - - /** - * Terminate Input and set EndReason to the word Stopped. - */ - Stop() => void - - /** - * Wait until Input terminates (InProgress is false). - */ - Wait([MaxTime]) => Integer -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#SendLevel|A_SendLevel} + * Used to get or set the send level of a thread. + * The value should be between `0` and `100`, with `0` being the default of all threads until changed. + * This controls whether the current thread can affect hotkeys and hotstrings that are hooked. + * If the thread is higher + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SendLevel.htm|SendLevel()} + * @example + * ; All threads are started at 0 + * ; This won't affect either hotkey + * Send('ab') + * MsgBox('Send level 0.`nWhat tray tips popped up?') + * + * ; The thread now has a send level of 1 + * A_SendLevel := 1 + * ; Because the thread is level 1 and the 'a' hotkey + * ; is level 0, this send will activate the 'a' hotkey + * ; The 'b' hotkey is not affected b/c its level is 5 + * Send('ab') + * MsgBox('Send level 1.`nWhat tray tips popped up?') + * + * ; Set current thread to level 6 + * A_SendLevel := 6 + * ; This send activates both the 'a' (level 0) and + * ; 'b' (level 5) hotkeys because 6 is higher than 0 and 5 + * Send('ab') + * MsgBox('Send level 6.`nWhat tray tips popped up?') + * + * ; Hotkeys have a default send level of 0 + * $a::TrayTip(A_ThisHotkey ' was fired!') + * + * ; All hotkeys past here are level 5 + * #InputLevel 5 + * $b::TrayTip(A_ThisHotkey ' was fired!') + */ +A_SendLevel: Integer -class Integer extends Number { - /** - * Convert a numeric string or numerical to an integer. - */ - static Call(Value) => Integer -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#SendMode|A_SendMode} + * Used to get or set the the current default mode used for. + * {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode} affects the sending method of multiple functions, including + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()}, + * {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#Text|SendText()}, + * {@link https://www.autohotkey.com/docs/v2/lib/Click.htm|Click()}, + * {@link https://www.autohotkey.com/docs/v2/lib/MouseMove.htm|MouseMove()}, + * {@link https://www.autohotkey.com/docs/v2/lib/MouseClick.htm|MouseClick()}, + * and {@link https://www.autohotkey.com/docs/v2/lib/MouseClickDrag.htm|MouseclickDrag()}. + * This variable can be set to the following values: + * - `Event` = Uses {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendEvent|SendEvent()}. + * - `Input` = Uses {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInput|SendInput()}. + * If this fails, {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendEvent|SendEvent()} is used as the {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInputUnavail|fallback}. + * This is the default value. + * - `InputThenPlay` = Uses {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInput|SendInput()} + * If this fails, {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlay|SendPlay()} is used as the {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendInputUnavail|fallback}. + * - `Play` = Uses {@link https://www.autohotkey.com/docs/v2/lib/Send.htm#SendPlay|SendPlay()}. + * @type String + * @see {@link https://www.autohotkey.com/docs/v2/lib/SendMode.htm|SendMode()} + */ +A_SendMode: String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Space|A_Space} + * Contains a single space character. + * @type String + * @example + * txt := 'Hello' A_Space 'World' + * MsgBox(txt) + */ +A_Space: ' ' -class Map extends Object { - /** - * The Map object associates or maps a set of values called keys to another set of values. - */ - __New([Key1, Value1, *]) => void - - /** - * Enumerates key-value pairs. - */ - __Enum(NumberOfVars?) => Enumerator - - /** - * Retrieves or sets the value of a key-value pair. - */ - __Item[Index] { - get => V - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#StartMenu|A_StartMenu} + * This variable contains the path to the user's Start menu folder. + * Typically, this contains: `C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu` + * @type String + * @example + * MsgBox('Path to the user`'s Start menu folder: ' A_StartMenu) + */ +A_StartMenu: String - /** - * Remove all key-value pairs from the map. - */ - Clear() => void - - /** - * Return a shallow copy of the object. - */ - Clone() => this - - /** - * Remove key-value pairs from the map. - */ - Delete(Key) => V - - /** - * Returns the value or default value associated with the key. - */ - Get(Key [, Default]) => V - - /** - * If Key has an associated value in the map, it returns true, otherwise it returns false. - */ - Has(Key) => Integer - - /** - * Set zero or more items. - */ - Set(Key1, Value1, *) => void - - /** - * Retrieve the number of key-value pairs present in the map. - */ - Count => Integer - - /** - * Retrieve or set the current capacity of the mapping. - */ - Capacity { - get => Integer - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#StartMenuCommon|A_StartMenuCommon} + * This variable contains the path to the user's Start menu folder. + * Typically, this contains: `C:\ProgramData\Microsoft\Windows\Start Menu` + * @type String + * @example + * MsgBox('Path to the common Start menu folder: ' A_StartMenuCommon) + */ +A_StartMenuCommon: String - /** - * Retrieve or set the case sensitivity setting of the mapping. - */ - CaseSense { - get => String - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Startup|A_Startup} + * This variable contains the path to the user's Start menu Startup folder. + * Typically, this contains: `C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup` + * @type String + * @example + * MsgBox('User`'s Start menu Startup folder: ' A_Startup) + */ +A_Startup: String - /** - * Define the default value returned when the key is not found. - */ - Default?: V -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#StartupCommon|A_StartupCommon} + * This variable contains the path to the common/all-user Start menu Startup folder. + * Typically, this contains: `C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup` + * @type String + * @example + * MsgBox('Common Start menu Startup folder: ' A_StartupCommon) + */ +A_StartupCommon: String -class MemberError extends UnsetError { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#StoreCapsLockMode|A_StoreCapsLockMode} + * Used to get or set whether the CapsLock state is restored to its former value after a {@link https://www.autohotkey.com/docs/v2/lib/Send.htm|Send()} function has been used. + * This variable can be set to the following values: + * - `1` = Enabled. This is the default value. + * - `0` = Disabled. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetStoreCapsLockMode.htm|SetStoreCapsLockMode()} + * @example + */ +A_StoreCapsLockMode: Integer -class MemoryError extends Error { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Tab|A_Tab} + * Contains a single tab character. + * @type String + * @example + * MsgBox('one:' + * '`n' A_Tab 'Cut a hole in the box.' + * '`ntwo:' + * '`n' A_Tab 'Put your code in the box.' + * '`nthree:' + * '`n' A_Tab 'Make her open the box.' + * '`n`nAnd that`'s the way you do it.' + * '`nIt`'s AHK in a box!') + */ +A_Tab: '`t' -class Menu extends Object { - /** - * Retrieve or set the number of clicks required to activate the default item of the tray menu. - */ - ClickCount => Integer - - /** - * Retrieve or set the default menu item. - */ - Default { - get => String - set => void - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#Temp|A_Temp} + * This variable contains the path to the user's temporary folder. + * Typically, this contains: `C:\Users\\AppData\Local\Temp` + * @type String + * @example + * ; A ping tester activated by typing: /pingtest + * :*?:/pingtest:: { + * ; This will ping Google's DNS server until stopped + * Run(A_ComSpec ' /c ping -t 8.8.8.8') + * ToolTip('Press control+c to stop the pinging or close the window.') + * } + * @type + * @example + */ +A_Temp: String - /** - * Retrieve the Win32 handle of the menu. - */ - Handle => Integer - - /** - * Create a new Menu or MenuBar object. - */ - __New() => void - - /** - * Add or modify menu items. - */ - Add([MenuItemName, CallbackOrSubmenu, Options]) => void - - /** - * Add a visible check mark next to the menu item. - */ - Check(MenuItemName) => void - - /** - * Delete one or all menu items. - */ - Delete([MenuItemName]) => void - - /** - * Change the menu item to gray, indicating that the user cannot select it. - */ - Disable(MenuItemName) => void - - /** - * If it was previously disabled (grey), the user is allowed to select the menu item again. - */ - Enable(MenuItemName) => void - - /** - * Insert a new item before the specified item. - */ - Insert([ItemToInsertBefore, NewItemName, CallbackOrSubmenu, Options]) => void - - /** - * Rename the menu item (if NewName is empty or omitted, the MenuItemName will be converted to a divider). - */ - Rename(MenuItemName [, NewName]) => void - - /** - * Change the background color of the menu. - */ - SetColor(ColorValue := 'Default', Submenus := true) => void - - /** - * Set the icon to be displayed next to the menu item. - */ - SetIcon(MenuItemName, FileName: $FilePath [, IconNumber, IconWidth]) => void - - /** - * Display the menu. - * @param Wait [@since v2.1-alpha.1] If this parameter is 1 (true), the method will not return until after the menu is closed. Specify 0 (false) to return immediately, allowing the script to continue execution while the menu is being displayed. - * - * The default value of this parameter depends on the menu style. If the script has applied the MNS_MODELESS style (typically via DllCall), the default is 0 (no wait); otherwise, the default is 1 (wait). - */ - Show([X, Y, Wait]) => void - - /** - * Toggle the check mark next to the menu item. - */ - ToggleCheck(MenuItemName) => void - - /** - * Enable or disable menu items. - */ - ToggleEnable(MenuItemName) => void - - /** - * Remove the check mark (if any) from the menu item. - */ - Uncheck(MenuItemName) => void - - /** - * Added standard tray menu items. - */ - AddStandard() => void -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ThisFunc|A_ThisFunc} + * The name of the function that is currently executing. + * If in global space (not in a function), this variable contains an empty string. + * @type String + * @see {@link https://www.autohotkey.com/docs/v2/lib/Func.htm#Name|Name property (Func)} + * @example + * ; Run the function. + * my_function() + * + * my_function() { + * ; Get the current functions name. + * MsgBox('Currently inside the function called:`n' A_ThisFunc) + * + * ; An example of using this variable. + * If (MsgBox('Run function again?',, 'YesNo') = 'Yes') + * ; SetTimer requires an object but this contains a string. + * ; We can dereference it by wrapping it in percent signs. + * SetTimer(%A_ThisFunc%, -1) + * Else ExitApp() + * } + */ +A_ThisFunc: String -class MenuBar extends Menu { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#ThisHotkey|A_ThisHotkey} + * Contains the text of the last executed hotkey or non-auto-replacing hotstring (a hotstring that uses the `x` option). + * The string will include any + * @type String + * @example + * ; Function that will continuously show the current A_ThisHotkey. + * last_key_checker() + * + * last_key_checker() { + * if (A_ThisHotkey = '') + * ToolTip('') + * else ToolTip(A_ThisHotkey) + * SetTimer(%A_ThisFunc%, -50) + * } + * + * ; Try out each of these to see which shows up by the checker function. + * :?*:test1::This is an auto-replace hotstring + * :?*x:test2::MsgBox('This is not an auto-replace hotstring') + * *F1::MsgBox('This is a hotkey') + * F2 & F3::MsgBox('Custom combo hotkey') + */ +A_ThisHotkey: String -class MethodError extends MemberError { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TickCount|A_TickCount} + * The number of elapsed milliseconds since the computer was last started. + * This value maxes out at 49.7 days and the system will need to be rebooted to make use of A_TickCount again. + * A_TickCount can be used to measure elapsed time by saving the current A_TickCount and subtracting it from a future call to A_TickCount. + * If higher precision is needed, use {@link https://www.autohotkey.com/docs/v2/lib/DllCall.htm#ExQPC|QueryPerformanceCounter()}. + * @type Integer + * @example + * MsgBox('Start randomized sleep.') + * start := A_TickCount + * Sleep(Random(500, 2000)) + * seconds_passed := (A_TickCount - start) / 1000 + * MsgBox('The sleep lasted ' Round(seconds_passed, 3) ' seconds') + */ +A_TickCount: Integer -class Number extends Primitive { - /** - * Convert a numeric string or numerical to integer or floating point number. - */ - static Call(Value) => Integer | Float -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TimeIdle|A_TimeIdle} + * Contains the time, in milliseconds, since the system received input from the mouse or keyboard. + * Both physical input from the user and artificial input from a script will reset this timer. + * The tracked time is not exact, so do not look for an exact time match. Use `>` and `<`. + * @type Integer + * @example + * idle_checker() + * + * idle_checker() { + * ; Check if it's been more than 5 seconds. + * if (A_TimeIdle > 5000) + * MsgBox("You've been AFK for over 5 seconds!") + * ; Run this function one more time in 100ms. + * SetTimer(idle_checker, -100) + * } + */ +A_TimeIdle: Integer -class Object extends Any { - /** - * Construct a new instance of the class. - */ - static Call() => this - - /** - * Return a shallow copy of the object. - */ - Clone() => this - - /** - * Define a new own attribute. - */ - DefineProp(Name, Desc) => this - - /** - * Delete the attributes owned by the object. - */ - DeleteProp(Name) => Any - - /** - * Returns the descriptor of a given own property, compatible with DefineProp. - */ - GetOwnPropDesc(Name) => { - Get?: Func, Set?: Func, Call?: Func, Value?: Any, - /** @since v2.1-alpha.3 */ - Type?: String | Integer | Class - } +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TimeIdleKeyboard|A_TimeIdleKeyboard} + * Contains the time, in milliseconds, since the system received input from the keyboard. + * This only applies if the {@link https://www.autohotkey.com/docs/v2/lib/InstallKeybdHook.htm|keyboard hook} is installed. + * Otherwise, `A_TimeIdleKeyboard` contains the same value as `A_TimeIdle`. + * The tracked time is not exact, so do not look for an exact time match. Use `>` and `<`. + * @type Integer + * @example + * InstallKeybdHook(1) + * idle_checker() + * + * idle_checker() { + * ; Check if it's been more than 5 seconds. + * if (A_TimeIdleKeyboard > 5000) + * MsgBox("It has been over 5 seconds since the keyboard was used.") + * ; Run this function one more time in 100ms. + * SetTimer(idle_checker, -100) + * } + */ +A_TimeIdleKeyboard: Integer - /** - * If the object has the attribute of the name, it returns true, otherwise it returns false. - */ - HasOwnProp(Name) => Integer +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TimeIdleMouse|A_TimeIdleMouse} + * Contains the time, in milliseconds, since the system received input from the mouse. + * This only applies if the {@link https://www.autohotkey.com/docs/v2/lib/InstallMouseHook.htm|mouse hook} is installed. + * Otherwise, `A_TimeIdleMouse` contains the same value as `A_TimeIdle`. + * The tracked time is not exact, so do not look for an exact time match. Use `>` and `<`. + * @type Integer + * @example + * InstallKeybdHook(1) + * idle_checker() + * + * idle_checker() { + * ; Check if it's been more than 5 seconds. + * if (A_TimeIdleMouse > 5000) + * MsgBox("It has been over 5 seconds since the mouse was used.") + * ; Run this function one more time in 100ms. + * SetTimer(idle_checker, -100) + * } + */ +A_TimeIdleMouse: Integer - /** - * Enumerate the properties of the object. - */ - OwnProps() => Enumerator -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TimeIdlePhysical|A_TimeIdlePhysical} + * Contains the time, in milliseconds, since the system received input from the mouse or keyboard. + * This only applies to physical input from the user. Artificial input from a script will not reset this timer. + * The tracked time is not exact, so do not look for an exact time match. Use `>` and `<`. + * @type Integer + * @example + * idle_checker() + * + * idle_checker() { + * ; Check if it's been more than 5 seconds. + * if (A_TimeIdlePhysical > 5000) + * MsgBox("It has been over 5 seconds since a physical action was taken.") + * ; Run this function one more time in 100ms. + * SetTimer(idle_checker, -100) + * } + */ +A_TimeIdlePhysical: Integer -class OSError extends Error { - __New(ErrorCode := A_LastError, What?, Extra?) => void -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TimeSincePriorHotkey|A_TimeSincePriorHotkey} + * Tracks how many milliseconds have elapsed since the hotkey prior to the most current one was pressed. + * This is a useful variable when writing code that activates on a double tap or to otherwise track prior key sequences. + * Contains an empty string if a prior hotkey has not been pressed since script launch. + * @type Integer + * @example + * ; Creating code that activates on double tap + * *Space:: { + * ; Initially, A_TimeSincePriorHotkey and A_PriorHotkey are empty strings. + * ; Using an empty string in a comparison is an error. + * ; Try prevents this initial inevitable error. + * try + * if (A_TimeSincePriorHotkey < 400 && A_ThisHotkey = A_PriorHotkey) + * MsgBox('Double tap detected!') + * else Send(' ') + * ; On failure, send space as the default action. + * catch + * Send(' ') + * } + */ +A_TimeSincePriorHotkey: Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TimeSinceThisHotkey|A_TimeSinceThisHotkey} + * Tracks how many milliseconds have elapsed since the most current hotkey was pressed. + * Contains an empty string if the hotkey hasn't been pressed since script launch. + * @type Integer + * @example + * *F1:: { + * ToolTip('Temporary message') + * while (A_TimeSinceThisHotkey < 1500) + * Sleep(100) + * ToolTip() + * } + */ +A_TimeSinceThisHotkey: Integer + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TitleMatchMode|A_TitleMatchMode} + * Used to get or set the mode used when matching {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitles}. + * This variable can be set to the following values: + * - `1` = A window's title must start with the specified WinTitle to be a match. + * - `2` = Default behavior. A window's title can contain WinTitle anywhere inside it to be a match. + * This is the default value. + * - `3` = A window's title must exactly match WinTitle to be a match. + * - `RegEx` = Changes WinTitle, WinText, ExcludeTitle, and ExcludeText to accept {@link https://www.autohotkey.com/docs/v2/misc/RegEx-QuickRef.htm|regular expressions}. + * @type Primitive + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} + * @example + * A_TitleMatchMode := 2 + * if WinExist('AutoHotkey') + * MsgBox('An AHK script exists.') + * else MsgBox('No AHK scripts were found.') + */ +A_TitleMatchMode: String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TitleMatchModeSpeed|A_TitleMatchModeSpeed} + * Used to get or set the speed mode used when matching {@link https://www.autohotkey.com/docs/v2/misc/WinTitle.htm|WinTitles}. + * This variable can be set to the following values: + * - `Fast` = Default behavior. Performance may be substantially better than the slow mode, but certain types of controls are not detected. + * This is the default value. + * - `Slow` = Can be much slower, but works with all controls which respond to the {@link https://learn.microsoft.com/windows/win32/winmsg/wm-gettext|WM_GETTEXT} message. + * @type String + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetTitleMatchMode.htm|SetTitleMatchMode()} + * @example + */ +A_TitleMatchModeSpeed: String + +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TrayMenu|A_TrayMenu} + * Returns a {@link https://www.autohotkey.com/docs/v2/lib/Menu.htm|Menu object} to the script's system tray menu. + * This is the menu that pops up you right click the tray icon in the system tray. + * @type Menu + * @example + * ; Get the script's menu tray object. + * tray := A_TrayMenu + * ; Delete everything from the menu. + * tray.Delete() + * ; Add a simple customized menu. + * tray.Add('Customized Tray Menu', (*) => '') + * tray.Add() + * ; Example of using an anonymous function as a callback. + * ; The thing that runs when an event occurs. + * tray.Add('Exit', (*) => ExitApp()) + * + * MsgBox('Right click the tray icon in system tray.' + * '`nThe only menu item should be "Exit".') + */ +A_TrayMenu: Menu -class Primitive extends Any { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#UserName|A_UserName} + * The username of the user that launched the script. + * This is not necessarily the same as the current logged in user. + * @type + * @example + */ +A_UserName: String -class PropertyError extends MemberError { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#WDay|A_WDay} + * The one digit number of the current day of the week: `1`-`7` + * Sunday is always day 1. + * @type String + * @example + * + * MsgBox('The current day is: ' A_DDDD + * '`nThis is week day number: ' A_WDay) + */ +A_WDay: String -class RegExMatchInfo extends Object { - static Call() => throw - - /** - * Returns the overall match or a captured subpattern. - * @param {Integer|String} N - */ - __Item[N?] => String - - /** - * Returns the position of the overall matched or captured sub-pattern. - */ - Pos[N?] => Integer - - /** - * Returns the position of the overall matched or captured sub-pattern. - */ - Pos(N?) => Integer - - /** - * Returns the length of the overall matched or captured sub-pattern. - */ - Len[N?] => Integer - - /** - * Returns the length of the overall matched or captured sub-pattern. - */ - Len(N?) => Integer - - /** - * Return the name of the given submode (if any). - */ - Name[N] => String - - /** - * Return the name of the given submode (if any). - */ - Name(N) => String - - /** - * Returns the total number of sub-patterns. - */ - Count => Integer - - /** - * If applicable, return the last name encountered (*MARK: NAME). - */ - Mark => String -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#WinDelay|A_WinDelay} + * Used to get or set the delay, in milliseconds, that occurs after {@link https://www.autohotkey.com/docs/v2/lib/Win.htm|Window functions} are used. + * This variable can be set to the following values: + * - Positive value = The amount of time to wait, in ms. + * - `0` = Use the smallest possible delay. + * - `-1` = Use no delay. + * @type Integer + * @see {@link https://www.autohotkey.com/docs/v2/lib/SetWinDelay.htm|SetWinDelay()} + * @example + * ; This will cause a 0.5 second delay between + * ; window activation and sending the keystrokes. + * A_WinDelay := 500 + * WinActivate('ahk_exe SomeProgram.exe') + * Send('Hello, world!') + */ +A_WinDelay: Integer -class String extends Primitive { - /** - * Convert the value to a string. - */ - static Call(Value) => String -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#WinDir|A_WinDir} + * This variable contains the path to the Windows main system folder. + * Typically, this contains: `C:\Windows` + * @type String + * @example + * MsgBox('Main Windows path is: ' A_WinDir) + */ +A_WinDir: String -class TargetError extends Error { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#WorkingDir|A_WorkingDir} + * Get or set the script's current working directory. This is the default folder that is checked when a file is referenced without a path. + * The final backslash is not included unless it is a root directory: `C:\` vs `C:\My Documents` + * {@link https://www.autohotkey.com/docs/v2/lib/SetWorkingDir.htm|SetWorkingDir()} can also be used to change the working directory. + * The default directory is always {@link https://www.autohotkey.com/docs/v2/Variables.htm#ScriptDir|A_ScriptDir} until it's set to something else. + * @type String + * @example + * ; Showing the default working directory. + * MsgBox(A_WorkingDir) + * ; Making the desktop the new working directory. + * A_WorkingDir := A_Desktop + */ +A_WorkingDir: String -class TimeoutError extends Error { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#YDay|A_YDay} + * Current day of the year: `1`-`366` + * This value is not zero-padded. + * To retrieve a zero-padded value, use the following: `FormatTime(, "YDay0")` + * @type String + * @example + * MsgBox('The current day of the year is: ' A_YDay) + */ +A_YDay: String -class TypeError extends Error { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#YYYY|A_Year} + * The current 4-digit year: `2024` + * This is identical to `A_YYYY`. + * @type String + * @example + * MsgBox("Today's date is:" + * '`n' A_DDDD ', ' A_MMMM ' ' A_DD ', ' A_Year) + */ +A_Year: String -class UnsetError extends Error { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#YWeek|A_YWeek} + * Current year and week number without a separator according to ISO 8601 (see {@link {@link https://www.iso.org/obp/ui/#iso:std:iso:8601:-1:ed-1:v1:en|RFC 3339}). + * This will always be a 6 digit number. + * To get the week only, use SubStr() to get the last two digits. + * To separate the year from the week, use Year := SubStr(A_YWeek, 1, 4) and Week := SubStr(A_YWeek, -2). + * Defining first week: + * If January 1st belongs to a week with at least 4 days, that's week one. + * If the week has fewer than 4 days, that week is considered the last week of the previous year and the next week starts the first week. + * In other words, January 1st must fall be between Sunday and Wednesday (inclusive) for that week to be considered the first week. + * @type String + * @example + * MsgBox('A_YWeek = ' A_YWeek) + * + * ; Use SubStr() to separate week from year. + * ; The last 2 digits are always the week. + * week := SubStr(A_YWeek, -2) + * ; Normally, you wouldn't waste time getting the year like this. + * ; The variables A_Year and A_YYYY already contain this information. + * year := SubStr(A_YWeek, 1, 4) + * MsgBox("The current week number is: " week + * "`nAnd the current year is: " year) + */ +A_YWeek: String -class UnsetItemError extends UnsetError { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#YYYY|A_YYYY} + * The current 4-digit year: `2024` + * This is identical to `A_Year`. + * @type String + * @example + * MsgBox("Today's date is:" + * '`n' A_DDDD ', ' A_MMMM ' ' A_DD ', ' A_YYYY) + */ +A_YYYY: String -class ValueError extends Error { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TrueFalse|true} + * Contains the number 1. + * All things in AHK are true except for the values: `0` and `''` (an empty string) + * @type Integer + * @example Truthy/falsy evaluation examples. + * ; Create an associative array of values. + * ; Then test each value to see if they evaluate as true. + * values := Map(true, 'true variable' + * , 1 , 'The number 1' + * , false , 'false variable' + * , 0 , 'The number 0' + * ,'String' , 'String with characters' + * , '' , 'Empty string' + * , Object(), 'An object literal' + * , Array() , 'An array object' + * , Gui() , 'A GUI object') + * ; Loop through each item + * for value, definition in values + * ; Check if each value is considered true or false + * if (value) + * MsgBox(definition ' is considered truthy.' + * '`n`nRemember, EVERYTHING in AHK is considered true except:' + * '`n- The number 0' + * '`n- An empty string') + * else MsgBox(definition ' is considered falsy.' + * '`n`nRemember, the only two things in AHK considered false are:' + * '`n- The number 0' + * '`n- An empty string') + */ +true: 1 -class VarRef extends Any { -} +/** + * @description {@link https://www.autohotkey.com/docs/v2/Variables.htm#TrueFalse|false} + * Contains the number 0. + * All things in AHK are true except for the values: `0` and `''` (an empty string) + * @type Integer + * @example Truthy/falsy evaluation examples. + * ; Create an associative array of values. + * ; Then test each value to see if they evaluate as true. + * values := Map(true, 'true variable' + * , 1 , 'The number 1' + * , false , 'false variable' + * , 0 , 'The number 0' + * ,'String' , 'String with characters' + * , '' , 'Empty string' + * , Object(), 'An object literal' + * , Array() , 'An array object' + * , Gui() , 'A GUI object') + * + * ; Loop through each item + * for value, definition in values + * ; Check if each value is considered true or false + * if (value) + * MsgBox(definition ' is considered truthy.' + * '`n`nRemember, EVERYTHING in AHK is considered true except:' + * '`n- The number 0' + * '`n- An empty string') + * else MsgBox(definition ' is considered falsy.' + * '`n`nRemember, the only two things in AHK considered false are:' + * '`n- The number 0' + * '`n- An empty string') + */ +false: 0 -class ZeroDivisionError extends Error { -} -;@endregion +/** + * @description {@link https://www.autohotkey.com/docs/v2/Language.htm#unset|unset} + * Sets a variable or value to an unset state, freeing any data and making the variable unusable until a new value is set to it. + * unset is not a type of value. It's a state meaning the value or variable is uninitialized. + * Attempting to use something that's unset will throw an error. + * The {@link https://www.autohotkey.com/docs/v2/lib/IsSet.htm|IsSet()} function can be used to check if a value is unset. + * @type unset + * @see {@link https://www.autohotkey.com/docs/v2/Variables.htm#maybe|? (Maybe operator)} | + * {@link https://www.autohotkey.com/docs/v2/Variables.htm#or-maybe|?? (Or-Maybe operator)} | + * {@link https://www.autohotkey.com/docs/v2/lib/IsSet.htm|IsSet()} + * @example + * ; Example of assigning a variable an initial value of unset: + * ; Create an unset variable + * x := unset + * + * ; Example of using an unset variable as an object value: + * arr := [1, unset, 3] + * + * ; Example of using an unset variable as a default parameter: + * ; Optional + * some_func(mandatory_param, optional_param := unset) { + * ; Check if value is unset. + * if !IsSet(optional_param) + * ; If unset, give it a default value. + * optional_param := 'Default value' + * } + */ +unset: unset +;@endregion \ No newline at end of file diff --git a/syntaxes/ahk2.json b/syntaxes/ahk2.json index 9d23f298..c25f7936 100644 --- a/syntaxes/ahk2.json +++ b/syntaxes/ahk2.json @@ -1,49 +1,57 @@ { + "//": ";* Copyright 2023-2024 [GroggyOtter](https://github.com/GroggyOtter/ahkv2_definition_rewrite/issues/8), used with permission", + "version": 1.4, "directives": [ { - "body": "#ClipboardTimeout ${0:Milliseconds}", + "body": "#ClipboardTimeout ${0:milliseconds}", "description": "Set time between retrying the clipboard in milliseconds. 0 = try once, -1 = try indefinitely, omit = default search restored.", "prefix": "#ClipboardTimeout" }, { - "body": "#DllLoad", - "description": "Load the DLL or EXE file before the script starts executing or omit to to reset default search strategy.", - "syntax": "#DllLoad [FileOrDirName]" + "body": "#DllLoad ", + "description": "Load the DLL or EXE file before the script starts executing or omit to to reset default search strategy." }, { - "body": "#ErrorStdOut ${1|'CP0','UTF-8','UTF-16','CP###'|}", - "description": "Send any syntax errors that prevent the script from running to stderr instead of displaying a dialog box.", - "prefix": "#ErrorStdOut", - "syntax": "#ErrorStdOut [Encoding]" + "body": "#ErrorStdOut ${1|'CP0','UTF-8','UTF-8-RAW','UTF-16','UTF-16-RAW','CP###'|}", + "description": "Syntax errors that prevent a script from launching as sent to standard error stream (stderr).", + "prefix": "#ErrorStdOut" }, { - "body": "#HotIf", - "description": "Create context-sensitive hotkeys and hotstrings that are enabled when the criteria is true. Use #HotIf to reset criteria.", - "syntax": "HotIf [Expression]" + "body": "#HotIf ", + "description": "Create context-sensitive hotkeys and hotstrings that are enabled when the criteria is true. Use #HotIf to reset criteria." }, { - "body": "#HotIf WinActive('$0')", + "body": "#HotIf WinActive(${3:'Title' }${1|'ahk_exe ,'ahk_class ,'ahk_id ,'ahk_pid ,'ahk_group |}${2:identifier}')", "description": "Create context-sensitive hotkeys and hotstrings that work when the specified window is active. Use #HotIf to reset criteria.", "prefix": "#HotIfWinActive" }, { - "body": "#HotIf WinExist('$0')", + "body": "#HotIf WinExist(${3:'Title' }${1|'ahk_exe ,'ahk_class ,'ahk_id ,'ahk_pid ,'ahk_group |}${2:}')", "description": "Create context-sensitive hotkeys and hotstrings that work when the specified window exists. Use #HotIf to reset criteria.", "prefix": "#HotIfWinExist" }, { - "body": "#HotIfTimeout ${0:Timeout}", + "body": "#HotIfTimeout ${0:milliseconds}", "description": "Max time spent evaluating #HotIf criteria. Default is 1000.", "prefix": "#HotIfTimeout" }, { - "body": "#Hotstring ${1|NoMouse,EndChars |}", - "description": "```ahk2\n#Hotstring EndChars NewChars\n#Hotstring NewOptions\n```\nChange the default options for hotstrings or their ending char.\n```ahk2\n#Hotstring NoMouse\n```\nPrevents mouse clicks from resetting the hotstring recognizer.", - "prefix": "#Hotstring", - "syntax": "" + "body": "#Hotstring EndChars ${0:-()[]{\\}':;\"/\\,.?!`n`s`t}", + "description": "Change the default options for hotstrings or their ending char.", + "prefix": "#Hotstring EndChars" }, { - "body": "#Include ${0:File_Dir_Or_LibName}", + "body": "#Hotstring NoMouse", + "description": "Prevents mouse clicks from resetting the hotstring recognizer.", + "prefix": "#Hotstring NoMouse" + }, + { + "body": "#Hotstring ${0:NewOptions}", + "description": "Change the default options for hotstrings or their ending char.", + "prefix": "#Hotstring" + }, + { + "body": "#Include ${0:File_Dir_Or_}", "description": "File contents are inserted here when script runs, but not if already included earlier.", "prefix": "#Include" }, @@ -59,7 +67,7 @@ }, { "body": "#MaxThreads ${0:1_to_255}", - "description": "Sets the maximum number of simultaneous threads. Default is 10.", + "description": "Set max number of simultaneous threads that can run. Default is 10.", "prefix": "#MaxThreads" }, { @@ -68,19 +76,18 @@ "prefix": "#MaxThreadsBuffer" }, { - "body": "#MaxThreadsPerHotkey ${0:1_to_255}", + "body": "#MaxThreadsPerHotkey ${0:Between_1_and_255}", "description": "Set the maximum number of threads that can exist simultaneously for each hotkey or hotstring.", "prefix": "#MaxThreadsPerHotkey" }, { "body": "#NoTrayIcon", - "description": "Disables the showing of a tray icon." + "description": "Removes the script's tray icon." }, { - "body": "#Requires AutoHotkey${1| , >, >=, <, <=, =|}v2.${2:0}${3| , 32-bit, 64-bit|}", + "body": "#Requires AutoHotkey${1| , >, >=, <, <=, =|}v2${2|.0,.1|}${3|.18,.17,.16,.15,.14,.13,.12,.11,.10,.9,.8,.7,.6,.5,.4,.3,.2,.1,.0|}${4|+,+ 32-bit,+ 64-bit|}", "description": "The required version of AutoHotkey for the script to run otherwise script s and quits.", - "prefix": "#Requires", - "syntax": "#Requires Requirement" + "prefix": "#Requires" }, { "body": "#SingleInstance ${1|Force,Ignore,Prompt,Off|}", @@ -99,7 +106,7 @@ }, { "body": "#Warn ${1|All,VarUnset,LocalSameAsGlobal,Unreachable|}, ${2|MsgBox,StdOut,OutputDebug,Off|}", - "description": "Enable or disable warnings for certain critera. Can catch multiple types of s.", + "description": "Enable or disable warnings for certain criteria. Can catch multiple types of s.", "prefix": "#Warn" }, { @@ -152,7 +159,7 @@ "prefix": "@Ahk2Exe-Let" }, { - "body": ";@Ahk2Exe-Obey ${0:Name}, ${2:CmdOrExp [, Extra]}", + "body": ";@Ahk2Exe-Obey ${1:Name}, ${2:CmdOrExp [, Extra]}", "description": "Execute a command or expression independent of AutoHotkey, and the result is U_Name.", "prefix": "@Ahk2Exe-Obey" }, @@ -169,238 +176,232 @@ { "body": ";@Ahk2Exe-SetCompanyName ${0:CompanyName}", "description": "Changes the company name.", - "prefix": "@Ahk2Exe-SetCompanyName" + "prefix": ";@Ahk2Exe-SetCompanyName" }, { "body": ";@Ahk2Exe-SetCopyright ${0:CopyrightInfo}", "description": "Changes the legal copyright information.", - "prefix": "@Ahk2Exe-SetCopyright" + "prefix": ";@Ahk2Exe-SetCopyright" }, { "body": ";@Ahk2Exe-SetDescription ${0:Description}", "description": "Changes the file description and changes script's name in Task Manager under \"Processes\".", - "prefix": "@Ahk2Exe-SetDescription" + "prefix": ";@Ahk2Exe-SetDescription" }, { "body": ";@Ahk2Exe-SetFileVersion ${0:Version}", "description": "Changes the file version, in both text and raw binary format.", - "prefix": "@Ahk2Exe-SetFileVersion" + "prefix": ";@Ahk2Exe-SetFileVersion" }, { "body": ";@Ahk2Exe-SetInternalName ${0:InternalName}", "description": "Changes the internal name.", - "prefix": "@Ahk2Exe-SetInternalName" + "prefix": ";@Ahk2Exe-SetInternalName" }, { "body": ";@Ahk2Exe-SetLanguage ${0:0x0409}", "description": "Changes the language code. Must include 0x prefix.", - "prefix": "@Ahk2Exe-SetLanguage" + "prefix": ";@Ahk2Exe-SetLanguage" }, { "body": ";@Ahk2Exe-SetLegalTrademarks ${0:Trademark}", "description": "Changes the legal trademarks information.", - "prefix": "@Ahk2Exe-SetLegalTrademarks" + "prefix": ";@Ahk2Exe-SetLegalTrademarks" }, { "body": ";@Ahk2Exe-SetName ${0:Name}", "description": "Changes the product name and the internal name.", - "prefix": "@Ahk2Exe-SetName" + "prefix": ";@Ahk2Exe-SetName" }, { "body": ";@Ahk2Exe-SetOrigFilename ${0:OriginalFilename}", "description": "Changes the original filename information.", - "prefix": "@Ahk2Exe-SetOrigFilename" + "prefix": ";@Ahk2Exe-SetOrigFilename" }, { "body": ";@Ahk2Exe-SetProductName ${0:ProductName}", "description": "Changes the product name.", - "prefix": "@Ahk2Exe-SetProductName" + "prefix": ";@Ahk2Exe-SetProductName" }, { "body": ";@Ahk2Exe-SetProductVersion ${0:Version}", "description": "Changes the product version, in both text and raw binary format.", - "prefix": "@Ahk2Exe-SetProductVersion" + "prefix": ";@Ahk2Exe-SetProductVersion" }, { "body": ";@Ahk2Exe-SetVersion ${0:Version}", "description": "Changes the file version and the product version, in both text and raw binary format.", - "prefix": "@Ahk2Exe-SetVersion" + "prefix": ";@Ahk2Exe-SetVersion" }, { "body": ";@Ahk2Exe-UpdateManifest ${1|0,1,2|}${2| ,[\\, Name\\, Version\\, UIAccess]|}", "description": "Changes details in the .exe's manifest. This directive is for specialised use only.", - "prefix": "@Ahk2Exe-UpdateManifest" + "prefix": ";@Ahk2Exe-UpdateManifest" }, { "body": ";@Ahk2Exe-UseResourceLang ${0:0x0409}", "description": "Changes the resource language used by ;@Ahk2Exe-AddResource.", - "prefix": "@Ahk2Exe-UseResourceLang" + "prefix": ";@Ahk2Exe-UseResourceLang" } ], "keywords": [ { - "body": "and", - "description": "`(x and y)` Both items must be true. Same as: `&&`" + "body": "AND", + "description": "Both items must evaluate true.\nSame as: &&\nif (x AND y)\nif (x && y)" }, { - "body": "as" + "body": "AS", + "description": "" }, { - "body": "in" + "body": "IN", + "description": "Used with for-loops to identify object.\nFor key, value IN obj" }, { - "body": "is", - "description": "`(Var is Type)` Compare value to a class type. String, Array, etc." + "body": "IS", + "description": "Check if item is of a certain class type, such as number, string, object, or array.\nSame as using: if (Type() = \"TypeName\")\nif (var IS Number)\nif (my_arr is Array)\nif !(item IS object)" }, { - "body": "not", - "description": "`(not Expression)` Item must not be true. Same as: `!`." + "body": "NOT", + "description": "Item must not be true.\nSame as: !\nif NOT (false)\nif !false" }, { - "body": "or", - "description": "`(x or y)` One or other must be true. Same as: `||`." + "body": "OR", + "description": "One item OR the other must bet true.\nSame as: ||\nif (var1 OR var2)\nif (var1 OR !var2)" }, { "body": "break", - "description": "End any [Loop/While/For] loop immediately.", - "syntax": "break [LoopLabel]\nbreak('Label')" + "description": "Immediately ends any type of loop, including a For-Loop/While-Loop/Loop [Count/Read/Reg/Parse]." }, { - "body": "catch", - "description": "Specify the code to be executed when an exception is raised during the execution of the try statement.", - "syntax": "catch [ErrorClass] [as OutputVar] {\n\tStatements\n}" + "body": "catch${1| , Error , MemoryError , OSError , TargetError , TimeoutError , TypeError , UnsetError , MemberError , PropertyError , MethodError , UnsetItemError , ValueError , IndexError , ZeroDivisionError |}${2| ,as OutputVar|}", + "description": "Catch is used with Try and is the code that runs when if a try statement encounters an error.", + "prefix": "catch" }, { "body": "continue", - "description": "Skip the rest of the current iteration of the loop statement, and then start a new loop.", - "syntax": "continue [LoopLabel]\ncontinue('Label')" + "description": "Immediately ends the current loop iteration and starts the next.\nIf there are no more iterations, the loop ends." }, { - "body": "else if ", - "description": "Adds another decision to check if prior were false.", + "body": "else If ", + "description": "Adds another decision branch to check if prior checks were false.", "prefix": "elif" }, { "body": "else", - "description": "Specifies one or more statements to execute if the associated statement's body did not execute.\nThe condition for an Else statement executing depends on the associated statement:\n- If expression: The expression evaluated to false.\n- For, Loop (any kind), While: The loop had zero iterations.\n- Loop Read: As above, but the presence of Else also prevents an error from being thrown if the file or path is not found. Therefore, Else executes if the file is empty or does not exist.\n- Try...Catch: No exception was thrown within the Try block." + "description": "Defines the code block that should run when all prior evaluations have failed." }, { "body": "finally", - "description": "Code block to run after a try/catch has completed." + "description": "Used with try/catch statements to ensure some code is guaranteed to run after the try/catch has finished." }, { - "body": "for $1 in $0", - "description": "Repeat a series of functions for each key-value pair in the object.", - "prefix": "for", - "syntax": "for value1 [, value2...] in Expression" + "body": "for id, value IN ${0:Obj}", + "description": "Iterate through each element of an Array, Map, Gui, or other enumerable object.\nMost objects can be looped through by referencing their .OwnProps() method.\nFor prop, value in obj.OwnProps()", + "prefix": "for" }, { "body": "global", - "description": "Mark a variable or function as global so it can be changed from inside a function or method.", - "syntax": "global [Var]" + "description": "Sets a variable or entire function to global scope, making the variable(s) available to all other functions, objects, and classes.\nGenerally, global variables are not needed." }, { - "body": "goto", - "description": "Jump to the specified label and continue execution.", - "syntax": "goto Label\ngoto('Label')" + "body": "goto('${0:Label}')", + "description": "Jump to the specified label and continue execution.\nGenerally, Goto programming should only be used when jumping around inside of a loop or with a Switch statement.", + "prefix": "goto" }, { - "body": "if ", - "description": "Specify one or more statements to be executed when the expression evaluates to true.", - "syntax": "if Expression" + "body": "if", + "description": "Creates a decision branch. When the supplied expression evaluates as true, the following code block is executed.\nif (1 = 1)\nif (var1 = var2)" }, { - "body": "loop files ${0:FilePattern [, Mode]}", - "description": "Loop through a directory. MODES: D=Get Directories, F=Get Files, R=Recurse", + "body": "loop files ${2:FilePattern}, '${1|>File\\,Directory\\,Recurse,F,D,FD,FR,DR,FDR|}'", + "description": "Loop through a directory's files and/or sub-folders.\n- FilePattern = A file path to check. Wildcards * can be used to match all.\n- MODES:\n D = Get directories.\n F = Get files.\n R = Recurse into sub-folders.\n\nBuilt-in loop vars:\n- A_LoopFileName = File name and extension, no path.\n- A_LoopFileExt = File extension.\n- A_LoopFilePath = Path using absolute or relative path.\n- A_LoopFileFullPath = Absolute path.\n- A_LoopFileShortPath = 8.3 path if supported.\n- A_LoopFileShortName = 8.3 file name if supported.\n- A_LoopFileDir = Directory of the current file or sub-directory.\n- A_LoopFileTimeModified = Last modification time of file.\n- A_LoopFileTimeCreated = Creation time of file.\n- A_LoopFileTimeAccessed = Last access time of file.\n- A_LoopFileAttrib = List of file's attributes.\n- A_LoopFileSize = Size of file in bytes.\n- A_LoopFileSizeKB = Size of file in kilobytes.\n- A_LoopFileSizeMB = Size of file in megabytes.", "prefix": "loop files" }, { - "body": "loop parse ${0:String [, Delimiters|'CSV', OmitChars]}", - "description": "Loop through a string by substrings. String is parsed by each char if no Delimiter is provided.", + "body": "loop parse ${1:Text}, ${2:DelimitChar}, ${3:OmitChar}", + "description": "Loop through a string by character or substrings.\n- Text = The text to parse through.\n- Delimiter = The character that's separating each desired substring. Omit delimiter to parse through each character.\n- `Omit` = Characters to ignore at the beginning and end of each substring.\n\n- Built-in loop vars:\n- A_Index = Tracks the current iteration Number.\n- A_LoopField = Contains the current substring or character.", "prefix": "loop parse" }, { - "body": "loop read ${0:InputFile [, OutputFile]}", - "description": "Retrieve the lines in the text file, one line at a time.", + "body": "loop read ${1:FilePath}${2:, OutputFile|}", + "description": "Parse through text one line at a time.\n- FilePath = Path to the text file to read.\n- OutputFile = File to keep open for the duration of the loop. Use FileAppend() with a filename to automatically append text to the OutputFile.\n\n- Built-in loop vars:\n- A_Index = Tracks the current iteration Number.\n- A_LoopReadLine = The text of the current line.", "prefix": "loop read" }, { - "body": "loop reg ${0:KeyName [, Mode]}", - "description": "Retrieve the contents of the specified registry subkey. Modes: K=Key, V=Value, R=Recurse", + "body": "loop reg '${2|HKEY_LOCAL_MACHINE,HKEY_USERS,HKEY_CURRENT_USER,HKEY_CLASSES_ROOT,HKEY_CURRENT_CONFIG|}\\\\$3', '${1|>Choose Key\\,Value\\,Recurse,K,V,KV,KR,VR,KVR|}'", + "description": "Retrieve the contents of the specified registry subkey.\n- Modes:\n V = Get value.\n K = Get key.\n R = Recurse into sub keys.\n\n- Built-in loop vars:\n- A_Index = Tracks the current iteration Number.\n- A_LoopRegName = Name of the current value or subkey.\n- A_LoopRegType = The data type of the current item. KEY, REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ, REG_DWORD, REG_QWORD, REG_BINARY, REG_LINK, REG_RESOURCE_LIST, REG_FULL_RESOURCE_DESCRIPTOR, REG_RESOURCE_REQUIREMENTS_LIST, REG_DWORD_BIG_ENDIAN\n- A_LoopRegKey = Full key name of the current item.\n- A_LoopRegTimeModified = The time, in YYYYMMDDHH24MISS format, of the last modification made to the current registry key.", "prefix": "loop reg" }, { - "body": "loop", - "description": "Repeat a series of functions: you can specify a number representing the number of repetitions or until a break is encountered.", - "syntax": "loop [Count]" + "body": "loop ${0:Count}", + "description": "Used to repeatedly execute a block of code.\nCount is the number of times the loop should run. If omitted, the loop will continue to run.\nTo stop a loop, use Break or set an Until condition.", + "prefix": "loop" }, { - "body": "local ${0:Var}", - "description": "Sets a variable or all function variables to local scope, causing them to be private to the function. Local variables can be the same as globals.", - "prefix": "local" + "body": "local ", + "description": "Sets a variable or a function's scope to local only. A local variable can only be seen inside the function/class they belong to." }, { - "body": "case $1:", - "description": "One or more values to compare against the Switch value or evaluate if no value is provided.", - "prefix": "case", - "syntax": "case ExpressionOrValue:" + "body": "case $1: ", + "description": "Used with Switch statements, these define each 'check' to be made.\nChecks are done against the Switch's value or, if no value is provided, each case is evaluated individually.\nOnce the first match is made, no further cases are evaluated and the code does not 'fall through' to the other cases.", + "prefix": "case" }, { - "body": "default:", - "description": "The default code block to run if no Switch cases match.", - "prefix": "default" + "body": "default: ", + "description": "Used with switch statements. This case must be defined after all other cases and contains any code that should run if no other cases make a match.\nThe `default:` case is optional and does not need to be included.", + "prefix": "default:" }, { "body": "return", - "description": "Return the flow of code to the original caller, along with an optional return value.", - "syntax": "return [Expression]" + "description": "Return the flow of code to the original caller. If there is no caller to return to, Return acts as an Exit() command, ending the current code thread.\nTo return multiple values, put them in a map, array, or other object.\nAlternatively, use &VarRef parameters to get multiple pieces of data back from a function." }, { - "body": "static", + "body": "static ${1:name}${2|(), := , += , -= , *= , /= |}", "description": "A static variable or function persists through the life of the script and does not get erased at the end of a function call.", - "syntax": "static [Var]\nstatic Method()\nstatic Property" + "prefix": "static" }, { - "body": "throw", + "body": "throw ${1|Error,MemoryError,OSError,TargetError,TimeoutError,TypeError,UnsetError,MemberError,PropertyError,MethodError,UnsetItemError,ValueError,IndexError,ZeroDivisionError|}('${2:Message}', ${3:A_ThisFunc}, ${4:ExtraInfo})", "description": "Indicates that an error has occurred. The signal can be caught by a try-catch statement.", - "syntax": "throw Expression" + "prefix": "throw" }, { - "body": "try", - "description": "Guards one or more statements against runtime errors and values thrown by the Throw statement." + "body": "try ", + "description": "Try attempts to execute a block of code while suppressing any errors that may be thrown.\nIf an error happens, the associated Catch statement's code block is ran.\nCatch statements are optional." }, { - "body": "until ", - "description": "Apply the condition to the continuation of the loop or for loop.", - "syntax": "until Expression" + "body": "until ($1)", + "description": "A condition that is checked at the end of every loop iteration.\nIf it evaluates as true, the loop ends as though Break() was used.\nUntil can be used with normal loops and their variants [count/read/parse/reg] as well as for-loops, but does not work with while-loops.", + "prefix": "until" }, { - "body": "while ", - "description": "While expression evaluates to true, continue to run code block", - "syntax": "while Expression" + "body": "while ($1)", + "description": "Defines a loop that continues running as long as the provided evaluate remains true.\n\n- Built-in loop vars:\n- A_Index = Tracks the current iteration Number.", + "prefix": "while" } ], "options": { "ahk_criteria": [ { "body": "ahk_class", - "description": "ahk_class is used to match one or more windows using the class name of the application." + "description": "Identify one or more windows by their class name. See [WinTitle](https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_)" }, { "body": "ahk_exe", - "description": "ahk_exe is used to match one or more windows using the exe name of the process that owns the window." + "description": "Identify one or more windows by their executable/process name. See [WinTitle](https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_)" }, { "body": "ahk_group", - "description": "ahk_group is used to match a group of one or more windows that have been previously defined using GroupAdd()." + "description": "Identify one or more windows that have been added to an AHK window group. See [WinTitle](https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_) | [Window Groups](https://www.autohotkey.com/docs/v2/lib/GroupAdd.htm)" }, { "body": "ahk_id", - "description": "ahk_id is used to match a window using the window's unique ID (HWND). This number is not static and changes every time the application is launched." + "description": "Identify one or more windows by their window handle, a unique number assigned by the operating system at window creation. See [WinTitle](https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_)" }, { "body": "ahk_pid", - "description": "ahk_pid is used to match one or more windows using the process ID of that application. This number is not static and changes every time the application is launched." + "description": "Identify one or more windows by the parent process ID, a unique number assigned by the operating system at the launch of an exe. See [WinTitle](https://www.autohotkey.com/docs/v2/misc/WinTitle.htm#ahk_)" } ], "hotstring": [ @@ -425,7 +426,7 @@ "description": "Do not conform to typed case. Use this option to make auto-replace hotstrings case-insensitive and prevent them from conforming to the case of the characters you actually type. Case-conforming hotstrings (which are the default) produce their replacement text in all caps if you type the abbreviation in all caps. If you type the first letter in caps, the first letter of the replacement will also be capitalized (if it is a letter). If you type the case in any other way, the replacement is sent exactly as defined." }, { - "body": "Kn", + "body": "K#", "description": "Key-delay: This rarely-used option sets the delay between keystrokes produced by auto-backspacing or auto-replacement. Specify the new delay for n; for example, specify `k10` to have a 10 ms delay and `k-1` to have no delay." }, { @@ -433,7 +434,7 @@ "description": "Omit the ending character of auto-replace hotstrings when the replacement is produced. This is useful when you want a hotstring to be kept unambiguous by still requiring an ending character, but don't actually want the ending character to be shown on the screen. Use `O0` to turn this option back off." }, { - "body": "Pn", + "body": "P#", "description": "The priority of the hotstring (e.g. `P1`). This rarely-used option has no effect on auto-replace hotstrings." }, { From c05e25ede71fb57a15c9e1fa18606068a2a8a88e Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:40:42 -0700 Subject: [PATCH 57/60] Fix block style none (#74) --- .github/workflows/{node.js.yml => build.yml} | 2 +- .../test/formatting/array_object_style.ahk | 26 ------------------- ...object_style.in.ahk => block-style.in.ahk} | 0 ...ject_style.out.ahk => block-style.out.ahk} | 4 +-- package.json | 3 +++ server/src/lexer.ts | 4 +-- 6 files changed, 7 insertions(+), 32 deletions(-) rename .github/workflows/{node.js.yml => build.yml} (96%) delete mode 100644 client/src/test/formatting/array_object_style.ahk rename client/src/test/formatting/{array_object_style.in.ahk => block-style.in.ahk} (100%) rename client/src/test/formatting/{array_object_style.out.ahk => block-style.out.ahk} (90%) diff --git a/.github/workflows/node.js.yml b/.github/workflows/build.yml similarity index 96% rename from .github/workflows/node.js.yml rename to .github/workflows/build.yml index 14607a3c..16b95eaa 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/build.yml @@ -29,4 +29,4 @@ jobs: node-version: ${{ matrix.node-version }} cache: 'npm' - run: npm install - - run: npm run validate + - run: npm run validate:ci diff --git a/client/src/test/formatting/array_object_style.ahk b/client/src/test/formatting/array_object_style.ahk deleted file mode 100644 index 896273f9..00000000 --- a/client/src/test/formatting/array_object_style.ahk +++ /dev/null @@ -1,26 +0,0 @@ -;@format array_style: expand, object_style: expand -list := [ - { - name: 1, - age: 2 - }, - { - name: 2, - age: 3 - } -] -;@format array_style: collapse, object_style: expand -list := [{ - name: 1, - age: 2 -}, { - name: 2, - age: 3 -}] -;@format array_style: expand, object_style: collapse -list := [ - { name: 1, age: 2 }, - { name: 2, age: 3 } -] -;@format array_style: collapse, object_style: collapse -list := [{ name: 1, age: 2 }, { name: 2, age: 3 }] \ No newline at end of file diff --git a/client/src/test/formatting/array_object_style.in.ahk b/client/src/test/formatting/block-style.in.ahk similarity index 100% rename from client/src/test/formatting/array_object_style.in.ahk rename to client/src/test/formatting/block-style.in.ahk diff --git a/client/src/test/formatting/array_object_style.out.ahk b/client/src/test/formatting/block-style.out.ahk similarity index 90% rename from client/src/test/formatting/array_object_style.out.ahk rename to client/src/test/formatting/block-style.out.ahk index d8c32b13..7029bdfc 100644 --- a/client/src/test/formatting/array_object_style.out.ahk +++ b/client/src/test/formatting/block-style.out.ahk @@ -1,7 +1,5 @@ ;* No directive -list := [{ name: 1, age: 2 -}, { name: 2, age: 3 -}] +list := [{ name: 1, age: 2 }, { name: 2, age: 3 }] ;@format array_style: expand, object_style: expand list := [ { diff --git a/package.json b/package.json index 25e98ace..907df094 100644 --- a/package.json +++ b/package.json @@ -51,13 +51,16 @@ "sort-package-json": "sort-package-json --check", "sort-package-json:fix": "sort-package-json", "test": "npm run test:grammar && npm run test:unit && npm run test:e2e", + "test:ci": "npm run test:grammar && npm run test:unit && npm run test:e2e:ci", "pretest:e2e": "npm run build:e2e", "test:e2e": "vscode-test", + "test:e2e:ci": "npm run test:e2e -- --forbid-only", "test:grammar": "vscode-tmgrammar-snap \"tmgrammar-test/*.ahk\"", "pretest:unit": "npm run compile-ts", "test:unit": "mocha", "prevalidate": "npm run clean", "validate": "npm run lint && npm run test && echo ✅ All checks passed", + "validate:ci": "npm run lint && npm run test:ci && echo ✅ All checks passed", "prevalidate:fix": "npm run clean", "validate:fix": "npm run lint:fix && npm run test && echo ✅ All checks passed", "vscode:prepublish": "npm run validate", diff --git a/server/src/lexer.ts b/server/src/lexer.ts index 36bd7440..b0c41f69 100644 --- a/server/src/lexer.ts +++ b/server/src/lexer.ts @@ -5509,7 +5509,7 @@ export class Lexer { const style = flags.array_style ?? opt.array_style; if (style === OBJECT_STYLE.collapse || last_text === '[' || flags.indentation_level >= previous_flags.indentation_level) trim_newlines(); - else if (style || input_wanted_newline && opt.preserve_newlines) + else if (style !== 'none' || input_wanted_newline && opt.preserve_newlines) print_newline(true); } else if ((last_type === 'TK_END_EXPR' || last_type === 'TK_END_BLOCK') && flags.indentation_level >= previous_flags.indentation_level) trim_newlines(); @@ -5576,7 +5576,7 @@ export class Lexer { const style = flags.object_style ?? opt.object_style; if (style === OBJECT_STYLE.collapse || last_text === '{') trim_newlines(); - else if (style || input_wanted_newline && opt.preserve_newlines) + else if (style !== 'none' || input_wanted_newline && opt.preserve_newlines) print_newline(true); output_space_before_token = space_in_other && last_text !== '{'; } else if (opt.brace_style !== 'Preserve' || input_wanted_newline) From 16c0722e2d176da1cacc976c823c8df139e1af50 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:46:48 -0700 Subject: [PATCH 58/60] Add logs to initpathenv (#75) --- server/src/scriptrunner.ts | 8 ++++++-- server/src/server.ts | 12 ++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/server/src/scriptrunner.ts b/server/src/scriptrunner.ts index 253b802c..b0a09088 100644 --- a/server/src/scriptrunner.ts +++ b/server/src/scriptrunner.ts @@ -7,13 +7,17 @@ import { resolve } from 'path'; * Simple runner for LSP server initializiaton via AHK. * Not used for running user-defined scripts. */ -export function runscript(script: string) { +export function runscript(script: string): string | undefined { + const funcName = 'runscript'; const executePath = resolvePath(interpreterPath, true); + console.log(`${funcName} executePath`, executePath); if (!executePath) return; const process = spawnSync(`"${executePath}" /CP65001 /ErrorStdOut=utf-8 *`, [], { cwd: executePath.replace(/[\\/].+?$/, ''), shell: true, input: script }); + const result = (process?.stdout ?? '').toString(); + console.log(`${funcName} result`, result) if (process) - return (process.stdout ?? '').toString(); + return result; } export function existsSync(path: string): boolean { diff --git a/server/src/server.ts b/server/src/server.ts index 84ffa7ca..6c2ad148 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -276,6 +276,8 @@ async function patherr(msg: string) { } async function initpathenv(samefolder = false, retry = true): Promise { + const funcName = 'initpathenv'; + console.log(`Starting ${funcName}(${samefolder}, ${retry})`); const script = ` #NoTrayIcon #Warn All, Off @@ -289,6 +291,7 @@ async function initpathenv(samefolder = false, retry = true): Promise { }`; let fail = 0, data = runscript(script); + console.log(`data:`, data); if (data === undefined) { if (retry) return initpathenv(samefolder, false); patherr(setting.ahkpatherr()); @@ -316,10 +319,15 @@ async function initpathenv(samefolder = false, retry = true): Promise { } else fail = 1; if (fail !== 2 && retry) return initpathenv(samefolder, false); if (!a_vars.mydocuments) - connection.window.showErrorMessage(setting.getenverr()); + console.log('a_vars', a_vars); + connection.window.showWarningMessage(setting.getenverr()); return false; } - Object.assign(a_vars, Object.fromEntries(data.replace(/|[A-Z]:\\/g, m => m.toLowerCase()).split('\n').map(l => l.split('|')))); + const intermediateData = data.replace(/|[A-Z]:\\/g, m => m.toLowerCase()).split('\n').map(l => l.split('|')); + console.log('intermediateData', intermediateData); + const finalData = Object.fromEntries(intermediateData); + console.log('finalData', finalData); + Object.assign(a_vars, finalData); a_vars.ahkpath ??= interpreterPath; set_version(a_vars.ahkversion ??= '2.0.0'); if (a_vars.ahkversion.startsWith('1.')) From 22d94d87c46270b6729f18ef3350a7605c700842 Mon Sep 17 00:00:00 2001 From: Mark Wiemer <7833360+mark-wiemer@users.noreply.github.com> Date: Sat, 2 Nov 2024 06:50:06 -0700 Subject: [PATCH 59/60] Remove unused function (#76) --- client/src/utils.test.ts | 9 --------- client/src/utils.ts | 33 --------------------------------- 2 files changed, 42 deletions(-) delete mode 100644 client/src/utils.test.ts delete mode 100644 client/src/utils.ts diff --git a/client/src/utils.test.ts b/client/src/utils.test.ts deleted file mode 100644 index b27833b2..00000000 --- a/client/src/utils.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import * as assert from 'assert'; -import { suite, test } from 'mocha'; -import { resolvePath } from './utils'; - -suite('resolvePath', () => { - test('empty string', () => { - assert.strictEqual(resolvePath(''), ''); - }); -}); diff --git a/client/src/utils.ts b/client/src/utils.ts deleted file mode 100644 index 96242b26..00000000 --- a/client/src/utils.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { execSync } from 'child_process'; -import { lstatSync, readlinkSync } from 'fs'; -import { resolve } from 'path'; - -/** - * Returns the provided path as an absolute path. - * Resolves the provided path against the provided workspace. - * Resolves symbolic links by default. - * Returns empty string if resolution fails. - */ -export function resolvePath( - path: string | undefined, - workspace?: string, - resolveSymbolicLink = true, -): string { - if (!path) return ''; - const paths: string[] = []; - // If the path does not contain a colon, resolve it relative to the workspace - if (!path.includes(':')) paths.push(resolve(workspace ?? '', path)); - // If there are no slashes or backslashes in the path and the platform is Windows - if (!/[\\/]/.test(path) && process.platform === 'win32') - paths.push(execSync(`where ${path}`, { encoding: 'utf-8' }).trim()); - paths.push(path); - for (let path of paths) { - if (!path) continue; - try { - if (lstatSync(path).isSymbolicLink() && resolveSymbolicLink) - path = resolve(path, '..', readlinkSync(path)); - return path; - } catch {} - } - return ''; -} From a6c9fc568023749bc8ce434538dddb96ef1fb3aa Mon Sep 17 00:00:00 2001 From: Mark Wiemer Date: Sat, 2 Nov 2024 07:08:06 -0700 Subject: [PATCH 60/60] validate:fix --- CHANGELOG.md | 1 + README.zh-CN.md | 106 ++++++++++++++++++++++++------------------------ package.json | 8 ++-- readme.md | 1 - 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c05a441d..d306ed81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ ## 2.5.4 + - 修复[#610](https://github.com/thqby/vscode-autohotkey2-lsp/issues/610) - 修复[#615](https://github.com/thqby/vscode-autohotkey2-lsp/issues/615) - 修复[#623](https://github.com/thqby/vscode-autohotkey2-lsp/issues/623) diff --git a/README.zh-CN.md b/README.zh-CN.md index e8d051e1..2c25f362 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -233,49 +233,49 @@ node install.js ```json { - "clients": { - "lsp-ahk2": { - "enabled": true, - "command": [ - "node", - "/server/dist/server.js", - "--stdio" - ], // 更新node.exe的路径(可能已经在环境变量中,所以你不需要设置)和vscode-autohotkey2-lsp的文件夹 - "selector": "source.ahk2", // 与AutoHotkey2.sublime-syntax中的scope相同 - "schemes": ["file", "buffer", "res"], - "initializationOptions": { - "locale": "en-us", // or "zh-cn" - "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" - "CommentTags": "^;;\\s*(?.+)", - "CompleteFunctionParens": false, - "Diagnostics": { - "ClassStaticMemberCheck": true, - "ParamsCheck": true - }, - "ActionWhenV1IsDetected": "Continue", - "FormatOptions": { - "array_style": "none", // or "collapse" or "expand" - "break_chained_methods": false, - "ignore_comment": false, - "indent_string": "\t", - "max_preserve_newlines": 2, - "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" - "object_style": "none", // or "collapse" or "expand" - "preserve_newlines": true, - "space_after_double_colon": true, - "space_before_conditional": true, - "space_in_empty_paren": false, - "space_in_other": true, - "space_in_paren": false, - "wrap_line_length": 0 - }, - "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", - "WorkingDirs": [], - "SymbolFoldingFromOpenBrace": false - } - } - }, - "semantic_highlighting": true + "clients": { + "lsp-ahk2": { + "enabled": true, + "command": [ + "node", + "/server/dist/server.js", + "--stdio" + ], // 更新node.exe的路径(可能已经在环境变量中,所以你不需要设置)和vscode-autohotkey2-lsp的文件夹 + "selector": "source.ahk2", // 与AutoHotkey2.sublime-syntax中的scope相同 + "schemes": ["file", "buffer", "res"], + "initializationOptions": { + "locale": "en-us", // or "zh-cn" + "AutoLibInclude": "Disabled", // or "Local" or "User and Standard" or "All" + "CommentTags": "^;;\\s*(?.+)", + "CompleteFunctionParens": false, + "Diagnostics": { + "ClassStaticMemberCheck": true, + "ParamsCheck": true + }, + "ActionWhenV1IsDetected": "Continue", + "FormatOptions": { + "array_style": "none", // or "collapse" or "expand" + "break_chained_methods": false, + "ignore_comment": false, + "indent_string": "\t", + "max_preserve_newlines": 2, + "brace_style": "One True Brace", // or "Allman" or "One True Brace Variant" + "object_style": "none", // or "collapse" or "expand" + "preserve_newlines": true, + "space_after_double_colon": true, + "space_before_conditional": true, + "space_in_empty_paren": false, + "space_in_other": true, + "space_in_paren": false, + "wrap_line_length": 0 + }, + "InterpreterPath": "C:/Program Files/AutoHotkey/v2/AutoHotkey.exe", + "WorkingDirs": [], + "SymbolFoldingFromOpenBrace": false + } + } + }, + "semantic_highlighting": true } ``` @@ -294,16 +294,16 @@ git clone --branch release https://github.com/neoclide/coc.nvim.git --depth=1 ```json { - "languageserver": { - "lsp-ahk2": { - "module": "/server/dist/server.js", - "filetypes": ["autohotkey"], - "args": ["--node-ipc"], - "initializationOptions": { - // Same as initializationOptions for Sublime Text4 - } - } - } + "languageserver": { + "lsp-ahk2": { + "module": "/server/dist/server.js", + "filetypes": ["autohotkey"], + "args": ["--node-ipc"], + "initializationOptions": { + // Same as initializationOptions for Sublime Text4 + } + } + } } ``` diff --git a/package.json b/package.json index 6cf3302e..57c30d46 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,8 @@ { "name": "vscode-autohotkey2-lsp", "displayName": "AutoHotkey v2 Language Support", - "description": "AutoHotkey v2 Language Support, based on vscode-lsp.", - "author": "thqby", - "publisher": "thqby", "version": "2.5.4", - "license": "LGPLv3.0", + "description": "AutoHotkey v2 Language Support, based on vscode-lsp.", "categories": [ "Formatters", "Programming Languages", @@ -25,6 +22,9 @@ "type": "git", "url": "https://github.com/thqby/vscode-autohotkey2-lsp" }, + "license": "LGPLv3.0", + "author": "thqby", + "publisher": "thqby", "main": "./client/dist/extension", "browser": "./client/dist/browserClientMain", "scripts": { diff --git a/readme.md b/readme.md index aaf4eba7..c1985ed0 100644 --- a/readme.md +++ b/readme.md @@ -15,7 +15,6 @@ Supports running on the Web, such as `Chrome/Edge`. https://vscode.dev or https: If you wish to donate, donations can be sent here: [alipay](https://qr.alipay.com/fkx19566u7ctegoppmu5i13) or [alipay qrcode](./pic/alipay.jpg) or [paypal](https://paypal.me/thqby) - - [AutoHotkey v2 Language Support](#autohotkey-v2-language-support) - [Language Features](#language-features) - [Rename Symbol](#rename-symbol)