Compare commits

...

1 Commits

Author SHA1 Message Date
jasonwilliams
7c5ac11622 made a start 2024-05-07 23:41:08 +01:00
11 changed files with 8762 additions and 6047 deletions

1
.husky/.gitignore vendored
View File

@ -1 +0,0 @@
_

View File

@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged

65
build.mjs Normal file
View File

@ -0,0 +1,65 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
import esbuild from 'esbuild';
import path from 'path';
import url from 'url';
const production = process.argv[2] === '--production';
const watch = process.argv[2] === '--watch';
let desktopContext;
let browserContext;
const filename = url.fileURLToPath(import.meta.url);
const dirname = path.dirname(filename);
// This is the base config that will be used by both web and desktop versions of the extension
const baseConfig = {
entryPoints: ['./extension.ts'],
bundle: true,
external: ['vscode'],
sourcemap: !production,
minify: production,
target: 'ES2022',
format: 'cjs',
};
try {
[desktopContext, browserContext] = await Promise.all([
// https://esbuild.github.io/getting-started/#bundling-for-node
esbuild.context({ ...baseConfig, outfile: './out/extension.js', platform: 'node' }),
// https://esbuild.github.io/getting-started/#bundling-for-the-browser
esbuild.context({
...baseConfig,
external: [
'child_process',
'vscode',
'node:events',
'node:net',
'node:util',
'fs',
'zlib',
'http',
'https',
],
alias: {
os: 'os-browserify/browser',
path: 'path-browserify',
process: 'process/browser',
util: 'util',
platform: path.resolve(dirname, 'src', 'platform', 'browser'),
},
outfile: './out/extensionWeb.js',
platform: 'browser',
}),
]);
} catch (e) {
console.error(e);
process.exit(1);
}
if (watch) {
await desktopContext.watch();
await browserContext.watch();
} else {
desktopContext.rebuild();
browserContext.rebuild();
desktopContext.dispose();
browserContext.dispose();
}

View File

@ -1,190 +0,0 @@
const gulp = require('gulp');
const bump = require('gulp-bump');
const git = require('gulp-git');
const tag_version = require('gulp-tag-version');
const ts = require('gulp-typescript');
const PluginError = require('plugin-error');
const minimist = require('minimist');
const path = require('path');
const webpack = require('webpack');
const webpack_stream = require('webpack-stream');
const es = require('event-stream');
const webpack_config = require('./webpack.config.js');
const webpack_dev_config = require('./webpack.dev.js');
const releaseOptions = {
semver: '',
};
function validateArgs(done) {
const options = minimist(process.argv.slice(2), releaseOptions);
if (!options.semver) {
return done(
new PluginError('updateVersion', {
message: 'Missing `--semver` option. Possible values: patch, minor, major',
}),
);
}
if (!['patch', 'minor', 'major'].includes(options.semver)) {
return done(
new PluginError('updateVersion', {
message: 'Invalid `--semver` option. Possible values: patch, minor, major',
}),
);
}
done();
}
function createGitTag() {
return gulp.src(['./package.json']).pipe(tag_version());
}
function createGitCommit() {
return gulp.src(['./package.json', './yarn.lock']).pipe(git.commit('bump version'));
}
function updateVersion(done) {
var options = minimist(process.argv.slice(2), releaseOptions);
return gulp
.src(['./package.json', './yarn.lock'])
.pipe(bump({ type: options.semver }))
.pipe(gulp.dest('./'))
.on('end', () => {
done();
});
}
function updatePath() {
const input = es.through();
const output = input.pipe(
es.mapSync((f) => {
const contents = f.contents.toString('utf8');
const filePath = f.path;
let platformRelativepath = path.relative(
path.dirname(filePath),
path.resolve(process.cwd(), 'out/src/platform/node'),
);
platformRelativepath = platformRelativepath.replace(/\\/g, '/');
f.contents = Buffer.from(
contents.replace(
/\(\"platform\/([^"]*)\"\)/g,
'("' + (platformRelativepath === '' ? './' : platformRelativepath + '/') + '$1")',
),
'utf8',
);
return f;
}),
);
return es.duplex(input, output);
}
function copyPackageJson() {
return gulp.src('./package.json').pipe(gulp.dest('out'));
}
gulp.task('tsc', function () {
var isError = false;
var tsProject = ts.createProject('tsconfig.json', { noEmitOnError: true });
var tsResult = tsProject
.src()
.pipe(tsProject())
.on('error', () => {
isError = true;
})
.on('finish', () => {
isError && process.exit(1);
});
return tsResult.js.pipe(updatePath()).pipe(gulp.dest('out'));
});
gulp.task('webpack', function () {
return webpack_stream(
{
config: webpack_config,
entry: ['./extension.ts', './extensionWeb.ts'],
},
webpack,
).pipe(gulp.dest('out'));
});
gulp.task('webpack-dev', function () {
return webpack_stream(
{
config: webpack_dev_config,
entry: ['./extension.ts'],
},
webpack,
).pipe(gulp.dest('out'));
});
gulp.task('commit-hash', function (done) {
git.revParse({ args: 'HEAD', quiet: true }, function (err, hash) {
require('fs').writeFileSync('out/version.txt', hash);
done();
});
});
// test
gulp.task('run-test', function (done) {
// the flag --grep takes js regex as a string and filters by test and test suite names
var knownOptions = {
string: 'grep',
default: { grep: '' },
};
var options = minimist(process.argv.slice(2), knownOptions);
var spawn = require('child_process').spawn;
const dockerTag = 'vscodevim';
console.log('Building container...');
var dockerBuildCmd = spawn(
'docker',
['build', '-f', './build/Dockerfile', './build/', '-t', dockerTag],
{
cwd: process.cwd(),
stdio: 'inherit',
},
);
dockerBuildCmd.on('exit', function (exitCode) {
if (exitCode !== 0) {
return done(
new PluginError('test', {
message: 'Docker build failed.',
}),
);
}
const dockerRunArgs = [
'run',
'-it',
'--rm',
'--env',
`MOCHA_GREP=${options.grep}`,
'-v',
process.cwd() + ':/app',
dockerTag,
];
console.log('Running tests inside container...');
var dockerRunCmd = spawn('docker', dockerRunArgs, {
cwd: process.cwd(),
stdio: 'inherit',
});
dockerRunCmd.on('exit', function (exitCode) {
done(exitCode);
});
});
});
gulp.task('build', gulp.series('webpack', 'commit-hash'));
gulp.task('build-dev', gulp.series('webpack-dev', 'commit-hash'));
gulp.task('prepare-test', gulp.parallel('tsc', copyPackageJson));
gulp.task('test', gulp.series('prepare-test', 'run-test'));
gulp.task('release', gulp.series(validateArgs, updateVersion, createGitCommit, createGitTag));
gulp.task('default', gulp.series('build', 'test'));

8656
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1172,17 +1172,15 @@
},
"scripts": {
"vscode:prepublish": "gulp build",
"build": "gulp build",
"build-dev": "gulp build-dev",
"build": "node build.mjs",
"build-prod": "gulp build.mjs --production",
"build-test": "gulp prepare-test",
"test": "node ./out/test/runTest.js",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"prettier": "prettier --write .",
"prettier:check": "prettier --check .",
"watch": "webpack -c webpack.dev.js --watch",
"package": "yarn run vsce package --yarn --allow-star-activation",
"prepare": "husky install"
"watch": "node build.mjs --watch"
},
"dependencies": {
"diff-match-patch": "1.0.5",
@ -1215,14 +1213,12 @@
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-jsdoc": "^48.0.0",
"eslint-plugin-prefer-arrow": "^1.2.3",
"esbuild": "^0.21.1",
"event-stream": "4.0.1",
"fork-ts-checker-webpack-plugin": "9.0.2",
"gulp": "5.0.0",
"gulp-bump": "3.2.0",
"gulp-git": "2.10.1",
"gulp-tag-version": "1.3.1",
"gulp-typescript": "5.0.1",
"husky": "^9.0.0",
"lint-staged": "^15.0.0",
"minimist": "1.2.8",
"mocha": "10.4.0",

View File

@ -914,7 +914,7 @@ class CommandClearLine extends BaseCommand {
@RegisterAction
class CommandExitVisualMode extends BaseCommand {
modes = [Mode.Visual];
keys = ['v'];
keys = ['m'];
public override async exec(position: Position, vimState: VimState): Promise<void> {
await vimState.setCurrentMode(Mode.Normal);
@ -924,7 +924,7 @@ class CommandExitVisualMode extends BaseCommand {
@RegisterAction
class CommandVisualMode extends BaseCommand {
modes = [Mode.Normal, Mode.VisualLine, Mode.VisualBlock];
keys = ['v'];
keys = ['m'];
override isCompleteAction = false;
public override async exec(position: Position, vimState: VimState): Promise<void> {

View File

@ -1,34 +1,34 @@
import * as vscode from 'vscode';
import { ChangeOperator, DeleteOperator, YankOperator } from './operator';
import { CursorMoveByUnit, CursorMovePosition, TextEditor } from './../textEditor';
import { isVisualMode, Mode } from './../mode/mode';
import { PairMatcher } from './../common/matching/matcher';
import { QuoteMatcher } from './../common/matching/quoteMatcher';
import { RegisterAction } from './base';
import { RegisterMode } from './../register/register';
import { TagMatcher } from './../common/matching/tagMatcher';
import { VimState } from './../state/vimState';
import { configuration } from './../configuration/configuration';
import { shouldWrapKey } from './wrapping';
import { VimError, ErrorCode } from '../error';
import { BaseMovement, SelectionType, IMovement, isIMovement, failedMovement } from './baseMotion';
import { globalState } from '../state/globalState';
import { reportSearch } from '../util/statusBarTextUtils';
import { SneakForward, SneakBackward } from './plugins/sneak';
import { Notation } from '../configuration/notation';
import { StatusBar } from '../statusBar';
import { clamp, isHighSurrogate, isLowSurrogate } from '../util/util';
import { getCurrentParagraphBeginning, getCurrentParagraphEnd } from '../textobject/paragraph';
import { PythonDocument } from './languages/python/motion';
import { Position } from 'vscode';
import { sorted } from '../common/motion/position';
import { Notation } from '../configuration/notation';
import { ErrorCode, VimError } from '../error';
import { ModeDataFor } from '../mode/modeData';
import { globalState } from '../state/globalState';
import { StatusBar } from '../statusBar';
import { getCurrentParagraphBeginning, getCurrentParagraphEnd } from '../textobject/paragraph';
import { WordType } from '../textobject/word';
import { CommandInsertAtCursor } from './commands/actions';
import { reportSearch } from '../util/statusBarTextUtils';
import { clamp, isHighSurrogate, isLowSurrogate } from '../util/util';
import { SearchDirection } from '../vimscript/pattern';
import { PairMatcher } from './../common/matching/matcher';
import { QuoteMatcher } from './../common/matching/quoteMatcher';
import { TagMatcher } from './../common/matching/tagMatcher';
import { configuration } from './../configuration/configuration';
import { Mode, isVisualMode } from './../mode/mode';
import { RegisterMode } from './../register/register';
import { VimState } from './../state/vimState';
import { CursorMoveByUnit, CursorMovePosition, TextEditor } from './../textEditor';
import { RegisterAction } from './base';
import { BaseMovement, IMovement, SelectionType, failedMovement, isIMovement } from './baseMotion';
import { CommandInsertAtCursor } from './commands/actions';
import { PythonDocument } from './languages/python/motion';
import { ChangeOperator, DeleteOperator, YankOperator } from './operator';
import { SneakBackward, SneakForward } from './plugins/sneak';
import { SmartQuoteMatcher, WhichQuotes } from './plugins/targets/smartQuotesMatcher';
import { useSmartQuotes } from './plugins/targets/targetsConfig';
import { ModeDataFor } from '../mode/modeData';
import { shouldWrapKey } from './wrapping';
/**
* A movement is something like 'h', 'k', 'w', 'b', 'gg', etc.
@ -803,7 +803,7 @@ class MoveToColumn extends BaseMovement {
}
/**
* Returns the Postion of the next instance of `char` on the line
* Returns the Postion of the next instance of `char` in the document
* @param char character to look for
* @param count number of times to look
* @param direction direction to look in
@ -815,20 +815,25 @@ function findHelper(
count: number,
direction: 'forward' | 'backward',
): Position | undefined {
const line = vimState.document.lineAt(start);
let line = vimState.document.lineAt(start);
let index = start.character;
while (count > 0 && index >= 0) {
while (count > 0 && line.lineNumber < vimState.document.lineCount) {
if (direction === 'forward') {
index = line.text.indexOf(char, index + 1);
} else {
index = line.text.lastIndexOf(char, index - 1);
}
count--;
if (index >= 0) {
count--;
} else {
line = vimState.document.lineAt(line.lineNumber + 1);
}
}
if (index >= 0) {
return new Position(start.line, index);
return new Position(line.lineNumber, index);
}
return undefined;
@ -1382,6 +1387,7 @@ class EndOfSpecificLine extends BaseMovement {
export class MoveWordBegin extends BaseMovement {
keys = ['w'];
protected override selectionType: SelectionType = SelectionType.Expanding;
public override async execAction(
position: Position,
vimState: VimState,

View File

@ -1,138 +0,0 @@
//@ts-check
'use strict';
const path = require('path');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
/**@type {import('webpack').Configuration}*/
const config = {
target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
mode: 'production',
entry: './extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'out' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'out'),
filename: 'extension.js',
libraryTarget: 'commonjs2',
devtoolModuleFilenameTemplate: '../[resource-path]',
},
externals: {
vscode: 'commonjs vscode', // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
},
resolve: {
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js'],
alias: {
path: 'path-browserify',
platform: path.resolve(__dirname, 'src', 'platform', 'node'),
},
},
optimization: {
minimize: true,
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
loader: 'ts-loader',
options: {
// Don't type check - ForkTsCheckerWebpackPlugin does this faster
transpileOnly: true,
},
},
],
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [], // disable initial clean
}),
new ForkTsCheckerWebpackPlugin(),
new CircularDependencyPlugin({
// exclude detection of files based on a RegExp
exclude: /node_modules/,
// include specific files based on a RegExp
include: /src/,
// add errors to webpack instead of warnings
failOnError: true,
// allow import cycles that include an asyncronous import,
// e.g. via import(/* webpackMode: "weak" */ './file.js')
allowAsyncCycles: true,
// set the current working directory for displaying module paths
cwd: process.cwd(),
}),
],
};
/**@type {import('webpack').Configuration}*/
const nodelessConfig = {
target: 'webworker', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
mode: 'development',
entry: './extensionWeb.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'out' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'out'),
filename: 'extensionWeb.js',
libraryTarget: 'umd',
},
externals: {
vscode: 'commonjs vscode', // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
},
resolve: {
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js'],
alias: {
platform: path.resolve(__dirname, 'src', 'platform', 'browser'),
},
fallback: {
os: require.resolve('os-browserify/browser'),
path: require.resolve('path-browserify'),
process: require.resolve('process/browser'),
util: require.resolve('util'),
},
},
optimization: {
minimize: true,
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
loader: 'ts-loader',
options: {
// Don't type check - ForkTsCheckerWebpackPlugin does this faster
transpileOnly: true,
},
},
],
},
plugins: [
new webpack.IgnorePlugin({
resourceRegExp: /\/neovim$/,
}),
new webpack.IgnorePlugin({
resourceRegExp: /\/imswitcher$/,
}),
new webpack.IgnorePlugin({
resourceRegExp: /\/vimrc$/,
}),
new webpack.IgnorePlugin({
resourceRegExp: /child_process$/,
}),
new webpack.ProvidePlugin({
process: 'process/browser', // util requires this internally
}),
new ForkTsCheckerWebpackPlugin(),
],
};
module.exports = [config, nodelessConfig];

View File

@ -1,15 +0,0 @@
const merge = require('webpack-merge');
const prod_configs = require('./webpack.config.js');
module.exports = [
merge.merge(prod_configs[0], {
mode: 'development',
devtool: 'source-map',
optimization: {
minimize: false,
removeAvailableModules: false,
removeEmptyChunks: false,
splitChunks: false,
},
}),
];

5660
yarn.lock

File diff suppressed because it is too large Load Diff