g commands are implemented

This commit is contained in:
jwilliams720 2023-11-12 19:24:48 +00:00
parent 8ae4f6d73e
commit e66541133c
23 changed files with 1234 additions and 1458 deletions

View File

@ -1,6 +1,5 @@
{
"printWidth": 100,
"semi": false,
"printWidth": 120,
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "always",

324
package-lock.json generated
View File

@ -12,14 +12,14 @@
"@types/http-errors": "^1.8.0",
"@types/node": "^20.8.9",
"@types/vscode": "^1.83.1",
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.42.1",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"bumpp": "^8.2.1",
"esbuild": "^0.19.5",
"eslint": "^8.27.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-prettier": "^9.0.0",
"esno": "^0.16.3",
"prettier": "^2.7.1",
"prettier": "^3.0.3",
"rimraf": "^3.0.2",
"string.prototype.matchall": "^4.0.2",
"typescript": "^5.2.2",
@ -480,6 +480,30 @@
"node": ">=12"
}
},
"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",
"integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
"dev": true,
"dependencies": {
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
}
},
"node_modules/@eslint-community/regexpp": {
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
"integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
"dev": true,
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
"node_modules/@eslint/eslintrc": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz",
@ -623,9 +647,9 @@
"dev": true
},
"node_modules/@types/json-schema": {
"version": "7.0.11",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true
},
"node_modules/@types/node": {
@ -638,9 +662,9 @@
}
},
"node_modules/@types/semver": {
"version": "7.3.13",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz",
"integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==",
"dev": true
},
"node_modules/@types/vscode": {
@ -650,31 +674,33 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.1.tgz",
"integrity": "sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz",
"integrity": "sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.42.1",
"@typescript-eslint/type-utils": "5.42.1",
"@typescript-eslint/utils": "5.42.1",
"@eslint-community/regexpp": "^4.5.1",
"@typescript-eslint/scope-manager": "6.10.0",
"@typescript-eslint/type-utils": "6.10.0",
"@typescript-eslint/utils": "6.10.0",
"@typescript-eslint/visitor-keys": "6.10.0",
"debug": "^4.3.4",
"ignore": "^5.2.0",
"natural-compare-lite": "^1.4.0",
"regexpp": "^3.2.0",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
"graphemer": "^1.4.0",
"ignore": "^5.2.4",
"natural-compare": "^1.4.0",
"semver": "^7.5.4",
"ts-api-utils": "^1.0.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
"@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
"eslint": "^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"typescript": {
@ -683,9 +709,9 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@ -697,41 +723,27 @@
"node": ">=10"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"dependencies": {
"tslib": "^1.8.1"
},
"engines": {
"node": ">= 6"
},
"peerDependencies": {
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
}
},
"node_modules/@typescript-eslint/parser": {
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz",
"integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz",
"integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.42.1",
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/typescript-estree": "5.42.1",
"@typescript-eslint/scope-manager": "6.10.0",
"@typescript-eslint/types": "6.10.0",
"@typescript-eslint/typescript-estree": "6.10.0",
"@typescript-eslint/visitor-keys": "6.10.0",
"debug": "^4.3.4"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
"eslint": "^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"typescript": {
@ -740,16 +752,16 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz",
"integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz",
"integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/visitor-keys": "5.42.1"
"@typescript-eslint/types": "6.10.0",
"@typescript-eslint/visitor-keys": "6.10.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
@ -757,25 +769,25 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.1.tgz",
"integrity": "sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz",
"integrity": "sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==",
"dev": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "5.42.1",
"@typescript-eslint/utils": "5.42.1",
"@typescript-eslint/typescript-estree": "6.10.0",
"@typescript-eslint/utils": "6.10.0",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
"ts-api-utils": "^1.0.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "*"
"eslint": "^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"typescript": {
@ -783,28 +795,13 @@
}
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"dependencies": {
"tslib": "^1.8.1"
},
"engines": {
"node": ">= 6"
},
"peerDependencies": {
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
}
},
"node_modules/@typescript-eslint/types": {
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz",
"integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz",
"integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
@ -812,21 +809,21 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz",
"integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz",
"integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/visitor-keys": "5.42.1",
"@typescript-eslint/types": "6.10.0",
"@typescript-eslint/visitor-keys": "6.10.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
"semver": "^7.5.4",
"ts-api-utils": "^1.0.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
@ -839,9 +836,9 @@
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@ -853,51 +850,35 @@
"node": ">=10"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"dependencies": {
"tslib": "^1.8.1"
},
"engines": {
"node": ">= 6"
},
"peerDependencies": {
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
}
},
"node_modules/@typescript-eslint/utils": {
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.1.tgz",
"integrity": "sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz",
"integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"@types/semver": "^7.3.12",
"@typescript-eslint/scope-manager": "5.42.1",
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/typescript-estree": "5.42.1",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0",
"semver": "^7.3.7"
"@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0",
"@typescript-eslint/scope-manager": "6.10.0",
"@typescript-eslint/types": "6.10.0",
"@typescript-eslint/typescript-estree": "6.10.0",
"semver": "^7.5.4"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
"eslint": "^7.0.0 || ^8.0.0"
}
},
"node_modules/@typescript-eslint/utils/node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@ -910,16 +891,16 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz",
"integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz",
"integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.42.1",
"eslint-visitor-keys": "^3.3.0"
"@typescript-eslint/types": "6.10.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
@ -1950,9 +1931,9 @@
}
},
"node_modules/eslint-config-prettier": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
"integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
"integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
"dev": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
@ -1961,28 +1942,6 @@
"eslint": ">=7.0.0"
}
},
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
"dev": true,
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^4.1.1"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/eslint-scope/node_modules/estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true,
"engines": {
"node": ">=4.0"
}
},
"node_modules/eslint-utils": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
@ -2011,12 +1970,15 @@
}
},
"node_modules/eslint-visitor-keys": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint/node_modules/ansi-styles": {
@ -2524,6 +2486,12 @@
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
"dev": true
},
"node_modules/graphemer": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
"dev": true
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -2645,9 +2613,9 @@
]
},
"node_modules/ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
"dev": true,
"engines": {
"node": ">= 4"
@ -3147,12 +3115,6 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"node_modules/natural-compare-lite": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"dev": true
},
"node_modules/node-abi": {
"version": "3.28.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.28.0.tgz",
@ -3426,15 +3388,15 @@
}
},
"node_modules/prettier": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
"integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=10.13.0"
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
@ -3962,11 +3924,17 @@
"node": ">=8.0"
}
},
"node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
"node_modules/ts-api-utils": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
"integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
"dev": true,
"engines": {
"node": ">=16.13.0"
},
"peerDependencies": {
"typescript": ">=4.2.0"
}
},
"node_modules/tsx": {
"version": "3.11.0",

View File

@ -29,7 +29,7 @@
"dist"
],
"engines": {
"vscode": "^1.69.0"
"vscode": "^1.80.0"
},
"activationEvents": [
"onStartupFinished"
@ -90,13 +90,13 @@
"@types/http-errors": "^1.8.0",
"@types/node": "^20.8.9",
"@types/vscode": "^1.83.1",
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.42.1",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"bumpp": "^8.2.1",
"eslint": "^8.27.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-prettier": "^9.0.0",
"esno": "^0.16.3",
"prettier": "^2.7.1",
"prettier": "^3.0.3",
"rimraf": "^3.0.2",
"string.prototype.matchall": "^4.0.2",
"typescript": "^5.2.2",

View File

@ -1,10 +1,6 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { VimState } from './vim_state_types'
import { ParseKeysStatus } from './parse_keys_types'
import { HelixState } from './helix_state_types';
import { ParseKeysStatus } from './parse_keys_types';
export type Action = (
vimState: VimState,
keys: string[],
editor: vscode.TextEditor,
) => ParseKeysStatus
export type Action = (vimState: HelixState, keys: string[], editor: vscode.TextEditor) => ParseKeysStatus;

View File

@ -1,23 +1,23 @@
import * as vscode from 'vscode'
import { Action } from '../action_types'
import * as vscode from 'vscode';
import { Action } from '../action_types';
import {
enterInsertMode,
enterOccurrenceMode,
enterVisualLineMode,
enterVisualMode,
setModeCursorStyle,
} from '../modes'
import { Mode } from '../modes_types'
import { parseKeysExact, parseKeysRegex } from '../parse_keys'
import * as positionUtils from '../position_utils'
import { putAfter } from '../put_utils/put_after'
import { putBefore } from '../put_utils/put_before'
import { removeTypeSubscription } from '../type_subscription'
import { VimState } from '../vim_state_types'
import { setVisualLineSelections } from '../visual_line_utils'
import { flashYankHighlight } from '../yank_highlight'
import KeyMap from './keymaps'
import { yank } from './operators'
} from '../modes';
import { Mode } from '../modes_types';
import { parseKeysExact, parseKeysRegex } from '../parse_keys';
import * as positionUtils from '../position_utils';
import { putAfter } from '../put_utils/put_after';
import { putBefore } from '../put_utils/put_before';
import { removeTypeSubscription } from '../type_subscription';
import { HelixState } from '../helix_state_types';
import { setVisualLineSelections } from '../visual_line_utils';
import { flashYankHighlight } from '../yank_highlight';
import KeyMap from './keymaps';
import { yank } from './operators';
enum Direction {
Up,
@ -26,126 +26,117 @@ enum Direction {
/* eslint @typescript-eslint/no-unused-vars: 0 */
export const actions: Action[] = [
// parseKeysExact([':'], [Mode.Normal], (vimState, editor) => {
// vscode.commands.executeCommand('workbench.action.gotoLine')
// }),
// parseKeysExact(['m', 'l'], [Mode.Normal], (vimState, editor) => {
// vscode.commands.executeCommand('bookmarks.list')
// }),
// parseKeysExact(['m', 'L'], [Mode.Normal], (vimState, editor) => {
// vscode.commands.executeCommand('bookmarks.listFromAllFiles')
// }),
// parseKeysExact(['m', 'i'], [Mode.Normal], (vimState, editor) => {
// vscode.commands.executeCommand('bookmarks.jumpToPrevious')
// }),
// parseKeysExact(['m', 'k'], [Mode.Normal], (vimState, editor) => {
// vscode.commands.executeCommand('bookmarks.jumpToNext')
// }),
// new space actions
parseKeysExact([' ', ' '], [Mode.Normal], (vimState, editor) => {
enterOccurrenceMode(vimState)
vscode.commands.executeCommand('editor.action.addSelectionToNextFindMatch')
enterOccurrenceMode(vimState);
vscode.commands.executeCommand('editor.action.addSelectionToNextFindMatch');
}),
parseKeysExact(['p'], [Mode.Occurrence], (vimState, editor) => {
vscode.commands.executeCommand('editor.action.addSelectionToPreviousFindMatch')
vscode.commands.executeCommand('editor.action.addSelectionToPreviousFindMatch');
}),
parseKeysExact(['n'], [Mode.Occurrence], (vimState, editor) => {
vscode.commands.executeCommand('editor.action.addSelectionToNextFindMatch')
vscode.commands.executeCommand('editor.action.addSelectionToNextFindMatch');
}),
parseKeysExact(['a'], [Mode.Occurrence], (vimState, editor) => {
vscode.commands.executeCommand('editor.action.selectHighlights')
vscode.commands.executeCommand('editor.action.selectHighlights');
}),
parseKeysExact([' ', 'z'], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('undo')
vscode.commands.executeCommand('undo');
}),
parseKeysExact([' ', 'r'], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('redo')
vscode.commands.executeCommand('redo');
}),
parseKeysExact([' ', 'i'], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('extension.helixKeymap.scrollUpHalfPage')
vscode.commands.executeCommand('extension.helixKeymap.scrollUpHalfPage');
}),
parseKeysExact([' ', 'k'], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('extension.helixKeymap.scrollDownHalfPage')
vscode.commands.executeCommand('extension.helixKeymap.scrollDownHalfPage');
}),
// G actions
// TODO: Goto last accessed file, Goto last modified file don't have any VSCode equivalent.
parseKeysExact(['g', '.'], [Mode.Normal], () => {
vscode.commands.executeCommand('workbench.action.navigateToLastEditLocation')
vscode.commands.executeCommand('workbench.action.navigateToLastEditLocation');
}),
parseKeysExact(['g', 'e'], [Mode.Normal], () => {
vscode.commands.executeCommand('cursorBottom')
vscode.commands.executeCommand('cursorBottom');
}),
parseKeysExact(['g', 'g'], [Mode.Normal], () => {
vscode.commands.executeCommand('cursorTop')
vscode.commands.executeCommand('cursorTop');
}),
parseKeysExact(['g', 'h'], [Mode.Normal], () => {
vscode.commands.executeCommand('cursorLineStart')
vscode.commands.executeCommand('cursorLineStart');
}),
parseKeysExact(['g', 'l'], [Mode.Normal], () => {
vscode.commands.executeCommand('cursorLineEnd')
vscode.commands.executeCommand('cursorLineEnd');
}),
parseKeysExact(['g', 's'], [Mode.Normal], () => {
vscode.commands.executeCommand('cursorHome')
vscode.commands.executeCommand('cursorHome');
}),
parseKeysExact(['g', 'd'], [Mode.Normal], () => {
vscode.commands.executeCommand('editor.action.revealDefinition')
vscode.commands.executeCommand('editor.action.revealDefinition');
}),
parseKeysExact(['g', 'y'], [Mode.Normal], () => {
vscode.commands.executeCommand('editor.action.goToTypeDefinition')
vscode.commands.executeCommand('editor.action.goToTypeDefinition');
}),
parseKeysExact(['g', 'r'], [Mode.Normal], () => {
vscode.commands.executeCommand('editor.action.goToReferences')
vscode.commands.executeCommand('editor.action.goToReferences');
}),
parseKeysExact(['g', 't'], [Mode.Normal], () => {
vscode.commands.executeCommand('cursorPageUp')
vscode.commands.executeCommand('cursorPageUp');
}),
parseKeysExact(['g', 'b'], [Mode.Normal], () => {
vscode.commands.executeCommand('cursorPageDown')
vscode.commands.executeCommand('cursorPageDown');
}),
parseKeysExact(['g', 'c'], [Mode.Normal], () => {
vscode.commands.executeCommand('cursorMove', {
to: 'viewPortCenter',
})
});
}),
parseKeysExact(['g', 'k'], [Mode.Normal], () => {
vscode.commands.executeCommand('scrollLineUp')
vscode.commands.executeCommand('scrollLineUp');
}),
parseKeysExact(['g', 'j'], [Mode.Normal], () => {
vscode.commands.executeCommand('scrollLineDown')
vscode.commands.executeCommand('scrollLineDown');
}),
parseKeysExact(['g', '.'], [Mode.Normal], () => {
vscode.commands.executeCommand('workbench.action.navigateToLastEditLocation')
vscode.commands.executeCommand('workbench.action.navigateToLastEditLocation');
}),
parseKeysExact(['g', 'a'], [Mode.Normal], () => {
vscode.commands.executeCommand('workbench.action.quickOpenNavigatePreviousInEditorPicker')
parseKeysExact(['g', 'a'], [Mode.Normal], (helixState) => {
// VS Code has no concept of "last accessed file" so instead we'll need to keep track of previous text editors
const editor = helixState.editorState.previousEditor;
if (!editor) return;
vscode.window.showTextDocument(editor.document);
}),
parseKeysExact(['g', 'm'], [Mode.Normal], (helixState) => {
// VS Code has no concept of "last accessed file" so instead we'll need to keep track of previous text editors
const document = helixState.editorState.lastModifiedDocument;
if (!document) return;
vscode.window.showTextDocument(document);
}),
// existing
@ -153,100 +144,99 @@ export const actions: Action[] = [
[KeyMap.Actions.InsertMode],
[Mode.Normal, Mode.Visual, Mode.VisualLine, Mode.Occurrence],
(vimState, editor) => {
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
enterInsertMode(vimState);
setModeCursorStyle(vimState.mode, editor);
removeTypeSubscription(vimState);
},
),
parseKeysExact([KeyMap.Actions.InsertAtLineStart], [Mode.Normal], (vimState, editor) => {
editor.selections = editor.selections.map((selection) => {
const character = editor.document.lineAt(
selection.active.line,
).firstNonWhitespaceCharacterIndex
const newPosition = selection.active.with({ character: character })
return new vscode.Selection(newPosition, newPosition)
})
const character = editor.document.lineAt(selection.active.line).firstNonWhitespaceCharacterIndex;
const newPosition = selection.active.with({ character: character });
return new vscode.Selection(newPosition, newPosition);
});
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
enterInsertMode(vimState);
setModeCursorStyle(vimState.mode, editor);
removeTypeSubscription(vimState);
}),
parseKeysExact(['a'], [Mode.Normal], (vimState, editor) => {
editor.selections = editor.selections.map((selection) => {
const newPosition = positionUtils.right(editor.document, selection.active)
return new vscode.Selection(newPosition, newPosition)
})
const newPosition = positionUtils.right(editor.document, selection.active);
return new vscode.Selection(newPosition, newPosition);
});
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
enterInsertMode(vimState);
setModeCursorStyle(vimState.mode, editor);
removeTypeSubscription(vimState);
}),
parseKeysExact([KeyMap.Actions.InsertAtLineEnd], [Mode.Normal], (vimState, editor) => {
editor.selections = editor.selections.map((selection) => {
const lineLength = editor.document.lineAt(selection.active.line).text.length
const newPosition = selection.active.with({ character: lineLength })
return new vscode.Selection(newPosition, newPosition)
})
const lineLength = editor.document.lineAt(selection.active.line).text.length;
const newPosition = selection.active.with({ character: lineLength });
return new vscode.Selection(newPosition, newPosition);
});
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
enterInsertMode(vimState);
setModeCursorStyle(vimState.mode, editor);
removeTypeSubscription(vimState);
}),
parseKeysExact(['v'], [Mode.Normal, Mode.VisualLine], (vimState, editor) => {
if (vimState.mode === Mode.Normal) {
editor.selections = editor.selections.map((selection) => {
const lineLength = editor.document.lineAt(selection.active.line).text.length
const lineLength = editor.document.lineAt(selection.active.line).text.length;
if (lineLength === 0) return selection
if (lineLength === 0) return selection;
return new vscode.Selection(
selection.active,
positionUtils.right(editor.document, selection.active),
)
})
return new vscode.Selection(selection.active, positionUtils.right(editor.document, selection.active));
});
}
enterVisualMode(vimState)
setModeCursorStyle(vimState.mode, editor)
enterVisualMode(vimState);
setModeCursorStyle(vimState.mode, editor);
}),
parseKeysExact(['x'], [Mode.Normal, Mode.Visual], (vimState, editor) => {
enterVisualLineMode(vimState)
setModeCursorStyle(vimState.mode, editor)
setVisualLineSelections(editor)
enterVisualLineMode(vimState);
setModeCursorStyle(vimState.mode, editor);
setVisualLineSelections(editor);
}),
parseKeysExact([KeyMap.Actions.NewLineBelow], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('editor.action.insertLineAfter')
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
vscode.commands.executeCommand('editor.action.insertLineAfter');
enterInsertMode(vimState);
setModeCursorStyle(vimState.mode, editor);
removeTypeSubscription(vimState);
}),
parseKeysExact([KeyMap.Actions.NewLineAbove], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('editor.action.insertLineBefore')
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
vscode.commands.executeCommand('editor.action.insertLineBefore');
enterInsertMode(vimState);
setModeCursorStyle(vimState.mode, editor);
removeTypeSubscription(vimState);
}),
parseKeysExact(['P'], [Mode.Normal, Mode.Visual, Mode.VisualLine], putAfter),
parseKeysExact(['p'], [Mode.Normal], putBefore),
parseKeysExact(['u'], [Mode.Normal, Mode.Visual, Mode.VisualLine], (vimState, editor) => {
vscode.commands.executeCommand('undo')
vscode.commands.executeCommand('undo');
}),
parseKeysExact(['d', 'd'], [Mode.Normal], (vimState, editor) => {
deleteLine(vimState, editor)
deleteLine(vimState, editor);
}),
parseKeysExact(['D'], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('deleteAllRight')
vscode.commands.executeCommand('deleteAllRight');
}),
parseKeysRegex(/(\\d+)g/, /^g$/, [Mode.Normal, Mode.Visual], (helixState, editor, match) => {
new vscode.Position(parseInt(match[1]), 0);
}),
// add 1 character swap
@ -257,10 +247,10 @@ export const actions: Action[] = [
end: s.active.with({
character: s.active.character + 1,
}),
})
builder.replace(oneChar, match[1])
})
})
});
builder.replace(oneChar, match[1]);
});
});
}),
// these allow you to the delete n lines above/below
@ -270,10 +260,10 @@ export const actions: Action[] = [
/^(d|d\d+)$/,
[Mode.Normal, Mode.Visual],
(vimState, editor, match) => {
const lineCount = parseInt(match[1])
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down
const lineCount = parseInt(match[1]);
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down;
// console.log(`delete ${lineCount} lines down`);
deleteLines(vimState, editor, lineCount, direction)
deleteLines(vimState, editor, lineCount, direction);
},
),
@ -283,14 +273,14 @@ export const actions: Action[] = [
/^(c|c\d+)$/,
[Mode.Normal, Mode.Visual],
(vimState, editor, match) => {
const lineCount = parseInt(match[1])
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down
const lineCount = parseInt(match[1]);
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down;
// console.log(`delete ${lineCount} lines down`);
deleteLines(vimState, editor, lineCount, direction)
deleteLines(vimState, editor, lineCount, direction);
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
enterInsertMode(vimState);
setModeCursorStyle(vimState.mode, editor);
removeTypeSubscription(vimState);
},
),
@ -300,10 +290,10 @@ export const actions: Action[] = [
/^(s|s\d+)$/,
[Mode.Normal, Mode.Visual],
(vimState, editor, match) => {
const lineCount = parseInt(match[1])
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down
const lineCount = parseInt(match[1]);
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down;
// console.log(`delete ${lineCount} lines up`);
editor.selections = makeMultiLineSelection(vimState, editor, lineCount, direction)
editor.selections = makeMultiLineSelection(vimState, editor, lineCount, direction);
},
),
@ -313,14 +303,14 @@ export const actions: Action[] = [
/^(y|y\d+)$/,
[Mode.Normal, Mode.Visual],
(vimState, editor, match) => {
const lineCount = parseInt(match[1])
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down
const lineCount = parseInt(match[1]);
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down;
// console.log(`delete ${lineCount} lines up`);
const selections = makeMultiLineSelection(vimState, editor, lineCount, direction)
const selections = makeMultiLineSelection(vimState, editor, lineCount, direction);
yank(vimState, editor, selections, true)
yank(vimState, editor, selections, true);
flashYankHighlight(editor, selections)
flashYankHighlight(editor, selections);
},
),
@ -330,14 +320,14 @@ export const actions: Action[] = [
/^(r|r\d+)$/,
[Mode.Normal, Mode.Visual],
(vimState, editor, match) => {
const lineCount = parseInt(match[1])
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down
const lineCount = parseInt(match[1]);
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down;
// console.log(`delete ${lineCount} lines up`);
const selections = makeMultiLineSelection(vimState, editor, lineCount, direction)
const selections = makeMultiLineSelection(vimState, editor, lineCount, direction);
yank(vimState, editor, selections, true)
yank(vimState, editor, selections, true);
deleteLines(vimState, editor, lineCount, direction)
deleteLines(vimState, editor, lineCount, direction);
},
),
@ -347,18 +337,18 @@ export const actions: Action[] = [
/^(q|q\d+)$/,
[Mode.Normal, Mode.Visual],
(vimState, editor, match) => {
const lineCount = parseInt(match[1])
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down
const lineCount = parseInt(match[1]);
const direction = match[2] == KeyMap.Motions.MoveUp ? Direction.Up : Direction.Down;
// console.log(`delete ${lineCount} lines up`);
editor.selections = makeMultiLineSelection(vimState, editor, lineCount, direction)
vscode.commands.executeCommand('editor.action.copyLinesDownAction')
editor.selections = makeMultiLineSelection(vimState, editor, lineCount, direction);
vscode.commands.executeCommand('editor.action.copyLinesDownAction');
},
),
parseKeysExact(['c', 'c'], [Mode.Normal], (vimState, editor) => {
editor.edit((editBuilder) => {
editor.selections.forEach((selection) => {
const line = editor.document.lineAt(selection.active.line)
const line = editor.document.lineAt(selection.active.line);
editBuilder.delete(
new vscode.Range(
selection.active.with({
@ -366,63 +356,63 @@ export const actions: Action[] = [
}),
selection.active.with({ character: line.text.length }),
),
)
})
})
);
});
});
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
enterInsertMode(vimState);
setModeCursorStyle(vimState.mode, editor);
removeTypeSubscription(vimState);
}),
parseKeysExact(['C'], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('deleteAllRight')
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
vscode.commands.executeCommand('deleteAllRight');
enterInsertMode(vimState);
setModeCursorStyle(vimState.mode, editor);
removeTypeSubscription(vimState);
}),
parseKeysExact(['y', 'y'], [Mode.Normal], (vimState, editor) => {
yankLine(vimState, editor)
yankLine(vimState, editor);
// Yank highlight
const highlightRanges = editor.selections.map((selection) => {
const lineLength = editor.document.lineAt(selection.active.line).text.length
const lineLength = editor.document.lineAt(selection.active.line).text.length;
return new vscode.Range(
selection.active.with({ character: 0 }),
selection.active.with({ character: lineLength }),
)
})
flashYankHighlight(editor, highlightRanges)
);
});
flashYankHighlight(editor, highlightRanges);
}),
parseKeysExact(['Y'], [Mode.Normal], (vimState, editor) => {
yankToEndOfLine(vimState, editor)
yankToEndOfLine(vimState, editor);
// Yank highlight
const highlightRanges = editor.selections.map((selection) => {
const lineLength = editor.document.lineAt(selection.active.line).text.length
return new vscode.Range(selection.active, selection.active.with({ character: lineLength }))
})
flashYankHighlight(editor, highlightRanges)
const lineLength = editor.document.lineAt(selection.active.line).text.length;
return new vscode.Range(selection.active, selection.active.with({ character: lineLength }));
});
flashYankHighlight(editor, highlightRanges);
}),
parseKeysExact(['q', 'q'], [Mode.Normal, Mode.Visual], () => {
vscode.commands.executeCommand('editor.action.copyLinesDownAction')
vscode.commands.executeCommand('editor.action.copyLinesDownAction');
}),
parseKeysExact(['Q', 'Q'], [Mode.Normal, Mode.Visual], () => {
vscode.commands.executeCommand('editor.action.copyLinesUpAction')
vscode.commands.executeCommand('editor.action.copyLinesUpAction');
}),
parseKeysExact(['r', 'r'], [Mode.Normal], (vimState, editor) => {
yankLine(vimState, editor)
deleteLine(vimState, editor)
yankLine(vimState, editor);
deleteLine(vimState, editor);
}),
parseKeysExact(['R'], [Mode.Normal], (vimState, editor) => {
yankToEndOfLine(vimState, editor)
vscode.commands.executeCommand('deleteAllRight')
yankToEndOfLine(vimState, editor);
vscode.commands.executeCommand('deleteAllRight');
}),
parseKeysExact(['s', 's'], [Mode.Normal], (vimState, editor) => {
@ -430,23 +420,20 @@ export const actions: Action[] = [
return new vscode.Selection(
selection.active.with({ character: 0 }),
positionUtils.lineEnd(editor.document, selection.active),
)
})
);
});
enterVisualLineMode(vimState)
setModeCursorStyle(vimState.mode, editor)
enterVisualLineMode(vimState);
setModeCursorStyle(vimState.mode, editor);
}),
parseKeysExact(['S'], [Mode.Normal], (vimState, editor) => {
editor.selections = editor.selections.map((selection) => {
return new vscode.Selection(
selection.active,
positionUtils.lineEnd(editor.document, selection.active),
)
})
return new vscode.Selection(selection.active, positionUtils.lineEnd(editor.document, selection.active));
});
enterVisualMode(vimState)
setModeCursorStyle(vimState.mode, editor)
enterVisualMode(vimState);
setModeCursorStyle(vimState.mode, editor);
}),
// parseKeysExact(['h'], [Mode.Normal], (vimState, editor) => {
@ -454,92 +441,92 @@ export const actions: Action[] = [
// }),
parseKeysExact(['n'], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('deleteRight')
vscode.commands.executeCommand('deleteRight');
}),
parseKeysExact(['z', KeyMap.Motions.MoveUp], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('revealLine', {
lineNumber: editor.selection.active.line,
at: 'top',
})
});
}),
parseKeysExact(['z', 'z'], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('revealLine', {
lineNumber: editor.selection.active.line,
at: 'center',
})
});
}),
parseKeysExact(['z', KeyMap.Motions.MoveDown], [Mode.Normal], (vimState, editor) => {
vscode.commands.executeCommand('revealLine', {
lineNumber: editor.selection.active.line,
at: 'bottom',
})
});
}),
parseKeysExact([';'], [Mode.Normal], (vimState, editor) => {
vimState.semicolonAction(vimState, editor)
vimState.semicolonAction(vimState, editor);
}),
parseKeysExact([','], [Mode.Normal], (vimState, editor) => {
vimState.commaAction(vimState, editor)
vimState.commaAction(vimState, editor);
}),
]
];
function makeMultiLineSelection(
vimState: VimState,
vimState: HelixState,
editor: vscode.TextEditor,
lineCount: number,
direction: Direction,
): vscode.Selection[] {
return editor.selections.map((selection) => {
if (direction == Direction.Up) {
const endLine = selection.active.line - lineCount + 1
const startPos = positionUtils.lineEnd(editor.document, selection.active)
const endPos = endLine >= 0 ? new vscode.Position(endLine, 0) : new vscode.Position(0, 0)
return new vscode.Selection(startPos, endPos)
const endLine = selection.active.line - lineCount + 1;
const startPos = positionUtils.lineEnd(editor.document, selection.active);
const endPos = endLine >= 0 ? new vscode.Position(endLine, 0) : new vscode.Position(0, 0);
return new vscode.Selection(startPos, endPos);
} else {
const endLine = selection.active.line + lineCount - 1
const startPos = new vscode.Position(selection.active.line, 0)
const endLine = selection.active.line + lineCount - 1;
const startPos = new vscode.Position(selection.active.line, 0);
const endPos =
endLine < editor.document.lineCount
? new vscode.Position(endLine, editor.document.lineAt(endLine).text.length)
: positionUtils.lastChar(editor.document)
: positionUtils.lastChar(editor.document);
return new vscode.Selection(startPos, endPos)
return new vscode.Selection(startPos, endPos);
}
})
});
}
function deleteLines(
vimState: VimState,
vimState: HelixState,
editor: vscode.TextEditor,
lineCount: number,
direction: Direction = Direction.Down,
): void {
const selections = editor.selections.map((selection) => {
if (direction == Direction.Up) {
const endLine = selection.active.line - lineCount
const endLine = selection.active.line - lineCount;
if (endLine >= 0) {
const startPos = positionUtils.lineEnd(editor.document, selection.active)
const endPos = new vscode.Position(endLine, editor.document.lineAt(endLine).text.length)
return new vscode.Selection(startPos, endPos)
const startPos = positionUtils.lineEnd(editor.document, selection.active);
const endPos = new vscode.Position(endLine, editor.document.lineAt(endLine).text.length);
return new vscode.Selection(startPos, endPos);
} else {
const startPos =
selection.active.line + 1 <= editor.document.lineCount
? new vscode.Position(selection.active.line + 1, 0)
: positionUtils.lineEnd(editor.document, selection.active)
: positionUtils.lineEnd(editor.document, selection.active);
const endPos = new vscode.Position(0, 0)
return new vscode.Selection(startPos, endPos)
const endPos = new vscode.Position(0, 0);
return new vscode.Selection(startPos, endPos);
}
} else {
const endLine = selection.active.line + lineCount
const endLine = selection.active.line + lineCount;
if (endLine <= editor.document.lineCount - 1) {
const startPos = new vscode.Position(selection.active.line, 0)
const endPos = new vscode.Position(endLine, 0)
return new vscode.Selection(startPos, endPos)
const startPos = new vscode.Position(selection.active.line, 0);
const endPos = new vscode.Position(endLine, 0);
return new vscode.Selection(startPos, endPos);
} else {
const startPos =
selection.active.line - 1 >= 0
@ -547,53 +534,45 @@ function deleteLines(
selection.active.line - 1,
editor.document.lineAt(selection.active.line - 1).text.length,
)
: new vscode.Position(selection.active.line, 0)
: new vscode.Position(selection.active.line, 0);
const endPos = positionUtils.lastChar(editor.document)
return new vscode.Selection(startPos, endPos)
const endPos = positionUtils.lastChar(editor.document);
return new vscode.Selection(startPos, endPos);
}
}
})
});
editor
.edit((builder) => {
selections.forEach((sel) => builder.replace(sel, ''))
selections.forEach((sel) => builder.replace(sel, ''));
})
.then(() => {
editor.selections = editor.selections.map((selection) => {
const character = editor.document.lineAt(
selection.active.line,
).firstNonWhitespaceCharacterIndex
const newPosition = selection.active.with({ character: character })
return new vscode.Selection(newPosition, newPosition)
})
})
const character = editor.document.lineAt(selection.active.line).firstNonWhitespaceCharacterIndex;
const newPosition = selection.active.with({ character: character });
return new vscode.Selection(newPosition, newPosition);
});
});
}
function deleteLine(
vimState: VimState,
editor: vscode.TextEditor,
direction: Direction = Direction.Down,
): void {
deleteLines(vimState, editor, 1, direction)
function deleteLine(vimState: HelixState, editor: vscode.TextEditor, direction: Direction = Direction.Down): void {
deleteLines(vimState, editor, 1, direction);
}
function yankLine(vimState: VimState, editor: vscode.TextEditor): void {
function yankLine(vimState: HelixState, editor: vscode.TextEditor): void {
vimState.registers = {
contentsList: editor.selections.map((selection) => {
return editor.document.lineAt(selection.active.line).text
return editor.document.lineAt(selection.active.line).text;
}),
linewise: true,
}
};
}
function yankToEndOfLine(vimState: VimState, editor: vscode.TextEditor): void {
function yankToEndOfLine(vimState: HelixState, editor: vscode.TextEditor): void {
vimState.registers = {
contentsList: editor.selections.map((selection) => {
return editor.document
.lineAt(selection.active.line)
.text.substring(selection.active.character)
return editor.document.lineAt(selection.active.line).text.substring(selection.active.character);
}),
linewise: false,
}
};
}

View File

@ -1,44 +1,44 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { Mode } from '../modes_types'
import { Action } from '../action_types'
import { parseKeysExact, parseKeysRegex } from '../parse_keys'
import { Mode } from '../modes_types';
import { Action } from '../action_types';
import { parseKeysExact, parseKeysRegex } from '../parse_keys';
import {
vscodeToVimVisualSelection,
vimToVscodeVisualLineSelection,
vimToVscodeVisualSelection,
vscodeToVimVisualLineSelection,
} from '../selection_utils'
import * as positionUtils from '../position_utils'
import { VimState } from '../vim_state_types'
import { wordRanges, whitespaceWordRanges } from '../word_utils'
import { searchForward, searchBackward } from '../search_utils'
import { paragraphForward, paragraphBackward } from '../paragraph_utils'
import { setVisualLineSelections } from '../visual_line_utils'
import { setVisualSelections } from '../visual_utils'
import KeyMap from './keymaps'
} from '../selection_utils';
import * as positionUtils from '../position_utils';
import { HelixState } from '../helix_state_types';
import { wordRanges, whitespaceWordRanges } from '../word_utils';
import { searchForward, searchBackward } from '../search_utils';
import { paragraphForward, paragraphBackward } from '../paragraph_utils';
import { setVisualLineSelections } from '../visual_line_utils';
import { setVisualSelections } from '../visual_utils';
import KeyMap from './keymaps';
export const motions: Action[] = [
parseKeysExact([KeyMap.Motions.MoveRight], [Mode.Normal, Mode.Visual], (vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
return positionUtils.rightNormal(document, position)
})
return positionUtils.rightNormal(document, position);
});
}),
parseKeysExact([KeyMap.Motions.MoveLeft], [Mode.Normal, Mode.Visual], (vimState, editor) => {
execMotion(vimState, editor, ({ position }) => {
return positionUtils.left(position)
})
return positionUtils.left(position);
});
}),
parseKeysExact([KeyMap.Motions.MoveUp], [Mode.Normal], (_vimState, _editor) => {
vscode.commands.executeCommand('cursorMove', {
to: 'up',
by: 'wrappedLine',
})
});
}),
parseKeysExact([KeyMap.Motions.MoveUp], [Mode.Visual], (vimState, editor) => {
const originalSelections = editor.selections
const originalSelections = editor.selections;
vscode.commands
.executeCommand('cursorMove', {
@ -47,25 +47,23 @@ export const motions: Action[] = [
select: true,
})
.then(() => {
setVisualSelections(editor, originalSelections)
})
setVisualSelections(editor, originalSelections);
});
}),
parseKeysExact([KeyMap.Motions.MoveUp], [Mode.VisualLine], (vimState, editor) => {
vscode.commands
.executeCommand('cursorMove', { to: 'up', by: 'line', select: true })
.then(() => {
setVisualLineSelections(editor)
})
vscode.commands.executeCommand('cursorMove', { to: 'up', by: 'line', select: true }).then(() => {
setVisualLineSelections(editor);
});
}),
parseKeysExact([KeyMap.Motions.MoveDown], [Mode.Normal], (_vimState, _editor) => {
vscode.commands.executeCommand('cursorMove', {
to: 'down',
by: 'wrappedLine',
})
});
}),
parseKeysExact([KeyMap.Motions.MoveDown], [Mode.Visual], (vimState, editor) => {
const originalSelections = editor.selections
const originalSelections = editor.selections;
vscode.commands
.executeCommand('cursorMove', {
@ -74,134 +72,108 @@ export const motions: Action[] = [
select: true,
})
.then(() => {
setVisualSelections(editor, originalSelections)
})
setVisualSelections(editor, originalSelections);
});
}),
parseKeysExact([KeyMap.Motions.MoveDown], [Mode.VisualLine], (vimState, editor) => {
vscode.commands
.executeCommand('cursorMove', { to: 'down', by: 'line', select: true })
.then(() => {
setVisualLineSelections(editor)
})
vscode.commands.executeCommand('cursorMove', { to: 'down', by: 'line', select: true }).then(() => {
setVisualLineSelections(editor);
});
}),
parseKeysExact(['w'], [Mode.Normal, Mode.Visual], createWordForwardHandler(wordRanges)),
parseKeysExact(['W'], [Mode.Normal, Mode.Visual], createWordForwardHandler(whitespaceWordRanges)),
parseKeysExact(['b'], [Mode.Normal, Mode.Visual], createWordBackwardHandler(wordRanges)),
parseKeysExact(
['B'],
[Mode.Normal, Mode.Visual],
createWordBackwardHandler(whitespaceWordRanges),
),
parseKeysExact(['B'], [Mode.Normal, Mode.Visual], createWordBackwardHandler(whitespaceWordRanges)),
parseKeysExact(['e'], [Mode.Normal, Mode.Visual], createWordEndHandler(wordRanges)),
parseKeysExact(['E'], [Mode.Normal, Mode.Visual], createWordEndHandler(whitespaceWordRanges)),
parseKeysRegex(/^f(..)$/, /^(f|f.)$/, [Mode.Normal, Mode.Visual], (vimState, editor, match) => {
findForward(vimState, editor, match)
findForward(vimState, editor, match);
vimState.semicolonAction = (innerVimState, innerEditor) => {
findForward(innerVimState, innerEditor, match)
}
findForward(innerVimState, innerEditor, match);
};
vimState.commaAction = (innerVimState, innerEditor) => {
findBackward(innerVimState, innerEditor, match)
}
findBackward(innerVimState, innerEditor, match);
};
}),
parseKeysRegex(/^F(..)$/, /^(F|F.)$/, [Mode.Normal, Mode.Visual], (vimState, editor, match) => {
findBackward(vimState, editor, match)
findBackward(vimState, editor, match);
vimState.semicolonAction = (innerVimState, innerEditor) => {
findBackward(innerVimState, innerEditor, match)
}
findBackward(innerVimState, innerEditor, match);
};
vimState.commaAction = (innerVimState, innerEditor) => {
findForward(innerVimState, innerEditor, match)
}
findForward(innerVimState, innerEditor, match);
};
}),
parseKeysRegex(/^t(.)$/, /^t$/, [Mode.Normal, Mode.Visual], (vimState, editor, match) => {
tillForward(vimState, editor, match)
tillForward(vimState, editor, match);
vimState.semicolonAction = (innerVimState, innerEditor) => {
tillForward(innerVimState, innerEditor, match)
}
tillForward(innerVimState, innerEditor, match);
};
vimState.commaAction = (innerVimState, innerEditor) => {
tillBackward(innerVimState, innerEditor, match)
}
tillBackward(innerVimState, innerEditor, match);
};
}),
parseKeysRegex(/^T(.)$/, /^T$/, [Mode.Normal, Mode.Visual], (vimState, editor, match) => {
tillBackward(vimState, editor, match)
tillBackward(vimState, editor, match);
vimState.semicolonAction = (innerVimState, innerEditor) => {
tillBackward(innerVimState, innerEditor, match)
}
tillBackward(innerVimState, innerEditor, match);
};
vimState.commaAction = (innerVimState, innerEditor) => {
tillForward(innerVimState, innerEditor, match)
}
}),
parseKeysExact(['g', 'g'], [Mode.Normal, Mode.Visual, Mode.VisualLine], (vimState, editor) => {
execMotion(vimState, editor, () => {
return new vscode.Position(0, 0)
})
}),
parseKeysExact(['G'], [Mode.Normal, Mode.Visual, Mode.VisualLine], (vimState, editor) => {
execMotion(vimState, editor, ({ document }) => {
return new vscode.Position(document.lineCount - 1, 0)
})
tillForward(innerVimState, innerEditor, match);
};
}),
parseKeysExact(['}'], [Mode.Normal, Mode.Visual, Mode.VisualLine], (vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
return new vscode.Position(paragraphForward(document, position.line), 0)
})
return new vscode.Position(paragraphForward(document, position.line), 0);
});
}),
parseKeysExact(['{'], [Mode.Normal, Mode.Visual, Mode.VisualLine], (vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
return new vscode.Position(paragraphBackward(document, position.line), 0)
})
return new vscode.Position(paragraphBackward(document, position.line), 0);
});
}),
parseKeysExact(
[KeyMap.Motions.MoveLineEnd],
[Mode.Normal, Mode.Visual, Mode.VisualLine],
(vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
const lineLength = document.lineAt(position.line).text.length
return position.with({ character: Math.max(lineLength - 1, 0) })
})
},
),
parseKeysExact([KeyMap.Motions.MoveLineEnd], [Mode.Normal, Mode.Visual, Mode.VisualLine], (vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
const lineLength = document.lineAt(position.line).text.length;
return position.with({ character: Math.max(lineLength - 1, 0) });
});
}),
parseKeysExact(
[KeyMap.Motions.MoveLineStart],
[Mode.Normal, Mode.Visual, Mode.VisualLine],
(vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
const line = document.lineAt(position.line)
return position.with({
character: line.firstNonWhitespaceCharacterIndex,
})
})
},
),
parseKeysExact([KeyMap.Motions.MoveLineStart], [Mode.Normal, Mode.Visual, Mode.VisualLine], (vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
const line = document.lineAt(position.line);
return position.with({
character: line.firstNonWhitespaceCharacterIndex,
});
});
}),
parseKeysExact(['H'], [Mode.Normal], (_vimState, _editor) => {
vscode.commands.executeCommand('cursorMove', {
to: 'viewPortTop',
by: 'line',
})
});
}),
parseKeysExact(['H'], [Mode.Visual], (vimState, editor) => {
const originalSelections = editor.selections
const originalSelections = editor.selections;
vscode.commands
.executeCommand('cursorMove', {
@ -210,8 +182,8 @@ export const motions: Action[] = [
select: true,
})
.then(() => {
setVisualSelections(editor, originalSelections)
})
setVisualSelections(editor, originalSelections);
});
}),
parseKeysExact(['H'], [Mode.VisualLine], (vimState, editor) => {
vscode.commands
@ -221,18 +193,18 @@ export const motions: Action[] = [
select: true,
})
.then(() => {
setVisualLineSelections(editor)
})
setVisualLineSelections(editor);
});
}),
parseKeysExact(['M'], [Mode.Normal], (_vimState, _editor) => {
vscode.commands.executeCommand('cursorMove', {
to: 'viewPortCenter',
by: 'line',
})
});
}),
parseKeysExact(['M'], [Mode.Visual], (vimState, editor) => {
const originalSelections = editor.selections
const originalSelections = editor.selections;
vscode.commands
.executeCommand('cursorMove', {
@ -241,8 +213,8 @@ export const motions: Action[] = [
select: true,
})
.then(() => {
setVisualSelections(editor, originalSelections)
})
setVisualSelections(editor, originalSelections);
});
}),
parseKeysExact(['M'], [Mode.VisualLine], (vimState, editor) => {
vscode.commands
@ -252,18 +224,18 @@ export const motions: Action[] = [
select: true,
})
.then(() => {
setVisualLineSelections(editor)
})
setVisualLineSelections(editor);
});
}),
parseKeysExact(['L'], [Mode.Normal], (_vimState, _editor) => {
vscode.commands.executeCommand('cursorMove', {
to: 'viewPortBottom',
by: 'line',
})
});
}),
parseKeysExact(['L'], [Mode.Visual], (vimState, editor) => {
const originalSelections = editor.selections
const originalSelections = editor.selections;
vscode.commands
.executeCommand('cursorMove', {
@ -272,8 +244,8 @@ export const motions: Action[] = [
select: true,
})
.then(() => {
setVisualSelections(editor, originalSelections)
})
setVisualSelections(editor, originalSelections);
});
}),
parseKeysExact(['L'], [Mode.VisualLine], (vimState, editor) => {
vscode.commands
@ -283,28 +255,28 @@ export const motions: Action[] = [
select: true,
})
.then(() => {
setVisualLineSelections(editor)
})
setVisualLineSelections(editor);
});
}),
]
];
type MotionArgs = {
document: vscode.TextDocument
position: vscode.Position
selectionIndex: number
vimState: VimState
}
document: vscode.TextDocument;
position: vscode.Position;
selectionIndex: number;
vimState: HelixState;
};
type RegexMotionArgs = {
document: vscode.TextDocument
position: vscode.Position
selectionIndex: number
vimState: VimState
match: RegExpMatchArray
}
document: vscode.TextDocument;
position: vscode.Position;
selectionIndex: number;
vimState: HelixState;
match: RegExpMatchArray;
};
function execRegexMotion(
vimState: VimState,
vimState: HelixState,
editor: vscode.TextEditor,
match: RegExpMatchArray,
regexMotion: (args: RegexMotionArgs) => vscode.Position,
@ -313,16 +285,12 @@ function execRegexMotion(
return regexMotion({
...motionArgs,
match: match,
})
})
});
});
}
function execMotion(
vimState: VimState,
editor: vscode.TextEditor,
motion: (args: MotionArgs) => vscode.Position,
) {
const document = editor.document
function execMotion(vimState: HelixState, editor: vscode.TextEditor, motion: (args: MotionArgs) => vscode.Position) {
const document = editor.document;
const newSelections = editor.selections.map((selection, i) => {
if (vimState.mode === Mode.Normal) {
@ -331,184 +299,159 @@ function execMotion(
position: selection.active,
selectionIndex: i,
vimState: vimState,
})
return new vscode.Selection(newPosition, newPosition)
});
return new vscode.Selection(newPosition, newPosition);
} else if (vimState.mode === Mode.Visual) {
const vimSelection = vscodeToVimVisualSelection(document, selection)
const vimSelection = vscodeToVimVisualSelection(document, selection);
const motionPosition = motion({
document: document,
position: vimSelection.active,
selectionIndex: i,
vimState: vimState,
})
});
return vimToVscodeVisualSelection(
document,
new vscode.Selection(vimSelection.anchor, motionPosition),
)
return vimToVscodeVisualSelection(document, new vscode.Selection(vimSelection.anchor, motionPosition));
} else if (vimState.mode === Mode.VisualLine) {
const vimSelection = vscodeToVimVisualLineSelection(document, selection)
const vimSelection = vscodeToVimVisualLineSelection(document, selection);
const motionPosition = motion({
document: document,
position: vimSelection.active,
selectionIndex: i,
vimState: vimState,
})
});
return vimToVscodeVisualLineSelection(
document,
new vscode.Selection(vimSelection.anchor, motionPosition),
)
return vimToVscodeVisualLineSelection(document, new vscode.Selection(vimSelection.anchor, motionPosition));
} else {
return selection
return selection;
}
})
});
editor.selections = newSelections
editor.selections = newSelections;
editor.revealRange(
new vscode.Range(newSelections[0].active, newSelections[0].active),
vscode.TextEditorRevealType.InCenterIfOutsideViewport,
)
);
}
function findForward(
vimState: VimState,
editor: vscode.TextEditor,
outerMatch: RegExpMatchArray,
): void {
function findForward(vimState: HelixState, editor: vscode.TextEditor, outerMatch: RegExpMatchArray): void {
execRegexMotion(vimState, editor, outerMatch, ({ document, position, match }) => {
const fromPosition = position.with({ character: position.character + 1 })
const result = searchForward(document, match[1], fromPosition)
const fromPosition = position.with({ character: position.character + 1 });
const result = searchForward(document, match[1], fromPosition);
if (result) {
return result
return result;
} else {
return position
return position;
}
})
});
}
function findBackward(
vimState: VimState,
editor: vscode.TextEditor,
outerMatch: RegExpMatchArray,
): void {
function findBackward(vimState: HelixState, editor: vscode.TextEditor, outerMatch: RegExpMatchArray): void {
execRegexMotion(vimState, editor, outerMatch, ({ document, position, match }) => {
const fromPosition = positionLeftWrap(document, position)
const result = searchBackward(document, match[1], fromPosition)
const fromPosition = positionLeftWrap(document, position);
const result = searchBackward(document, match[1], fromPosition);
if (result) {
return result
return result;
} else {
return position
return position;
}
})
});
}
function tillForward(
vimState: VimState,
editor: vscode.TextEditor,
outerMatch: RegExpMatchArray,
): void {
function tillForward(vimState: HelixState, editor: vscode.TextEditor, outerMatch: RegExpMatchArray): void {
execRegexMotion(vimState, editor, outerMatch, ({ document, position, match }) => {
const lineText = document.lineAt(position.line).text
const result = lineText.indexOf(match[1], position.character + 1)
const lineText = document.lineAt(position.line).text;
const result = lineText.indexOf(match[1], position.character + 1);
if (result >= 0) {
return position.with({ character: result })
return position.with({ character: result });
} else {
return position
return position;
}
})
});
}
function tillBackward(
vimState: VimState,
editor: vscode.TextEditor,
outerMatch: RegExpMatchArray,
): void {
function tillBackward(vimState: HelixState, editor: vscode.TextEditor, outerMatch: RegExpMatchArray): void {
execRegexMotion(vimState, editor, outerMatch, ({ document, position, match }) => {
const lineText = document.lineAt(position.line).text
const result = lineText.lastIndexOf(match[1], position.character - 1)
const lineText = document.lineAt(position.line).text;
const result = lineText.lastIndexOf(match[1], position.character - 1);
if (result >= 0) {
return position.with({ character: result })
return position.with({ character: result });
} else {
return position
return position;
}
})
});
}
function positionLeftWrap(
document: vscode.TextDocument,
position: vscode.Position,
): vscode.Position {
function positionLeftWrap(document: vscode.TextDocument, position: vscode.Position): vscode.Position {
if (position.character === 0) {
if (position.line === 0) {
return position
return position;
} else {
const lineLength = document.lineAt(position.line - 1).text.length
return new vscode.Position(position.line - 1, lineLength)
const lineLength = document.lineAt(position.line - 1).text.length;
return new vscode.Position(position.line - 1, lineLength);
}
} else {
return position.with({ character: position.character - 1 })
return position.with({ character: position.character - 1 });
}
}
function createWordForwardHandler(
wordRangesFunction: (text: string) => { start: number; end: number }[],
): (vimState: VimState, editor: vscode.TextEditor) => void {
): (vimState: HelixState, editor: vscode.TextEditor) => void {
return (vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
const lineText = document.lineAt(position.line).text
const ranges = wordRangesFunction(lineText)
const lineText = document.lineAt(position.line).text;
const ranges = wordRangesFunction(lineText);
const result = ranges.find((x) => x.start > position.character)
const result = ranges.find((x) => x.start > position.character);
if (result) {
return position.with({ character: result.start })
return position.with({ character: result.start });
} else {
return position
return position;
}
})
}
});
};
}
function createWordBackwardHandler(
wordRangesFunction: (text: string) => { start: number; end: number }[],
): (vimState: VimState, editor: vscode.TextEditor) => void {
): (vimState: HelixState, editor: vscode.TextEditor) => void {
return (vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
const lineText = document.lineAt(position.line).text
const ranges = wordRangesFunction(lineText)
const lineText = document.lineAt(position.line).text;
const ranges = wordRangesFunction(lineText);
const result = ranges.reverse().find((x) => x.start < position.character)
const result = ranges.reverse().find((x) => x.start < position.character);
if (result) {
return position.with({ character: result.start })
return position.with({ character: result.start });
} else {
return position
return position;
}
})
}
});
};
}
function createWordEndHandler(
wordRangesFunction: (text: string) => { start: number; end: number }[],
): (vimState: VimState, editor: vscode.TextEditor) => void {
): (vimState: HelixState, editor: vscode.TextEditor) => void {
return (vimState, editor) => {
execMotion(vimState, editor, ({ document, position }) => {
const lineText = document.lineAt(position.line).text
const ranges = wordRangesFunction(lineText)
const lineText = document.lineAt(position.line).text;
const ranges = wordRangesFunction(lineText);
const result = ranges.find((x) => x.end > position.character)
const result = ranges.find((x) => x.end > position.character);
if (result) {
return position.with({ character: result.end })
return position.with({ character: result.end });
} else {
return position
return position;
}
})
}
});
};
}

View File

@ -1,27 +1,17 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { createOperatorRangeExactKeys, createOperatorRangeRegex } from '../parse_keys'
import { OperatorRange } from '../parse_keys_types'
import {
searchForward,
searchBackward,
searchBackwardBracket,
searchForwardBracket,
} from '../search_utils'
import * as positionUtils from '../position_utils'
import { wordRanges, whitespaceWordRanges } from '../word_utils'
import {
paragraphForward,
paragraphBackward,
paragraphRangeOuter,
paragraphRangeInner,
} from '../paragraph_utils'
import { VimState } from '../vim_state_types'
import { quoteRanges, findQuoteRange } from '../quote_utils'
import { indentLevelRange } from '../indent_utils'
import { blockRange } from '../block_utils'
import { getTags } from '../tag_utils'
import { arrayFindLast } from '../array_utils'
import { createOperatorRangeExactKeys, createOperatorRangeRegex } from '../parse_keys';
import { OperatorRange } from '../parse_keys_types';
import { searchForward, searchBackward, searchBackwardBracket, searchForwardBracket } from '../search_utils';
import * as positionUtils from '../position_utils';
import { wordRanges, whitespaceWordRanges } from '../word_utils';
import { paragraphForward, paragraphBackward, paragraphRangeOuter, paragraphRangeInner } from '../paragraph_utils';
import { HelixState } from '../helix_state_types';
import { quoteRanges, findQuoteRange } from '../quote_utils';
import { indentLevelRange } from '../indent_utils';
import { blockRange } from '../block_utils';
import { getTags } from '../tag_utils';
import { arrayFindLast } from '../array_utils';
// import KeyMap from "./keymap";
export const operatorRanges: OperatorRange[] = [
@ -106,63 +96,60 @@ export const operatorRanges: OperatorRange[] = [
createOperatorRangeExactKeys(['a', 'W'], false, createOuterWordHandler(whitespaceWordRanges)),
createOperatorRangeRegex(/^f(..)$/, /^(f|f.)$/, false, (vimState, document, position, match) => {
const fromPosition = position.with({ character: position.character + 1 })
const result = searchForward(document, match[1], fromPosition)
const fromPosition = position.with({ character: position.character + 1 });
const result = searchForward(document, match[1], fromPosition);
if (result) {
return new vscode.Range(position, result)
return new vscode.Range(position, result);
} else {
return undefined
return undefined;
}
}),
createOperatorRangeRegex(/^F(..)$/, /^(F|F.)$/, false, (vimState, document, position, match) => {
const fromPosition = position.with({ character: position.character - 1 })
const result = searchBackward(document, match[1], fromPosition)
const fromPosition = position.with({ character: position.character - 1 });
const result = searchBackward(document, match[1], fromPosition);
if (result) {
return new vscode.Range(position, result)
return new vscode.Range(position, result);
} else {
return undefined
return undefined;
}
}),
createOperatorRangeRegex(/^t(.)$/, /^t$/, false, (vimState, document, position, match) => {
const lineText = document.lineAt(position.line).text
const result = lineText.indexOf(match[1], position.character + 1)
const lineText = document.lineAt(position.line).text;
const result = lineText.indexOf(match[1], position.character + 1);
if (result >= 0) {
return new vscode.Range(position, position.with({ character: result }))
return new vscode.Range(position, position.with({ character: result }));
} else {
return undefined
return undefined;
}
}),
createOperatorRangeRegex(/^T(.)$/, /^T$/, false, (vimState, document, position, match) => {
const lineText = document.lineAt(position.line).text
const result = lineText.lastIndexOf(match[1], position.character - 1)
const lineText = document.lineAt(position.line).text;
const result = lineText.lastIndexOf(match[1], position.character - 1);
if (result >= 0) {
const newPosition = positionUtils.right(document, position.with({ character: result }))
return new vscode.Range(newPosition, position)
const newPosition = positionUtils.right(document, position.with({ character: result }));
return new vscode.Range(newPosition, position);
} else {
return undefined
return undefined;
}
}),
createOperatorRangeExactKeys(['g', 'g'], true, (vimState, document, position) => {
const lineLength = document.lineAt(position.line).text.length
const lineLength = document.lineAt(position.line).text.length;
return new vscode.Range(new vscode.Position(0, 0), position.with({ character: lineLength }))
return new vscode.Range(new vscode.Position(0, 0), position.with({ character: lineLength }));
}),
createOperatorRangeExactKeys(['G'], true, (vimState, document, position) => {
const lineLength = document.lineAt(document.lineCount - 1).text.length
const lineLength = document.lineAt(document.lineCount - 1).text.length;
return new vscode.Range(
position.with({ character: 0 }),
new vscode.Position(document.lineCount - 1, lineLength),
)
return new vscode.Range(position.with({ character: 0 }), new vscode.Position(document.lineCount - 1, lineLength));
}),
// TODO: return undefined?
@ -170,7 +157,7 @@ export const operatorRanges: OperatorRange[] = [
return new vscode.Range(
position.with({ character: 0 }),
new vscode.Position(paragraphForward(document, position.line), 0),
)
);
}),
// TODO: return undefined?
@ -178,32 +165,32 @@ export const operatorRanges: OperatorRange[] = [
return new vscode.Range(
new vscode.Position(paragraphBackward(document, position.line), 0),
position.with({ character: 0 }),
)
);
}),
createOperatorRangeExactKeys(['i', 'p'], true, (vimState, document, position) => {
const result = paragraphRangeInner(document, position.line)
const result = paragraphRangeInner(document, position.line);
if (result) {
return new vscode.Range(
new vscode.Position(result.start, 0),
new vscode.Position(result.end, document.lineAt(result.end).text.length),
)
);
} else {
return undefined
return undefined;
}
}),
createOperatorRangeExactKeys(['a', 'p'], true, (vimState, document, position) => {
const result = paragraphRangeOuter(document, position.line)
const result = paragraphRangeOuter(document, position.line);
if (result) {
return new vscode.Range(
new vscode.Position(result.start, 0),
new vscode.Position(result.end, document.lineAt(result.end).text.length),
)
);
} else {
return undefined
return undefined;
}
}),
@ -229,18 +216,16 @@ export const operatorRanges: OperatorRange[] = [
createOperatorRangeExactKeys(['a', '<'], false, createOuterBracketHandler('<', '>')),
createOperatorRangeExactKeys(['i', 't'], false, (vimState, document, position) => {
const tags = getTags(document)
const tags = getTags(document);
const closestTag = arrayFindLast(tags, (tag) => {
if (tag.closing) {
return (
position.isAfterOrEqual(tag.opening.start) && position.isBeforeOrEqual(tag.closing.end)
)
return position.isAfterOrEqual(tag.opening.start) && position.isBeforeOrEqual(tag.closing.end);
} else {
// Self-closing tags have no inside
return false
return false;
}
})
});
if (closestTag) {
if (closestTag.closing) {
@ -249,27 +234,27 @@ export const operatorRanges: OperatorRange[] = [
character: closestTag.opening.end.character + 1,
}),
closestTag.closing.start,
)
);
} else {
throw new Error('We should have already filtered out self-closing tags above')
throw new Error('We should have already filtered out self-closing tags above');
}
} else {
return undefined
return undefined;
}
}),
createOperatorRangeExactKeys(['a', 't'], false, (vimState, document, position) => {
const tags = getTags(document)
const tags = getTags(document);
const closestTag = arrayFindLast(tags, (tag) => {
const afterStart = position.isAfterOrEqual(tag.opening.start)
const afterStart = position.isAfterOrEqual(tag.opening.start);
if (tag.closing) {
return afterStart && position.isBeforeOrEqual(tag.closing.end)
return afterStart && position.isBeforeOrEqual(tag.closing.end);
} else {
return afterStart && position.isBeforeOrEqual(tag.opening.end)
return afterStart && position.isBeforeOrEqual(tag.opening.end);
}
})
});
if (closestTag) {
if (closestTag.closing) {
@ -278,47 +263,43 @@ export const operatorRanges: OperatorRange[] = [
closestTag.closing.end.with({
character: closestTag.closing.end.character + 1,
}),
)
);
} else {
return new vscode.Range(
closestTag.opening.start,
closestTag.opening.end.with({
character: closestTag.opening.end.character + 1,
}),
)
);
}
} else {
return undefined
return undefined;
}
}),
// TODO: return undefined?
createOperatorRangeExactKeys(['i', 'i'], true, (vimState, document, position) => {
const simpleRange = indentLevelRange(document, position.line)
const simpleRange = indentLevelRange(document, position.line);
return new vscode.Range(
new vscode.Position(simpleRange.start, 0),
new vscode.Position(simpleRange.end, document.lineAt(simpleRange.end).text.length),
)
);
}),
createOperatorRangeExactKeys(['a', 'b'], true, (vimState, document, position) => {
const range = blockRange(document, position)
const range = blockRange(document, position);
return range
return range;
}),
]
];
function createInnerBracketHandler(
openingChar: string,
closingChar: string,
): (
vimState: VimState,
document: vscode.TextDocument,
position: vscode.Position,
) => vscode.Range | undefined {
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
return (vimState, document, position) => {
const bracketRange = getBracketRange(document, position, openingChar, closingChar)
const bracketRange = getBracketRange(document, position, openingChar, closingChar);
if (bracketRange) {
return new vscode.Range(
@ -326,33 +307,26 @@ function createInnerBracketHandler(
character: bracketRange.start.character + 1,
}),
bracketRange.end,
)
);
} else {
return undefined
return undefined;
}
}
};
}
function createOuterBracketHandler(
openingChar: string,
closingChar: string,
): (
vimState: VimState,
document: vscode.TextDocument,
position: vscode.Position,
) => vscode.Range | undefined {
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
return (vimState, document, position) => {
const bracketRange = getBracketRange(document, position, openingChar, closingChar)
const bracketRange = getBracketRange(document, position, openingChar, closingChar);
if (bracketRange) {
return new vscode.Range(
bracketRange.start,
bracketRange.end.with({ character: bracketRange.end.character + 1 }),
)
return new vscode.Range(bracketRange.start, bracketRange.end.with({ character: bracketRange.end.character + 1 }));
} else {
return undefined
return undefined;
}
}
};
}
function getBracketRange(
@ -361,205 +335,162 @@ function getBracketRange(
openingChar: string,
closingChar: string,
): vscode.Range | undefined {
const lineText = document.lineAt(position.line).text
const currentChar = lineText[position.character]
const lineText = document.lineAt(position.line).text;
const currentChar = lineText[position.character];
let start
let end
let start;
let end;
if (currentChar === openingChar) {
start = position
end = searchForwardBracket(
document,
openingChar,
closingChar,
positionUtils.rightWrap(document, position),
)
start = position;
end = searchForwardBracket(document, openingChar, closingChar, positionUtils.rightWrap(document, position));
} else if (currentChar === closingChar) {
start = searchBackwardBracket(
document,
openingChar,
closingChar,
positionUtils.leftWrap(document, position),
)
end = position
start = searchBackwardBracket(document, openingChar, closingChar, positionUtils.leftWrap(document, position));
end = position;
} else {
start = searchBackwardBracket(document, openingChar, closingChar, position)
end = searchForwardBracket(document, openingChar, closingChar, position)
start = searchBackwardBracket(document, openingChar, closingChar, position);
end = searchForwardBracket(document, openingChar, closingChar, position);
}
if (start && end) {
return new vscode.Range(start, end)
return new vscode.Range(start, end);
} else {
return undefined
return undefined;
}
}
function createInnerQuoteHandler(
quoteChar: string,
): (
vimState: VimState,
document: vscode.TextDocument,
position: vscode.Position,
) => vscode.Range | undefined {
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
return (vimState, document, position) => {
const lineText = document.lineAt(position.line).text
const ranges = quoteRanges(quoteChar, lineText)
const result = findQuoteRange(ranges, position)
const lineText = document.lineAt(position.line).text;
const ranges = quoteRanges(quoteChar, lineText);
const result = findQuoteRange(ranges, position);
if (result) {
return new vscode.Range(
position.with({ character: result.start + 1 }),
position.with({ character: result.end }),
)
return new vscode.Range(position.with({ character: result.start + 1 }), position.with({ character: result.end }));
} else {
return undefined
return undefined;
}
}
};
}
function createOuterQuoteHandler(
quoteChar: string,
): (
vimState: VimState,
document: vscode.TextDocument,
position: vscode.Position,
) => vscode.Range | undefined {
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
return (vimState, document, position) => {
const lineText = document.lineAt(position.line).text
const ranges = quoteRanges(quoteChar, lineText)
const result = findQuoteRange(ranges, position)
const lineText = document.lineAt(position.line).text;
const ranges = quoteRanges(quoteChar, lineText);
const result = findQuoteRange(ranges, position);
if (result) {
return new vscode.Range(
position.with({ character: result.start }),
position.with({ character: result.end + 1 }),
)
return new vscode.Range(position.with({ character: result.start }), position.with({ character: result.end + 1 }));
} else {
return undefined
return undefined;
}
}
};
}
function createWordForwardHandler(
wordRangesFunction: (text: string) => { start: number; end: number }[],
): (vimState: VimState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range {
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range {
return (vimState, document, position) => {
const lineText = document.lineAt(position.line).text
const ranges = wordRangesFunction(lineText)
const lineText = document.lineAt(position.line).text;
const ranges = wordRangesFunction(lineText);
const result = ranges.find((x) => x.start > position.character)
const result = ranges.find((x) => x.start > position.character);
if (result) {
return new vscode.Range(position, position.with({ character: result.start }))
return new vscode.Range(position, position.with({ character: result.start }));
} else {
return new vscode.Range(position, position.with({ character: lineText.length }))
return new vscode.Range(position, position.with({ character: lineText.length }));
}
}
};
}
function createWordBackwardHandler(
wordRangesFunction: (text: string) => { start: number; end: number }[],
): (
vimState: VimState,
document: vscode.TextDocument,
position: vscode.Position,
) => vscode.Range | undefined {
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
return (vimState, document, position) => {
const lineText = document.lineAt(position.line).text
const ranges = wordRangesFunction(lineText)
const lineText = document.lineAt(position.line).text;
const ranges = wordRangesFunction(lineText);
const result = ranges.reverse().find((x) => x.start < position.character)
const result = ranges.reverse().find((x) => x.start < position.character);
if (result) {
return new vscode.Range(position.with({ character: result.start }), position)
return new vscode.Range(position.with({ character: result.start }), position);
} else {
return undefined
return undefined;
}
}
};
}
function createWordEndHandler(
wordRangesFunction: (text: string) => { start: number; end: number }[],
): (
vimState: VimState,
document: vscode.TextDocument,
position: vscode.Position,
) => vscode.Range | undefined {
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
return (vimState, document, position) => {
const lineText = document.lineAt(position.line).text
const ranges = wordRangesFunction(lineText)
const lineText = document.lineAt(position.line).text;
const ranges = wordRangesFunction(lineText);
const result = ranges.find((x) => x.end > position.character)
const result = ranges.find((x) => x.end > position.character);
if (result) {
return new vscode.Range(
position,
positionUtils.right(document, position.with({ character: result.end })),
)
return new vscode.Range(position, positionUtils.right(document, position.with({ character: result.end })));
} else {
return undefined
return undefined;
}
}
};
}
function createInnerWordHandler(
wordRangesFunction: (text: string) => { start: number; end: number }[],
): (
vimState: VimState,
document: vscode.TextDocument,
position: vscode.Position,
) => vscode.Range | undefined {
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
return (vimState, document, position) => {
const lineText = document.lineAt(position.line).text
const ranges = wordRangesFunction(lineText)
const lineText = document.lineAt(position.line).text;
const ranges = wordRangesFunction(lineText);
const result = ranges.find((x) => x.start <= position.character && position.character <= x.end)
const result = ranges.find((x) => x.start <= position.character && position.character <= x.end);
if (result) {
return new vscode.Range(
position.with({ character: result.start }),
positionUtils.right(document, position.with({ character: result.end })),
)
);
} else {
return undefined
return undefined;
}
}
};
}
function createOuterWordHandler(
wordRangesFunction: (text: string) => { start: number; end: number }[],
): (
vimState: VimState,
document: vscode.TextDocument,
position: vscode.Position,
) => vscode.Range | undefined {
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
return (vimState, document, position) => {
const lineText = document.lineAt(position.line).text
const ranges = wordRangesFunction(lineText)
const lineText = document.lineAt(position.line).text;
const ranges = wordRangesFunction(lineText);
for (let i = 0; i < ranges.length; ++i) {
const range = ranges[i]
const range = ranges[i];
if (range.start <= position.character && position.character <= range.end) {
if (i < ranges.length - 1) {
return new vscode.Range(
position.with({ character: range.start }),
position.with({ character: ranges[i + 1].start }),
)
);
} else if (i > 0) {
return new vscode.Range(
positionUtils.right(document, position.with({ character: ranges[i - 1].end })),
positionUtils.right(document, position.with({ character: range.end })),
)
);
} else {
return new vscode.Range(
position.with({ character: range.start }),
positionUtils.right(document, position.with({ character: range.end })),
)
);
}
}
}
return undefined
}
return undefined;
};
}

View File

@ -1,202 +1,187 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { Action } from '../action_types'
import { operatorRanges } from './operator_ranges'
import { parseKeysOperator } from '../parse_keys'
import {
enterInsertMode,
enterNormalMode,
setModeCursorStyle,
enterVisualLineMode,
enterVisualMode,
} from '../modes'
import { removeTypeSubscription } from '../type_subscription'
import { VimState } from '../vim_state_types'
import { Mode } from '../modes_types'
import { flashYankHighlight } from '../yank_highlight'
import { Action } from '../action_types';
import { HelixState } from '../helix_state_types';
import { enterVisualLineMode, enterVisualMode, setModeCursorStyle } from '../modes';
import { Mode } from '../modes_types';
import { parseKeysOperator } from '../parse_keys';
import { operatorRanges } from './operator_ranges';
export const operators: Action[] = [
parseKeysOperator(['d'], operatorRanges, (vimState, editor, ranges, linewise) => {
if (ranges.every((x) => x === undefined)) return
// parseKeysOperator(['d'], operatorRanges, (vimState, editor, ranges, linewise) => {
// if (ranges.every((x) => x === undefined)) return;
cursorsToRangesStart(editor, ranges)
// cursorsToRangesStart(editor, ranges);
delete_(editor, ranges, linewise)
// delete_(editor, ranges, linewise);
if (vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) {
enterNormalMode(vimState)
setModeCursorStyle(vimState.mode, editor)
}
}),
parseKeysOperator(['c'], operatorRanges, (vimState, editor, ranges, _linewise) => {
if (ranges.every((x) => x === undefined)) return
// if (vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) {
// enterNormalMode(vimState);
// setModeCursorStyle(vimState.mode, editor);
// }
// }),
// parseKeysOperator(['c'], operatorRanges, (vimState, editor, ranges, _linewise) => {
// if (ranges.every((x) => x === undefined)) return;
cursorsToRangesStart(editor, ranges)
// cursorsToRangesStart(editor, ranges);
editor.edit((editBuilder) => {
ranges.forEach((range) => {
if (!range) return
editBuilder.delete(range)
})
})
// editor.edit((editBuilder) => {
// ranges.forEach((range) => {
// if (!range) return;
// editBuilder.delete(range);
// });
// });
enterInsertMode(vimState)
setModeCursorStyle(vimState.mode, editor)
removeTypeSubscription(vimState)
}),
parseKeysOperator(['y'], operatorRanges, (vimState, editor, ranges, linewise) => {
if (ranges.every((x) => x === undefined)) return
// enterInsertMode(vimState);
// setModeCursorStyle(vimState.mode, editor);
// removeTypeSubscription(vimState);
// }),
// parseKeysOperator(['y'], operatorRanges, (vimState, editor, ranges, linewise) => {
// if (ranges.every((x) => x === undefined)) return;
yank(vimState, editor, ranges, linewise)
// yank(vimState, editor, ranges, linewise);
if (vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) {
// Move cursor to start of yanked text
editor.selections = editor.selections.map((selection) => {
return new vscode.Selection(selection.start, selection.start)
})
// if (vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) {
// // Move cursor to start of yanked text
// editor.selections = editor.selections.map((selection) => {
// return new vscode.Selection(selection.start, selection.start);
// });
enterNormalMode(vimState)
setModeCursorStyle(vimState.mode, editor)
} else {
// Yank highlight
const highlightRanges: vscode.Range[] = []
ranges.forEach((range) => {
if (range) {
highlightRanges.push(new vscode.Range(range.start, range.end))
}
})
flashYankHighlight(editor, highlightRanges)
}
}),
parseKeysOperator(['r'], operatorRanges, (vimState, editor, ranges, linewise) => {
if (ranges.every((x) => x === undefined)) return
// enterNormalMode(vimState);
// setModeCursorStyle(vimState.mode, editor);
// } else {
// // Yank highlight
// const highlightRanges: vscode.Range[] = [];
// ranges.forEach((range) => {
// if (range) {
// highlightRanges.push(new vscode.Range(range.start, range.end));
// }
// });
// flashYankHighlight(editor, highlightRanges);
// }
// }),
// parseKeysOperator(['r'], operatorRanges, (vimState, editor, ranges, linewise) => {
// if (ranges.every((x) => x === undefined)) return;
cursorsToRangesStart(editor, ranges)
// cursorsToRangesStart(editor, ranges);
yank(vimState, editor, ranges, linewise)
delete_(editor, ranges, linewise)
// yank(vimState, editor, ranges, linewise);
// delete_(editor, ranges, linewise);
if (vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) {
enterNormalMode(vimState)
setModeCursorStyle(vimState.mode, editor)
}
}),
parseKeysOperator(['s'], operatorRanges, (vimState, editor, ranges, linewise) => {
if (
ranges.every((x) => x === undefined) ||
vimState.mode === Mode.Visual ||
vimState.mode === Mode.VisualLine
) {
return
// if (vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) {
// enterNormalMode(vimState);
// setModeCursorStyle(vimState.mode, editor);
// }
// }),
// Match Mode
parseKeysOperator(['m'], operatorRanges, (vimState, editor, ranges, linewise) => {
if (ranges.every((x) => x === undefined) || vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) {
return;
}
editor.selections = ranges.map((range, i) => {
if (range) {
const start = range.start
const end = range.end
return new vscode.Selection(start, end)
const start = range.start;
const end = range.end;
return new vscode.Selection(start, end);
} else {
return editor.selections[i]
return editor.selections[i];
}
})
});
if (linewise) {
enterVisualLineMode(vimState)
enterVisualLineMode(vimState);
} else {
enterVisualMode(vimState)
enterVisualMode(vimState);
}
setModeCursorStyle(vimState.mode, editor)
setModeCursorStyle(vimState.mode, editor);
}),
parseKeysOperator(['q'], operatorRanges, (vimState, editor, ranges, _linewise) => {
if (
ranges.every((x) => x === undefined) ||
vimState.mode === Mode.Visual ||
vimState.mode === Mode.VisualLine
) {
return
if (ranges.every((x) => x === undefined) || vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) {
return;
}
editor.selections = ranges.map((range, i) => {
if (range) {
const start = range.start
const end = range.end
return new vscode.Selection(start, end)
const start = range.start;
const end = range.end;
return new vscode.Selection(start, end);
} else {
return editor.selections[i]
return editor.selections[i];
}
})
});
vscode.commands.executeCommand('editor.action.copyLinesDownAction')
vscode.commands.executeCommand('editor.action.copyLinesDownAction');
}),
]
];
function cursorsToRangesStart(editor: vscode.TextEditor, ranges: (vscode.Range | undefined)[]) {
function cursorsToRangesStart(
editor: vscode.TextEditor,
ranges: readonly (vscode.Range | vscode.Selection[] | undefined)[],
) {
editor.selections = editor.selections.map((selection, i) => {
const range = ranges[i]
const range = ranges[i];
if (range) {
const newPosition = range.start
return new vscode.Selection(newPosition, newPosition)
const newPosition = range.start;
return new vscode.Selection(newPosition, newPosition);
} else {
return selection
return selection;
}
})
});
}
function delete_(
editor: vscode.TextEditor,
ranges: (vscode.Range | undefined)[],
ranges: (vscode.Range | vscode.Selection[] | undefined)[],
linewise: boolean,
) {
editor
.edit((editBuilder) => {
ranges.forEach((range) => {
if (!range) return
if (!range) return;
let deleteRange = range
let deleteRange = range;
if (linewise) {
const start = range.start
const end = range.end
const start = range.start;
const end = range.end;
if (end.line === editor.document.lineCount - 1) {
if (start.line === 0) {
deleteRange = new vscode.Range(start.with({ character: 0 }), end)
deleteRange = new vscode.Range(start.with({ character: 0 }), end);
} else {
deleteRange = new vscode.Range(
new vscode.Position(
start.line - 1,
editor.document.lineAt(start.line - 1).text.length,
),
new vscode.Position(start.line - 1, editor.document.lineAt(start.line - 1).text.length),
end,
)
);
}
} else {
deleteRange = new vscode.Range(range.start, new vscode.Position(end.line + 1, 0))
deleteRange = new vscode.Range(range.start, new vscode.Position(end.line + 1, 0));
}
}
editBuilder.delete(deleteRange)
})
editBuilder.delete(deleteRange);
});
})
.then(() => {
// For linewise deletions, make sure cursor is at beginning of line
editor.selections = editor.selections.map((selection, i) => {
const range = ranges[i]
const range = ranges[i];
if (range && linewise) {
const newPosition = selection.start.with({ character: 0 })
return new vscode.Selection(newPosition, newPosition)
const newPosition = selection.start.with({ character: 0 });
return new vscode.Selection(newPosition, newPosition);
} else {
return selection
return selection;
}
})
})
});
});
}
export function yank(
vimState: VimState,
vimState: HelixState,
editor: vscode.TextEditor,
ranges: (vscode.Range | undefined)[],
linewise: boolean,
@ -204,11 +189,11 @@ export function yank(
vimState.registers = {
contentsList: ranges.map((range, i) => {
if (range) {
return editor.document.getText(range)
return editor.document.getText(range);
} else {
return vimState.registers.contentsList[i]
return vimState.registers.contentsList[i];
}
}),
linewise: linewise,
}
};
}

View File

@ -1,53 +1,50 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { VimState } from './vim_state_types'
import { enterNormalMode, setModeCursorStyle } from './modes'
import { addTypeSubscription } from './type_subscription'
import { typeHandler } from './type_handler'
import * as positionUtils from './position_utils'
import { Mode } from './modes_types'
import { HelixState } from './helix_state_types';
import { enterNormalMode, setModeCursorStyle } from './modes';
import { addTypeSubscription } from './type_subscription';
import { typeHandler } from './type_handler';
import * as positionUtils from './position_utils';
import { Mode } from './modes_types';
export function escapeHandler(vimState: VimState): void {
const editor = vscode.window.activeTextEditor
export function escapeHandler(vimState: HelixState): void {
const editor = vscode.window.activeTextEditor;
if (!editor) return
if (!editor) return;
if (vimState.mode === Mode.Insert || vimState.mode === Mode.Occurrence) {
editor.selections = editor.selections.map((selection) => {
const newPosition = positionUtils.left(selection.active)
return new vscode.Selection(newPosition, newPosition)
})
const newPosition = positionUtils.left(selection.active);
return new vscode.Selection(newPosition, newPosition);
});
enterNormalMode(vimState)
setModeCursorStyle(vimState.mode, editor)
addTypeSubscription(vimState, typeHandler)
enterNormalMode(vimState);
setModeCursorStyle(vimState.mode, editor);
addTypeSubscription(vimState, typeHandler);
} else if (vimState.mode === Mode.Normal) {
// Clear multiple cursors
if (editor.selections.length > 1) {
editor.selections = [editor.selections[0]]
editor.selections = [editor.selections[0]];
}
} else if (vimState.mode === Mode.Visual) {
editor.selections = editor.selections.map((selection) => {
const newPosition = new vscode.Position(
selection.active.line,
Math.max(selection.active.character - 1, 0),
)
return new vscode.Selection(newPosition, newPosition)
})
const newPosition = new vscode.Position(selection.active.line, Math.max(selection.active.character - 1, 0));
return new vscode.Selection(newPosition, newPosition);
});
enterNormalMode(vimState)
setModeCursorStyle(vimState.mode, editor)
enterNormalMode(vimState);
setModeCursorStyle(vimState.mode, editor);
} else if (vimState.mode === Mode.VisualLine) {
editor.selections = editor.selections.map((selection) => {
const newPosition = selection.active.with({
character: Math.max(selection.active.character - 1, 0),
})
return new vscode.Selection(newPosition, newPosition)
})
});
return new vscode.Selection(newPosition, newPosition);
});
enterNormalMode(vimState)
setModeCursorStyle(vimState.mode, editor)
enterNormalMode(vimState);
setModeCursorStyle(vimState.mode, editor);
}
vimState.keysPressed = []
vimState.keysPressed = [];
}

41
src/eventHandlers.ts Normal file
View File

@ -0,0 +1,41 @@
import type { TextEditor, TextEditorSelectionChangeEvent, TextDocumentChangeEvent } from 'vscode';
import { TextEditorSelectionChangeKind } from 'vscode';
import { enterNormalMode, enterVisualMode, setModeCursorStyle } from './modes';
import { Mode } from './modes_types';
import { HelixState } from './helix_state_types';
/** Currently this handler is used for implementing "g", "m" (go to last modified file) */
export function onDidChangeTextDocument(HelixState: HelixState, e: TextDocumentChangeEvent) {
HelixState.editorState.lastModifiedDocument = e.document;
}
/** Currently this handler is used for implementing "g", "a" (go to last accessed file) */
export function onDidChangeActiveTextEditor(helixState: HelixState, editor: TextEditor | undefined) {
if (!editor) return;
// The user has switched editors, re-set the editor state so we can go back
helixState.editorState.previousEditor = helixState.editorState.activeEditor;
helixState.editorState.activeEditor = editor;
}
export function onSelectionChange(helixState: HelixState, e: TextEditorSelectionChangeEvent): void {
if (helixState.mode === Mode.Insert) return;
if (e.selections.every((selection) => selection.isEmpty)) {
// It would be nice if we could always go from visual to normal mode when all selections are empty
// but visual mode on an empty line will yield an empty selection and there's no good way of
// distinguishing that case from the rest. So we only do it for mouse events.
if (
(helixState.mode === Mode.Visual || helixState.mode === Mode.VisualLine) &&
e.kind === TextEditorSelectionChangeKind.Mouse
) {
enterNormalMode(helixState);
setModeCursorStyle(helixState.mode, e.textEditor);
}
} else {
if (helixState.mode === Mode.Normal) {
enterVisualMode(helixState);
setModeCursorStyle(helixState.mode, e.textEditor);
}
}
}

19
src/file_utils.ts Normal file
View File

@ -0,0 +1,19 @@
import { TextEditor, window } from 'vscode'
let currentEditor: TextEditor | undefined
let previousEditor: TextEditor | undefined
export const registerActiveTextEditorChangeListener = () => {
window.onDidChangeActiveTextEditor((textEditor) => {
previousEditor = currentEditor
currentEditor = textEditor
})
}
export const getPreviousEditor = () => {
return previousEditor
}
export const getCurrentEditor = () => {
return currentEditor
}

25
src/helix_state_types.ts Normal file
View File

@ -0,0 +1,25 @@
import { TextEditor, Range } from 'vscode';
import type { Disposable, TextDocument } from 'vscode';
import type { Mode } from './modes_types';
/** This represents the global Helix state used across the board */
export type HelixState = {
typeSubscription: Disposable | undefined;
mode: Mode;
keysPressed: string[];
registers: {
contentsList: (string | undefined)[];
linewise: boolean;
};
editorState: {
activeEditor: TextEditor | undefined;
previousEditor: TextEditor | undefined;
lastModifiedDocument: TextDocument | undefined;
};
semicolonAction: (vimState: HelixState, editor: TextEditor) => void;
commaAction: (vimState: HelixState, editor: TextEditor) => void;
lastPutRanges: {
ranges: (Range | undefined)[];
linewise: boolean;
};
};

View File

@ -1,14 +1,15 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { Mode } from './modes_types'
import * as scrollCommands from './scroll_commands'
import { enterNormalMode, enterVisualMode, setModeCursorStyle } from './modes'
import { typeHandler } from './type_handler'
import { addTypeSubscription, removeTypeSubscription } from './type_subscription'
import { VimState } from './vim_state_types'
import { escapeHandler } from './escape_handler'
import { Mode } from './modes_types';
import * as scrollCommands from './scroll_commands';
import { enterNormalMode } from './modes';
import { typeHandler } from './type_handler';
import { addTypeSubscription, removeTypeSubscription } from './type_subscription';
import { HelixState } from './helix_state_types';
import { escapeHandler } from './escape_handler';
import { onSelectionChange, onDidChangeActiveTextEditor, onDidChangeTextDocument } from './eventHandlers';
const globalVimState: VimState = {
const globalhelixState: HelixState = {
typeSubscription: undefined,
mode: Mode.Insert,
keysPressed: [],
@ -16,89 +17,39 @@ const globalVimState: VimState = {
contentsList: [],
linewise: true,
},
editorState: {
activeEditor: undefined,
previousEditor: undefined,
lastModifiedDocument: undefined,
},
semicolonAction: () => undefined,
commaAction: () => undefined,
lastPutRanges: {
ranges: [],
linewise: true,
},
}
function onSelectionChange(vimState: VimState, e: vscode.TextEditorSelectionChangeEvent): void {
if (vimState.mode === Mode.Insert) return
if (e.selections.every((selection) => selection.isEmpty)) {
// It would be nice if we could always go from visual to normal mode when all selections are empty
// but visual mode on an empty line will yield an empty selection and there's no good way of
// distinguishing that case from the rest. So we only do it for mouse events.
if (
(vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) &&
e.kind === vscode.TextEditorSelectionChangeKind.Mouse
) {
enterNormalMode(vimState)
setModeCursorStyle(vimState.mode, e.textEditor)
}
} else {
if (vimState.mode === Mode.Normal) {
enterVisualMode(vimState)
setModeCursorStyle(vimState.mode, e.textEditor)
}
}
}
function onDidChangeActiveTextEditor(vimState: VimState, editor: vscode.TextEditor | undefined) {
if (!editor) return
if (editor.selections.every((selection) => selection.isEmpty)) {
if (vimState.mode === Mode.Visual || vimState.mode === Mode.VisualLine) {
enterNormalMode(vimState)
}
} else {
if (vimState.mode === Mode.Normal) {
enterVisualMode(vimState)
}
}
setModeCursorStyle(vimState.mode, editor)
vimState.keysPressed = []
}
};
export function activate(context: vscode.ExtensionContext): void {
context.subscriptions.push(
vscode.window.onDidChangeActiveTextEditor((editor) =>
onDidChangeActiveTextEditor(globalVimState, editor),
),
vscode.window.onDidChangeTextEditorSelection((e) => onSelectionChange(globalVimState, e)),
vscode.commands.registerCommand('extension.helixKeymap.escapeKey', () =>
escapeHandler(globalVimState),
),
vscode.commands.registerCommand(
'extension.helixKeymap.scrollDownHalfPage',
scrollCommands.scrollDownHalfPage,
),
vscode.commands.registerCommand(
'extension.helixKeymap.scrollUpHalfPage',
scrollCommands.scrollUpHalfPage,
),
vscode.commands.registerCommand(
'extension.helixKeymap.scrollDownPage',
scrollCommands.scrollDownPage,
),
vscode.commands.registerCommand(
'extension.helixKeymap.scrollUpPage',
scrollCommands.scrollUpPage,
),
)
vscode.window.onDidChangeActiveTextEditor((editor) => onDidChangeActiveTextEditor(globalhelixState, editor)),
vscode.window.onDidChangeTextEditorSelection((e) => onSelectionChange(globalhelixState, e)),
vscode.workspace.onDidChangeTextDocument((e) => onDidChangeTextDocument(globalhelixState, e)),
vscode.commands.registerCommand('extension.helixKeymap.escapeKey', () => escapeHandler(globalhelixState)),
vscode.commands.registerCommand('extension.helixKeymap.scrollDownHalfPage', scrollCommands.scrollDownHalfPage),
vscode.commands.registerCommand('extension.helixKeymap.scrollUpHalfPage', scrollCommands.scrollUpHalfPage),
vscode.commands.registerCommand('extension.helixKeymap.scrollDownPage', scrollCommands.scrollDownPage),
vscode.commands.registerCommand('extension.helixKeymap.scrollUpPage', scrollCommands.scrollUpPage),
);
enterNormalMode(globalVimState)
addTypeSubscription(globalVimState, typeHandler)
enterNormalMode(globalhelixState);
addTypeSubscription(globalhelixState, typeHandler);
if (vscode.window.activeTextEditor) {
onDidChangeActiveTextEditor(globalVimState, vscode.window.activeTextEditor)
onDidChangeActiveTextEditor(globalhelixState, vscode.window.activeTextEditor);
}
}
export function deactivate(): void {
removeTypeSubscription(globalVimState)
removeTypeSubscription(globalhelixState);
}

View File

@ -1,31 +1,31 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { Mode } from './modes_types'
import { VimState } from './vim_state_types'
import { Mode } from './modes_types';
import { HelixState } from './helix_state_types';
export function enterInsertMode(vimState: VimState): void {
vimState.mode = Mode.Insert
setModeContext('extension.helixKeymap.insertMode')
export function enterInsertMode(vimState: HelixState): void {
vimState.mode = Mode.Insert;
setModeContext('extension.helixKeymap.insertMode');
}
export function enterNormalMode(vimState: VimState): void {
vimState.mode = Mode.Normal
setModeContext('extension.helixKeymap.normalMode')
export function enterNormalMode(vimState: HelixState): void {
vimState.mode = Mode.Normal;
setModeContext('extension.helixKeymap.normalMode');
}
export function enterVisualMode(vimState: VimState): void {
vimState.mode = Mode.Visual
setModeContext('extension.helixKeymap.visualMode')
export function enterVisualMode(vimState: HelixState): void {
vimState.mode = Mode.Visual;
setModeContext('extension.helixKeymap.visualMode');
}
export function enterVisualLineMode(vimState: VimState): void {
vimState.mode = Mode.VisualLine
setModeContext('extension.helixKeymap.visualLineMode')
export function enterVisualLineMode(vimState: HelixState): void {
vimState.mode = Mode.VisualLine;
setModeContext('extension.helixKeymap.visualLineMode');
}
export function enterOccurrenceMode(vimState: VimState): void {
vimState.mode = Mode.Occurrence
setModeContext('extension.helixKeymap.occurrenceMode')
export function enterOccurrenceMode(vimState: HelixState): void {
vimState.mode = Mode.Occurrence;
setModeContext('extension.helixKeymap.occurrenceMode');
}
function setModeContext(key: string) {
@ -35,19 +35,19 @@ function setModeContext(key: string) {
'extension.helixKeymap.visualMode',
'extension.helixKeymap.visualLineMode',
'extension.helixKeymap.occurrenceMode',
]
];
modeKeys.forEach((modeKey) => {
vscode.commands.executeCommand('setContext', modeKey, key === modeKey)
})
vscode.commands.executeCommand('setContext', modeKey, key === modeKey);
});
}
export function setModeCursorStyle(mode: Mode, editor: vscode.TextEditor): void {
if (mode === Mode.Insert || mode === Mode.Occurrence) {
editor.options.cursorStyle = vscode.TextEditorCursorStyle.Line
editor.options.cursorStyle = vscode.TextEditorCursorStyle.Line;
} else if (mode === Mode.Normal) {
editor.options.cursorStyle = vscode.TextEditorCursorStyle.Block
editor.options.cursorStyle = vscode.TextEditorCursorStyle.Block;
} else if (mode === Mode.Visual || mode === Mode.VisualLine) {
editor.options.cursorStyle = vscode.TextEditorCursorStyle.Block
editor.options.cursorStyle = vscode.TextEditorCursorStyle.Block;
}
}

View File

@ -1,126 +1,123 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { VimState } from './vim_state_types'
import { Mode } from './modes_types'
import { HelixState } from './helix_state_types';
import { Mode } from './modes_types';
import {
ParseKeysStatus,
OperatorRange,
ParseFailure,
ParseOperatorPartSuccess,
ParseOperatorRangeSuccess,
} from './parse_keys_types'
import { Action } from './action_types'
} from './parse_keys_types';
import { Action } from './action_types';
export function arrayStartsWith<T>(prefix: T[], xs: T[]) {
if (xs.length < prefix.length) {
return false
return false;
}
for (let i = 0; i < prefix.length; ++i) {
if (prefix[i] !== xs[i]) {
return false
return false;
}
}
return true
return true;
}
export function arrayEquals<T>(xs: T[], ys: T[]) {
if (xs.length !== ys.length) {
return false
return false;
}
for (let i = 0; i < xs.length; ++i) {
if (xs[i] !== ys[i]) {
return false
return false;
}
}
return true
return true;
}
export function parseKeysExact(
matchKeys: string[],
modes: Mode[],
action: (vimState: VimState, editor: vscode.TextEditor) => void,
action: (vimState: HelixState, editor: vscode.TextEditor) => void,
): Action {
return (vimState, keys, editor) => {
if (modes && modes.indexOf(vimState.mode) < 0) {
return ParseKeysStatus.NO
return ParseKeysStatus.NO;
}
if (arrayEquals(keys, matchKeys)) {
action(vimState, editor)
return ParseKeysStatus.YES
action(vimState, editor);
return ParseKeysStatus.YES;
} else if (arrayStartsWith(keys, matchKeys)) {
return ParseKeysStatus.MORE_INPUT
return ParseKeysStatus.MORE_INPUT;
} else {
return ParseKeysStatus.NO
return ParseKeysStatus.NO;
}
}
};
}
export function parseKeysRegex(
doesPattern: RegExp,
couldPattern: RegExp,
modes: Mode[],
action: (vimState: VimState, editor: vscode.TextEditor, match: RegExpMatchArray) => void,
action: (vimState: HelixState, editor: vscode.TextEditor, match: RegExpMatchArray) => void,
): Action {
return (vimState, keys, editor) => {
if (modes && modes.indexOf(vimState.mode) < 0) {
return ParseKeysStatus.NO
return ParseKeysStatus.NO;
}
const keysStr = keys.join('')
const doesMatch = keysStr.match(doesPattern)
const keysStr = keys.join('');
const doesMatch = keysStr.match(doesPattern);
if (doesMatch) {
action(vimState, editor, doesMatch)
return ParseKeysStatus.YES
action(vimState, editor, doesMatch);
return ParseKeysStatus.YES;
} else if (keysStr.match(couldPattern)) {
return ParseKeysStatus.MORE_INPUT
return ParseKeysStatus.MORE_INPUT;
} else {
return ParseKeysStatus.NO
return ParseKeysStatus.NO;
}
}
};
}
function parseOperatorPart(
keys: string[],
operatorKeys: string[],
): ParseFailure | ParseOperatorPartSuccess {
function parseOperatorPart(keys: string[], operatorKeys: string[]): ParseFailure | ParseOperatorPartSuccess {
if (arrayStartsWith(operatorKeys, keys)) {
return {
kind: 'success',
rest: keys.slice(operatorKeys.length),
}
};
} else if (arrayStartsWith(keys, operatorKeys)) {
return {
kind: 'failure',
status: ParseKeysStatus.MORE_INPUT,
}
};
} else {
return {
kind: 'failure',
status: ParseKeysStatus.NO,
}
};
}
}
function parseOperatorRangePart(
vimState: VimState,
vimState: HelixState,
keys: string[],
editor: vscode.TextEditor,
motions: OperatorRange[],
): ParseFailure | ParseOperatorRangeSuccess {
let could = false
let could = false;
for (const motion of motions) {
const result = motion(vimState, keys, editor)
const result = motion(vimState, keys, editor);
if (result.kind === 'success') {
return result
return result;
} else if (result.status === ParseKeysStatus.MORE_INPUT) {
could = true
could = true;
}
}
@ -128,12 +125,12 @@ function parseOperatorRangePart(
return {
kind: 'failure',
status: ParseKeysStatus.MORE_INPUT,
}
};
} else {
return {
kind: 'failure',
status: ParseKeysStatus.NO,
}
};
}
}
@ -141,76 +138,72 @@ export function parseKeysOperator(
operatorKeys: string[],
motions: OperatorRange[],
operator: (
vimState: VimState,
vimState: HelixState,
editor: vscode.TextEditor,
ranges: (vscode.Range | undefined)[],
ranges: readonly (vscode.Range | vscode.Selection[] | undefined)[],
linewise: boolean,
) => void,
): Action {
return (vimState, keys, editor) => {
const operatorResult = parseOperatorPart(keys, operatorKeys)
const operatorResult = parseOperatorPart(keys, operatorKeys);
if (operatorResult.kind === 'failure') {
return operatorResult.status
return operatorResult.status;
}
let ranges: (vscode.Range | undefined)[]
let linewise = true
let ranges: readonly (vscode.Range | vscode.Selection[] | undefined)[];
let linewise = true;
if (vimState.mode === Mode.Normal) {
if (operatorResult.rest.length === 0) {
return ParseKeysStatus.MORE_INPUT
return ParseKeysStatus.MORE_INPUT;
}
const motionResult = parseOperatorRangePart(vimState, operatorResult.rest, editor, motions)
const motionResult = parseOperatorRangePart(vimState, operatorResult.rest, editor, motions);
if (motionResult.kind === 'failure') {
return motionResult.status
return motionResult.status;
}
ranges = motionResult.ranges
linewise = motionResult.linewise
ranges = motionResult.ranges;
linewise = motionResult.linewise;
} else if (vimState.mode === Mode.VisualLine) {
ranges = editor.selections
linewise = true
ranges = editor.selections;
linewise = true;
} else {
ranges = editor.selections
linewise = false
ranges = editor.selections;
linewise = false;
}
operator(vimState, editor, ranges, linewise)
return ParseKeysStatus.YES
}
operator(vimState, editor, ranges, linewise);
return ParseKeysStatus.YES;
};
}
export function createOperatorRangeExactKeys(
matchKeys: string[],
linewise: boolean,
f: (
vimState: VimState,
document: vscode.TextDocument,
position: vscode.Position,
) => vscode.Range | undefined,
f: (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined,
): OperatorRange {
return (vimState, keys, editor) => {
if (arrayEquals(keys, matchKeys)) {
const ranges = editor.selections.map((selection) => {
return f(vimState, editor.document, selection.active)
})
return f(vimState, editor.document, selection.active);
});
return {
kind: 'success',
ranges: ranges,
linewise: linewise,
}
};
} else if (arrayStartsWith(keys, matchKeys)) {
return {
kind: 'failure',
status: ParseKeysStatus.MORE_INPUT,
}
};
} else {
return {
kind: 'failure',
status: ParseKeysStatus.NO,
}
};
}
}
};
}
export function createOperatorRangeRegex(
@ -218,35 +211,35 @@ export function createOperatorRangeRegex(
couldPattern: RegExp,
linewise: boolean,
f: (
vimState: VimState,
vimState: HelixState,
document: vscode.TextDocument,
position: vscode.Position,
match: RegExpMatchArray,
) => vscode.Range | undefined,
): OperatorRange {
return (vimState, keys, editor) => {
const keysStr = keys.join('')
const doesMatch = keysStr.match(doesPattern)
const keysStr = keys.join('');
const doesMatch = keysStr.match(doesPattern);
if (doesMatch) {
const ranges = editor.selections.map((selection) => {
return f(vimState, editor.document, selection.active, doesMatch)
})
return f(vimState, editor.document, selection.active, doesMatch);
});
return {
kind: 'success',
ranges: ranges,
linewise: linewise,
}
};
} else if (keysStr.match(couldPattern)) {
return {
kind: 'failure',
status: ParseKeysStatus.MORE_INPUT,
}
};
} else {
return {
kind: 'failure',
status: ParseKeysStatus.NO,
}
};
}
}
};
}

View File

@ -1,6 +1,6 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { VimState } from './vim_state_types'
import { HelixState } from './helix_state_types';
export enum ParseKeysStatus {
YES,
@ -9,28 +9,28 @@ export enum ParseKeysStatus {
}
export type ParseFailure = {
kind: 'failure'
status: ParseKeysStatus
}
kind: 'failure';
status: ParseKeysStatus;
};
export type ParseOperatorPartSuccess = {
kind: 'success'
rest: string[]
}
kind: 'success';
rest: string[];
};
export type ParseOperatorRangeSuccess = {
kind: 'success'
ranges: (vscode.Range | undefined)[]
linewise: boolean
}
kind: 'success';
ranges: (vscode.Range | undefined)[];
linewise: boolean;
};
export type ParseOperatorSuccess = {
kind: 'success'
motion: OperatorRange | undefined
}
kind: 'success';
motion: OperatorRange | undefined;
};
export type OperatorRange = (
vimState: VimState,
vimState: HelixState,
keys: string[],
editor: vscode.TextEditor,
) => ParseFailure | ParseOperatorRangeSuccess
) => ParseFailure | ParseOperatorRangeSuccess;

View File

@ -1,19 +1,19 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { VimState } from '../vim_state_types'
import { HelixState } from '../helix_state_types';
export function getRegisterContentsList(vimState: VimState, editor: vscode.TextEditor) {
if (vimState.registers.contentsList.length === 0) return undefined
export function getRegisterContentsList(vimState: HelixState, editor: vscode.TextEditor) {
if (vimState.registers.contentsList.length === 0) return undefined;
let registerContentsList = vimState.registers.contentsList
let registerContentsList = vimState.registers.contentsList;
// Handle putting with a different number of cursors than when you yanked
if (vimState.registers.contentsList.length !== editor.selections.length) {
const combinedContents = vimState.registers.contentsList.join('\n')
registerContentsList = editor.selections.map(() => combinedContents)
const combinedContents = vimState.registers.contentsList.join('\n');
registerContentsList = editor.selections.map(() => combinedContents);
}
return registerContentsList
return registerContentsList;
}
// Given contents and positions at the end of the contents, return the position at the beginning of the contents
@ -23,106 +23,98 @@ export function getInsertRangesFromEnd(
contentsList: (string | undefined)[],
) {
return positions.map((position, i) => {
const contents = contentsList[i]
if (!contents) return undefined
const contents = contentsList[i];
if (!contents) return undefined;
const lines = contents.split(/\r?\n/)
const lines = contents.split(/\r?\n/);
let beginningPosition
let beginningPosition;
if (lines.length > 1) {
const beginningLine = position.line - (lines.length - 1)
const beginningCharacter = document.lineAt(beginningLine).text.length - lines[0].length
beginningPosition = new vscode.Position(beginningLine, beginningCharacter)
const beginningLine = position.line - (lines.length - 1);
const beginningCharacter = document.lineAt(beginningLine).text.length - lines[0].length;
beginningPosition = new vscode.Position(beginningLine, beginningCharacter);
} else {
beginningPosition = position.with({
character: position.character - lines[0].length,
})
});
}
return new vscode.Range(beginningPosition, position)
})
return new vscode.Range(beginningPosition, position);
});
}
// Given positions and contents inserted at those positions, return the range that will
// select that contents
export function getInsertRangesFromBeginning(
positions: vscode.Position[],
contentsList: (string | undefined)[],
) {
export function getInsertRangesFromBeginning(positions: vscode.Position[], contentsList: (string | undefined)[]) {
return positions.map((position, i) => {
const contents = contentsList[i]
if (!contents) return undefined
const contents = contentsList[i];
if (!contents) return undefined;
const lines = contents.split(/\r?\n/)
const endLine = position.line + lines.length - 1
const endCharacter =
lines.length === 1 ? position.character + lines[0].length : lines[lines.length - 1].length
const lines = contents.split(/\r?\n/);
const endLine = position.line + lines.length - 1;
const endCharacter = lines.length === 1 ? position.character + lines[0].length : lines[lines.length - 1].length;
return new vscode.Range(position, new vscode.Position(endLine, endCharacter))
})
return new vscode.Range(position, new vscode.Position(endLine, endCharacter));
});
}
// Given positions and contents inserted at those positions, figure out how the positions will move
// when the contents is inserted. For example inserting a line above a position will increase its
// line number by one.
export function adjustInsertPositions(
positions: vscode.Position[],
contentsList: (string | undefined)[],
) {
export function adjustInsertPositions(positions: vscode.Position[], contentsList: (string | undefined)[]) {
const indexPositions = positions.map((position, i) => ({
originalIndex: i,
position: position,
}))
}));
indexPositions.sort((a, b) => {
if (a.position.isBefore(b.position)) return -1
else if (a.position.isEqual(b.position)) return 0
else return 1
})
if (a.position.isBefore(b.position)) return -1;
else if (a.position.isEqual(b.position)) return 0;
else return 1;
});
const adjustedIndexPositions = []
let lineOffset = 0
let characterOffset = 0
let lineNumber = 0
const adjustedIndexPositions = [];
let lineOffset = 0;
let characterOffset = 0;
let lineNumber = 0;
for (const indexPosition of indexPositions) {
// Adjust position
const adjustedLine = indexPosition.position.line + lineOffset
const adjustedLine = indexPosition.position.line + lineOffset;
let adjustedCharacter = indexPosition.position.character
let adjustedCharacter = indexPosition.position.character;
if (indexPosition.position.line === lineNumber) {
adjustedCharacter += characterOffset
adjustedCharacter += characterOffset;
}
adjustedIndexPositions.push({
originalIndex: indexPosition.originalIndex,
position: new vscode.Position(adjustedLine, adjustedCharacter),
})
});
// Increase offsets
const contents = contentsList[indexPosition.originalIndex]
const contents = contentsList[indexPosition.originalIndex];
if (contents !== undefined) {
const contentsLines = contents.split(/\r?\n/)
const contentsLines = contents.split(/\r?\n/);
lineOffset += contentsLines.length - 1
lineOffset += contentsLines.length - 1;
if (indexPosition.position.line === lineNumber) {
if (contentsLines.length === 1) {
characterOffset += contentsLines[0].length
characterOffset += contentsLines[0].length;
} else {
characterOffset +=
contentsLines[contentsLines.length - 1].length - indexPosition.position.character
characterOffset += contentsLines[contentsLines.length - 1].length - indexPosition.position.character;
}
} else {
characterOffset = 0
lineNumber = indexPosition.position.line
characterOffset = 0;
lineNumber = indexPosition.position.line;
}
}
}
adjustedIndexPositions.sort((a, b) => a.originalIndex - b.originalIndex)
return adjustedIndexPositions.map((indexPosition) => indexPosition.position)
adjustedIndexPositions.sort((a, b) => a.originalIndex - b.originalIndex);
return adjustedIndexPositions.map((indexPosition) => indexPosition.position);
}

View File

@ -1,132 +1,124 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import * as positionUtils from '../position_utils'
import { VimState } from '../vim_state_types'
import { Mode } from '../modes_types'
import { enterNormalMode, setModeCursorStyle } from '../modes'
import * as positionUtils from '../position_utils';
import { HelixState } from '../helix_state_types';
import { Mode } from '../modes_types';
import { enterNormalMode, setModeCursorStyle } from '../modes';
import {
getRegisterContentsList,
adjustInsertPositions,
getInsertRangesFromBeginning,
getInsertRangesFromEnd,
} from './common'
} from './common';
export function putAfter(vimState: VimState, editor: vscode.TextEditor) {
const registerContentsList = getRegisterContentsList(vimState, editor)
if (registerContentsList === undefined) return
export function putAfter(vimState: HelixState, editor: vscode.TextEditor) {
const registerContentsList = getRegisterContentsList(vimState, editor);
if (registerContentsList === undefined) return;
if (vimState.mode === Mode.Normal) {
if (vimState.registers.linewise) {
normalModeLinewise(vimState, editor, registerContentsList)
normalModeLinewise(vimState, editor, registerContentsList);
} else {
normalModeCharacterwise(vimState, editor, registerContentsList)
normalModeCharacterwise(vimState, editor, registerContentsList);
}
} else if (vimState.mode === Mode.Visual) {
visualMode(vimState, editor, registerContentsList)
visualMode(vimState, editor, registerContentsList);
} else {
visualLineMode(vimState, editor, registerContentsList)
visualLineMode(vimState, editor, registerContentsList);
}
}
function normalModeLinewise(
vimState: VimState,
vimState: HelixState,
editor: vscode.TextEditor,
registerContentsList: (string | undefined)[],
) {
const insertContentsList = registerContentsList.map((contents) => {
if (contents === undefined) return undefined
else return `\n${contents}`
})
if (contents === undefined) return undefined;
else return `\n${contents}`;
});
const insertPositions = editor.selections.map((selection) => {
const lineLength = editor.document.lineAt(selection.active.line).text.length
return new vscode.Position(selection.active.line, lineLength)
})
const lineLength = editor.document.lineAt(selection.active.line).text.length;
return new vscode.Position(selection.active.line, lineLength);
});
const adjustedInsertPositions = adjustInsertPositions(insertPositions, insertContentsList)
const rangeBeginnings = adjustedInsertPositions.map(
(position) => new vscode.Position(position.line + 1, 0),
)
const adjustedInsertPositions = adjustInsertPositions(insertPositions, insertContentsList);
const rangeBeginnings = adjustedInsertPositions.map((position) => new vscode.Position(position.line + 1, 0));
editor
.edit((editBuilder) => {
insertPositions.forEach((position, i) => {
const contents = insertContentsList[i]
if (contents === undefined) return
const contents = insertContentsList[i];
if (contents === undefined) return;
editBuilder.insert(position, contents)
})
editBuilder.insert(position, contents);
});
})
.then(() => {
editor.selections = rangeBeginnings.map(
(position) => new vscode.Selection(position, position),
)
})
editor.selections = rangeBeginnings.map((position) => new vscode.Selection(position, position));
});
vimState.lastPutRanges = {
ranges: getInsertRangesFromBeginning(rangeBeginnings, registerContentsList),
linewise: true,
}
};
}
function normalModeCharacterwise(
vimState: VimState,
vimState: HelixState,
editor: vscode.TextEditor,
registerContentsList: (string | undefined)[],
) {
const insertPositions = editor.selections.map((selection) => {
return positionUtils.right(editor.document, selection.active)
})
return positionUtils.right(editor.document, selection.active);
});
const adjustedInsertPositions = adjustInsertPositions(insertPositions, registerContentsList)
const insertRanges = getInsertRangesFromBeginning(adjustedInsertPositions, registerContentsList)
const adjustedInsertPositions = adjustInsertPositions(insertPositions, registerContentsList);
const insertRanges = getInsertRangesFromBeginning(adjustedInsertPositions, registerContentsList);
editor
.edit((editBuilder) => {
insertPositions.forEach((insertPosition, i) => {
const registerContents = registerContentsList[i]
if (registerContents === undefined) return
const registerContents = registerContentsList[i];
if (registerContents === undefined) return;
editBuilder.insert(insertPosition, registerContents)
})
editBuilder.insert(insertPosition, registerContents);
});
})
.then(() => {
editor.selections = editor.selections.map((selection, i) => {
const range = insertRanges[i]
if (range === undefined) return selection
const range = insertRanges[i];
if (range === undefined) return selection;
const position = positionUtils.left(range.end)
return new vscode.Selection(position, position)
})
})
const position = positionUtils.left(range.end);
return new vscode.Selection(position, position);
});
});
vimState.lastPutRanges = {
ranges: insertRanges,
linewise: false,
}
};
}
function visualMode(
vimState: VimState,
editor: vscode.TextEditor,
registerContentsList: (string | undefined)[],
) {
function visualMode(vimState: HelixState, editor: vscode.TextEditor, registerContentsList: (string | undefined)[]) {
const insertContentsList = vimState.registers.linewise
? registerContentsList.map((contents) => {
if (!contents) return undefined
else return '\n' + contents + '\n'
if (!contents) return undefined;
else return '\n' + contents + '\n';
})
: registerContentsList
: registerContentsList;
editor
.edit((editBuilder) => {
editor.selections.forEach((selection, i) => {
const contents = insertContentsList[i]
if (contents === undefined) return
const contents = insertContentsList[i];
if (contents === undefined) return;
editBuilder.delete(selection)
editBuilder.insert(selection.start, contents)
})
editBuilder.delete(selection);
editBuilder.insert(selection.start, contents);
});
})
.then(() => {
vimState.lastPutRanges = {
@ -136,45 +128,39 @@ function visualMode(
insertContentsList,
),
linewise: vimState.registers.linewise,
}
};
editor.selections = editor.selections.map((selection) => {
const newPosition = positionUtils.left(selection.active)
return new vscode.Selection(newPosition, newPosition)
})
})
const newPosition = positionUtils.left(selection.active);
return new vscode.Selection(newPosition, newPosition);
});
});
enterNormalMode(vimState)
setModeCursorStyle(vimState.mode, editor)
enterNormalMode(vimState);
setModeCursorStyle(vimState.mode, editor);
}
function visualLineMode(
vimState: VimState,
editor: vscode.TextEditor,
registerContentsList: (string | undefined)[],
) {
function visualLineMode(vimState: HelixState, editor: vscode.TextEditor, registerContentsList: (string | undefined)[]) {
editor
.edit((editBuilder) => {
editor.selections.forEach((selection, i) => {
const registerContents = registerContentsList[i]
if (registerContents === undefined) return
const registerContents = registerContentsList[i];
if (registerContents === undefined) return;
editBuilder.replace(selection, registerContents)
})
editBuilder.replace(selection, registerContents);
});
})
.then(() => {
vimState.lastPutRanges = {
ranges: editor.selections.map(
(selection) => new vscode.Range(selection.start, selection.end),
),
ranges: editor.selections.map((selection) => new vscode.Range(selection.start, selection.end)),
linewise: vimState.registers.linewise,
}
};
editor.selections = editor.selections.map((selection) => {
return new vscode.Selection(selection.start, selection.start)
})
return new vscode.Selection(selection.start, selection.start);
});
enterNormalMode(vimState)
setModeCursorStyle(vimState.mode, editor)
})
enterNormalMode(vimState);
setModeCursorStyle(vimState.mode, editor);
});
}

View File

@ -1,93 +1,89 @@
import * as vscode from 'vscode'
import * as positionUtils from '../position_utils'
import type { VimState } from '../vim_state_types'
import {
adjustInsertPositions,
getInsertRangesFromBeginning,
getRegisterContentsList,
} from './common'
import * as vscode from 'vscode';
import * as positionUtils from '../position_utils';
import type { HelixState } from '../helix_state_types';
import { adjustInsertPositions, getInsertRangesFromBeginning, getRegisterContentsList } from './common';
export function putBefore(vimState: VimState, editor: vscode.TextEditor) {
const registerContentsList = getRegisterContentsList(vimState, editor)
if (registerContentsList === undefined) return
export function putBefore(vimState: HelixState, editor: vscode.TextEditor) {
const registerContentsList = getRegisterContentsList(vimState, editor);
if (registerContentsList === undefined) return;
if (vimState.registers.linewise) {
normalModeLinewise(vimState, editor, registerContentsList)
normalModeLinewise(vimState, editor, registerContentsList);
} else {
normalModeCharacterwise(vimState, editor, registerContentsList)
normalModeCharacterwise(vimState, editor, registerContentsList);
}
}
function normalModeLinewise(
vimState: VimState,
vimState: HelixState,
editor: vscode.TextEditor,
registerContentsList: (string | undefined)[],
) {
const insertContentsList = registerContentsList.map((contents) => {
if (contents === undefined) return undefined
else return `${contents}\n`
})
if (contents === undefined) return undefined;
else return `${contents}\n`;
});
const insertPositions = editor.selections.map((selection) => {
return new vscode.Position(selection.active.line, 0)
})
return new vscode.Position(selection.active.line, 0);
});
const adjustedInsertPositions = adjustInsertPositions(insertPositions, insertContentsList)
const adjustedInsertPositions = adjustInsertPositions(insertPositions, insertContentsList);
editor
.edit((editBuilder) => {
insertPositions.forEach((position, i) => {
const contents = insertContentsList[i]
if (contents === undefined) return
const contents = insertContentsList[i];
if (contents === undefined) return;
editBuilder.insert(position, contents)
})
editBuilder.insert(position, contents);
});
})
.then(() => {
editor.selections = editor.selections.map((selection, i) => {
const position = adjustedInsertPositions[i]
if (position === undefined) return selection
const position = adjustedInsertPositions[i];
if (position === undefined) return selection;
return new vscode.Selection(position, position)
})
})
return new vscode.Selection(position, position);
});
});
vimState.lastPutRanges = {
ranges: getInsertRangesFromBeginning(adjustedInsertPositions, registerContentsList),
linewise: true,
}
};
}
function normalModeCharacterwise(
vimState: VimState,
vimState: HelixState,
editor: vscode.TextEditor,
registerContentsList: (string | undefined)[],
) {
const insertPositions = editor.selections.map((selection) => selection.active)
const adjustedInsertPositions = adjustInsertPositions(insertPositions, registerContentsList)
const insertRanges = getInsertRangesFromBeginning(adjustedInsertPositions, registerContentsList)
const insertPositions = editor.selections.map((selection) => selection.active);
const adjustedInsertPositions = adjustInsertPositions(insertPositions, registerContentsList);
const insertRanges = getInsertRangesFromBeginning(adjustedInsertPositions, registerContentsList);
editor
.edit((editBuilder) => {
insertPositions.forEach((insertPosition, i) => {
const registerContents = registerContentsList[i]
if (registerContents === undefined) return
const registerContents = registerContentsList[i];
if (registerContents === undefined) return;
editBuilder.insert(insertPosition, registerContents)
})
editBuilder.insert(insertPosition, registerContents);
});
})
.then(() => {
editor.selections = editor.selections.map((selection, i) => {
const range = insertRanges[i]
if (range === undefined) return selection
const range = insertRanges[i];
if (range === undefined) return selection;
const position = positionUtils.left(range.end)
return new vscode.Selection(position, position)
})
})
const position = positionUtils.left(range.end);
return new vscode.Selection(position, position);
});
});
vimState.lastPutRanges = {
ranges: insertRanges,
linewise: false,
}
};
}

View File

@ -1,33 +1,33 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { ParseKeysStatus } from './parse_keys_types'
import { actions } from './actions'
import { VimState } from './vim_state_types'
import { ParseKeysStatus } from './parse_keys_types';
import { actions } from './actions';
import { HelixState } from './helix_state_types';
export function typeHandler(vimState: VimState, char: string): void {
const editor = vscode.window.activeTextEditor
export function typeHandler(vimState: HelixState, char: string): void {
const editor = vscode.window.activeTextEditor;
if (!editor) return
if (!editor) return;
vimState.keysPressed.push(char)
vimState.keysPressed.push(char);
try {
let could = false
let could = false;
for (const action of actions) {
const result = action(vimState, vimState.keysPressed, editor)
const result = action(vimState, vimState.keysPressed, editor);
if (result === ParseKeysStatus.YES) {
vimState.keysPressed = []
break
vimState.keysPressed = [];
break;
} else if (result === ParseKeysStatus.MORE_INPUT) {
could = true
could = true;
}
}
if (!could) {
vimState.keysPressed = []
vimState.keysPressed = [];
}
} catch (error) {
console.error(error)
console.error(error);
}
}

View File

@ -1,18 +1,18 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import { VimState } from './vim_state_types'
import { HelixState } from './helix_state_types';
export function addTypeSubscription(
vimState: VimState,
typeHandler: (vimState: VimState, char: string) => void,
vimState: HelixState,
typeHandler: (vimState: HelixState, char: string) => void,
): void {
vimState.typeSubscription = vscode.commands.registerCommand('type', (e) => {
typeHandler(vimState, e.text)
})
typeHandler(vimState, e.text);
});
}
export function removeTypeSubscription(vimState: VimState): void {
export function removeTypeSubscription(vimState: HelixState): void {
if (vimState.typeSubscription) {
vimState.typeSubscription.dispose()
vimState.typeSubscription.dispose();
}
}

View File

@ -1,19 +0,0 @@
import * as vscode from 'vscode'
import type { Mode } from './modes_types'
export type VimState = {
typeSubscription: vscode.Disposable | undefined
mode: Mode
keysPressed: string[]
registers: {
contentsList: (string | undefined)[]
linewise: boolean
}
semicolonAction: (vimState: VimState, editor: vscode.TextEditor) => void
commaAction: (vimState: VimState, editor: vscode.TextEditor) => void
lastPutRanges: {
ranges: (vscode.Range | undefined)[]
linewise: boolean
}
}

View File

@ -1,37 +1,31 @@
import * as vscode from 'vscode'
import * as vscode from 'vscode';
import * as positionUtils from './position_utils'
import * as positionUtils from './position_utils';
// This fixes the selection anchor when selection is changed so that active and anchor are reversed.
// For most motions we use execMotion for perfect visual mode emulation, but for some we need to
// use VSCode's cursorMove instead and this function allows us to fix the selection after the fact.
export function setVisualSelections(
editor: vscode.TextEditor,
originalSelections: vscode.Selection[],
): void {
export function setVisualSelections(editor: vscode.TextEditor, originalSelections: readonly vscode.Selection[]): void {
editor.selections = editor.selections.map((selection, i) => {
const originalSelection = originalSelections[i]
const originalSelection = originalSelections[i];
let activePosition = selection.active
let activePosition = selection.active;
if (!selection.isReversed && selection.active.character === 0) {
activePosition = positionUtils.right(editor.document, selection.active)
activePosition = positionUtils.right(editor.document, selection.active);
}
if (
originalSelection.active.isBefore(originalSelection.anchor) &&
selection.active.isAfterOrEqual(selection.anchor)
) {
return new vscode.Selection(positionUtils.left(selection.anchor), activePosition)
return new vscode.Selection(positionUtils.left(selection.anchor), activePosition);
} else if (
originalSelection.active.isAfter(originalSelection.anchor) &&
selection.active.isBeforeOrEqual(selection.anchor)
) {
return new vscode.Selection(
positionUtils.right(editor.document, selection.anchor),
activePosition,
)
return new vscode.Selection(positionUtils.right(editor.document, selection.anchor), activePosition);
} else {
return new vscode.Selection(selection.anchor, activePosition)
return new vscode.Selection(selection.anchor, activePosition);
}
})
});
}