Repository: microsoft/inshellisense
Pull request #291 (2024-10-24 16:07:45)

fix: complex paths 
Fixes some weird completion issues for paths introduced in #290 along with improving handling quoted & escaped paths for completions across all shells. 

Related to #289


Patch:
diff --git a/package-lock.json b/package-lock.json
index e4cdbe6..cbc4fba 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -51,7 +51,7 @@
         "lint-staged": "^15.2.2",
         "prettier": "3.0.3",
         "ts-jest": "^29.1.1",
-        "ts-node": "^10.9.2",
+        "tsx": "^4.19.1",
         "typescript": "^5.2.2"
       },
       "engines": {
@@ -740,6 +740,8 @@
       "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
       "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "dependencies": {
         "@jridgewell/trace-mapping": "0.3.9"
       },
@@ -752,11 +754,397 @@
       "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
       "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "dependencies": {
         "@jridgewell/resolve-uri": "^3.0.3",
         "@jridgewell/sourcemap-codec": "^1.4.10"
       }
     },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz",
+      "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz",
+      "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz",
+      "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz",
+      "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz",
+      "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz",
+      "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz",
+      "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz",
+      "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz",
+      "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz",
+      "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz",
+      "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz",
+      "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz",
+      "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz",
+      "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz",
+      "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz",
+      "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz",
+      "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz",
+      "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz",
+      "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz",
+      "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz",
+      "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz",
+      "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz",
+      "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz",
+      "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
     "node_modules/@eslint-community/eslint-utils": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@@ -1909,25 +2297,33 @@
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
       "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "node_modules/@tsconfig/node12": {
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
       "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "node_modules/@tsconfig/node14": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
       "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "node_modules/@tsconfig/node16": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
       "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "node_modules/@tsconfig/node18": {
       "version": "18.2.2",
@@ -2363,6 +2759,8 @@
       "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz",
       "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "engines": {
         "node": ">=0.4.0"
       }
@@ -2435,7 +2833,9 @@
       "version": "4.1.3",
       "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
       "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "node_modules/argparse": {
       "version": "1.0.10",
@@ -3233,7 +3633,9 @@
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
       "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "node_modules/cross-spawn": {
       "version": "7.0.3",
@@ -3407,6 +3809,8 @@
       "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
       "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "engines": {
         "node": ">=0.3.1"
       }
@@ -3616,6 +4020,45 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/esbuild": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz",
+      "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==",
+      "dev": true,
+      "hasInstallScript": true,
+      "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.1",
       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -4463,6 +4906,18 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/get-tsconfig": {
+      "version": "4.8.1",
+      "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
+      "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
+      "dev": true,
+      "dependencies": {
+        "resolve-pkg-maps": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+      }
+    },
     "node_modules/github-from-package": {
       "version": "0.0.0",
       "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
@@ -7652,6 +8107,15 @@
         "node": ">=8"
       }
     },
+    "node_modules/resolve-pkg-maps": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+      "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+      }
+    },
     "node_modules/resolve.exports": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
@@ -8404,6 +8868,8 @@
       "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
       "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "dependencies": {
         "@cspotcode/source-map-support": "^0.8.0",
         "@tsconfig/node10": "^1.0.7",
@@ -8442,6 +8908,25 @@
         }
       }
     },
+    "node_modules/tsx": {
+      "version": "4.19.1",
+      "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz",
+      "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==",
+      "dev": true,
+      "dependencies": {
+        "esbuild": "~0.23.0",
+        "get-tsconfig": "^4.7.5"
+      },
+      "bin": {
+        "tsx": "dist/cli.mjs"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      }
+    },
     "node_modules/tunnel-agent": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -8625,7 +9110,9 @@
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
       "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "node_modules/v8-to-istanbul": {
       "version": "9.1.3",
@@ -8973,6 +9460,8 @@
       "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
       "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "engines": {
         "node": ">=6"
       }
@@ -9512,6 +10001,8 @@
       "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
       "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "requires": {
         "@jridgewell/trace-mapping": "0.3.9"
       },
@@ -9521,6 +10012,8 @@
           "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
           "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
           "dev": true,
+          "optional": true,
+          "peer": true,
           "requires": {
             "@jridgewell/resolve-uri": "^3.0.3",
             "@jridgewell/sourcemap-codec": "^1.4.10"
@@ -9528,6 +10021,174 @@
         }
       }
     },
+    "@esbuild/aix-ppc64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz",
+      "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-arm": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz",
+      "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz",
+      "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz",
+      "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz",
+      "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz",
+      "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz",
+      "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz",
+      "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz",
+      "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz",
+      "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ia32": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz",
+      "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-loong64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz",
+      "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-mips64el": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz",
+      "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ppc64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz",
+      "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-riscv64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz",
+      "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-s390x": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz",
+      "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz",
+      "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/netbsd-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz",
+      "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/openbsd-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz",
+      "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/openbsd-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz",
+      "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/sunos-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz",
+      "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-arm64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz",
+      "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-ia32": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz",
+      "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-x64": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz",
+      "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==",
+      "dev": true,
+      "optional": true
+    },
     "@eslint-community/eslint-utils": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@@ -10334,25 +10995,33 @@
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
       "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "@tsconfig/node12": {
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
       "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "@tsconfig/node14": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
       "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "@tsconfig/node16": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
       "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "@tsconfig/node18": {
       "version": "18.2.2",
@@ -10684,7 +11353,9 @@
       "version": "8.3.1",
       "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz",
       "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "ajv": {
       "version": "8.12.0",
@@ -10729,7 +11400,9 @@
       "version": "4.1.3",
       "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
       "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "argparse": {
       "version": "1.0.10",
@@ -11291,7 +11964,9 @@
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
       "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "cross-spawn": {
       "version": "7.0.3",
@@ -11412,7 +12087,9 @@
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
       "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "diff-sequences": {
       "version": "29.6.3",
@@ -11583,6 +12260,38 @@
         "is-symbol": "^1.0.2"
       }
     },
+    "esbuild": {
+      "version": "0.23.1",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz",
+      "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==",
+      "dev": true,
+      "requires": {
+        "@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"
+      }
+    },
     "escalade": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -12193,6 +12902,15 @@
         "get-intrinsic": "^1.1.1"
       }
     },
+    "get-tsconfig": {
+      "version": "4.8.1",
+      "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
+      "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
+      "dev": true,
+      "requires": {
+        "resolve-pkg-maps": "^1.0.0"
+      }
+    },
     "github-from-package": {
       "version": "0.0.0",
       "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
@@ -14432,6 +15150,12 @@
       "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
       "dev": true
     },
+    "resolve-pkg-maps": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+      "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+      "dev": true
+    },
     "resolve.exports": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
@@ -14936,6 +15660,8 @@
       "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
       "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "requires": {
         "@cspotcode/source-map-support": "^0.8.0",
         "@tsconfig/node10": "^1.0.7",
@@ -14952,6 +15678,17 @@
         "yn": "3.1.1"
       }
     },
+    "tsx": {
+      "version": "4.19.1",
+      "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz",
+      "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==",
+      "dev": true,
+      "requires": {
+        "esbuild": "~0.23.0",
+        "fsevents": "~2.3.3",
+        "get-tsconfig": "^4.7.5"
+      }
+    },
     "tunnel-agent": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -15072,7 +15809,9 @@
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
       "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "v8-to-istanbul": {
       "version": "9.1.3",
@@ -15335,7 +16074,9 @@
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
       "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "yocto-queue": {
       "version": "0.1.0",
diff --git a/package.json b/package.json
index 648bd84..162cd2e 100644
--- a/package.json
+++ b/package.json
@@ -18,12 +18,12 @@
   ],
   "scripts": {
     "build": "tsc",
-    "dev": "node --loader ts-node/esm src/index.ts -V",
+    "dev": "node --import=tsx src/index.ts -V",
     "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
     "test:e2e": "tui-test",
     "lint": "eslint src/ --ext .ts,.tsx && prettier src/ --check",
     "lint:fix": "eslint src/ --ext .ts,.tsx --fix && prettier src/ --write",
-    "debug": "node --inspect --loader ts-node/esm src/index.ts -V",
+    "debug": "node --inspect --import=tsx src/index.ts -V",
     "pre-commit": "lint-staged"
   },
   "repository": {
@@ -77,7 +77,7 @@
     "lint-staged": "^15.2.2",
     "prettier": "3.0.3",
     "ts-jest": "^29.1.1",
-    "ts-node": "^10.9.2",
+    "tsx": "^4.19.1",
     "typescript": "^5.2.2"
   },
   "lint-staged": {
diff --git a/src/runtime/alias.ts b/src/runtime/alias.ts
index fe6f4ea..7359ff6 100644
--- a/src/runtime/alias.ts
+++ b/src/runtime/alias.ts
@@ -24,7 +24,7 @@ const loadBashAliases = async () => {
     .split("\n")
     .forEach((line) => {
       const [alias, ...commandSegments] = line.replace("alias ", "").replaceAll("'\\''", "'").split("=");
-      loadedAliases[alias] = parseCommand(commandSegments.join("=").slice(1, -1) + " ");
+      loadedAliases[alias] = parseCommand(commandSegments.join("=").slice(1, -1) + " ", Shell.Bash);
     });
 };
 
@@ -40,7 +40,7 @@ const loadZshAliases = async () => {
     .split("\n")
     .forEach((line) => {
       const [alias, ...commandSegments] = line.replaceAll("'\\''", "'").split("=");
-      loadedAliases[alias] = parseCommand(commandSegments.join("=").slice(1, -1) + " ");
+      loadedAliases[alias] = parseCommand(commandSegments.join("=").slice(1, -1) + " ", Shell.Zsh);
     });
 };
 
diff --git a/src/runtime/parser.ts b/src/runtime/parser.ts
index 652d9e0..2e9a508 100644
--- a/src/runtime/parser.ts
+++ b/src/runtime/parser.ts
@@ -1,33 +1,68 @@
 // Copyright (c) Microsoft Corporation.
 // Licensed under the MIT License.
 
+import wcwidth from "wcwidth";
+import { Shell } from "../utils/shell.js";
+import { getShellWhitespaceEscapeChar } from "./utils.js";
+
 export type CommandToken = {
   token: string;
+  tokenLength: number;
   complete: boolean;
   isOption: boolean;
   isPersistent?: boolean;
   isPath?: boolean;
   isPathComplete?: boolean;
-  isQuoted?: boolean;
+  isQuoted?: boolean; // used for any token starting with quotes
+  isQuoteContinued?: boolean; // used for strings that are fully wrapped in quotes with content after the quotes
 };
 
 const cmdDelim = /(\|\|)|(&&)|(;)|(\|)/;
 const spaceRegex = /\s/;
 
-export const parseCommand = (command: string): CommandToken[] => {
+export const parseCommand = (command: string, shell: Shell): CommandToken[] => {
   const lastCommand = command.split(cmdDelim).at(-1)?.trimStart();
-  return lastCommand ? lex(lastCommand) : [];
+  const tokens = lastCommand ? lex(lastCommand, shell) : [];
+  return sanitizeTokens(tokens, shell);
+};
+
+const sanitizeTokens = (cmdTokens: CommandToken[], shell: Shell): CommandToken[] => unwrapQuotedTokens(unescapeSpaceTokens(cmdTokens, shell));
+
+// remove escapes around spaces
+const unescapeSpaceTokens = (cmdTokens: CommandToken[], shell: Shell): CommandToken[] => {
+  const escapeChar = getShellWhitespaceEscapeChar(shell);
+  return cmdTokens.map((cmdToken) => {
+    const { token, isQuoted } = cmdToken;
+    if (!isQuoted && token.includes(`${escapeChar} `)) {
+      return { ...cmdToken, token: token.replaceAll(`${escapeChar} `, " ") };
+    }
+    return cmdToken;
+  });
 };
 
-const lex = (command: string): CommandToken[] => {
+// need to unwrap tokens that are quoted with content after the quotes like `"hello"world`
+const unwrapQuotedTokens = (cmdTokens: CommandToken[]): CommandToken[] => {
+  return cmdTokens.map((cmdToken) => {
+    const { token, isQuoteContinued } = cmdToken;
+    if (isQuoteContinued) {
+      const quoteChar = token[0];
+      const unquotedToken = token.replaceAll(`\\${quoteChar}`, "\u001B").replaceAll(quoteChar, "").replaceAll("\u001B", quoteChar);
+      return { ...cmdToken, token: unquotedToken };
+    }
+    return cmdToken;
+  });
+};
+
+const lex = (command: string, shell: Shell): CommandToken[] => {
   const tokens: CommandToken[] = [];
-  let [readingQuotedString, readingFlag, readingCmd] = [false, false, false];
+  const escapeChar = getShellWhitespaceEscapeChar(shell);
+  let [readingQuotedString, readingQuoteContinuedString, readingFlag, readingCmd] = [false, false, false, false];
   let readingIdx = 0;
   let readingQuoteChar = "";
 
   [...command].forEach((char, idx) => {
-    const reading = readingQuotedString || readingFlag || readingCmd;
-    if (!reading && (char === `'` || char === `"`)) {
+    const reading = readingQuotedString || readingQuoteContinuedString || readingFlag || readingCmd;
+    if (!reading && (char === `'` || char === `"` || char == "`")) {
       [readingQuotedString, readingIdx, readingQuoteChar] = [true, idx, char];
       return;
     } else if (!reading && char === `-`) {
@@ -38,44 +73,71 @@ const lex = (command: string): CommandToken[] => {
       return;
     }
 
-    if (readingQuotedString && char === readingQuoteChar && command.at(idx - 1) !== "\\") {
+    if (readingQuotedString && char === readingQuoteChar && command.at(idx - 1) !== escapeChar && !spaceRegex.test(command.at(idx + 1) ?? " ")) {
+      readingQuotedString = false;
+      readingQuoteContinuedString = true;
+    } else if (readingQuotedString && char === readingQuoteChar && command.at(idx - 1) !== escapeChar) {
       readingQuotedString = false;
       const complete = idx + 1 < command.length && spaceRegex.test(command[idx + 1]);
       tokens.push({
         token: command.slice(readingIdx + 1, idx),
+        tokenLength: wcwidth(command.slice(readingIdx + 1, idx)) + 2, // +2 for both quotes
         complete,
         isOption: false,
         isQuoted: true,
       });
+    } else if (readingQuoteContinuedString && spaceRegex.test(char) && command.at(idx - 1) !== escapeChar) {
+      readingQuoteContinuedString = false;
+      tokens.push({
+        token: command.slice(readingIdx, idx),
+        tokenLength: wcwidth(command.slice(readingIdx, idx)),
+        complete: true,
+        isOption: false,
+        isQuoted: true,
+        isQuoteContinued: true,
+      });
     } else if ((readingFlag && spaceRegex.test(char)) || char === "=") {
       readingFlag = false;
       tokens.push({
         token: command.slice(readingIdx, idx),
+        tokenLength: wcwidth(command.slice(readingIdx, idx)),
         complete: true,
         isOption: true,
       });
-    } else if (readingCmd && spaceRegex.test(char) && command.at(idx - 1) !== "\\") {
+    } else if (readingCmd && spaceRegex.test(char) && command.at(idx - 1) !== escapeChar) {
       readingCmd = false;
       tokens.push({
         token: command.slice(readingIdx, idx),
+        tokenLength: wcwidth(command.slice(readingIdx, idx)),
         complete: true,
         isOption: false,
       });
     }
   });
 
-  const reading = readingQuotedString || readingFlag || readingCmd;
+  const reading = readingQuotedString || readingQuoteContinuedString || readingFlag || readingCmd;
   if (reading) {
     if (readingQuotedString) {
       tokens.push({
         token: command.slice(readingIdx + 1),
+        tokenLength: wcwidth(command.slice(readingIdx + 1)) + 1, // +1 for the leading quote
+        complete: false,
+        isOption: false,
+        isQuoted: true,
+      });
+    } else if (readingQuoteContinuedString) {
+      tokens.push({
+        token: command.slice(readingIdx),
+        tokenLength: wcwidth(command.slice(readingIdx)),
         complete: false,
         isOption: false,
         isQuoted: true,
+        isQuoteContinued: true,
       });
     } else {
       tokens.push({
         token: command.slice(readingIdx),
+        tokenLength: wcwidth(command.slice(readingIdx)),
         complete: false,
         isOption: readingFlag,
       });
diff --git a/src/runtime/runtime.ts b/src/runtime/runtime.ts
index e1f12b8..1017d65 100644
--- a/src/runtime/runtime.ts
+++ b/src/runtime/runtime.ts
@@ -92,7 +92,7 @@ export const loadLocalSpecsSet = async () => {
 };
 
 export const getSuggestions = async (cmd: string, cwd: string, shell: Shell): Promise<SuggestionBlob | undefined> => {
-  let activeCmd = parseCommand(cmd);
+  let activeCmd = parseCommand(cmd, shell);
   const rootToken = activeCmd.at(0);
   if (activeCmd.length === 0 || !rootToken?.complete) {
     return;
@@ -110,13 +110,10 @@ export const getSuggestions = async (cmd: string, cwd: string, shell: Shell): Pr
     lastCommand.isPath = true;
     lastCommand.isPathComplete = pathyComplete;
   }
-  const result = await runSubcommand(activeCmd.slice(1), subcommand, resolvedCwd);
+  const result = await runSubcommand(activeCmd.slice(1), subcommand, resolvedCwd, shell);
   if (result == null) return;
 
-  let charactersToDrop = lastCommand?.complete ? 0 : lastCommand?.token.length ?? 0;
-  if (pathy) {
-    charactersToDrop = pathyComplete ? 0 : path.basename(lastCommand?.token ?? "").length;
-  }
+  const charactersToDrop = lastCommand?.complete ? 0 : lastCommand?.tokenLength;
   return { ...result, charactersToDrop };
 };
 
@@ -227,6 +224,7 @@ const runOption = async (
   option: Fig.Option,
   subcommand: Fig.Subcommand,
   cwd: string,
+  shell: Shell,
   persistentOptions: Fig.Option[],
   acceptedTokens: CommandToken[],
 ): Promise<SuggestionBlob | undefined> => {
@@ -237,12 +235,13 @@ const runOption = async (
   const isPersistent = persistentOptions.some((o) => (typeof o.name === "string" ? o.name === activeToken.token : o.name.includes(activeToken.token)));
   if ((option.args instanceof Array && option.args.length > 0) || option.args != null) {
     const args = option.args instanceof Array ? option.args : [option.args];
-    return runArg(tokens.slice(1), args, subcommand, cwd, persistentOptions, acceptedTokens.concat(activeToken), true, false);
+    return runArg(tokens.slice(1), args, subcommand, cwd, shell, persistentOptions, acceptedTokens.concat(activeToken), true, false);
   }
   return runSubcommand(
     tokens.slice(1),
     subcommand,
     cwd,
+    shell,
     persistentOptions,
     acceptedTokens.concat({
       ...activeToken,
@@ -256,17 +255,18 @@ const runArg = async (
   args: Fig.Arg[],
   subcommand: Fig.Subcommand,
   cwd: string,
+  shell: Shell,
   persistentOptions: Fig.Option[],
   acceptedTokens: CommandToken[],
   fromOption: boolean,
   fromVariadic: boolean,
 ): Promise<SuggestionBlob | undefined> => {
   if (args.length === 0) {
-    return runSubcommand(tokens, subcommand, cwd, persistentOptions, acceptedTokens, true, !fromOption);
+    return runSubcommand(tokens, subcommand, cwd, shell, persistentOptions, acceptedTokens, true, !fromOption);
   } else if (tokens.length === 0) {
-    return await getArgDrivenRecommendation(args, subcommand, persistentOptions, undefined, acceptedTokens, fromVariadic, cwd);
+    return await getArgDrivenRecommendation(args, subcommand, persistentOptions, undefined, acceptedTokens, fromVariadic, cwd, shell);
   } else if (!tokens.at(0)?.complete) {
-    return await getArgDrivenRecommendation(args, subcommand, persistentOptions, tokens[0], acceptedTokens, fromVariadic, cwd);
+    return await getArgDrivenRecommendation(args, subcommand, persistentOptions, tokens[0], acceptedTokens, fromVariadic, cwd, shell);
   }
 
   const activeToken = tokens[0];
@@ -274,20 +274,20 @@ const runArg = async (
     if (activeToken.isOption) {
       const option = getOption(activeToken, persistentOptions.concat(subcommand.options ?? []));
       if (option != null) {
-        return runOption(tokens, option, subcommand, cwd, persistentOptions, acceptedTokens);
+        return runOption(tokens, option, subcommand, cwd, shell, persistentOptions, acceptedTokens);
       }
       return;
     }
 
     const nextSubcommand = await genSubcommand(activeToken.token, subcommand);
     if (nextSubcommand != null) {
-      return runSubcommand(tokens.slice(1), nextSubcommand, cwd, persistentOptions, getPersistentTokens(acceptedTokens.concat(activeToken)));
+      return runSubcommand(tokens.slice(1), nextSubcommand, cwd, shell, persistentOptions, getPersistentTokens(acceptedTokens.concat(activeToken)));
     }
   }
 
   const activeArg = args[0];
   if (activeArg.isVariadic) {
-    return runArg(tokens.slice(1), args, subcommand, cwd, persistentOptions, acceptedTokens.concat(activeToken), fromOption, true);
+    return runArg(tokens.slice(1), args, subcommand, cwd, shell, persistentOptions, acceptedTokens.concat(activeToken), fromOption, true);
   } else if (activeArg.isCommand) {
     if (tokens.length <= 0) {
       return;
@@ -296,24 +296,25 @@ const runArg = async (
     if (spec == null) return;
     const subcommand = getSubcommand(spec);
     if (subcommand == null) return;
-    return runSubcommand(tokens.slice(1), subcommand, cwd);
+    return runSubcommand(tokens.slice(1), subcommand, cwd, shell);
   }
-  return runArg(tokens.slice(1), args.slice(1), subcommand, cwd, persistentOptions, acceptedTokens.concat(activeToken), fromOption, false);
+  return runArg(tokens.slice(1), args.slice(1), subcommand, cwd, shell, persistentOptions, acceptedTokens.concat(activeToken), fromOption, false);
 };
 
 const runSubcommand = async (
   tokens: CommandToken[],
   subcommand: Fig.Subcommand,
   cwd: string,
+  shell: Shell,
   persistentOptions: Fig.Option[] = [],
   acceptedTokens: CommandToken[] = [],
   argsDepleted = false,
   argsUsed = false,
 ): Promise<SuggestionBlob | undefined> => {
   if (tokens.length === 0) {
-    return getSubcommandDrivenRecommendation(subcommand, persistentOptions, undefined, argsDepleted, argsUsed, acceptedTokens, cwd);
+    return getSubcommandDrivenRecommendation(subcommand, persistentOptions, undefined, argsDepleted, argsUsed, acceptedTokens, cwd, shell);
   } else if (!tokens.at(0)?.complete) {
-    return getSubcommandDrivenRecommendation(subcommand, persistentOptions, tokens[0], argsDepleted, argsUsed, acceptedTokens, cwd);
+    return getSubcommandDrivenRecommendation(subcommand, persistentOptions, tokens[0], argsDepleted, argsUsed, acceptedTokens, cwd, shell);
   }
 
   const activeToken = tokens[0];
@@ -323,7 +324,7 @@ const runSubcommand = async (
   if (activeToken.isOption) {
     const option = getOption(activeToken, allOptions);
     if (option != null) {
-      return runOption(tokens, option, subcommand, cwd, persistentOptions, acceptedTokens);
+      return runOption(tokens, option, subcommand, cwd, shell, persistentOptions, acceptedTokens);
     }
     return;
   }
@@ -334,6 +335,7 @@ const runSubcommand = async (
       tokens.slice(1),
       nextSubcommand,
       cwd,
+      shell,
       getPersistentOptions(persistentOptions, subcommand.options),
       getPersistentTokens(acceptedTokens.concat(activeToken)),
     );
@@ -345,8 +347,8 @@ const runSubcommand = async (
 
   const args = getArgs(subcommand.args);
   if (args.length != 0) {
-    return runArg(tokens, args, subcommand, cwd, allOptions, acceptedTokens, false, false);
+    return runArg(tokens, args, subcommand, cwd, shell, allOptions, acceptedTokens, false, false);
   }
   // if the subcommand has no args specified, fallback to the subcommand and ignore this item
-  return runSubcommand(tokens.slice(1), subcommand, cwd, persistentOptions, acceptedTokens.concat(activeToken));
+  return runSubcommand(tokens.slice(1), subcommand, cwd, shell, persistentOptions, acceptedTokens.concat(activeToken));
 };
diff --git a/src/runtime/suggestion.ts b/src/runtime/suggestion.ts
index 0dd94f0..ef72c6e 100644
--- a/src/runtime/suggestion.ts
+++ b/src/runtime/suggestion.ts
@@ -8,6 +8,8 @@ import { runGenerator } from "./generator.js";
 import { runTemplates } from "./template.js";
 import { Suggestion, SuggestionBlob } from "./model.js";
 import log from "../utils/log.js";
+import { escapePath } from "./utils.js";
+import { getPathSeparator, Shell } from "../utils/shell.js";
 
 export enum SuggestionIcons {
   File = "📄",
@@ -200,15 +202,14 @@ const optionSuggestions = (
   return filter<Fig.Option>(validOptions ?? [], filterStrategy, partialCmd, "option");
 };
 
-const getEscapedPath = (value?: string): string | undefined => {
-  return value?.replaceAll(" ", "\\ ");
-};
+function adjustPathSuggestions(suggestions: Suggestion[], partialToken: CommandToken | undefined, shell: Shell): Suggestion[] {
+  if (partialToken == null) return suggestions;
 
-function adjustPathSuggestions(suggestions: Suggestion[], partialToken?: CommandToken): Suggestion[] {
-  if (partialToken == null || partialToken.isQuoted) return suggestions;
-  return suggestions.map((s) =>
-    s.pathy ? { ...s, insertValue: getEscapedPath(s.insertValue), name: s.insertValue == null ? getEscapedPath(s.name)! : s.name } : s,
-  );
+  const sep = getPathSeparator(shell);
+  return suggestions.map((s) => {
+    const fullPath = partialToken.isPath ? `${path.dirname(partialToken.token)}${sep}${s.insertValue}` : s.insertValue;
+    return s.pathy ? { ...s, insertValue: escapePath(fullPath, shell) } : s;
+  });
 }
 
 const removeAcceptedSuggestions = (suggestions: Suggestion[], acceptedTokens: CommandToken[]): Suggestion[] => {
@@ -239,6 +240,7 @@ export const getSubcommandDrivenRecommendation = async (
   argsFromSubcommand: boolean,
   acceptedTokens: CommandToken[],
   cwd: string,
+  shell: Shell,
 ): Promise<SuggestionBlob | undefined> => {
   log.debug({ msg: "suggestion point", subcommand, persistentOptions, partialToken, argsDepleted, argsFromSubcommand, acceptedTokens, cwd });
   if (argsDepleted && argsFromSubcommand) {
@@ -271,6 +273,7 @@ export const getSubcommandDrivenRecommendation = async (
           adjustPathSuggestions(
             suggestions.sort((a, b) => b.priority - a.priority),
             partialToken,
+            shell,
           ),
           acceptedTokens,
         ),
@@ -287,6 +290,7 @@ export const getArgDrivenRecommendation = async (
   acceptedTokens: CommandToken[],
   variadicArgBound: boolean,
   cwd: string,
+  shell: Shell,
 ): Promise<SuggestionBlob | undefined> => {
   let partialCmd = partialToken?.token;
   if (partialToken?.isPath) {
@@ -313,6 +317,7 @@ export const getArgDrivenRecommendation = async (
           adjustPathSuggestions(
             suggestions.sort((a, b) => b.priority - a.priority),
             partialToken,
+            shell,
           ),
           acceptedTokens,
         ),
diff --git a/src/runtime/utils.ts b/src/runtime/utils.ts
index bd09eba..c32fb23 100644
--- a/src/runtime/utils.ts
+++ b/src/runtime/utils.ts
@@ -6,7 +6,7 @@ import { spawn } from "node:child_process";
 import fsAsync from "node:fs/promises";
 
 import { CommandToken } from "./parser.js";
-import { getPathSeperator, gitBashPath, Shell } from "../utils/shell.js";
+import { getPathSeparator, gitBashPath, Shell } from "../utils/shell.js";
 import log from "../utils/log.js";
 
 export type ExecuteShellCommandTTYResult = {
@@ -27,8 +27,7 @@ const bashSpecialCharacters = /[&|<>\s]/g;
 const shouldEscapeArg = (arg: string) => {
   const hasSpecialCharacter = bashSpecialCharacters.test(arg);
   const isSingleCharacter = arg.length === 1;
-  const isQuoted = (arg.startsWith(`"`) && arg.endsWith(`"`)) || (arg.startsWith(`'`) && arg.endsWith(`'`));
-  return hasSpecialCharacter && !isSingleCharacter && !isQuoted;
+  return hasSpecialCharacter && !isSingleCharacter && !isQuoted(arg, `"`);
 };
 
 /* based on libuv process.c used by nodejs, only quotes are escaped for shells. if using git bash need to escape whitespace & special characters in an argument */
@@ -38,6 +37,55 @@ const escapeArgs = (shell: string | undefined, args: string[]) => {
   return args.map((arg) => (shouldEscapeArg(arg) ? `"${arg.replaceAll('"', '\\"')}"` : arg));
 };
 
+type QuoteChar = `"` | `'` | "`";
+
+const isQuoted = (value: string | undefined, quoteChar: QuoteChar): boolean => (value?.startsWith(quoteChar) && value?.endsWith(quoteChar)) ?? false;
+
+const quoteString = (value: string, quoteChar: QuoteChar): string => {
+  if (isQuoted(value, quoteChar)) return value;
+  const escapedValue = value.replaceAll(`\\${quoteChar}`, quoteChar).replaceAll(quoteChar, `\\${quoteChar}`);
+  return `${quoteChar}${escapedValue}${quoteChar}`;
+};
+
+const needsQuoted = (value: string, quoteChar: QuoteChar): boolean => isQuoted(value, quoteChar) || value.includes(" ");
+
+const getShellQuoteChar = (shell: Shell): QuoteChar => {
+  switch (shell) {
+    case Shell.Zsh:
+    case Shell.Bash:
+    case Shell.Fish:
+      return `"`;
+    case Shell.Xonsh:
+      return `'`;
+    case Shell.Nushell:
+      return "`";
+    case Shell.Pwsh:
+    case Shell.Powershell:
+      return `'`;
+    case Shell.Cmd:
+      return `"`;
+  }
+};
+
+export const getShellWhitespaceEscapeChar = (shell: Shell): string => {
+  switch (shell) {
+    case Shell.Zsh:
+    case Shell.Bash:
+    case Shell.Fish:
+    case Shell.Xonsh:
+    case Shell.Nushell:
+      return "\\";
+    case Shell.Pwsh:
+    case Shell.Powershell:
+      return "`";
+    case Shell.Cmd:
+      return "^";
+  }
+};
+
+export const escapePath = (value: string | undefined, shell: Shell): string | undefined =>
+  value != null && needsQuoted(value, getShellQuoteChar(shell)) ? quoteString(value, getShellQuoteChar(shell)) : value;
+
 export const buildExecuteShellCommand =
   async (timeout: number): Promise<Fig.ExecuteCommandFunction> =>
   async ({ command, env, args, cwd }: Fig.ExecuteCommandInput): Promise<Fig.ExecuteCommandOutput> => {
@@ -70,8 +118,9 @@ export const resolveCwd = async (
 ): Promise<{ cwd: string; pathy: boolean; complete: boolean }> => {
   if (cmdToken == null) return { cwd, pathy: false, complete: false };
   const { token: rawToken, isQuoted } = cmdToken;
-  const token = !isQuoted ? rawToken.replaceAll("\\ ", " ") : rawToken;
-  const sep = getPathSeperator(shell);
+  const escapedToken = !isQuoted ? rawToken.replaceAll(" ", "\\ ") : rawToken;
+  const token = escapedToken;
+  const sep = getPathSeparator(shell);
   if (!token.includes(sep)) return { cwd, pathy: false, complete: false };
   const resolvedCwd = path.isAbsolute(token) ? token : path.join(cwd, token);
   try {
diff --git a/src/utils/shell.ts b/src/utils/shell.ts
index adac7c7..212a58c 100644
--- a/src/utils/shell.ts
+++ b/src/utils/shell.ts
@@ -58,7 +58,7 @@ export const setupZshDotfiles = async () => {
   await fsAsync.cp(path.join(shellFolderPath, "shellIntegration-login.zsh"), path.join(zdotdir, ".zlogin"));
 };
 
-const findPareentProcess = async () => {
+const findParentProcess = async () => {
   try {
     return (await find("pid", process.ppid)).at(0);
   } catch (e) {
@@ -90,7 +90,7 @@ export const inferShell = async () => {
   }
 
   // try getting shell from parent process
-  const processResult = await findPareentProcess();
+  const processResult = await findParentProcess();
   const name = processResult?.name;
   return name != null ? supportedShells.find((shell) => name.includes(shell)) : undefined;
 };
@@ -143,7 +143,7 @@ const getGitBashPaths = async (): Promise<string[]> => {
 export const getBackspaceSequence = (press: KeyPressEvent, shell: Shell) =>
   shell === Shell.Pwsh || shell === Shell.Powershell || shell === Shell.Cmd || shell === Shell.Nushell ? "\u007F" : press[1].sequence;
 
-export const getPathSeperator = (shell: Shell) => (shell == Shell.Bash || shell == Shell.Xonsh || shell == Shell.Nushell ? "/" : path.sep);
+export const getPathSeparator = (shell: Shell) => (shell == Shell.Bash || shell == Shell.Xonsh || shell == Shell.Nushell ? "/" : path.sep);
 
 // nu fully re-writes the prompt every keystroke resulting in duplicate start/end sequences on the same line
 export const getShellPromptRewrites = (shell: Shell) => shell == Shell.Nushell;


Test patch:
diff --git a/src/tests/runtime/__snapshots__/alias.test.ts.snap b/src/tests/runtime/__snapshots__/alias.test.ts.snap
index 5234b1a..74fe826 100644
--- a/src/tests/runtime/__snapshots__/alias.test.ts.snap
+++ b/src/tests/runtime/__snapshots__/alias.test.ts.snap
@@ -6,6 +6,7 @@ exports[`aliasExpand expand on bash aliases 1`] = `
     "complete": false,
     "isOption": false,
     "token": "glo",
+    "tokenLength": 3,
   },
 ]
 `;
@@ -16,18 +17,21 @@ exports[`aliasExpand expand on bash aliases 2`] = `
     "complete": true,
     "isOption": false,
     "token": "echo",
+    "tokenLength": 4,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "lo",
+    "tokenLength": 4,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "la",
+    "tokenLength": 4,
   },
 ]
 `;
@@ -38,6 +42,7 @@ exports[`aliasExpand expand on bash aliases 3`] = `
     "complete": true,
     "isOption": false,
     "token": "git",
+    "tokenLength": 3,
   },
 ]
 `;
@@ -48,16 +53,19 @@ exports[`aliasExpand expand on bash aliases 4`] = `
     "complete": true,
     "isOption": false,
     "token": "ls",
+    "tokenLength": 2,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "--color",
+    "tokenLength": 7,
   },
   {
     "complete": true,
     "isOption": false,
     "token": "auto",
+    "tokenLength": 4,
   },
 ]
 `;
@@ -68,6 +76,7 @@ exports[`aliasExpand expand on zsh aliases 1`] = `
     "complete": false,
     "isOption": false,
     "token": "glo",
+    "tokenLength": 3,
   },
 ]
 `;
@@ -78,18 +87,21 @@ exports[`aliasExpand expand on zsh aliases 2`] = `
     "complete": true,
     "isOption": false,
     "token": "echo",
+    "tokenLength": 4,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "lo",
+    "tokenLength": 4,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "la",
+    "tokenLength": 4,
   },
 ]
 `;
@@ -100,6 +112,7 @@ exports[`aliasExpand expand on zsh aliases 3`] = `
     "complete": true,
     "isOption": false,
     "token": "git",
+    "tokenLength": 3,
   },
 ]
 `;
@@ -110,16 +123,19 @@ exports[`aliasExpand expand on zsh aliases 4`] = `
     "complete": true,
     "isOption": false,
     "token": "ls",
+    "tokenLength": 2,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "--color",
+    "tokenLength": 7,
   },
   {
     "complete": true,
     "isOption": false,
     "token": "auto",
+    "tokenLength": 4,
   },
 ]
 `;
diff --git a/src/tests/runtime/__snapshots__/parser.test.ts.snap b/src/tests/runtime/__snapshots__/parser.test.ts.snap
index fe6499f..1d53b17 100644
--- a/src/tests/runtime/__snapshots__/parser.test.ts.snap
+++ b/src/tests/runtime/__snapshots__/parser.test.ts.snap
@@ -1,11 +1,42 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`parseCommand \`cmd1\` 1`] = `
+[
+  {
+    "complete": false,
+    "isOption": false,
+    "isQuoted": true,
+    "token": "cmd1",
+    "tokenLength": 6,
+  },
+]
+`;
+
 exports[`parseCommand cmd  1`] = `
 [
   {
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
+  },
+]
+`;
+
+exports[`parseCommand cmd "value"  1`] = `
+[
+  {
+    "complete": true,
+    "isOption": false,
+    "token": "cmd",
+    "tokenLength": 3,
+  },
+  {
+    "complete": true,
+    "isOption": false,
+    "isQuoted": true,
+    "token": "value",
+    "tokenLength": 7,
   },
 ]
 `;
@@ -16,12 +47,14 @@ exports[`parseCommand cmd "value'  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": false,
     "isOption": false,
     "isQuoted": true,
     "token": "value' ",
+    "tokenLength": 8,
   },
 ]
 `;
@@ -32,12 +65,14 @@ exports[`parseCommand cmd "value'\\"\\""  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "value'\\"\\"",
+    "tokenLength": 12,
   },
 ]
 `;
@@ -48,12 +83,14 @@ exports[`parseCommand cmd 'value'  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "value",
+    "tokenLength": 7,
   },
 ]
 `;
@@ -64,16 +101,19 @@ exports[`parseCommand cmd --flag value 1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "--flag",
+    "tokenLength": 6,
   },
   {
     "complete": false,
     "isOption": false,
     "token": "value",
+    "tokenLength": 5,
   },
 ]
 `;
@@ -84,17 +124,20 @@ exports[`parseCommand cmd --flag="value"  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "--flag",
+    "tokenLength": 6,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "value",
+    "tokenLength": 7,
   },
 ]
 `;
@@ -105,17 +148,20 @@ exports[`parseCommand cmd --flag='value'  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "--flag",
+    "tokenLength": 6,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "value",
+    "tokenLength": 7,
   },
 ]
 `;
@@ -126,16 +172,19 @@ exports[`parseCommand cmd --flag=value 1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "--flag",
+    "tokenLength": 6,
   },
   {
     "complete": false,
     "isOption": false,
     "token": "value",
+    "tokenLength": 5,
   },
 ]
 `;
@@ -146,11 +195,13 @@ exports[`parseCommand cmd -f  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "-f",
+    "tokenLength": 2,
   },
 ]
 `;
@@ -161,17 +212,20 @@ exports[`parseCommand cmd -f 'value'  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "-f",
+    "tokenLength": 2,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "value",
+    "tokenLength": 7,
   },
 ]
 `;
@@ -182,11 +236,13 @@ exports[`parseCommand cmd -f 1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": false,
     "isOption": true,
     "token": "-f",
+    "tokenLength": 2,
   },
 ]
 `;
@@ -197,11 +253,13 @@ exports[`parseCommand cmd -f 2`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": false,
     "isOption": true,
     "token": "-f",
+    "tokenLength": 2,
   },
 ]
 `;
@@ -212,16 +270,19 @@ exports[`parseCommand cmd -f value  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "-f",
+    "tokenLength": 2,
   },
   {
     "complete": true,
     "isOption": false,
     "token": "value",
+    "tokenLength": 5,
   },
 ]
 `;
@@ -232,11 +293,13 @@ exports[`parseCommand cmd -f= 1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "-f",
+    "tokenLength": 2,
   },
 ]
 `;
@@ -247,17 +310,20 @@ exports[`parseCommand cmd -f="value"  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "-f",
+    "tokenLength": 2,
   },
   {
     "complete": true,
     "isOption": false,
     "isQuoted": true,
     "token": "value",
+    "tokenLength": 7,
   },
 ]
 `;
@@ -268,17 +334,20 @@ exports[`parseCommand cmd -f='val 1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "-f",
+    "tokenLength": 2,
   },
   {
     "complete": false,
     "isOption": false,
     "isQuoted": true,
     "token": "val",
+    "tokenLength": 4,
   },
 ]
 `;
@@ -289,16 +358,19 @@ exports[`parseCommand cmd -f=value  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": true,
     "token": "-f",
+    "tokenLength": 2,
   },
   {
     "complete": true,
     "isOption": false,
     "token": "value",
+    "tokenLength": 5,
   },
 ]
 `;
@@ -309,6 +381,7 @@ exports[`parseCommand cmd 1`] = `
     "complete": false,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
 ]
 `;
@@ -319,11 +392,13 @@ exports[`parseCommand cmd dir\\ 1/dir\\ 2/item1 1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": false,
     "isOption": false,
-    "token": "dir\\ 1/dir\\ 2/item1",
+    "token": "dir 1/dir 2/item1",
+    "tokenLength": 19,
   },
 ]
 `;
@@ -334,11 +409,83 @@ exports[`parseCommand cmd value  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd",
+    "tokenLength": 3,
   },
   {
     "complete": true,
     "isOption": false,
     "token": "value",
+    "tokenLength": 5,
+  },
+]
+`;
+
+exports[`parseCommand cmd1 "item1"item2 "item3" 1`] = `
+[
+  {
+    "complete": true,
+    "isOption": false,
+    "token": "cmd1",
+    "tokenLength": 4,
+  },
+  {
+    "complete": true,
+    "isOption": false,
+    "isQuoteContinued": true,
+    "isQuoted": true,
+    "token": "item1item2",
+    "tokenLength": 12,
+  },
+  {
+    "complete": false,
+    "isOption": false,
+    "isQuoted": true,
+    "token": "item3",
+    "tokenLength": 7,
+  },
+]
+`;
+
+exports[`parseCommand cmd1 "item1"item2 1`] = `
+[
+  {
+    "complete": true,
+    "isOption": false,
+    "token": "cmd1",
+    "tokenLength": 4,
+  },
+  {
+    "complete": false,
+    "isOption": false,
+    "isQuoteContinued": true,
+    "isQuoted": true,
+    "token": "item1item2",
+    "tokenLength": 12,
+  },
+]
+`;
+
+exports[`parseCommand cmd1 "item1"item2 item3 1`] = `
+[
+  {
+    "complete": true,
+    "isOption": false,
+    "token": "cmd1",
+    "tokenLength": 4,
+  },
+  {
+    "complete": true,
+    "isOption": false,
+    "isQuoteContinued": true,
+    "isQuoted": true,
+    "token": "item1item2",
+    "tokenLength": 12,
+  },
+  {
+    "complete": false,
+    "isOption": false,
+    "token": "item3",
+    "tokenLength": 5,
   },
 ]
 `;
@@ -349,6 +496,7 @@ exports[`parseCommand cmd1 | cmd2  1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd2",
+    "tokenLength": 4,
   },
 ]
 `;
@@ -359,11 +507,24 @@ exports[`parseCommand cmd1 - 1`] = `
     "complete": true,
     "isOption": false,
     "token": "cmd1",
+    "tokenLength": 4,
   },
   {
     "complete": false,
     "isOption": true,
     "token": "-",
+    "tokenLength": 1,
+  },
+]
+`;
+
+exports[`parseCommand 😁 1`] = `
+[
+  {
+    "complete": false,
+    "isOption": false,
+    "token": "😁",
+    "tokenLength": 2,
   },
 ]
 `;
diff --git a/src/tests/runtime/alias.test.ts b/src/tests/runtime/alias.test.ts
index 01ed74a..22b6c8a 100644
--- a/src/tests/runtime/alias.test.ts
+++ b/src/tests/runtime/alias.test.ts
@@ -8,6 +8,7 @@ const mockExecuteShellCommand = jest.fn();
 
 jest.unstable_mockModule("../../runtime/utils.js", () => ({
   buildExecuteShellCommand: () => mockExecuteShellCommand,
+  getShellWhitespaceEscapeChar: () => "\\",
 }));
 
 const { aliasExpand, loadAliases } = await import("../../runtime/alias.js");
@@ -27,10 +28,10 @@ alias ls='ls --color=auto'`,
     });
 
     await loadAliases(Shell.Bash);
-    expect(aliasExpand([{ token: "glo", complete: false, isOption: false }])).toMatchSnapshot();
-    expect(aliasExpand([{ token: "la", complete: true, isOption: false }])).toMatchSnapshot();
-    expect(aliasExpand([{ token: "git", complete: true, isOption: false }])).toMatchSnapshot();
-    expect(aliasExpand([{ token: "ls", complete: true, isOption: false }])).toMatchSnapshot();
+    expect(aliasExpand([{ token: "glo", complete: false, isOption: false, tokenLength: 3 }])).toMatchSnapshot();
+    expect(aliasExpand([{ token: "la", complete: true, isOption: false, tokenLength: 2 }])).toMatchSnapshot();
+    expect(aliasExpand([{ token: "git", complete: true, isOption: false, tokenLength: 3 }])).toMatchSnapshot();
+    expect(aliasExpand([{ token: "ls", complete: true, isOption: false, tokenLength: 2 }])).toMatchSnapshot();
   });
 
   test("expand on zsh aliases", async () => {
@@ -43,9 +44,9 @@ ls='ls --color=auto'`,
     });
 
     await loadAliases(Shell.Zsh);
-    expect(aliasExpand([{ token: "glo", complete: false, isOption: false }])).toMatchSnapshot();
-    expect(aliasExpand([{ token: "la", complete: true, isOption: false }])).toMatchSnapshot();
-    expect(aliasExpand([{ token: "git", complete: true, isOption: false }])).toMatchSnapshot();
-    expect(aliasExpand([{ token: "ls", complete: true, isOption: false }])).toMatchSnapshot();
+    expect(aliasExpand([{ token: "glo", complete: false, isOption: false, tokenLength: 3 }])).toMatchSnapshot();
+    expect(aliasExpand([{ token: "la", complete: true, isOption: false, tokenLength: 2 }])).toMatchSnapshot();
+    expect(aliasExpand([{ token: "git", complete: true, isOption: false, tokenLength: 3 }])).toMatchSnapshot();
+    expect(aliasExpand([{ token: "ls", complete: true, isOption: false, tokenLength: 2 }])).toMatchSnapshot();
   });
 });
diff --git a/src/tests/runtime/parser.test.ts b/src/tests/runtime/parser.test.ts
index ecab703..ee89193 100644
--- a/src/tests/runtime/parser.test.ts
+++ b/src/tests/runtime/parser.test.ts
@@ -2,6 +2,7 @@
 // Licensed under the MIT License.
 
 import { parseCommand } from "../../runtime/parser.js";
+import { Shell } from "../../utils/shell.js";
 
 const testData = [
   { command: `cmd --flag value` },
@@ -22,16 +23,22 @@ const testData = [
   { command: `cmd` },
   { command: `cmd ` },
   { command: `cmd "value' ` },
+  { command: `cmd "value" ` },
   { command: `cmd "value'\\"\\"" ` },
   { command: `cmd1 | cmd2 ` },
   { command: `cmd1 -` },
   { command: `cmd dir\\ 1/dir\\ 2/item1` },
+  { command: `cmd1 "item1"item2` },
+  { command: `cmd1 "item1"item2 item3` },
+  { command: `cmd1 "item1"item2 "item3"` },
+  { command: "`cmd1`" },
+  { command: "😁" },
 ];
 
 describe(`parseCommand`, () => {
   testData.forEach(({ command }) => {
     test(command, () => {
-      expect(parseCommand(command)).toMatchSnapshot();
+      expect(parseCommand(command, Shell.Bash)).toMatchSnapshot();
     });
   });
 });