Automate some pulling completions from upstream

pull/237664/head
Daniel Imms 2025-01-10 07:11:38 -08:00
parent 5f294d0920
commit 55c35c836f
No known key found for this signature in database
GPG Key ID: E5CF412B63651C69
18 changed files with 479 additions and 3 deletions

View File

@ -12,6 +12,7 @@
**/extensions/markdown-math/notebook-out/**
**/extensions/notebook-renderers/renderer-out/index.js
**/extensions/simple-browser/media/index.js
**/extensions/terminal-suggest/src/completions/**
**/extensions/typescript-language-features/test-workspace/**
**/extensions/typescript-language-features/extension.webpack.config.js
**/extensions/typescript-language-features/extension-browser.webpack.config.js

View File

@ -49,6 +49,7 @@ module.exports.unicodeFilter = [
'!extensions/ipynb/notebook-out/**',
'!extensions/notebook-renderers/renderer-out/**',
'!extensions/php-language-features/src/features/phpGlobalFunctions.ts',
'!extensions/terminal-suggest/src/completions/upstream/**',
'!extensions/typescript-language-features/test-workspace/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
@ -88,6 +89,7 @@ module.exports.indentationFilter = [
'!test/automation/out/**',
'!test/monaco/out/**',
'!test/smoke/out/**',
'!extensions/terminal-suggest/src/completions/upstream/**',
'!extensions/typescript-language-features/test-workspace/**',
'!extensions/typescript-language-features/resources/walkthroughs/**',
'!extensions/typescript-language-features/package-manager/node-maintainer/**',
@ -170,6 +172,7 @@ module.exports.copyrightFilter = [
'!extensions/markdown-math/notebook-out/**',
'!extensions/ipynb/notebook-out/**',
'!extensions/simple-browser/media/codicon.css',
'!extensions/terminal-suggest/src/completions/upstream/**',
'!extensions/typescript-language-features/node-maintainer/**',
'!extensions/html-language-features/server/src/modes/typescript/*',
'!extensions/*/server/bin/*',

View File

@ -0,0 +1 @@
third_party/

View File

@ -0,0 +1 @@
git clone https://github.com/withfig/autocomplete third_party/autocomplete

View File

@ -0,0 +1 @@
git clone https://github.com/withfig/autocomplete third_party/autocomplete

View File

@ -0,0 +1,16 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const fs = require('fs');
const path = require('path');
const upstreamSpecs = require('../out/constants.js').upstreamSpecs;
const extRoot = path.resolve(path.join(__dirname, '..'));
for (const spec of upstreamSpecs) {
const source = path.join(extRoot, `third_party/autocomplete/src/${spec}.ts`);
const destination = path.join(extRoot, `src/completions/upstream/${spec}.ts`);
fs.copyFileSync(source, destination);
}

View File

@ -0,0 +1 @@
node "$PSScriptRoot/update-specs.js"

View File

@ -0,0 +1 @@
node ./update-specs.js

View File

@ -666,7 +666,7 @@ declare namespace Fig {
* },
* ```
*/
generateSpec?: (tokens: string[], executeCommand: ExecuteCommandFunction) => Promise<Spec>;
generateSpec?: (tokens: string[], executeCommand: ExecuteCommandFunction) => Promise<Spec | undefined>;
/**
* Generating a spec can be expensive, but due to current guarantees they are not cached.

View File

@ -0,0 +1,42 @@
const environmentVariableGenerator: Fig.Generator = {
custom: async (tokens, _, context) => {
if (tokens.length < 3 || tokens[tokens.length - 1].startsWith("$")) {
return Object.keys(context.environmentVariables).map((suggestion) => ({
name: `$${suggestion}`,
type: "arg",
description: "Environment Variable",
}));
} else {
return [];
}
},
trigger: "$",
};
const completionSpec: Fig.Spec = {
name: "echo",
description: "Write arguments to the standard output",
args: {
name: "string",
isVariadic: true,
optionsCanBreakVariadicArg: false,
suggestCurrentToken: true,
generators: environmentVariableGenerator,
},
options: [
{
name: "-n",
description: "Do not print the trailing newline character",
},
{
name: "-e",
description: "Interpret escape sequences",
},
{
name: "-E",
description: "Disable escape sequences",
},
],
};
export default completionSpec;

View File

@ -0,0 +1,227 @@
const completionSpec: Fig.Spec = {
name: "ls",
description: "List directory contents",
args: {
isVariadic: true,
template: ["filepaths", "folders"],
filterStrategy: "fuzzy",
},
options: [
{
name: "-@",
description:
"Display extended attribute keys and sizes in long (-l) output",
},
{
name: "-1",
description:
"(The numeric digit ``one''.) Force output to be one entry per line. This is the default when output is not to a terminal",
},
{
name: "-A",
description:
"List all entries except for . and ... Always set for the super-user",
},
{
name: "-a",
description: "Include directory entries whose names begin with a dot (.)",
},
{
name: "-B",
description:
"Force printing of non-printable characters (as defined by ctype(3) and current locale settings) in file names as xxx, where xxx is the numeric value of the character in octal",
},
{
name: "-b",
description: "As -B, but use C escape codes whenever possible",
},
{
name: "-C",
description:
"Force multi-column output; this is the default when output is to a terminal",
},
{
name: "-c",
description:
"Use time when file status was last changed for sorting (-t) or long printing (-l)",
},
{
name: "-d",
description:
"Directories are listed as plain files (not searched recursively)",
},
{
name: "-e",
description:
"Print the Access Control List (ACL) associated with the file, if present, in long (-l) output",
},
{
name: "-F",
description:
"Display a slash (/) immediately after each pathname that is a directory, an asterisk (*) after each that is executable, an at sign (@) after each symbolic link, an equals sign (=) after each socket, a percent sign (%) after each whiteout, and a vertical bar (|) after each that is a FIFO",
},
{
name: "-f",
description: "Output is not sorted. This option turns on the -a option",
},
{
name: "-G",
description:
"Enable colorized output. This option is equivalent to defining CLICOLOR in the environment. (See below.)",
},
{
name: "-g",
description:
"This option is only available for compatibility with POSIX; it is used to display the group name in the long (-l) format output (the owner name is suppressed)",
},
{
name: "-H",
description:
"Symbolic links on the command line are followed. This option is assumed if none of the -F, -d, or -l options are specified",
},
{
name: "-h",
description:
"When used with the -l option, use unit suffixes: Byte, Kilobyte, Megabyte, Gigabyte, Terabyte and Petabyte in order to reduce the number of digits to three or less using base 2 for sizes",
},
{
name: "-i",
description:
"For each file, print the file's file serial number (inode number)",
},
{
name: "-k",
description:
"If the -s option is specified, print the file size allocation in kilobytes, not blocks. This option overrides the environment variable BLOCKSIZE",
},
{
name: "-L",
description:
"Follow all symbolic links to final target and list the file or directory the link references rather than the link itself. This option cancels the -P option",
},
{
name: "-l",
description:
"(The lowercase letter ``ell''.) List in long format. (See below.) A total sum for all the file sizes is output on a line before the long listing",
},
{
name: "-m",
description:
"Stream output format; list files across the page, separated by commas",
},
{
name: "-n",
description:
"Display user and group IDs numerically, rather than converting to a user or group name in a long (-l) output. This option turns on the -l option",
},
{
name: "-O",
description: "Include the file flags in a long (-l) output",
},
{ name: "-o", description: "List in long format, but omit the group id" },
{
name: "-P",
description:
"If argument is a symbolic link, list the link itself rather than the object the link references. This option cancels the -H and -L options",
},
{
name: "-p",
description:
"Write a slash (`/') after each filename if that file is a directory",
},
{
name: "-q",
description:
"Force printing of non-graphic characters in file names as the character `?'; this is the default when output is to a terminal",
},
{ name: "-R", description: "Recursively list subdirectories encountered" },
{
name: "-r",
description:
"Reverse the order of the sort to get reverse lexicographical order or the oldest entries first (or largest files last, if combined with sort by size",
},
{ name: "-S", description: "Sort files by size" },
{
name: "-s",
description:
"Display the number of file system blocks actually used by each file, in units of 512 bytes, where partial units are rounded up to the next integer value. If the output is to a terminal, a total sum for all the file sizes is output on a line before the listing. The environment variable BLOCKSIZE overrides the unit size of 512 bytes",
},
{
name: "-T",
description:
"When used with the -l (lowercase letter ``ell'') option, display complete time information for the file, including month, day, hour, minute, second, and year",
},
{
name: "-t",
description:
"Sort by time modified (most recently modified first) before sorting the operands by lexicographical order",
},
{
name: "-u",
description:
"Use time of last access, instead of last modification of the file for sorting (-t) or long printing (-l)",
},
{
name: "-U",
description:
"Use time of file creation, instead of last modification for sorting (-t) or long output (-l)",
},
{
name: "-v",
description:
"Force unedited printing of non-graphic characters; this is the default when output is not to a terminal",
},
{
name: "-W",
description: "Display whiteouts when scanning directories. (-S) flag)",
},
{
name: "-w",
description:
"Force raw printing of non-printable characters. This is the default when output is not to a terminal",
},
{
name: "-x",
description:
"The same as -C, except that the multi-column output is produced with entries sorted across, rather than down, the columns",
},
{
name: "-%",
description:
"Distinguish dataless files and directories with a '%' character in long (-l) output, and don't materialize dataless directories when listing them",
},
{
name: "-,",
description: `When the -l option is set, print file sizes grouped and separated by thousands using the non-monetary separator returned
by localeconv(3), typically a comma or period. If no locale is set, or the locale does not have a non-monetary separator, this
option has no effect. This option is not defined in IEEE Std 1003.1-2001 (POSIX.1)`,
dependsOn: ["-l"],
},
{
name: "--color",
description: `Output colored escape sequences based on when, which may be set to either always, auto, or never`,
requiresSeparator: true,
args: {
name: "when",
suggestions: [
{
name: ["always", "yes", "force"],
description: "Will make ls always output color",
},
{
name: "auto",
description:
"Will make ls output escape sequences based on termcap(5), but only if stdout is a tty and either the -G flag is specified or the COLORTERM environment variable is set and not empty",
},
{
name: ["never", "no", "none"],
description:
"Will disable color regardless of environment variables",
},
],
},
},
],
};
export default completionSpec;

View File

@ -0,0 +1,37 @@
const completionSpec: Fig.Spec = {
name: "mkdir",
description: "Make directories",
args: {
name: "directory name",
template: "folders",
suggestCurrentToken: true,
},
options: [
{
name: ["-m", "--mode"],
description: "Set file mode (as in chmod), not a=rwx - umask",
args: { name: "MODE" },
},
{
name: ["-p", "--parents"],
description: "No error if existing, make parent directories as needed",
},
{
name: ["-v", "--verbose"],
description: "Print a message for each created directory",
},
{
name: ["-Z", "--context"],
description:
"Set the SELinux security context of each created directory to CTX",
args: { name: "CTX" },
},
{ name: "--help", description: "Display this help and exit" },
{
name: "--version",
description: "Output version information and exit",
},
],
};
export default completionSpec;

View File

@ -0,0 +1,43 @@
const completionSpec: Fig.Spec = {
name: "rm",
description: "Remove directory entries",
args: {
isVariadic: true,
template: ["folders", "filepaths"],
},
options: [
{
name: ["-r", "-R"],
description:
"Recursive. Attempt to remove the file hierarchy rooted in each file argument",
isDangerous: true,
},
{
name: "-P",
description: "Overwrite regular files before deleting them",
isDangerous: true,
},
{
name: "-d",
description:
"Attempt to remove directories as well as other types of files",
},
{
name: "-f",
description:
"⚠️ Attempt to remove the files without prompting for confirmation",
isDangerous: true,
},
{
name: "-i",
description: "Request confirmation before attempting to remove each file",
},
{
name: "-v",
description: "Be verbose when deleting files",
},
],
};
export default completionSpec;

View File

@ -0,0 +1,18 @@
const completionSpec: Fig.Spec = {
name: "rmdir",
description: "Remove directories",
args: {
isVariadic: true,
template: "folders",
},
options: [
{
name: "-p",
description: "Remove each directory of path",
isDangerous: true,
},
],
};
export default completionSpec;

View File

@ -0,0 +1,59 @@
const completionSpec: Fig.Spec = {
name: "touch",
description: "Change file access and modification times",
args: {
name: "file",
isVariadic: true,
template: "folders",
suggestCurrentToken: true,
},
options: [
{
name: "-A",
description:
"Adjust the access and modification time stamps for the file by the specified value",
args: {
name: "time",
description: "[-][[hh]mm]SS",
},
},
{ name: "-a", description: "Change the access time of the file" },
{
name: "-c",
description: "Do not create the file if it does not exist",
},
{
name: "-f",
description:
"Attempt to force the update, even if the file permissions do not currently permit it",
},
{
name: "-h",
description:
"If the file is a symbolic link, change the times of the link itself rather than the file that the link points to",
},
{
name: "-m",
description: "Change the modification time of the file",
},
{
name: "-r",
description:
"Use the access and modifications times from the specified file instead of the current time of day",
args: {
name: "file",
},
},
{
name: "-t",
description:
"Change the access and modification times to the specified time instead of the current time of day",
args: {
name: "timestamp",
description: "[[CC]YY]MMDDhhmm[.SS]",
},
},
],
};
export default completionSpec;

View File

@ -0,0 +1,13 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export const upstreamSpecs = [
'echo',
'ls',
'mkdir',
'rm',
'rmdir',
'touch',
];

View File

@ -7,15 +7,23 @@ import * as os from 'os';
import * as fs from 'fs/promises';
import * as path from 'path';
import { ExecOptionsWithStringEncoding, execSync } from 'child_process';
import codeInsidersCompletionSpec from './completions/code-insiders';
import { upstreamSpecs } from './constants';
import codeCompletionSpec from './completions/code';
import cdSpec from './completions/cd';
import codeInsidersCompletionSpec from './completions/code-insiders';
let cachedAvailableCommandsPath: string | undefined;
let cachedAvailableCommands: Set<string> | undefined;
const cachedBuiltinCommands: Map<string, string[] | undefined> = new Map();
export const availableSpecs = [codeCompletionSpec, codeInsidersCompletionSpec, cdSpec];
export const availableSpecs: Fig.Spec[] = [
cdSpec,
codeInsidersCompletionSpec,
codeCompletionSpec,
];
for (const spec of upstreamSpecs) {
availableSpecs.push(require(`./completions/upstream/${spec}`).default);
}
function getBuiltinCommands(shell: string): string[] | undefined {
try {

View File

@ -11,6 +11,10 @@
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
// Needed to suppress warnings in upstream completions
"noImplicitReturns": false,
"noUnusedParameters": false
},
"include": [
"src/**/*",