diff --git a/extensions/terminal-suggest/scripts/clone-fig.sh b/extensions/terminal-suggest/scripts/clone-fig.sh old mode 100644 new mode 100755 diff --git a/extensions/terminal-suggest/scripts/update-specs.sh b/extensions/terminal-suggest/scripts/update-specs.sh old mode 100644 new mode 100755 diff --git a/extensions/terminal-suggest/src/completions/index.d.ts b/extensions/terminal-suggest/src/completions/index.d.ts index 4932e4fa4b40e..44dcb98144561 100644 --- a/extensions/terminal-suggest/src/completions/index.d.ts +++ b/extensions/terminal-suggest/src/completions/index.d.ts @@ -1157,7 +1157,7 @@ declare namespace Fig { */ script?: | string[] - | Function + | Function // <-- VS Code edit to make results correct | ExecuteCommandInput | Function; /** @@ -1174,7 +1174,7 @@ declare namespace Fig { * @returns An array of `Suggestion` objects. * */ - postProcess?: (out: string, tokens: string[]) => (Suggestion | null)[]; // <-- VS Code edit to make results correct + postProcess?: (out: string, tokens: string[]) => (Suggestion | null)[] | undefined; // <-- VS Code edit to make results correct /** * Syntactic sugar for `postProcess` function * diff --git a/extensions/terminal-suggest/src/completions/upstream/apt.ts b/extensions/terminal-suggest/src/completions/upstream/apt.ts new file mode 100644 index 0000000000000..c2157963fd9bd --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/apt.ts @@ -0,0 +1,359 @@ +// import { filepaths } from "@fig/autocomplete-generators"; + +const packages: Fig.Generator = { + // only trigger when the token length transitions to or from 0 + trigger: (current, previous) => + current.length === 0 || (previous.length === 0 && current.length > 0), + + // have to use `custom` to skip running the script when length is 0 + custom: async (tokens, executeShellCommand) => { + const finalToken = tokens[tokens.length - 1]; + if (finalToken.length === 0) { + return []; + } + const { stdout } = await executeShellCommand({ + command: "apt", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: ["list"], + }); + + // Only lines matching the first character, delete characters after '/' + return stdout + .trim() + .split("\n") + .filter((name) => name.startsWith(finalToken)) + .map((name) => name.replace(/\/.*/, "")) + .map((name) => ({ + name, + description: "Package", + icon: "πŸ“¦", + // make the suggestions... actually show up + // see https://github.com/withfig/autocomplete/pull/1429#discussion_r950688126 + priority: 50, + })); + }, +}; + +const installedPackages: Fig.Generator = { + script: ["apt", "list", "--installed"], + postProcess: function (a) { + return a + .trim() + .split("\n") + .map((b) => { + return { + name: b.substring(0, b.indexOf("/")), + description: "Package", + icon: "πŸ“¦", + }; + }); + }, +}; + +const upgradablePackages: Fig.Generator = { + script: ["apt", "list", "--upgradable"], + postProcess: function (a) { + return a + .trim() + .split("\n") + .map((b) => { + return { + name: b.substring(0, b.indexOf("/")), + description: "Package", + icon: "πŸ“¦", + }; + }); + }, +}; + +const yesNoOptions: Fig.Option[] = [ + { + name: "-y", + description: "Assume yes to all prompts", + exclusiveOn: ["--assume-no"], + }, + { + name: "--assume-no", + description: "Assume no to all prompts", + exclusiveOn: ["-y"], + }, +]; + +const installationOptions: Fig.Option[] = [ + { + name: ["-d", "--download-only"], + description: + "For any operation that would download packages, download them, but do nothing else", + }, + { + name: "--no-download", + description: + "Do not download packages, attempt to use already downloaded packages", + }, +]; + +const simulate: Fig.Option[] = [ + { + name: ["-s", "--simulate"], + description: + "Simulate running this command and show it's output, without actually changing anything", + }, +]; + +const completionSpec: Fig.Spec = { + name: "apt", + description: "Package manager for Debian-based Linux distributions", + subcommands: [ + { + name: "update", + description: "Update the package database", + options: [...yesNoOptions], + }, + { + name: "upgrade", + description: "Install all available upgrades", + args: { + name: "package", + description: "Package(s) to upgrade", + isVariadic: true, + isOptional: true, + generators: upgradablePackages, + }, + options: [...installationOptions, ...yesNoOptions, ...simulate], + }, + { + name: "full-upgrade", + description: + "Install available upgrades, removing currently installed packages if needed to upgrade the system as a whole", + options: [...installationOptions, ...yesNoOptions, ...simulate], + }, + { + name: "install", + description: "Install package(s)", + args: { + name: "package", + description: "The package you want to install", + isVariadic: true, + template: 'filepaths', + generators: [ + packages, + // filepaths({ extensions: ["deb"] }) + ], + }, + options: [ + ...installationOptions, + ...yesNoOptions, + ...simulate, + { + name: "--reinstall", + description: "Reinstall the package if it is already installed", + }, + { + name: ["-f", "--fix-broken"], + description: "Attempt to fix broken packages", + }, + ], + }, + { + name: "reinstall", + description: "Reinstall package(s)", + args: { + name: "package", + description: "The package you want to reinstall", + isVariadic: true, + generators: installedPackages, + }, + options: [...yesNoOptions, ...simulate], + }, + { + name: "remove", + description: "Remove package(s)", + args: { + name: "package", + description: "The package you want to remove", + isVariadic: true, + generators: installedPackages, + }, + options: [ + ...yesNoOptions, + ...simulate, + { + name: ["-f", "--fix-broken"], + description: "Attempt to fix broken packages", + }, + ], + }, + { + name: "purge", + description: "Remove package(s) and their configuration files", + args: { + name: "package", + description: "The package you want to purge", + isVariadic: true, + generators: installedPackages, + }, + options: [...yesNoOptions, ...simulate], + }, + { + name: ["autoremove", "auto-remove"], + description: "Remove unused packages", + options: [...yesNoOptions, ...simulate], + }, + { + name: "list", + description: "List packages", + options: [ + { + name: "--installed", + description: "List installed packages", + }, + { + name: "--upgradable", + description: "List upgradable packages", + }, + ], + }, + { + name: "search", + description: "Search for packages", + args: { + name: "query", + description: "The query to search for", + }, + options: [...yesNoOptions], + }, + { + name: "show", + description: "Show package details", + args: { + name: "package", + description: "The package you want to show", + generators: packages, + }, + }, + { + name: "satisfy", + description: "Satisfy package dependencies", + args: { + name: "package", + description: "The package you want to satisfy", + isVariadic: true, + generators: packages, + }, + options: [...installationOptions, ...yesNoOptions, ...simulate], + }, + { + name: "clean", + description: "Remove downloaded package files", + options: [...yesNoOptions, ...simulate], + }, + { + name: "edit-sources", + description: "Edit the list of package sources", + options: [...yesNoOptions], + }, + { + // docs for this weren't the greatest, some descriptions might be slightly (or very) wrong. + name: "source", + description: "Fetch package source files", + args: { + name: "package", + description: "The package you want to get source files for", + isVariadic: true, + generators: packages, + }, + options: [ + ...installationOptions, + ...yesNoOptions, + ...simulate, + { + name: "--compile", + description: + "Compile the package to a binary using dpkg-buildpackage", + }, + { + name: "--only-source", + // no idea how this works + }, + { + name: "--host-architecture", + description: "The architecture to build for", + args: { + name: "architecture", + description: "The architecture to build for", + }, + }, + ], + }, + { + // I don't understand this either + name: "build-dep", + description: + "Install/remove packages in an attempt to satisfy the build dependencies for a source package", + args: { + name: "package", + description: "The package you want to build dependencies for", + generators: packages, + }, + options: [ + ...installationOptions, + ...yesNoOptions, + ...simulate, + { + name: "--host-architecture", + description: "The architecture to build for", + args: { + name: "architecture", + description: "The architecture to build for", + }, + }, + { + name: "--only-source", + }, + ], + }, + { + name: "download", + description: "Download package binary into the current directory", + args: { + name: "package", + description: "The package you want to download", + generators: packages, + }, + options: [...installationOptions, ...yesNoOptions], + }, + { + name: ["autoclean", "auto-clean"], + description: + "Like clean, but only removes package files that can no longer be downloaded", + options: [...installationOptions, ...yesNoOptions, ...simulate], + }, + { + name: "changelog", + description: "Show the changelog for a package", + args: { + name: "package", + description: "The package you want to show the changelog for", + generators: packages, + isVariadic: true, + }, + options: [...installationOptions, ...yesNoOptions], + }, + ], + options: [ + { + name: ["-h", "--help"], + description: "Print help message and exit", + isPersistent: true, + priority: 40, + }, + { + name: ["-v", "--version"], + description: "Print version information and exit", + isPersistent: true, + priority: 40, + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/brew.ts b/extensions/terminal-suggest/src/completions/upstream/brew.ts new file mode 100644 index 0000000000000..99b87c45ca9a8 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/brew.ts @@ -0,0 +1,1675 @@ +const servicesGenerator = (action: string): Fig.Generator => ({ + script: ["bash", "-c", "brew services list | sed -e 's/ .*//' | tail -n +2"], + postProcess: function (out) { + return out + .split("\n") + .filter((line) => !line.includes("unbound")) + .map((line) => ({ + name: line, + icon: "fig://icon?type=package", + description: `${action} ${line}`, + })); + }, +}); + +const repositoriesGenerator = (): Fig.Generator => ({ + script: ["brew", "tap"], + postProcess: (out) => { + return out.split("\n").map((line) => ({ name: line })); + }, +}); + +const formulaeGenerator: Fig.Generator = { + script: ["brew", "list", "-1"], + postProcess: function (out) { + return out + .split("\n") + .filter((line) => !line.includes("=")) + .map((formula) => ({ + name: formula, + icon: "🍺", + description: "Installed formula", + })); + }, +}; + +const outdatedformulaeGenerator: Fig.Generator = { + script: ["brew", "outdated", "-q"], + postProcess: function (out) { + return out.split("\n").map((formula) => ({ + name: formula, + icon: "🍺", + description: "Outdated formula", + })); + }, +}; + +const generateAllFormulae: Fig.Generator = { + script: ["brew", "formulae"], + postProcess: function (out) { + return out.split("\n").map((formula) => ({ + name: formula, + icon: "🍺", + description: "Formula", + priority: 51, + })); + }, +}; + +const generateAllCasks: Fig.Generator = { + script: ["brew", "casks"], + postProcess: function (out) { + return out.split("\n").map((cask) => ({ + name: cask, + icon: "🍺", + description: "Cask", + priority: 52, + })); + }, +}; +const generateAliases: Fig.Generator = { + script: [ + "bash", + "-c", + 'find ~/.brew-aliases/ -type f ! -name "*.*" -d 1 | sed "s/.*\\///"', + ], + postProcess: function (out) { + return out + .split("\n") + .filter((line) => line && line.trim() !== "") + .map((line) => ({ + name: line, + icon: "fig://icon?type=command", + description: `Execute alias ${line}`, + })); + }, +}; + +const commonOptions: Fig.Option[] = [ + { + name: ["-d", "--debug"], + description: "Display any debugging information", + }, + { + name: ["-q", "--quiet"], + description: "Make some output more quiet", + }, + { + name: ["-v", "--verbose"], + description: "Make some output more verbose", + }, + { name: ["-h", "--help"], description: "Show help message" }, +]; + +const completionSpec: Fig.Spec = { + name: "brew", + description: "Package manager for macOS", + subcommands: [ + { + name: "list", + description: "List all installed formulae", + options: [ + ...commonOptions, + { + name: ["--formula", "--formulae"], + description: + "List only formulae, or treat all named arguments as formulae", + }, + { + name: ["--cask", "--casks"], + description: "List only casks, or treat all named arguments as casks", + }, + { + name: "--unbrewed", + description: + "List files in Homebrew's prefix not installed by Homebrew. (disabled; replaced by brew --prefix --unbrewed)", + }, + { + name: "--full-name", + description: + "Print formulae with fully-qualified names. Unless --full-name, --versions or", + }, + { + name: "--pinned", + description: + "List only pinned formulae, or only the specified (pinned) formulae if formula are provided", + }, + { + name: "--versions", + description: + "Show the version number for installed formulae, or only the specified formulae if formula are provided", + }, + { + name: "--multiple", + description: "Only show formulae with multiple versions installed", + }, + { + name: "--pinned", + description: + "List only pinned formulae, or only the specified (pinned) formulae if formula are provided. See also pin, unpin", + }, + { + name: "-1", + description: + "Force output to be one entry per line. This is the default when output is not to a terminal", + }, + { + name: "-l", + description: + "List formulae and/or casks in long format. Has no effect when a formula or cask name is passed as an argument", + }, + { + name: "-r", + description: + "Reverse the order of the formulae and/or casks sort to list the oldest entries first. Has no effect when a formula or cask name is passed as an argument", + }, + { + name: "-t", + description: + "Sort formulae and/or casks by time modified, listing most recently modified first. Has no effect when a formula or cask name is passed as an argument", + }, + ], + args: { + isOptional: true, + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + }, + { + name: "ls", + description: "List all installed formulae", + options: [ + ...commonOptions, + { + name: "--formula", + description: + "List only formulae, or treat all named arguments as formulae", + }, + { + name: "--cask", + description: "List only casks, or treat all named arguments as casks", + }, + { + name: "--unbrewed", + description: + "List files in Homebrew's prefix not installed by Homebrew. (disabled; replaced by brew --prefix --unbrewed)", + }, + { + name: "--full-name", + description: + "Print formulae with fully-qualified names. Unless --full-name, --versions or", + }, + { + name: "--pinned", + description: + "List only pinned formulae, or only the specified (pinned) formulae if formula are provided", + }, + { + name: "--versions", + description: + "Show the version number for installed formulae, or only the specified formulae if formula are provided", + }, + { + name: "--multiple", + description: "Only show formulae with multiple versions installed", + }, + { + name: "--pinned", + description: + "List only pinned formulae, or only the specified (pinned) formulae if formula are provided", + }, + { + name: "-1", + description: + "Force output to be one entry per line. This is the default when output is not to a terminal", + }, + { + name: "-l", + description: + "List formulae and/or casks in long format. Has no effect when a formula or cask name is passed as an argument", + }, + { + name: "-r", + description: + "Reverse the order of the formulae and/or casks sort to list the oldest entries first. Has no effect when a formula or cask name is passed as an argument", + }, + { + name: "-t", + description: + "Sort formulae and/or casks by time modified, listing most recently modified first. Has no effect when a formula or cask name is passed as an argument", + }, + ], + args: { + isOptional: true, + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + }, + { + name: "leaves", + description: + "List installed formulae that are not dependencies of another installed formula", + options: [ + { + name: ["-r", "--installed-on-request"], + description: "Show manually installed formula", + }, + { + name: ["-p", "--installed-as-dependency"], + description: "Show installed formula as dependencies", + }, + ], + }, + { + name: "doctor", + description: "Check your system for potential problems", + options: [ + ...commonOptions, + { + name: "--list-checks", + description: "List all audit methods", + }, + { + name: ["-D", "--audit-debug"], + description: "Enable debugging and profiling of audit methods", + }, + ], + }, + { + name: ["abv", "info"], + description: "Display brief statistics for your Homebrew installation", + args: { + isVariadic: true, + isOptional: true, + name: "formula", + description: "Formula or cask to summarize", + generators: [generateAllFormulae, generateAllCasks], + }, + options: [ + { + name: ["--cask", "--casks"], + description: "List only casks, or treat all named arguments as casks", + }, + { + name: "--analytics", + description: + "List global Homebrew analytics data or, if specified, installation and build error data for formula", + }, + { + name: "--days", + description: "How many days of analytics data to retrieve", + exclusiveOn: ["--analytics"], + args: { + name: "days", + description: "Number of days of data to retrieve", + suggestions: ["30", "90", "365"], + }, + }, + { + name: "--category", + description: "Which type of analytics data to retrieve", + exclusiveOn: ["--analytics"], + args: { + generators: { + custom: async (ctx) => { + // if anything provided after the subcommand does not begin with '-' + // then a formula has been provided and we should provide info on it + if ( + ctx.slice(2, ctx.length - 1).some((token) => token[0] !== "-") + ) { + return ["install", "install-on-request", "build-error"].map( + (sugg) => ({ + name: sugg, + }) + ); + } + + // if no formulas are specified, then we should provide system info + return ["cask-install", "os-version"].map((sugg) => ({ + name: sugg, + })); + }, + }, + }, + }, + { + name: "--github", + description: "Open the GitHub source page for formula in a browser", + }, + { + name: "--json", + description: "Print a JSON representation", + }, + { + name: "--installed", + exclusiveOn: ["--json"], + description: "Print JSON of formulae that are currently installed", + }, + { + name: "--all", + exclusiveOn: ["--json"], + description: "Print JSON of all available formulae", + }, + { + name: ["-v", "--verbose"], + description: "Show more verbose analytics data for formulae", + }, + { + name: "--formula", + description: "Treat all named arguments as formulae", + }, + { + name: "--cash", + description: "Treat all named arguments as casks", + }, + { + name: ["-d", "--debug"], + description: "Display any debugging information", + }, + { + name: ["-q", "--quiet"], + description: "List only the names of outdated kegs", + }, + { + name: ["-h", "--help"], + description: "Get help with services command", + }, + ], + }, + { + name: "update", + description: "Fetch the newest version of Homebrew and all formulae", + options: [ + { + name: ["-f", "--force"], + description: "Always do a slower, full update check", + }, + { + name: ["-v", "--verbose"], + description: + "Print the directories checked and git operations performed", + }, + { + name: ["-d", "--debug"], + description: + "Display a trace of all shell commands as they are executed", + }, + { name: ["-h", "--help"], description: "Show help message" }, + { + name: "--merge", + description: + "Use git merge to apply updates (rather than git rebase)", + }, + { + name: "--preinstall", + description: + "Run on auto-updates (e.g. before brew install). Skips some slower steps", + }, + ], + }, + { + name: "outdated", + description: + "List installed casks and formulae that have an updated version available", + options: [ + { + name: ["-d", "--debug"], + description: "Display any debugging information", + }, + { + name: ["-q", "--quiet"], + description: "List only the names of outdated kegs", + }, + { + name: ["-v", "--verbose"], + description: "Include detailed version information", + }, + { + name: ["-h", "--help"], + description: "Show help message for the outdated command", + }, + { name: "--cask", description: "List only outdated casks" }, + { + name: "--fetch-HEAD", + description: + "Fetch the upstream repository to detect if the HEAD installation of the formula is outdated", + }, + { name: "--formula", description: "List only outdated formulae" }, + { + name: "--greedy", + description: + "Print outdated casks with auto_updates or version :latest", + }, + { + name: "--greedy-latest", + description: + "Print outdated casks including those with version :latest", + }, + { + name: "--greedy-auto-updates", + description: + "Print outdated casks including those with auto_updates true", + }, + { name: "--json", description: "Print output in JSON format" }, + ], + }, + { + name: "pin", + description: "Pin formula, preventing them from being upgraded", + options: commonOptions, + args: { + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + }, + { + name: "unpin", + description: "Unpin formula, allowing them to be upgraded", + options: commonOptions, + args: { + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + }, + { + name: "upgrade", + description: + "Upgrade outdated casks and outdated, unpinned formulae using the same options they were originally installed with, plus any appended brew formula options", + options: [ + { + name: ["-d", "--debug"], + description: + "If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory", + }, + { + name: ["-f", "--force"], + description: + "Install formulae without checking for previously installed keg-only or non-migrated versions. When installing casks, overwrite existing files (binaries and symlinks are excluded, unless originally from the same cask)", + }, + { + name: ["-v", "--verbose"], + description: "Print the verification and postinstall steps", + }, + { + name: ["-n", "--dry-run"], + description: + "Show what would be upgraded, but do not actually upgrade anything", + }, + { + name: ["-s", "--build-from-source"], + description: + "Compile formula from source even if a bottle is provided. Dependencies will still be installed from bottles if they are available", + }, + { + name: ["-i", "--interactive"], + description: "Download and patch formula, then open a shell", + }, + { name: ["-g", "--git"], description: "Create a Git repository" }, + { + name: ["-q", "--quiet"], + description: "Make some output more quiet", + }, + { name: ["-h", "--help"], description: "Show this message" }, + { + name: ["--formula", "--formulae"], + description: + "Treat all named arguments as formulae. If no named arguments are specified, upgrade only outdated formulae", + }, + { + name: "--env", + description: "Disabled other than for internal Homebrew use", + }, + { + name: "--ignore-dependencies", + description: + "An unsupported Homebrew development flag to skip installing any dependencies of any kind. If the dependencies are not already present, the formula will have issues. If you're not developing Homebrew, consider adjusting your PATH rather than using this flag", + }, + { + name: "--only-dependencies", + description: + "Install the dependencies with specified options but do not install the formula itself", + }, + { + name: "--cc", + description: + "Attempt to compile using the specified compiler, which should be the name of the compiler's executable", + args: { + name: "compiler", + suggestions: ["gcc-7", "llvm_clang", "clang"], + }, + }, + { + name: "--force-bottle", + description: + "Install from a bottle if it exists for the current or newest version of macOS, even if it would not normally be used for installation", + }, + { + name: "--include-test", + description: + "Install testing dependencies required to run brew test formula", + }, + { + name: "--HEAD", + description: + "If formula defines it, install the HEAD version, aka. main, trunk, unstable, master", + }, + { + name: "--fetch-HEAD", + description: + "Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository's HEAD will only be checked for updates when a new stable or development version has been released", + }, + { + name: "--ignore-pinned", + description: + "Set a successful exit status even if pinned formulae are not upgraded", + }, + { + name: "--keep-tmp", + description: "Retain the temporary files created during installation", + }, + { + name: "--build-bottle", + description: + "Prepare the formula for eventual bottling during installation, skipping any post-install steps", + }, + { + name: "--bottle-arch", + description: + "Optimise bottles for the specified architecture rather than the oldest architecture supported by the version of macOS the bottles are built on", + }, + { + name: "--display-times", + description: + "Print install times for each formula at the end of the run", + }, + { + name: ["--cask", "--casks"], + description: + "Treat all named arguments as casks. If no named arguments are specified, upgrade only outdated casks", + }, + { + name: "--binaries", + description: + "Disable/enable linking of helper executables (default: enabled)", + exclusiveOn: ["--no-binaries"], + }, + { + name: "--no-binaries", + description: + "Disable/enable linking of helper executables (default: enabled)", + exclusiveOn: ["--binaries"], + }, + { + name: "--require-sha", + description: "Require all casks to have a checksum", + }, + { + name: "--quarantine", + description: + "Disable/enable quarantining of downloads (default: enabled)", + exclusiveOn: ["--no-quarantine"], + }, + { + name: "--no-quarantine", + description: + "Disable/enable quarantining of downloads (default: enabled)", + exclusiveOn: ["--quarantine"], + }, + { + name: "--skip-cask-deps", + description: "Skip installing cask dependencies", + }, + { + name: "--greedy", + description: + "Also include casks with auto_updates true or version :latest", + exclusiveOn: ["--greedy-latest", "--greedy-auto-updates"], + }, + { + name: "--greedy-latest", + description: "Also include casks with version :latest", + }, + { + name: "--greedy-auto-updates", + description: "Also include casks with auto_updates true", + }, + { + name: "--appdir", + description: + "Target location for Applications (default: /Applications)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--colorpickerdir", + description: + "Target location for Color Pickers (default: ~/Library/ColorPickers)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--prefpanedir", + description: + "Target location for Preference Panes (default: ~/Library/PreferencePanes)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--qlplugindir", + description: + "Target location for QuickLook Plugins (default: ~/Library/QuickLook)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--mdimporterdir", + description: + "Target location for Spotlight Plugins (default: ~/Library/Spotlight)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--dictionarydir", + description: + "Target location for Dictionaries (default: ~/Library/Dictionaries)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--fontdir", + description: "Target location for Fonts (default: ~/Library/Fonts)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--servicedir", + description: + "Target location for Services (default: ~/Library/Services)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--input-methoddir", + description: + "Target location for Input Methods (default: ~/Library/Input Methods)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--internet-plugindir", + description: + "Target location for Internet Plugins (default: ~/Library/Internet Plug-Ins)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--audio-unit-plugindir", + description: + "Target location for Audio Unit Plugins (default: ~/Library/Audio/Plug-Ins/Components)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--vst-plugindir", + description: + "Target location for VST Plugins (default: ~/Library/Audio/Plug-Ins/VST)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--vst3-plugindir", + description: + "Target location for VST3 Plugins (default: ~/Library/Audio/Plug-Ins/VST3)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--screen-saverdir", + description: + "Target location for Screen Savers (default: ~/Library/Screen Savers)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--language", + description: + "Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask's default language. The default value is the language of your system", + }, + ], + args: { + isVariadic: true, + isOptional: true, + name: "outdated_formula|outdated_cask", + generators: outdatedformulaeGenerator, + }, + }, + { + name: "search", + description: + "Perform a substring search of cask tokens and formula names", + options: [ + ...commonOptions, + { + name: "--formula", + description: "Search online and locally for formulae", + }, + { + name: "--cask", + description: "Search online and locally for casks", + }, + { + name: "--desc", + description: + "Search for formulae with a description matching text and casks with a name matching text", + }, + { + name: "--pull-request", + description: "Search for GitHub pull requests containing text", + }, + { + name: "--open", + description: "Search for only open GitHub pull requests", + }, + { + name: "--closed", + description: "Search for only closed GitHub pull requests", + }, + { + name: ["--repology", "--macports"], + description: "Search for text in the given database", + }, + { + name: ["--fink", "--opensuse"], + description: "Search for text in the given database", + }, + { + name: ["--fedora", "--debian"], + description: "Search for text in the given database", + }, + { + name: "--ubuntu", + description: "Search for text in the given database", + }, + ], + }, + { + name: "config", + description: "Show Homebrew and system configuration info", + }, + { + name: "postinstall", + description: "Rerun the post install step for formula", + options: [ + { + name: ["-d", "--debug"], + description: "Display any debugging information", + }, + { + name: ["-v", "--verbose"], + description: "Make some output more verbose", + }, + { + name: ["-q", "--quiet"], + description: "Make some output more quiet", + }, + { name: ["-h", "--help"], description: "Show this message" }, + ], + args: { + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + }, + { + name: "install", + description: "Install ", + options: [ + { + name: ["-f", "--force"], + description: + "Install formulae without checking for previously installed keg-only or non-migrated versions. When installing casks", + }, + { + name: ["-v", "--verbose"], + description: "Print the verification and postinstall steps", + }, + { + name: ["-s", "--build-from-source"], + description: + "Compile formula from source even if a bottle is provided. Dependencies will still be installed from bottles if they are available", + }, + { + name: ["-i", "--interactive"], + description: "Download and patch formula", + }, + { name: ["-g", "--git"], description: "Create a Git repository" }, + { + name: ["-q", "--quiet"], + description: "Make some output more quiet", + }, + { name: ["-h", "--help"], description: "Show this message" }, + { + name: "--formula", + description: "Treat all named arguments as formulae", + }, + { + name: "--env", + description: "Disabled other than for internal Homebrew use", + }, + { + name: "--ignore-dependencies", + description: + "An unsupported Homebrew development flag to skip installing any dependencies of any kind. If the dependencies are not already present, the formula will have issues. If you're not developing Homebrew, consider adjusting your PATH rather than using this flag", + }, + { + name: "--only-dependencies", + description: + "Install the dependencies with specified options but do not install the formula itself", + }, + { + name: "--cc", + description: + "Attempt to compile using the specified compiler, which should be the name of the compiler's executable", + args: { + name: "compiler", + suggestions: ["gcc-7", "llvm_clang", "clang"], + }, + }, + { + name: "--force-bottle", + description: + "Install from a bottle if it exists for the current or newest version of macOS, even if it would not normally be used for installation", + }, + { + name: "--include-test", + description: + "Install testing dependencies required to run brew test formula", + }, + { + name: "--HEAD", + description: + "If formula defines it, install the HEAD version, aka. main, trunk, unstable, master", + }, + { + name: "--fetch-HEAD", + description: + "Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository's HEAD will only be checked for updates when a new stable or development version has been released", + }, + { + name: "--keep-tmp", + description: "Retain the temporary files created during installation", + }, + { + name: "--build-bottle", + description: + "Prepare the formula for eventual bottling during installation, skipping any post-install steps", + }, + { + name: "--bottle-arch", + description: + "Optimise bottles for the specified architecture rather than the oldest architecture supported by the version of macOS the bottles are built on", + }, + { + name: "--display-times", + description: + "Print install times for each formula at the end of the run", + }, + { + name: "--cask", + description: "--casks Treat all named arguments as casks", + }, + { + name: "--binaries", + description: + "Disable/enable linking of helper executables (default: enabled)", + }, + { + name: "--no-binaries", + description: + "Disable/enable linking of helper executables (default: enabled)", + }, + { + name: "--require-sha", + description: "Require all casks to have a checksum", + }, + { + name: "--quarantine", + description: + "Disable/enable quarantining of downloads (default: enabled)", + }, + { + name: "--no-quarantine", + description: + "Disable/enable quarantining of downloads (default: enabled)", + }, + { + name: "--skip-cask-deps", + description: "Skip installing cask dependencies", + }, + { + name: "--appdir", + description: + "Target location for Applications (default: /Applications)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--colorpickerdir", + description: + "Target location for Color Pickers (default: ~/Library/ColorPickers)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--prefpanedir", + description: + "Target location for Preference Panes (default: ~/Library/PreferencePanes)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--qlplugindir", + description: + "Target location for QuickLook Plugins (default: ~/Library/QuickLook)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--mdimporterdir", + description: + "Target location for Spotlight Plugins (default: ~/Library/Spotlight)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--dictionarydir", + description: + "Target location for Dictionaries (default: ~/Library/Dictionaries)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--fontdir", + description: "Target location for Fonts (default: ~/Library/Fonts)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--servicedir", + description: + "Target location for Services (default: ~/Library/Services)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--input-methoddir", + description: + "Target location for Input Methods (default: ~/Library/Input Methods)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--internet-plugindir", + description: + "Target location for Internet Plugins (default: ~/Library/Internet Plug-Ins)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--audio-unit-plugindir", + description: + "Target location for Audio Unit Plugins (default: ~/Library/Audio/Plug-Ins/Components)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--vst-plugindir", + description: + "Target location for VST Plugins (default: ~/Library/Audio/Plug-Ins/VST)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--vst3-plugindir", + description: + "Target location for VST3 Plugins (default: ~/Library/Audio/Plug-Ins/VST3)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--screen-saverdir", + description: + "Target location for Screen Savers (default: ~/Library/Screen Savers)", + args: { + name: "location", + template: "folders", + }, + }, + { + name: "--language", + description: + "Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask's default language. The default value is the language of your system", + }, + ], + args: { + isVariadic: true, + name: "formula", + description: "Formula or cask to install", + generators: [generateAllFormulae, generateAllCasks], + }, + }, + { + name: "reinstall", + description: + "Uninstall and then reinstall a formula or cask using the same options it was originally installed with, plus any appended options specific to a formula", + options: [ + { + name: ["-d", "--debug"], + description: + "If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory", + }, + { + name: ["-f", "--force"], + description: + "Install formulae without checking for previously installed keg-only or non-migrated versions. When installing casks", + }, + { + name: ["-v", "--verbose"], + description: "Print the verification and postinstall steps", + }, + { + name: ["-s", "--build-from-source"], + description: + "Compile formula from source even if a bottle is provided. Dependencies will still be installed from bottles if they are available", + }, + { + name: ["-i", "--interactive"], + description: "Download and patch formula", + }, + { name: ["-g", "--git"], description: "Create a Git repository" }, + { + name: "--formula", + description: "Treat all named arguments as formulae", + }, + { + name: "--force-bottle", + description: + "Install from a bottle if it exists for the current or newest version of macOS, even if it would not normally be used for installation", + }, + { + name: "--keep-tmp", + description: "Retain the temporary files created during installation", + }, + { + name: "--display-times", + description: + "Print install times for each formula at the end of the run", + }, + { + name: "--cask", + description: "--casks Treat all named arguments as casks", + }, + { + name: "--binaries", + description: + "Disable/enable linking of helper executables (default: enabled)", + exclusiveOn: ["--no-binaries"], + }, + { + name: "--no-binaries", + description: + "Disable/enable linking of helper executables (default: enabled)", + exclusiveOn: ["--binaries"], + }, + { + name: "--require-sha", + description: "Require all casks to have a checksum", + }, + { + name: "--quarantine", + description: + "Disable/enable quarantining of downloads (default: enabled)", + exclusiveOn: ["--no-quarantine"], + }, + { + name: "--no-quarantine", + description: + "Disable/enable quarantining of downloads (default: enabled)", + exclusiveOn: ["--quarantine"], + }, + { + name: "--skip-cask-deps", + description: "Skip installing cask dependencies", + }, + ], + args: { + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + }, + { + name: ["uninstall", "remove", "rm"], + description: "Uninstall a formula or cask", + args: { + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + }, + { + // NOTE: this is actually a command even if it has the double dash in the front + name: "--prefix", + description: "Prefix of ", + args: { + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + options: [ + { + name: "--unbrewed", + description: + "List files in Homebrew's prefix not installed by Homebrew", + }, + { + name: "--installed", + description: + "Outputs nothing and returns a failing status code if formula is not installed", + }, + ], + }, + { + name: "cask", + description: + "Homebrew Cask provides a friendly CLI workflow for the administration of macOS applications distributed as binaries", + subcommands: [ + { + name: "install", + description: "Installs the given cask", + args: { + name: "cask", + description: "Cask to install", + }, + }, + { + name: "uninstall", + description: "Uninstalls the given cask", + options: [ + ...commonOptions, + { + name: "--zap", + description: + "Remove all files associated with a cask. May remove files which are shared between applications", + }, + { + name: "--ignore-dependencies", + description: + "Don't fail uninstall, even if formula is a dependency of any installed formulae", + }, + { + name: "--formula", + description: "Treat all named arguments as formulae", + }, + { + name: "--cask", + description: "Treat all named arguments as casks", + }, + ], + args: { + isVariadic: true, + + generators: { + script: ["brew", "list", "-1", "--cask"], + postProcess: function (out) { + return out.split("\n").map((formula) => { + return { + name: formula, + icon: "🍺", + description: "Installed formula", + }; + }); + }, + }, + }, + }, + ], + }, + { + name: "cleanup", + description: + "Remove stale lock files and outdated downloads for all formulae and casks and remove old versions of installed formulae", + options: [ + ...commonOptions, + { + name: ["--prune", "--prune=all"], + description: "Remove all cache files older than specified days", + }, + { + name: ["-n", "--dry-run"], + description: + "Show what would be removed, but do not actually remove anything", + }, + { + name: "-s", + description: + "Scrub the cache, including downloads for even the latest versions", + }, + { + name: "--prune-prefix", + description: + "Only prune the symlinks and directories from the prefix and remove no other files", + }, + ], + args: { + isVariadic: true, + isOptional: true, + generators: servicesGenerator("Cleanup"), + }, + }, + { + name: "services", + description: + "Manage background services with macOS' launchctl(1) daemon manager", + options: [ + ...commonOptions, + { + name: "--file", + description: + "Use the plist file from this location to start or run the service", + }, + { + name: "--all", + description: "Run subcommand on all services", + }, + { + name: ["-v", "--verbose"], + description: "Make some output more verbose", + }, + { + name: ["-h", "--help"], + description: "Get help with services command", + }, + ], + subcommands: [ + { + name: "cleanup", + description: "Remove all unused services", + }, + { + name: "list", + description: "List all services", + }, + { + name: "run", + description: + "Run the service formula without registering to launch at login (or boot)", + options: [ + { + name: "--all", + description: "Start all services", + }, + ], + args: { + isVariadic: true, + generators: servicesGenerator("Run"), + }, + }, + { + name: "start", + description: + "Start the service formula immediately and register it to launch at login", + options: [ + { + name: "--all", + description: "Start all services", + }, + ], + args: { + isVariadic: true, + generators: servicesGenerator("Start"), + }, + }, + { + name: "stop", + description: + "Stop the service formula immediately and unregister it from launching at", + options: [ + { + name: "--all", + description: "Start all services", + }, + ], + args: { + isVariadic: true, + generators: servicesGenerator("Stop"), + }, + }, + { + name: "restart", + description: + "Stop (if necessary) and start the service formula immediately and register it to launch at login (or boot)", + options: [ + { + name: "--all", + description: "Start all services", + }, + ], + args: { + isVariadic: true, + generators: servicesGenerator("Restart"), + }, + }, + ], + }, + { + name: "analytics", + description: "Manages analytics preferences", + subcommands: [ + { + name: "on", + description: "Turns on analytics", + }, + { + name: "off", + description: "Turns off analytics", + }, + { + name: "regenerate-uuid", + description: "Regenerate the UUID used for analytics", + }, + ], + }, + { + name: "autoremove", + description: + "Uninstall formulae that were only installed as a dependency of another formula and are now no longer needed", + options: [ + { + name: ["-n", "--dry-run"], + description: + "List what would be uninstalled, but do not actually uninstall anything", + }, + ], + }, + { + name: "tap", + description: "Tap a formula repository", + options: [ + ...commonOptions, + { + name: "--full", + description: + "Convert a shallow clone to a full clone without untapping", + }, + { + name: "--shallow", + description: "Fetch tap as a shallow clone rather than a full clone", + }, + { + name: "--force-auto-update", + description: "Auto-update tap even if it is not hosted on GitHub", + }, + { + name: "--repair", + description: + "Migrate tapped formulae from symlink-based to directory-based structure", + }, + { + name: "--list-pinned", + description: "List all pinned taps", + }, + ], + args: { + name: "user/repo or URL", + }, + }, + { + name: "untap", + description: "Remove a tapped formula repository", + args: { + name: "repository", + generators: repositoriesGenerator(), + }, + options: [ + { + name: ["-f", "--force"], + description: + "Untap even if formulae or casks from this tap are currently installed", + }, + { + name: ["-d", "--debug"], + description: "Display any debugging information", + }, + { + name: ["-q", "--quiet"], + description: "Make some output more quiet", + }, + { + name: ["-v", "--verbose"], + description: "Make some output more verbose", + }, + { + name: ["-h", "--help"], + description: "Show help message", + }, + ], + }, + { + name: "link", + description: + "Symlink all of formula's installed files into Homebrew's prefix", + args: { + isOptional: true, + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + options: [ + { + name: "--overwrite", + description: + "Delete files that already exist in the prefix while linking", + }, + { + name: ["-n", "--dry-run"], + description: + "List files which would be linked or deleted by brew link --overwrite without actually linking or deleting any files", + }, + { + name: ["-f", "--force"], + description: "Allow keg-only formulae to be linked", + }, + { + name: "--HEAD", + description: + "Link the HEAD version of the formula if it is installed", + }, + ], + }, + { + name: "unlink", + description: "Remove symlinks for formula from Homebrew's prefix", + args: { + isOptional: true, + isVariadic: true, + name: "formula", + generators: formulaeGenerator, + }, + options: [ + { + name: ["-n", "--dry-run"], + description: + "List files which would be unlinked without actually unlinking or deleting any files", + }, + ], + }, + { + name: "formulae", + description: "List all available formulae", + }, + { + name: "casks", + description: "List all available casks", + }, + { + name: "edit", + description: "", + args: { + isVariadic: true, + isOptional: true, + name: "formula", + description: "Formula or cask to install", + generators: [generateAllFormulae, generateAllCasks], + }, + options: [ + ...commonOptions, + { + name: ["--formula", "--formulae"], + description: "Treat all named arguments as formulae", + }, + { + name: ["--cask", "--casks"], + description: "Treat all named arguments as casks", + }, + ], + }, + { + name: ["home", "homepage"], + description: + "Open a formula, cask's homepage in a browser, or open Homebrew's own homepage if no argument is provided", + args: { + isVariadic: true, + isOptional: true, + name: "formula", + description: "Formula or cask to open homepage for", + generators: [generateAllFormulae, generateAllCasks], + }, + options: [ + ...commonOptions, + { + name: ["--formula", "--formulae"], + description: "Treat all named arguments as formulae", + }, + { + name: ["--cask", "--casks"], + description: "Treat all named arguments as casks", + }, + ], + }, + { + name: "alias", + description: "Manage custom user created brew aliases", + options: [ + { + name: "--edit", + description: "Edit aliases in a text editor", + }, + { + name: ["-d", "--debug"], + description: "Display any debugging information", + }, + { + name: ["-q", "--quiet"], + description: "Make some output more quiet", + }, + { + name: ["-v", "--verbose"], + description: "Make some output more verbose", + }, + { + name: ["-h", "--help"], + description: "Show help message", + }, + ], + args: { + name: "alias", + generators: generateAliases, + description: "Display the alias command", + isOptional: true, + }, + }, + { + name: "developer", + description: "Display the current state of Homebrew's developer mode", + args: { + name: "state", + description: "Turn Homebrew's developer mode on or off respectively", + suggestions: ["on", "off"], + isOptional: true, + }, + }, + ], + options: [ + { + name: "--version", + description: "The current Homebrew version", + }, + ], + args: { + name: "alias", + generators: generateAliases, + description: "Custom user defined brew alias", + isOptional: true, + }, +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/cat.ts b/extensions/terminal-suggest/src/completions/upstream/cat.ts new file mode 100644 index 0000000000000..4e06dacd8b47c --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/cat.ts @@ -0,0 +1,50 @@ +const completionSpec: Fig.Spec = { + name: "cat", + description: "Concatenate and print files", + args: { + isVariadic: true, + template: "filepaths", + }, + options: [ + { + name: "-b", + description: "Number the non-blank output lines, starting at 1", + }, + + { + name: "-e", + description: + "Display non-printing characters (see the -v option), and display a dollar sign (β€˜$’) at the end of each line", + }, + + { + name: "-l", + description: + "Set an exclusive advisory lock on the standard output file descriptor. This lock is set using fcntl(2) with the F_SETLKW command. If the output file is already locked, cat will block until the lock is acquired", + }, + + { name: "-n", description: "Number the output lines, starting at 1" }, + + { + name: "-s", + description: + "Squeeze multiple adjacent empty lines, causing the output to be single spaced", + }, + + { + name: "-t", + description: + "Display non-printing characters (see the -v option), and display tab characters as β€˜^I’", + }, + + { name: "-u", description: "Disable output buffering" }, + + { + name: "-v", + description: + "Display non-printing characters so they are visible. Control characters print as β€˜^X’ for control-X; the delete character (octal 0177) prints as β€˜^?’. Non-ASCII characters (with the high bit set) are printed as β€˜M-’ (for meta) followed by the character for the low 7 bits", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/chmod.ts b/extensions/terminal-suggest/src/completions/upstream/chmod.ts new file mode 100644 index 0000000000000..93bc7264e8bba --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/chmod.ts @@ -0,0 +1,88 @@ +const completionSpec: Fig.Spec = { + name: "chmod", + description: "Change file modes or Access Control Lists", + args: [ + { + name: "mode", + suggestions: [ + // Some of the most common chmod's (non-exhaustive) + { + name: "u+x", + type: "arg", + description: "Give execute permission for the user", + icon: "πŸ”", + }, + { + name: "a+rx", + type: "arg", + description: "Adds read and execute permissions for all classes", + icon: "πŸ”", + }, + { + name: "744", + type: "arg", + description: + "Sets read, write, and execute permissions for user, and sets read permission for Group and Others", + icon: "πŸ”", + }, + { + name: "664", + type: "arg", + description: + "Sets read and write permissions for user and Group, and provides read to Others", + icon: "πŸ”", + }, + { + name: "777", + type: "arg", + description: "⚠️ allows all actions for all users", + icon: "πŸ”", + }, + ], + }, + { + // Modifying + template: "filepaths", + }, + ], + + options: [ + { + name: "-f", + description: + "Do not display a diagnostic message if chmod could not modify the mode for file, nor modify the exit status to reflect such failures", + }, + { + name: "-H", + description: + "If the -R option is specified, symbolic links on the command line are followed and hence unaffected by the command. (Symbolic links encountered during tree traversal are not followed.)", + }, + { + name: "-h", + description: + "If the file is a symbolic link, change the mode of the link itself rather than the file that the link points to", + }, + { + name: "-L", + description: + "If the -R option is specified, all symbolic links are followed", + }, + { + name: "-P", + description: + "If the -R option is specified, no symbolic links are followed. This is the default", + }, + { + name: "-R", + description: + "Change the modes of the file hierarchies rooted in the files, instead of just the files themselves. Beware of unintentionally matching the ``..'' hard link to the parent directory when using wildcards like ``.*''", + }, + { + name: "-v", + description: + "Cause chmod to be verbose, showing filenames as the mode is modified. If the -v flag is specified more than once, the old and new modes of the file will also be printed, in both octal and symbolic notation", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/chown.ts b/extensions/terminal-suggest/src/completions/upstream/chown.ts new file mode 100644 index 0000000000000..c271be0bd4016 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/chown.ts @@ -0,0 +1,117 @@ +export const existingUsersandGroups: Fig.Generator = { + custom: async function (tokens, executeShellCommand) { + const colonAdded = tokens.find((token) => token.includes(":")); + const nFlagUsed = tokens.find((token) => /^-.*n.*/.test(token)); + + let shell: string; + // Using `:` as a trigger, check to see if a colon is added + // in the current command. If it is, get the system groups + // else retrieve the list of system users + if (colonAdded) { + const { stdout } = await executeShellCommand({ + command: "bash", + args: [ + "-c", + "dscl . -list /Groups PrimaryGroupID | tr -s ' '| sort -r", + ], + }); + shell = stdout; + } else { + const { stdout } = await executeShellCommand({ + command: "bash", + args: ["-c", "dscl . -list /Users UniqueID | tr -s ' '| sort -r"], + }); + shell = stdout; + } + + return ( + shell + .split("\n") + // The shell command retrieves a table + // with rows that look like `user uid` + // so each row is split again to get the + // user/group and uid/gid + .map((line) => line.split(" ")) + .map((value) => { + return { + // If the user has entered the option n + // suggest the uid/gid instead of user/group + name: nFlagUsed ? value[1] : value[0], + description: colonAdded + ? `Group - ${nFlagUsed ? value[0] : `gid: ${value[1]}`}` + : `User - ${nFlagUsed ? value[0] : `uid: ${value[1]}`}`, + icon: colonAdded ? "πŸ‘₯" : "πŸ‘€", + priority: 90, + }; + }) + ); + }, + trigger: ":", + getQueryTerm: ":", +}; + +const completionSpec: Fig.Spec = { + name: "chown", + description: + "Change the user and/or group ownership of a given file, directory, or symbolic link", + args: [ + { + name: "owner[:group] or :group", + generators: existingUsersandGroups, + }, + { + name: "file/directory", + isVariadic: true, + template: ["filepaths", "folders"], + }, + ], + options: [ + { + name: "-f", + description: + "Don't report any failure to change file owner or group, nor modify the exit status to reflect such failures", + }, + { + name: "-h", + description: + "If the file is a symbolic link, change the user ID and/or the group ID of the link itself", + }, + { + name: "-n", + description: + "Interpret user ID and group ID as numeric, avoiding name lookups", + }, + { + name: "-v", + description: + "Cause chown to be verbose, showing files as the owner is modified", + }, + { + name: "-R", + description: + "Change the user ID and/or the group ID for the file hierarchies rooted in the files instead of just the files themselves", + }, + { + name: "-H", + description: + "If the -R option is specified, symbolic links on the command line are followed", + exclusiveOn: ["-L", "-P"], + dependsOn: ["-R"], + }, + { + name: "-L", + description: + "If the -R option is specified, all symbolic links are followed", + exclusiveOn: ["-H", "-P"], + dependsOn: ["-R"], + }, + { + name: "-P", + description: + "If the -R option is specified, no symbolic links are followed", + exclusiveOn: ["-H", "-L"], + dependsOn: ["-R"], + }, + ], +}; +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/cp.ts b/extensions/terminal-suggest/src/completions/upstream/cp.ts new file mode 100644 index 0000000000000..65d3d065cfdab --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/cp.ts @@ -0,0 +1,79 @@ +const completionSpec: Fig.Spec = { + name: "cp", + description: "Copy files and directories", + args: [ + { + name: "source", + template: ["filepaths", "folders"], + isVariadic: true, + }, + { + name: "target", + template: ["filepaths", "folders"], + }, + ], + options: [ + { + name: "-a", + description: + "Preserves structure and attributes of files but not directory structure", + }, + { + name: "-f", + description: + "If the destination file cannot be opened, remove it and create a new file, without prompting for confirmation", + exclusiveOn: ["-n"], + }, + { + name: "-H", + description: + "If the -R option is specified, symbolic links on the command line are followed", + exclusiveOn: ["-L", "-P"], + dependsOn: ["-R"], + }, + { + name: "-i", + description: + "Cause cp to write a prompt to the standard error output before copying a file that would overwrite an existing file", + exclusiveOn: ["-n"], + }, + { + name: "-L", + description: + "If the -R option is specified, all symbolic links are followed", + exclusiveOn: ["-H", "-P"], + dependsOn: ["-R"], + }, + { + name: "-n", + description: "Do not overwrite an existing file", + exclusiveOn: ["-f", "-i"], + }, + { + name: "-P", + description: + "If the -R option is specified, no symbolic links are followed", + exclusiveOn: ["-H", "-L"], + dependsOn: ["-R"], + }, + { + name: "-R", + description: + "If source designates a directory, cp copies the directory and the entire subtree connected at that point. If source ends in a /, the contents of the directory are copied rather than the directory itself", + }, + { + name: "-v", + description: "Cause cp to be verbose, showing files as they are copied", + }, + { + name: "-X", + description: "Do not copy Extended Attributes (EAs) or resource forks", + }, + { + name: "-c", + description: "Copy files using clonefile", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/curl.ts b/extensions/terminal-suggest/src/completions/upstream/curl.ts new file mode 100644 index 0000000000000..d47732b644727 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/curl.ts @@ -0,0 +1,914 @@ +const completionSpec: Fig.Spec = { + name: "curl", + description: "Transfer a URL", + args: { name: "URL", template: "history" }, + options: [ + { + name: ["-a", "--append"], + description: "Append to target file when uploading", + }, + { + name: ["-E", "--cert"], + description: "Client certificate file and password", + args: { + name: "certificate[:password]", + generators: { + getQueryTerm: ":", + }, + }, + }, + { + name: ["-K", "--config"], + description: "Read config from a file", + args: { name: "file", template: "filepaths" }, + }, + { + name: ["-C", "--continue-at"], + description: "Resumed transfer offset", + args: { name: "offset" }, + }, + { + name: ["-b", "--cookie"], + description: "Send cookies from string/file", + args: { name: "data or filename", template: "filepaths" }, + }, + { + name: ["-c", "--cookie-jar"], + description: "Write cookies to after operation", + args: { name: "filename", template: "filepaths" }, + }, + { + name: ["-d", "--data"], + description: "HTTP POST data", + insertValue: "-d '{cursor}'", + args: { name: "data" }, + isRepeatable: true, + }, + { name: ["-q", "--disable"], description: "Disable .curlrc" }, + { + name: ["-D", "--dump-header"], + description: "Write the received headers to ", + args: { name: "filename", template: "filepaths" }, + }, + { + name: ["-f", "--fail"], + description: "Fail silently (no output at all) on HTTP errors", + }, + { + name: ["-F", "--form"], + description: "Specify multipart MIME data", + args: { name: "content" }, + isRepeatable: true, + }, + { + name: ["-P", "--ftp-port"], + description: "Use PORT instead of PASV", + args: { name: "address" }, + }, + { + name: ["-G", "--get"], + description: "Put the post data in the URL and use GET", + }, + { + name: ["-g", "--globoff"], + description: "Disable URL sequences and ranges using {} and []", + }, + { name: ["-I", "--head"], description: "Show document info only" }, + { + name: ["-H", "--header"], + description: "Pass custom header(s) to server", + args: { + name: "header/file", + suggestions: [ + { name: "Content-Type: application/json" }, + { name: "Content-Type: application/x-www-form-urlencoded" }, + ], + }, + }, + { name: ["-h", "--help"], description: "This help text" }, + { name: ["-0", "--http1.0"], description: "Use HTTP 1.0" }, + { + name: ["-i", "--include"], + description: "Include protocol response headers in the output", + }, + { + name: ["-k", "--insecure"], + description: "Allow insecure server connections when using SSL", + }, + { name: ["-4", "--ipv4"], description: "Resolve names to IPv4 addresses" }, + { name: ["-6", "--ipv6"], description: "Resolve names to IPv6 addresses" }, + { + name: ["-j", "--junk-session-cookies"], + description: "Ignore session cookies read from file", + }, + { name: ["-l", "--list-only"], description: "List only mode" }, + { name: ["-L", "--location"], description: "Follow redirects" }, + { name: ["-M", "--manual"], description: "Display the full manual" }, + { + name: ["-m", "--max-time"], + description: "Maximum time allowed for the transfer", + args: { name: "seconds" }, + }, + { + name: ["-n", "--netrc"], + description: "Must read .netrc for user name and password", + }, + { + name: ["-:", "--next"], + description: "Make next URL use its separate set of options", + }, + { + name: ["-N", "--no-buffer"], + description: "Disable buffering of the output stream", + }, + { + name: ["-o", "--output"], + description: "Write to file instead of stdout", + args: { name: "file", template: "filepaths" }, + }, + { + name: ["-#", "--progress-bar"], + description: "Display transfer progress as a bar", + }, + { + name: ["-x", "--proxy"], + description: "[protocol://]host[:port] Use this proxy", + }, + { + name: ["-U", "--proxy-user"], + description: "Proxy user and password", + args: { name: "user:password" }, + }, + { + name: ["-p", "--proxytunnel"], + description: "Operate through an HTTP proxy tunnel (using CONNECT)", + }, + { + name: ["-Q", "--quote"], + description: "Send command(s) to server before transfer", + }, + { + name: ["-r", "--range"], + description: "Retrieve only the bytes within RANGE", + args: { name: "range" }, + }, + { + name: ["-e", "--referer"], + description: "Referrer URL", + args: { name: "URL" }, + }, + { + name: ["-J", "--remote-header-name"], + description: "Use the header-provided filename", + }, + { + name: ["-O", "--remote-name"], + description: "Write output to a file named as the remote file", + }, + { + name: ["-R", "--remote-time"], + description: "Set the remote file's time on the local output", + }, + { + name: ["-X", "--request"], + description: "Specify request command to use", + args: { + name: "command", + suggestions: [ + { name: "GET" }, + { name: "HEAD" }, + { name: "POST" }, + { name: "PUT" }, + { name: "DELETE" }, + { name: "CONNECT" }, + { name: "OPTIONS" }, + { name: "TRACE" }, + { name: "PATCH" }, + ], + }, + }, + { + name: ["-S", "--show-error"], + description: "Show error even when -s is used", + }, + { name: ["-s", "--silent"], description: "Silent mode" }, + { + name: ["-Y", "--speed-limit"], + description: "Stop transfers slower than this", + args: { name: "speed" }, + }, + { + name: ["-y", "--speed-time"], + description: "Trigger 'speed-limit' abort after this time", + args: { name: "seconds" }, + }, + { name: ["-2", "--sslv2"], description: "Use SSLv2" }, + { name: ["-3", "--sslv3"], description: "Use SSLv3" }, + { + name: ["-t", "--telnet-option"], + description: "Set telnet option", + args: { name: "val" }, + }, + { + name: ["-z", "--time-cond"], + description: "Transfer based on a time condition", + args: { name: "time" }, + }, + { name: ["-1", "--tlsv1"], description: "Use TLSv1.0 or greater" }, + { + name: ["-T", "--upload-file"], + description: "Transfer local FILE to destination", + args: { name: "file", template: "filepaths" }, + }, + { name: ["-B", "--use-ascii"], description: "Use ASCII/text transfer" }, + { + name: ["-u", "--user"], + description: "Server user and password", + args: { name: "user:password" }, + }, + { + name: ["-A", "--user-agent"], + description: "Send User-Agent to server", + args: { name: "name" }, + }, + { + name: ["-v", "--verbose"], + description: "Make the operation more talkative", + }, + { name: ["-V", "--version"], description: "Show version number and quit" }, + { + name: ["-w", "--write-out"], + description: "Use output FORMAT after completion", + args: { name: "format" }, + }, + { + name: "--abstract-unix-socket", + description: "Connect via abstract Unix domain socket", + args: { name: "path" }, + }, + { + name: "--alt-svc", + description: "Name> Enable alt-svc with this cache file", + args: { name: "file", template: "filepaths" }, + }, + { name: "--anyauth", description: "Pick any authentication method" }, + { name: "--basic", description: "Use HTTP Basic Authentication" }, + { + name: "--cacert", + description: "CA certificate to verify peer against", + args: { name: "file", template: "filepaths" }, + }, + { + name: "--capath", + description: "CA directory to verify peer against", + args: { name: "dir", template: "folders" }, + }, + { + name: "--cert-status", + description: "Verify the status of the server certificate", + }, + { + name: "--cert-type", + description: "Certificate file type", + args: { + name: "type", + suggestions: [{ name: "DER" }, { name: "PEM" }, { name: "ENG" }], + }, + }, + { + name: "--ciphers", + description: "Of ciphers> SSL ciphers to use", + args: { name: "list" }, + }, + { name: "--compressed", description: "Request compressed response" }, + { name: "--compressed-ssh", description: "Enable SSH compression" }, + { + name: "--connect-timeout", + description: "Maximum time allowed for connection", + args: { name: "seconds" }, + }, + { + name: "--connect-to", + description: "Connect to host", + args: { name: "HOST1:PORT1:HOST2:PORT2" }, + }, + { + name: "--create-dirs", + description: "Create necessary local directory hierarchy", + }, + { name: "--crlf", description: "Convert LF to CRLF in upload" }, + { + name: "--crlfile", + description: "Get a CRL list in PEM format from the given file", + args: { name: "file", template: "filepaths" }, + }, + { + name: "--data-ascii", + description: "HTTP POST ASCII data", + args: { name: "data" }, + }, + { + name: "--data-binary", + description: "HTTP POST binary data", + args: { name: "data" }, + }, + { + name: "--data-raw", + description: "HTTP POST data, '@' allowed", + args: { name: "data" }, + }, + { + name: "--data-urlencode", + description: "HTTP POST data url encoded", + args: { name: "data" }, + }, + { + name: "--delegation", + description: "GSS-API delegation permission", + args: { name: "LEVEL" }, + }, + { name: "--digest", description: "Use HTTP Digest Authentication" }, + { name: "--disable-eprt", description: "Inhibit using EPRT or LPRT" }, + { name: "--disable-epsv", description: "Inhibit using EPSV" }, + { + name: "--disallow-username-in-url", + description: "Disallow username in url", + }, + { + name: "--dns-interface", + description: "Interface to use for DNS requests", + args: { name: "interface" }, + }, + { + name: "--dns-ipv4-addr", + description: "IPv4 address to use for DNS requests", + args: { name: "address" }, + }, + { + name: "--dns-ipv6-addr", + description: "IPv6 address to use for DNS requests", + args: { name: "address" }, + }, + { + name: "--dns-servers", + description: "DNS server addrs to use", + args: { name: "addresses" }, + }, + { + name: "--doh-url", + description: "Resolve host names over DOH", + args: { name: "URL" }, + }, + { + name: "--egd-file", + description: "EGD socket path for random data", + args: { name: "file", template: "filepaths" }, + }, + { + name: "--engine", + description: "Crypto engine to use", + args: { name: "name" }, + }, + { + name: "--etag-compare", + description: + "Make a conditional HTTP request for the ETag read from the given file", + args: { name: "file" }, + }, + { + name: "--etag-save", + description: "Save an HTTP ETag to the specified file", + args: { name: "file" }, + }, + { + name: "--expect100-timeout", + description: "How long to wait for 100-continue", + args: { name: "seconds" }, + }, + { + name: "--fail-early", + description: "Fail on first transfer error, do not continue", + }, + { + name: "--fail-with-body", + description: + "On HTTP errors, return an error and also output any HTML response", + }, + { name: "--false-start", description: "Enable TLS False Start" }, + { + name: "--form-string", + description: "Specify multipart MIME data", + args: { name: "string" }, + }, + { + name: "--ftp-account", + description: "Account data string", + args: { name: "data" }, + }, + { + name: "--ftp-alternative-to-user", + description: "String to replace USER [name]", + args: { name: "command" }, + }, + { + name: "--ftp-create-dirs", + description: "Create the remote dirs if not present", + }, + { + name: "--ftp-method", + description: "Control CWD usage", + args: { name: "method" }, + }, + { name: "--ftp-pasv", description: "Use PASV/EPSV instead of PORT" }, + { name: "--ftp-pret", description: "Send PRET before PASV" }, + { name: "--ftp-skip-pasv-ip", description: "Skip the IP address for PASV" }, + { name: "--ftp-ssl-ccc", description: "Send CCC after authenticating" }, + { + name: "--ftp-ssl-ccc-mode", + description: "Set CCC mode", + args: { + name: "mode", + suggestions: [{ name: "active" }, { name: "passive" }], + }, + }, + { + name: "--ftp-ssl-control", + description: "Require SSL/TLS for FTP login, clear for transfer", + }, + { + name: "--happy-eyeballs-timeout-ms", + description: + "How long to wait in milliseconds for IPv6 before trying IPv4", + args: { name: "milliseconds" }, + }, + { + name: "--haproxy-protocol", + description: "Send HAProxy PROXY protocol v1 header", + }, + { + name: "--hostpubmd5", + description: "Acceptable MD5 hash of the host public key", + args: { name: "md5" }, + }, + { name: "--http0.9", description: "Allow HTTP 0.9 responses" }, + { name: "--http1.1", description: "Use HTTP 1.1" }, + { name: "--http2", description: "Use HTTP 2" }, + { + name: "--http2-prior-knowledge", + description: "Use HTTP 2 without HTTP/1.1 Upgrade", + }, + { + name: "--ignore-content-length", + description: "Ignore the size of the remote resource", + }, + { + name: "--interface", + description: "Use network INTERFACE (or address)", + args: { name: "name" }, + }, + { + name: "--keepalive-time", + description: "Interval time for keepalive probes", + args: { name: "seconds" }, + }, + { + name: "--key", + description: "Private key file name", + args: { name: "key" }, + }, + { + name: "--key-type", + description: "Private key file type", + args: { + name: "type", + suggestions: [{ name: "DER" }, { name: "PEM" }, { name: "ENG" }], + }, + }, + { + name: "--krb", + description: "Enable Kerberos with security ", + args: { name: "level" }, + }, + { + name: "--libcurl", + description: "Dump libcurl equivalent code of this command line", + args: { name: "file", template: "filepaths" }, + }, + { + name: "--limit-rate", + description: "Limit transfer speed to RATE", + args: { name: "speed" }, + }, + { + name: "--local-port", + description: "Force use of RANGE for local port numbers", + args: { name: "num/range" }, + }, + { + name: "--location-trusted", + description: "Like --location, and send auth to other hosts", + }, + { + name: "--login-options", + description: "Server login options", + args: { name: "options" }, + }, + { + name: "--mail-auth", + description: "Originator address of the original email", + args: { name: "address" }, + }, + { + name: "--mail-from", + description: "Mail from this address", + args: { name: "address" }, + }, + { + name: "--mail-rcpt", + description: "Mail to this address", + args: { name: "address" }, + }, + { + name: "--max-filesize", + description: "Maximum file size to download", + args: { name: "bytes" }, + }, + { + name: "--max-redirs", + description: "Maximum number of redirects allowed", + args: { name: "num" }, + }, + { + name: "--metalink", + description: "Process given URLs as metalink XML file", + }, + { + name: "--negotiate", + description: "Use HTTP Negotiate (SPNEGO) authentication", + }, + { + name: "--netrc-file", + description: "Specify FILE for netrc", + args: { name: "filename", template: "filepaths" }, + }, + { name: "--netrc-optional", description: "Use either .netrc or URL" }, + { name: "--no-alpn", description: "Disable the ALPN TLS extension" }, + { + name: "--no-keepalive", + description: "Disable TCP keepalive on the connection", + }, + { name: "--no-npn", description: "Disable the NPN TLS extension" }, + { name: "--no-sessionid", description: "Disable SSL session-ID reusing" }, + { + name: "--noproxy", + description: "List of hosts which do not use proxy", + args: { name: "no-proxy-list" }, + }, + { name: "--ntlm", description: "Use HTTP NTLM authentication" }, + { + name: "--ntlm-wb", + description: "Use HTTP NTLM authentication with winbind", + }, + { + name: "--oauth2-bearer", + description: "OAuth 2 Bearer Token", + args: { name: "token" }, + }, + { + name: "--pass", + description: "Pass phrase for the private key", + args: { name: "phrase" }, + }, + { + name: "--path-as-is", + description: "Do not squash .. sequences in URL path", + }, + { + name: "--pinnedpubkey", + description: "FILE/HASHES Public key to verify peer against", + args: { name: "hashes" }, + }, + { + name: "--post301", + description: "Do not switch to GET after following a 301", + }, + { + name: "--post302", + description: "Do not switch to GET after following a 302", + }, + { + name: "--post303", + description: "Do not switch to GET after following a 303", + }, + { + name: "--preproxy", + description: "[protocol://]host[:port] Use this proxy first", + }, + { + name: "--proto", + description: "Enable/disable PROTOCOLS", + args: { name: "protocols" }, + }, + { + name: "--proto-default", + description: "Use PROTOCOL for any URL missing a scheme", + args: { name: "protocol" }, + }, + { + name: "--proto-redir", + description: "Enable/disable PROTOCOLS on redirect", + args: { name: "protocols" }, + }, + { + name: "--proxy-anyauth", + description: "Pick any proxy authentication method", + }, + { + name: "--proxy-basic", + description: "Use Basic authentication on the proxy", + }, + { + name: "--proxy-cacert", + description: "CA certificate to verify peer against for proxy", + args: { name: "file", template: "filepaths" }, + }, + { + name: "--proxy-capath", + description: "CA directory to verify peer against for proxy", + args: { name: "dir", template: "folders" }, + }, + { + name: "--proxy-cert", + description: "Set client certificate for proxy", + args: { name: "cert[:passwd]" }, + }, + { + name: "--proxy-cert-type", + description: "Client certificate type for HTTPS proxy", + args: { name: "type" }, + }, + { + name: "--proxy-ciphers", + description: "SSL ciphers to use for proxy", + args: { name: "list" }, + }, + { + name: "--proxy-crlfile", + description: "Set a CRL list for proxy", + args: { name: "file", template: "filepaths" }, + }, + { + name: "--proxy-digest", + description: "Use Digest authentication on the proxy", + }, + { + name: "--proxy-header", + description: "Pass custom header(s) to proxy", + args: { + name: "header/file", + suggestions: [ + { name: "Content-Type: application/json" }, + { name: "Content-Type: application/x-www-form-urlencoded" }, + ], + }, + }, + { + name: "--proxy-insecure", + description: "Do HTTPS proxy connections without verifying the proxy", + }, + { + name: "--proxy-key", + description: "Private key for HTTPS proxy", + args: { name: "key" }, + }, + { + name: "--proxy-key-type", + description: "Private key file type for proxy", + args: { name: "type" }, + }, + { + name: "--proxy-negotiate", + description: "Use HTTP Negotiate (SPNEGO) authentication on the proxy", + }, + { + name: "--proxy-ntlm", + description: "Use NTLM authentication on the proxy", + }, + { + name: "--proxy-pass", + description: "Pass phrase for the private key for HTTPS proxy", + args: { name: "phrase" }, + }, + { + name: "--proxy-pinnedpubkey", + description: "FILE/HASHES public key to verify proxy with", + args: { name: "hashes" }, + }, + { + name: "--proxy-service-name", + description: "SPNEGO proxy service name", + args: { name: "name" }, + }, + { + name: "--proxy-ssl-allow-beast", + description: "Allow security flaw for interop for HTTPS proxy", + }, + { + name: "--proxy-tls13-ciphers", + description: "List> TLS 1.3 proxy cipher suites", + args: { name: "ciphersuite" }, + }, + { + name: "--proxy-tlsauthtype", + description: "TLS authentication type for HTTPS proxy", + args: { name: "type" }, + }, + { + name: "--proxy-tlspassword", + description: "TLS password for HTTPS proxy", + args: { name: "string" }, + }, + { + name: "--proxy-tlsuser", + description: "TLS username for HTTPS proxy", + args: { name: "name" }, + }, + { name: "--proxy-tlsv1", description: "Use TLSv1 for HTTPS proxy" }, + { + name: "--proxy1.0", + description: "Use HTTP/1.0 proxy on given port", + args: { name: "host[:port]" }, + }, + { + name: "--pubkey", + description: "SSH Public key file name", + args: { name: "key", template: "filepaths" }, + }, + { + name: "--random-file", + description: "File for reading random data from", + args: { name: "file", template: "filepaths" }, + }, + { name: "--raw", description: 'Do HTTP "raw"; no transfer decoding' }, + { + name: "--remote-name-all", + description: "Use the remote file name for all URLs", + }, + { + name: "--request-target", + description: "Specify the target for this request", + }, + { + name: "--resolve", + description: "Resolve the host+port to this address", + args: { name: "host:port:address[,address]..." }, + }, + { + name: "--retry", + description: "Retry request if transient problems occur", + args: { name: "num" }, + }, + { + name: "--retry-connrefused", + description: "Retry on connection refused (use with --retry)", + }, + { + name: "--retry-delay", + description: "Wait time between retries", + args: { name: "seconds" }, + }, + { + name: "--retry-max-time", + description: "Retry only within this period", + args: { name: "seconds" }, + }, + { + name: "--sasl-ir", + description: "Enable initial response in SASL authentication", + }, + { + name: "--service-name", + description: "SPNEGO service name", + args: { name: "name" }, + }, + { + name: "--socks4", + description: "SOCKS4 proxy on given host + port", + args: { name: "host[:port]" }, + }, + { + name: "--socks4a", + description: "SOCKS4a proxy on given host + port", + args: { name: "host[:port]" }, + }, + { + name: "--socks5", + description: "SOCKS5 proxy on given host + port", + args: { name: "host[:port]" }, + }, + { + name: "--socks5-basic", + description: "Enable username/password auth for SOCKS5 proxies", + }, + { + name: "--socks5-gssapi", + description: "Enable GSS-API auth for SOCKS5 proxies", + }, + { + name: "--socks5-gssapi-nec", + description: "Compatibility with NEC SOCKS5 server", + }, + { + name: "--socks5-gssapi-service", + description: "SOCKS5 proxy service name for GSS-API", + args: { name: "name" }, + }, + { + name: "--socks5-hostname", + description: "SOCKS5 proxy, pass host name to proxy", + args: { name: "host[:port]" }, + }, + { name: "--ssl", description: "Try SSL/TLS" }, + { + name: "--ssl-auto-client-cert", + description: "Obtain and use a client certificate automatically", + }, + { + name: "--ssl-allow-beast", + description: "Allow security flaw to improve interop", + }, + { + name: "--ssl-no-revoke", + description: "Disable cert revocation checks (Schannel)", + }, + { name: "--ssl-reqd", description: "Require SSL/TLS" }, + { name: "--stderr", description: "Where to redirect stderr" }, + { + name: "--styled-output", + description: "Enable styled output for HTTP headers", + }, + { + name: "--suppress-connect-headers", + description: "Suppress proxy CONNECT response headers", + }, + { name: "--tcp-fastopen", description: "Use TCP Fast Open" }, + { name: "--tcp-nodelay", description: "Use the TCP_NODELAY option" }, + { + name: "--tftp-blksize", + description: "Set TFTP BLKSIZE option", + args: { name: "value" }, + }, + { name: "--tftp-no-options", description: "Do not send any TFTP options" }, + { + name: "--tls-max", + description: "Set maximum allowed TLS version", + args: { name: "VERSION" }, + }, + { + name: "--tls13-ciphers", + description: "Of TLS 1.3 ciphersuites> TLS 1.3 cipher suites to use", + args: { name: "list" }, + }, + { + name: "--tlsauthtype", + description: "TLS authentication type", + args: { name: "type" }, + }, + { name: "--tlspassword", description: "TLS password" }, + { name: "--tlsuser", description: "TLS user name", args: { name: "name" } }, + { name: "--tlsv1.0", description: "Use TLSv1.0 or greater" }, + { name: "--tlsv1.1", description: "Use TLSv1.1 or greater" }, + { name: "--tlsv1.2", description: "Use TLSv1.2 or greater" }, + { name: "--tlsv1.3", description: "Use TLSv1.3 or greater" }, + { + name: "--tr-encoding", + description: "Request compressed transfer encoding", + }, + { + name: "--trace", + description: "Write a debug trace to FILE", + args: { name: "file", template: "filepaths" }, + }, + { + name: "--trace-ascii", + description: "Like --trace, but without hex output", + args: { name: "file", template: "filepaths" }, + }, + { + name: "--trace-time", + description: "Add time stamps to trace/verbose output", + }, + { + name: "--unix-socket", + description: "Connect through this Unix domain socket", + args: { name: "path" }, + }, + { name: "--url", description: "URL to work with", args: { name: "url" } }, + { + name: "--xattr", + description: "Store metadata in extended file attributes", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/df.ts b/extensions/terminal-suggest/src/completions/upstream/df.ts new file mode 100644 index 0000000000000..e7e005464ea91 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/df.ts @@ -0,0 +1,65 @@ +const completionSpec: Fig.Spec = { + name: "df", + description: "Display free disk space", + args: { + name: "file or filesystem", + }, + options: [ + { + name: "-a", + description: "Show all mount points", + }, + { + name: ["-b", "-P"], + description: "Use 512-byte blocks (default)", + exclusiveOn: ["-g", "-k", "-m"], + }, + { + name: "-g", + description: "Use 1073741824-byte (1-Gbyte) blocks", + exclusiveOn: ["-b", "-P", "-m", "-k"], + }, + { + name: "-m", + description: "Use 1048576-byte (1-Mbyte) blocks", + exclusiveOn: ["-b", "-P", "-g", "-k"], + }, + { + name: "-k", + description: "Use 1024-byte (1-Kbyte) blocks", + exclusiveOn: ["-b", "-P", "-g", "-m"], + }, + { + name: "-H", + description: '"Human-readable" output, uses base 10 unit suffixes', + exclusiveOn: ["-h"], + }, + { + name: "-h", + description: '"Human-readable" output, uses base 2 unit suffixes', + exclusiveOn: ["-H"], + }, + { + name: "-i", + description: "Include the number of free inodes", + }, + { + name: "-l", + description: "Only display information about locally-mounted filesystems", + }, + { + name: "-n", + description: "Print out the previously obtained statistics", + }, + { + name: "-T", + description: + "Only print out statistics for filesystems of the specified types (comma separated)", + args: { + name: "filesystem", + }, + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/du.ts b/extensions/terminal-suggest/src/completions/upstream/du.ts new file mode 100644 index 0000000000000..833fa52630f75 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/du.ts @@ -0,0 +1,93 @@ +const completionSpec: Fig.Spec = { + name: "du", + description: "Display disk usage statistics", + options: [ + { + name: "-a", + description: "Display an entry for each file in a file hierarchy", + exclusiveOn: ["-s", "-d"], + }, + { + name: "-c", + description: "Display a grand total", + }, + { + name: "-H", + description: + "Symbolic links on the command line are followed, symbolic links in file hierarchies are not followed", + exclusiveOn: ["-L", "-P"], + }, + { + name: "-h", + description: + '"Human-readable" output. Use unit suffixes: Byte, Kilobyte, Megabyte, Gigabyte, Terabyte and Petabyte', + exclusiveOn: ["-k", "-m", "-g"], + }, + { + name: "-g", + description: "Display block counts in 1073741824-byte (1-Gbyte) blocks", + exclusiveOn: ["-k", "-m", "-h"], + }, + { + name: "-k", + description: "Display block counts in 1024-byte (1-Kbyte) blocks", + exclusiveOn: ["-g", "-m", "-h"], + }, + { + name: "-m", + description: "Display block counts in 1048576-byte (1-Mbyte) blocks", + exclusiveOn: ["-g", "-k", "-h"], + }, + { + name: "-I", + description: "Ignore files and directories matching the specified mask", + args: { + name: "mask", + }, + }, + { + name: "-L", + description: + "Symbolic links on the command line and in file hierarchies are followed", + exclusiveOn: ["-H", "-P"], + }, + { + name: "-r", + description: + "Generate messages about directories that cannot be read, files that cannot be opened, and so on. This is the default case. This option exists solely for conformance with X/Open Portability Guide Issue 4 (``XPG4'')", + }, + { + name: "-P", + description: "No symbolic links are followed. This is the default", + exclusiveOn: ["-H", "-L"], + }, + { + name: "-d", + description: + "Display an entry for all files and directories depth directories deep", + exclusiveOn: ["-a", "-s"], + args: { + name: "depth", + suggestions: ["0", "1", "2"], + }, + }, + { + name: "-s", + description: + "Display an entry for each specified file. (Equivalent to -d 0)", + exclusiveOn: ["-a", "-d"], + }, + { + name: "-x", + description: + "Display an entry for each specified file. (Equivalent to -d 0)", + }, + ], + args: { + isOptional: true, + name: "files", + isVariadic: true, + template: ["filepaths", "folders"], + }, +}; +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/find.ts b/extensions/terminal-suggest/src/completions/upstream/find.ts new file mode 100644 index 0000000000000..5b5245cb5fddd --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/find.ts @@ -0,0 +1,71 @@ +const completionSpec: Fig.Spec = { + name: "find", + description: "Walk a file hierarchy", + args: [ + { + name: "path", + isOptional: true, + isVariadic: true, + template: ["folders"], + }, + { + // TODO Suggestions for primaries and operands. See `man find` + name: "expression", + description: "Composition of primaries and operands", + isOptional: true, + isVariadic: true, + }, + ], + options: [ + { + name: "-E", + description: + "Interpret regular expressions followed by -regex and -iregex primaries as extended", + }, + { + name: "-H", + description: + "Cause the file information and file type returned for each symbolic link specified to be those referenced by the link", + exclusiveOn: ["-L", "-P"], + }, + { + name: "-L", + description: + "Cause the file information and file type returned for each symbolic link to be those of the file referenced by the link", + exclusiveOn: ["-H", "-P"], + }, + { + name: "-P", + description: + "Cause the file information and file type returned for each symbolic link to be those for the link itself", + exclusiveOn: ["-H", "-L"], + }, + { + name: "-X", + description: "Permit find to be safely used in conjunction with xargs", + }, + { + name: "-d", + description: "Cause find to perform a depth-first traversal", + }, + { + name: "-f", + description: "Specify a file hierarch for find to traverse", + args: { + name: "path", + }, + }, + { + name: "-s", + description: + "Cause find to traverse the file hierarchies in lexicographical order", + }, + { + name: "-x", + description: + "Prevent find from descending into directories that have a device number different than that of the file from which the descent began", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/grep.ts b/extensions/terminal-suggest/src/completions/upstream/grep.ts new file mode 100644 index 0000000000000..a7c15281424ba --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/grep.ts @@ -0,0 +1,344 @@ +const completionSpec: Fig.Spec = { + name: "grep", + description: + "Matches patterns in input text. Supports simple patterns and regular expressions", + args: [ + { + name: "search pattern", + suggestCurrentToken: true, + }, + { + name: "file", + template: "filepaths", + }, + ], + options: [ + { + name: "--help", + description: + "Print a usage message briefly summarizing these command-line options and the bug-reporting address, then exit", + }, + { + name: ["-E", "--extended-regexp"], + description: + "Interpret PATTERN as an extended regular expression (-E is specified by POSIX.)", + }, + { + name: ["-F", "--fixed-string"], + description: + "Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched. (-F is specified by POSIX.)", + }, + { + name: ["-G", "--basic-regexp"], + description: + "Interpret PATTERN as a basic regular expression (BRE, see below). This is the default", + }, + { + name: ["-e", "--regexp"], + description: + "Use PATTERN as the pattern. This can be used to specify multiple search patterns, or to protect a pattern beginning with a hyphen (-). (-e is specified by POSIX.)", + args: { + name: "pattern", + }, + }, + { + name: ["-i", "--ignore-case", "-y"], + description: + "Ignore case distinctions in both the PATTERN and the input files. (-i is specified by POSIX.)", + }, + { + name: ["-v", "--invert-match"], + description: + "Invert the sense of matching, to select non-matching lines. (-v is specified by POSIX.)", + }, + { + name: ["-w", "--word-regexp"], + description: + "Select only those lines containing matches that form whole words. The test is that the matching substring must either be at the beginning of the line, or preceded by a non-word constituent character. Similarly, it must be either at the end of the line or followed by a non-word constituent character. Word-constituent characters are letters, digits, and the underscore", + }, + { + name: ["-x", "--line-regexp"], + description: + "Select only those matches that exactly match the whole line. (-x is specified by POSIX.)", + }, + { + name: ["-c", "--count"], + description: + "Suppress normal output; instead print a count of matching lines for each input file. With the -v, --invert-match option, count non-matching lines. (-c is specified by POSIX.)", + }, + { + name: "--color", + description: + "Surround the matched (non-empty) strings, matching lines, context lines, file names, line numbers, byte offsets, and separators (for fields and groups of context lines) with escape sequences to display them in color on the terminal. The colors are defined by the environment variable GREP_COLORS. The deprecated environment variable GREP_COLOR is still supported, but its setting does not have priority", + args: { + name: "WHEN", + default: "auto", + suggestions: ["never", "always", "auto"], + }, + }, + { + name: ["-L", "--files-without-match"], + exclusiveOn: ["-l", "--files-with-matches"], + description: + "Suppress normal output; instead print the name of each input file from which no output would normally have been printed. The scanning will stop on the first match", + }, + { + name: ["-l", "--files-with-matches"], + exclusiveOn: ["-L", "--files-without-match"], + description: + "Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match. (-l is specified by POSIX.)", + }, + { + name: ["-m", "--max-count"], + description: + "Stop reading a file after NUM matching lines. If the input is standard input from a regular file, and NUM matching lines are output, grep ensures that the standard input is positioned to just after the last matching line before exiting, regardless of the presence of trailing context lines. This enables a calling process to resume a search. When grep stops after NUM matching lines, it outputs any trailing context lines. When the -c or --count option is also used, grep does not output a count greater than NUM. When the -v or --invert-match option is also used, grep stops after outputting NUM non-matching lines", + args: { + name: "NUM", + }, + }, + { + name: ["-o", "--only-matching"], + description: + "Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line", + }, + { + name: ["-q", "--quiet", "--silent"], + description: + "Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected. Also see the -s or --no-messages option. (-q is specified by POSIX.)", + }, + { + name: ["-s", "--no-messages"], + description: + "Suppress error messages about nonexistent or unreadable files. Portability note: unlike GNU grep, 7th Edition Unix grep did not conform to POSIX, because it lacked -q and its -s option behaved like GNU grep's -q option. USG -style grep also lacked -q but its -s option behaved like GNU grep. Portable shell scripts should avoid both -q and -s and should redirect standard and error output to /dev/null instead. (-s is specified by POSIX.)", + }, + { + name: ["-b", "--byte-offset"], + description: + "Print the 0-based byte offset within the input file before each line of output. If -o (--only-matching) is specified, print the offset of the matching part itself", + }, + { + name: ["-H", "--with-filename"], + description: + "Print the file name for each match. This is the default when there is more than one file to search", + }, + { + name: ["-h", "--no-filename"], + description: + "Suppress the prefixing of file names on output. This is the default when there is only one file (or only standard input) to search", + }, + { + name: "--label", + description: + "Display input actually coming from standard input as input coming from file LABEL. This is especially useful when implementing tools like zgrep, e.g., gzip -cd foo.gz | grep --label=foo -H something", + args: { + name: "LABEL", + }, + }, + { + name: ["-n", "--line-number"], + description: + "Prefix each line of output with the 1-based line number within its input file. (-n is specified by POSIX.)", + }, + { + name: ["-T", "--initial-tab"], + description: + "Make sure that the first character of actual line content lies on a tab stop, so that the alignment of tabs looks normal. This is useful with options that prefix their output to the actual content: -H,-n, and -b. In order to improve the probability that lines from a single file will all start at the same column, this also causes the line number and byte offset (if present) to be printed in a minimum size field width", + }, + { + name: ["-u", "--unix-byte-offsets"], + description: + "Report Unix-style byte offsets. This switch causes grep to report byte offsets as if the file were a Unix-style text file, i.e., with CR characters stripped off. This will produce results identical to running grep on a Unix machine. This option has no effect unless -b option is also used; it has no effect on platforms other than MS-DOS and MS -Windows", + }, + { + name: "--null", + description: + "Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name. For example, grep -lZ outputs a zero byte after each file name instead of the usual newline. This option makes the output unambiguous, even in the presence of file names containing unusual characters like newlines. This option can be used with commands like find -print0, perl -0, sort -z, and xargs -0 to process arbitrary file names, even those that contain newline characters", + }, + { + name: ["-A", "--after-context"], + description: "Print num lines of trailing context after each match", + args: { + name: "NUM", + }, + }, + { + name: ["-B", "--before-context"], + description: + "Print num lines of leading context before each match. See also the -A and -C options", + args: { + name: "NUM", + }, + }, + { + name: ["-C", "--context"], + description: + "Print NUM lines of output context. Places a line containing a group separator (--) between contiguous groups of matches. With the -o or --only-matching option, this has no effect and a warning is given", + args: { + name: "NUM", + }, + }, + { + name: ["-a", "--text"], + description: + "Treat all files as ASCII text. Normally grep will simply print ``Binary file ... matches'' if files contain binary characters. Use of this option forces grep to output lines matching the specified pattern", + }, + { + name: "--binary-files", + description: "Controls searching and printing of binary files", + args: { + name: "value", + default: "binary", + suggestions: [ + { + name: "binary", + description: "Search binary files but do not print them", + }, + { + name: "without-match", + description: "Do not search binary files", + }, + { + name: "text", + description: "Treat all files as text", + }, + ], + }, + }, + { + name: ["-D", "--devices"], + description: "Specify the demanded action for devices, FIFOs and sockets", + args: { + name: "action", + default: "read", + suggestions: [ + { + name: "read", + description: "Read as if they were normal files", + }, + { + name: "skip", + description: "Devices will be silently skipped", + }, + ], + }, + }, + { + name: ["-d", "--directories"], + description: "Specify the demanded action for directories", + args: { + name: "action", + default: "read", + suggestions: [ + { + name: "read", + description: + "Directories are read in the same manner as normal files", + }, + { + name: "skip", + description: "Silently ignore the directories", + }, + { + name: "recurse", + description: "Read directories recursively", + }, + ], + }, + }, + { + name: "--exclude", + description: + "Note that --exclude patterns take priority over --include patterns, and if no --include pattern is specified, all files are searched that are not excluded. Patterns are matched to the full path specified, not only to the filename component", + args: { + name: "GLOB", + isOptional: true, + }, + }, + { + name: "--exclude-dir", + description: + "If -R is specified, only directories matching the given filename pattern are searched. Note that --exclude-dir patterns take priority over --include-dir patterns", + isRepeatable: true, + args: { + name: "dir", + template: "folders", + isOptional: true, + }, + }, + { + name: "-I", + description: + "Ignore binary files. This option is equivalent to --binary-file=without-match option", + }, + { + name: "--include", + description: + "If specified, only files matching the given filename pattern are searched. Note that --exclude patterns take priority over --include patterns. Patterns are matched to the full path specified, not only to the filename component", + args: { + name: "GLOB", + isOptional: true, + }, + }, + { + name: "--include-dir", + description: + "If -R is specified, only directories matching the given filename pattern are searched. Note that --exclude-dir patterns take priority over --include-dir patterns", + args: { + name: "dir", + template: "folders", + isOptional: true, + }, + }, + { + name: ["-R", "-r", "--recursive"], + description: "Recursively search subdirectories listed", + }, + { + name: "--line-buffered", + description: + "Force output to be line buffered. By default, output is line buffered when standard output is a terminal and block buffered otherwise", + }, + { + name: ["-U", "--binary"], + description: "Search binary files, but do not attempt to print them", + }, + { + name: ["-J", "-bz2decompress"], + description: + "Decompress the bzip2(1) compressed file before looking for the text", + }, + { + name: ["-V", "--version"], + description: "Print version number of grep to the standard output stream", + }, + { + name: ["-P", "--perl-regexp"], + description: "Interpret pattern as a Perl regular expression", + }, + { + name: ["-f", "--file"], + description: + "Obtain patterns from FILE, one per line. The empty file contains zero patterns, and therefore matches nothing. (-f is specified by POSIX.)", + args: { + name: "FILE", + template: "filepaths", + }, + }, + ], + additionalSuggestions: [ + { + name: "-RIn", + description: + "Search for a pattern [R]ecursively in the current directory, showing matching line [n]umbers, [I]gnoring non-text files", + insertValue: "-RI{cursor}", + }, + { + name: "-Hn", + description: + "Print file name with the corresponding line number (n) for each match", + insertValue: "-H{cursor}", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/head.ts b/extensions/terminal-suggest/src/completions/upstream/head.ts new file mode 100644 index 0000000000000..bc837e09dad19 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/head.ts @@ -0,0 +1,35 @@ +const completionSpec: Fig.Spec = { + name: "head", + description: "Output the first part of files", + args: { + name: "file", + template: "filepaths", + }, + options: [ + { + name: ["-c", "--bytes"], + description: "Print the first [numBytes] bytes of each file", + args: { name: "numBytes" }, + }, + { + name: ["-n", "--lines"], + description: "Print the first [numLines] lines instead of the first 10", + args: { name: "numLines" }, + }, + { + name: ["-q", "--quiet", "--silent"], + description: "Never print headers giving file names", + }, + { + name: ["-v", "--verbose"], + description: "Always print headers giving file names", + }, + { name: "--help", description: "Display this help and exit" }, + { + name: "--version", + description: "Output version information and exit", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/kill.ts b/extensions/terminal-suggest/src/completions/upstream/kill.ts new file mode 100644 index 0000000000000..5df83c453e191 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/kill.ts @@ -0,0 +1,63 @@ +// Compatibility: macOS + +function processIcon(path: string): string { + const idx = path.indexOf(".app/"); + if (idx === -1) { + return "fig://icon?type=gear"; + } + return "fig://" + path.slice(0, idx + 4); +} + +const completionSpec: Fig.Spec = { + name: "kill", + description: "Terminate or signal a process", + args: { + name: "pid", + isVariadic: true, + generators: { + script: ["bash", "-c", "ps axo pid,comm | sed 1d"], + postProcess: (result: string) => { + return result.split("\n").map((line) => { + const [pid, path] = line.trim().split(/\s+/); + const name = path.slice(path.lastIndexOf("/") + 1); + return { + name: pid, + description: path, + displayName: `${pid} (${name})`, + icon: processIcon(path), + }; + }); + }, + }, + }, + options: [ + { + name: "-s", + description: "A symbolic signal name specifying the signal to be sent", + args: { + name: "signal_name", + generators: { + // Bash's `kill` builtin has different output to /bin/kill + script: ["env", "kill", "-l"], + postProcess: (out) => + out.match(/\w+/g)?.map((name) => ({ + name, + description: `Send ${name} instead of TERM`, + icon: "fig://icon?type=string", + })), + }, + }, + }, + { + name: "-l", + description: + "If no operand is given, list the signal names; otherwise, write the signal name corresponding to exit_status", + args: { + name: "exit_status", + isOptional: true, + }, + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/killall.ts b/extensions/terminal-suggest/src/completions/upstream/killall.ts new file mode 100644 index 0000000000000..c22e55dd6a4fe --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/killall.ts @@ -0,0 +1,153 @@ +// Linux incompatible + +const signals = [ + "hup", + "int", + "quit", + "ill", + "trap", + "abrt", + "emt", + "fpe", + "kill", + "bus", + "segv", + "sys", + "pipe", + "alrm", + // This is the default signal + // "term", + "urg", + "stop", + "tstp", + "cont", + "chld", + "ttin", + "ttou", + "io", + "xcpu", + "xfsz", + "vtalrm", + "prof", + "winch", + "info", + "usr1", + "usr2", +]; + +const completionSpec: Fig.Spec = { + name: "killall", + description: "Kill processes by name", + args: { + name: "process_name", + isVariadic: true, + generators: { + // All processes, only display the path + script: ["bash", "-c", "ps -A -o comm | sort -u"], + postProcess: (out) => + out + .trim() + .split("\n") + .map((path) => { + const appExtIndex = path.indexOf(".app/"); + const isApp = appExtIndex !== -1; + const name = path.slice(path.lastIndexOf("/") + 1); + const nameChars = new Set(name); + const badChars = ["(", "_", "."]; + return { + name, + description: path, + priority: + !badChars.some((char) => nameChars.has(char)) && isApp + ? 51 + : 40, + icon: isApp + ? "fig://" + path.slice(0, appExtIndex + 4) + : "fig://icon?type=gear", + }; + }), + }, + }, + options: [ + { + name: "-d", + description: "Be verbose (dry run) and display number of user processes", + }, + { + name: "-e", + description: + "Use the effective user ID instead of the real user ID for matching processes with -u", + }, + { + name: "-help", + description: "Display help and exit", + }, + { + name: "-I", + description: "Request confirmation before killing each process", + }, + { + name: "-l", + description: "List the names of the available signals and exit", + }, + { + name: "-m", + description: "Match the process name as a regular expression", + }, + { + name: "-v", + description: "Be verbose", + }, + { + name: "-s", + description: "Be verbose (dry run)", + }, + ...signals.map((signal) => ({ + name: "-SIG" + signal.toUpperCase(), + description: `Send ${signal.toUpperCase()} instead of TERM`, + })), + { + name: "-u", + description: + "Limit potentially matching processes to those belonging to the user", + args: { + name: "user", + generators: { + script: ["bash", "-c", "dscl . -list /Users | grep -v '^_'"], + postProcess: (out) => + out + .trim() + .split("\n") + .map((username) => ({ + name: username, + icon: "fig://template?badge=πŸ‘€", + })), + }, + }, + }, + { + name: "-t", + description: + "Limit matching processes to those running on the specified TTY", + args: { + name: "tty", + }, + }, + { + name: "-c", + description: "Limit matching processes to those matching the given name", + args: { + name: "name", + }, + }, + { + name: "-q", + description: "Suppress error message if no processes are matched", + }, + { + name: "-z", + description: "Do not skip zombies", + }, + ], +}; +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/less.ts b/extensions/terminal-suggest/src/completions/upstream/less.ts new file mode 100644 index 0000000000000..f8994808a44d0 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/less.ts @@ -0,0 +1,676 @@ +const completionSpec: Fig.Spec = { + name: "less", + description: "Opposite of more", + args: { + isVariadic: true, + template: "filepaths", + }, + options: [ + { + name: ["-?", "--help"], + description: + 'This option displays a summary of the commands accepted by less (the same as the h command). (Depending on how your shell interprets the question mark, it may be necessary to quote the question mark, thus: "-?"', + }, + { + name: ["-a", "--search-skip-screen"], + description: `By default, forward searches start at the top of the displayed +screen and backwards searches start at the bottom of the +displayed screen (except for repeated searches invoked by the n +or N commands, which start after or before the "target" line +respectively; see the -j option for more about the target line). +The -a option causes forward searches to instead start at the +bottom of the screen and backward searches to start at the top +of the screen, thus skipping all lines displayed on the screen`, + }, + { + name: ["-A", "--SEARCH-SKIP-SCREEN"], + description: `Causes all forward searches (not just non-repeated searches) to +start just after the target line, and all backward searches to +start just before the target line. Thus, forward searches will +skip part of the displayed screen (from the first line up to and +including the target line). Similarly backwards searches will +skip the displayed screen from the last line up to and including +the target line. This was the default behavior in less versions +prior to 441`, + }, + + { + name: ["-b", "--buffers"], + args: { name: "n" }, + description: `Specifies the amount of buffer space less will use for each +file, in units of kilobytes (1024 bytes). By default 64Β KB of +buffer space is used for each file (unless the file is a pipe; +see the -B option). The -b option specifies instead that n +kilobytes of buffer space should be used for each file. If n is +-1, buffer space is unlimited; that is, the entire file can be +read into memory`, + }, + + { + name: ["-B", "--auto-buffers"], + description: `By default, when data is read from a pipe, buffers are allocated +automatically as needed. If a large amount of data is read from +the pipe, this can cause a large amount of memory to be +allocated. The -B option disables this automatic allocation of +buffers for pipes, so that only 64Β KB (or the amount of space +specified by the -b option) is used for the pipe. Warning: use +of -B can result in erroneous display, since only the most +recently viewed part of the piped data is kept in memory; any +earlier data is lost`, + }, + + { + name: ["-c", "--clear-screen"], + description: `Causes full screen repaints to be painted from the top line +down. By default, full screen repaints are done by scrolling +from the bottom of the screen`, + }, + + { + name: ["-C", "--CLEAR-SCREEN"], + description: `Same as -c, for compatibility with older versions of less`, + }, + + { + name: ["-d", "--dumb"], + description: `The -d option suppresses the error message normally displayed if +the terminal is dumb; that is, lacks some important capability, +such as the ability to clear the screen or scroll backward. The +-d option does not otherwise change the behavior of less on a +dumb terminal`, + }, + + { + name: ["-D", "--color"], + args: { name: "xcolor" }, + description: `Changes the color of different parts of the displayed text. x +is a single character which selects the type of text whose color +is being set: +B Binary characters. +C Control characters. +E Errors and informational messages. +M Mark letters in the status column. +N Line numbers enabled via the -N option. +P Prompts. +R The rscroll character. +S Search results. +W The highlight enabled via the -w option. +d Bold text. +k Blinking text. +s Standout text. +u Underlined text. +The uppercase letters can be used only when the --use-color +option is enabled. When text color is specified by both an +uppercase letter and a lowercase letter, the uppercase letter +takes precedence. For example, error messages are normally +displayed as standout text. So if both "s" and "E" are given a +color, the "E" color applies to error messages, and the "s" +color applies to other standout text. The "d" and "u" letters +refer to bold and underline text formed by overstriking with +backspaces (see the -u option), not to text using ANSI escape +sequences with the -R option. +A lowercase letter may be followed by a + to indicate that both +the normal format change and the specified color should both be +used. For example, -Dug displays underlined text as green +without underlining; the green color has replaced the usual +underline formatting. But -Du+g displays underlined text as +both green and in underlined format. +color is either a 4-bit color string or an 8-bit color string: +A 4-bit color string is zero, one or two characters, where the +first character specifies the foreground color and the second +specifies the background color as follows: +b Blue +c Cyan +g Green +k Black +m Magenta +r Red +w White +y Yellow +The corresponding upper-case letter denotes a brighter shade of +the color. For example, -DNGk displays line numbers as bright +green text on a black background, and -DEbR displays error +messages as blue text on a bright red background. If either +character is a "-" or is omitted, the corresponding color is set +to that of normal text. +An 8-bit color string is one or two decimal integers separated +by a dot, where the first integer specifies the foreground color +and the second specifies the background color. Each integer is +a value between 0 and 255 inclusive which selects a "CSI 38;5" +color value (see +https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) +If either integer is a "-" or is omitted, the corresponding +color is set to that of normal text. On MS-DOS versions of +less, 8-bit color is not supported; instead, decimal values are +interpreted as 4-bit CHAR_INFO.Attributes values (see +https://docs.microsoft.com/en-us/windows/console/char-info-str)`, + }, + + { + name: ["-e", "--quit-at-eof"], + description: `Causes less to automatically exit the second time it reaches +end-of-file. By default, the only way to exit less is via the +"q" command`, + }, + + { + name: ["-E", "--QUIT-AT-EOF"], + description: `Causes less to automatically exit the first time it reaches end- +of-file`, + }, + + { + name: ["-f", "--force"], + description: `Forces non-regular files to be opened. (A non-regular file is a +directory or a device special file.) Also suppresses the +warning message when a binary file is opened. By default, less +will refuse to open non-regular files. Note that some operating +systems will not allow directories to be read, even if -f is +set`, + }, + + { + name: ["-F", "--quit-if-one-screen"], + description: `Causes less to automatically exit if the entire file can be +displayed on the first screen`, + }, + + { + name: ["-g", "--hilite-search"], + description: `Normally, less will highlight ALL strings which match the last +search command. The -g option changes this behavior to +highlight only the particular string which was found by the last +search command. This can cause less to run somewhat faster than +the default`, + }, + + { + name: ["-G", "--HILITE-SEARCH"], + description: `The -G option suppresses all highlighting of strings found by +search commands`, + }, + + { + name: ["-h", "--max-back-scroll"], + args: { name: "n" }, + description: `Specifies a maximum number of lines to scroll backward. If it +is necessary to scroll backward more than n lines, the screen is +repainted in a forward direction instead. (If the terminal does +not have the ability to scroll backward, -h0 is implied.)`, + }, + + { + name: ["-i", "--ignore-case"], + description: `Causes searches to ignore case; that is, uppercase and lowercase +are considered identical. This option is ignored if any +uppercase letters appear in the search pattern; in other words, +if a pattern contains uppercase letters, then that search does +not ignore case`, + }, + + { + name: ["-I", "--IGNORE-CASE"], + description: `Like -i, but searches ignore case even if the pattern contains +uppercase letters`, + }, + + { + name: ["-j", "--jump-target"], + args: { name: "n" }, + description: `Specifies a line on the screen where the "target" line is to be +positioned. The target line is the line specified by any +command to search for a pattern, jump to a line number, jump to +a file percentage or jump to a tag. The screen line may be +specified by a number: the top line on the screen is 1, the next +is 2, and so on. The number may be negative to specify a line +relative to the bottom of the screen: the bottom line on the +screen is -1, the second to the bottom is -2, and so on. +Alternately, the screen line may be specified as a fraction of +the height of the screen, starting with a decimal point: .5 is +in the middle of the screen, .3 is three tenths down from the +first line, and so on. If the line is specified as a fraction, +the actual line number is recalculated if the terminal window is +resized, so that the target line remains at the specified +fraction of the screen height. If any form of the -j option is +used, repeated forward searches (invoked with "n" or "N") begin +at the line immediately after the target line, and repeated +backward searches begin at the target line, unless changed by -a +or -A. For example, if "-j4" is used, the target line is the +fourth line on the screen, so forward searches begin at the +fifth line on the screen. However nonrepeated searches (invoked +with "/" or "?") always begin at the start or end of the current +screen respectively`, + }, + + { + name: ["-J", "--status-column"], + description: `Displays a status column at the left edge of the screen. The +status column shows the lines that matched the current search, +and any lines that are marked (via the m or M command)`, + }, + + { + name: ["-k", "--lesskey-file"], + args: { name: "filename", template: "filepaths" }, + description: `Causes less to open and interpret the named file as a lesskey(1) +file. Multiple -k options may be specified. If the LESSKEY or +LESSKEY_SYSTEM environment variable is set, or if a lesskey file +is found in a standard place (see KEY BINDINGS), it is also used +as a lesskey file`, + }, + + { + name: ["-K", "--quit-on-intr"], + description: `Causes less to exit immediately (with status 2) when an +interrupt character (usually ^C) is typed. Normally, an +interrupt character causes less to stop whatever it is doing and +return to its command prompt. Note that use of this option +makes it impossible to return to the command prompt from the "F" +command`, + }, + + { + name: ["-L", "--no-lessopen"], + description: `Ignore the LESSOPEN environment variable (see the INPUT +PREPROCESSOR section below). This option can be set from within +less, but it will apply only to files opened subsequently, not +to the file which is currently open`, + }, + + { + name: ["-m", "--long-prompt"], + description: `Causes less to prompt verbosely (like more), with the percent +into the file. By default, less prompts with a colon`, + }, + + { + name: ["-M", "--LONG-PROMPT"], + description: `Causes less to prompt even more verbosely than more`, + }, + + { + name: ["-n", "--line-numbers"], + description: `Suppresses line numbers. The default (to use line numbers) may +cause less to run more slowly in some cases, especially with a +very large input file. Suppressing line numbers with the -n +option will avoid this problem. Using line numbers means: the +line number will be displayed in the verbose prompt and in the = +command, and the v command will pass the current line number to +the editor (see also the discussion of LESSEDIT in PROMPTS +below)`, + }, + + { + name: ["-N", "--LINE-NUMBERS"], + description: `Causes a line number to be displayed at the beginning of each +line in the display`, + }, + + { + name: ["-o", "--log-file"], + args: { name: "filename", template: "filepaths" }, + description: `Causes less to copy its input to the named file as it is being +viewed. This applies only when the input file is a pipe, not an +ordinary file. If the file already exists, less will ask for +confirmation before overwriting it`, + }, + + { + name: ["-O", "--LOG-FILE"], + args: { name: "filename", template: "filepaths" }, + description: `The -O option is like -o, but it will overwrite an existing file +without asking for confirmation. +If no log file has been specified, the -o and -O options can be +used from within less to specify a log file. Without a file +name, they will simply report the name of the log file. The "s" +command is equivalent to specifying -o from within less`, + }, + + { + name: ["-p", "--pattern"], + args: { name: "pattern" }, + description: `The -p option on the command line is equivalent to specifying ++/pattern; that is, it tells less to start at the first +occurrence of pattern in the file`, + }, + + { + name: ["-P", "--prompt"], + args: { name: "prompt" }, + description: `Provides a way to tailor the three prompt styles to your own +preference. This option would normally be put in the LESS +environment variable, rather than being typed in with each less +command. Such an option must either be the last option in the +LESS variable, or be terminated by a dollar sign. +-Ps followed by a string changes the default (short) prompt to +that string. +-Pm changes the medium (-m) prompt. +-PM changes the long (-M) prompt. +-Ph changes the prompt for the help screen. +-P= changes the message printed by the = command. +-Pw changes the message printed while waiting for data (in the +F command). +All prompt strings consist of a sequence of letters and special +escape sequences. See the section on PROMPTS for more details`, + }, + + { + name: ["-q", "--quiet", "--silent"], + description: `Causes moderately "quiet" operation: the terminal bell is not +rung if an attempt is made to scroll past the end of the file or +before the beginning of the file. If the terminal has a "visual +bell", it is used instead. The bell will be rung on certain +other errors, such as typing an invalid character. The default +is to ring the terminal bell in all such cases`, + }, + + { + name: ["-Q", "--QUIET", "--SILENT"], + description: `Causes totally "quiet" operation: the terminal bell is never +rung. If the terminal has a "visual bell", it is used in all +cases where the terminal bell would have been rung`, + }, + + { + name: ["-r", "--raw-control-chars"], + description: `Causes "raw" control characters to be displayed. The default is +to display control characters using the caret notation; for +example, a control-A (octal 001) is displayed as "^A". Warning: +when the -r option is used, less cannot keep track of the actual +appearance of the screen (since this depends on how the screen +responds to each type of control character). Thus, various +display problems may result, such as long lines being split in +the wrong place. +USE OF THE -r OPTION IS NOT RECOMMENDED`, + }, + + { + name: ["-R", "--RAW-CONTROL-CHARS"], + description: `Like -r, but only ANSI "color" escape sequences and OSC 8 +hyperlink sequences are output in "raw" form. Unlike -r, the +screen appearance is maintained correctly, provided that there +are no escape sequences in the file other than these types of +escape sequences. Color escape sequences are only supported +when the color is changed within one line, not across lines. In +other words, the beginning of each line is assumed to be normal +(non-colored), regardless of any escape sequences in previous +lines. For the purpose of keeping track of screen appearance, +these escape sequences are assumed to not move the cursor. +OSC 8 hyperlinks are sequences of the form: +ESC ] 8 ; +ANSI color escape sequences are sequences of the form: +ESC [ ... m +where the "..." is zero or more color specification characters. +You can make less think that characters other than "m" can end +ANSI color escape sequences by setting the environment variable +LESSANSIENDCHARS to the list of characters which can end a color +escape sequence. And you can make less think that characters +other than the standard ones may appear between the ESC and the +m by setting the environment variable LESSANSIMIDCHARS to the +list of characters which can appear`, + }, + + { + name: ["-s", "--squeeze-blank-lines"], + description: `Causes consecutive blank lines to be squeezed into a single +blank line. This is useful when viewing nroff output`, + }, + + { + name: ["-S", "--chop-long-lines"], + description: `Causes lines longer than the screen width to be chopped +(truncated) rather than wrapped. That is, the portion of a long +line that does not fit in the screen width is not displayed +until you press RIGHT-ARROW. The default is to wrap long lines; +that is, display the remainder on the next line`, + }, + + { + name: ["-t", "--tag"], + args: { name: "tag" }, + description: `The -t option, followed immediately by a TAG, will edit the file +containing that tag. For this to work, tag information must be +available; for example, there may be a file in the current +directory called "tags", which was previously built by ctags(1) +or an equivalent command. If the environment variable +LESSGLOBALTAGS is set, it is taken to be the name of a command +compatible with global(1), and that command is executed to find +the tag. (See http://www.gnu.org/software/global/global.html). +The -t option may also be specified from within less (using the +- command) as a way of examining a new file. The command ":t" +is equivalent to specifying -t from within less`, + }, + + { + name: ["-T", "--tag-file"], + args: { name: "tagsfile" }, + description: `Specifies a tags file to be used instead of "tags"`, + }, + + { + name: ["-u", "--underline-special"], + description: `Causes backspaces and carriage returns to be treated as +printable characters; that is, they are sent to the terminal +when they appear in the input`, + }, + + { + name: ["-U", "--UNDERLINE-SPECIAL"], + description: `Causes backspaces, tabs, carriage returns and "formatting +characters" (as defined by Unicode) to be treated as control +characters; that is, they are handled as specified by the -r +option. +By default, if neither -u nor -U is given, backspaces which +appear adjacent to an underscore character are treated +specially: the underlined text is displayed using the terminal's +hardware underlining capability. Also, backspaces which appear +between two identical characters are treated specially: the +overstruck text is printed using the terminal's hardware +boldface capability. Other backspaces are deleted, along with +the preceding character. Carriage returns immediately followed +by a newline are deleted. Other carriage returns are handled as +specified by the -r option. Unicode formatting characters, such +as the Byte Order Mark, are sent to the terminal. Text which is +overstruck or underlined can be searched for if neither -u nor +-U is in effect`, + }, + + { + name: ["-V", "--version"], + description: `Displays the version number of less`, + }, + + { + name: ["-w", "--hilite-unread"], + description: `Temporarily highlights the first "new" line after a forward +movement of a full page. The first "new" line is the line +immediately following the line previously at the bottom of the +screen. Also highlights the target line after a g or p command. +The highlight is removed at the next command which causes +movement. The entire line is highlighted, unless the -J option +is in effect, in which case only the status column is +highlighted`, + }, + + { + name: ["-W", "--HILITE-UNREAD"], + description: `Like -w, but temporarily highlights the first new line after any +forward movement command larger than one line`, + }, + + { + name: ["-x", "--tabs="], + args: { name: "n,..." }, + description: `Sets tab stops. If only one n is specified, tab stops are set +at multiples of n. If multiple values separated by commas are +specified, tab stops are set at those positions, and then +continue with the same spacing as the last two. For example, +-x9,17 will set tabs at positions 9, 17, 25, 33, etc. The +default for n is 8`, + }, + + { + name: ["-X", "--no-init"], + description: `Disables sending the termcap initialization and deinitialization +strings to the terminal. This is sometimes desirable if the +deinitialization string does something unnecessary, like +clearing the screen`, + }, + + { + name: ["-y", "--max-forw-scroll"], + args: { name: "n" }, + description: `Specifies a maximum number of lines to scroll forward. If it is +necessary to scroll forward more than n lines, the screen is +repainted instead. The -c or -C option may be used to repaint +from the top of the screen if desired. By default, any forward +movement causes scrolling`, + }, + + { + name: ["-z", "--window"], + args: { name: "n" }, + description: `Changes the default scrolling window size to n lines. The +default is one screenful. The z and w commands can also be used +to change the window size. The "z" may be omitted for +compatibility with some versions of more. If the number n is +negative, it indicates n lines less than the current screen +size. For example, if the screen is 24 lines, -z-4 sets the +scrolling window to 20 lines. If the screen is resized to 40 +lines, the scrolling window automatically changes to 36 lines`, + }, + + { + name: "--quotes", + description: `Changes the filename quoting character. This may be necessary +if you are trying to name a file which contains both spaces and +quote characters. Followed by a single character, this changes +the quote character to that character. Filenames containing a +space should then be surrounded by that character rather than by +double quotes. Followed by two characters, changes the open +quote to the first character, and the close quote to the second +character. Filenames containing a space should then be preceded +by the open quote character and followed by the close quote +character. Note that even after the quote characters are +changed, this option remains -" (a dash followed by a double +quote)`, + }, + + { + name: ["-~", "--tilde"], + description: `Normally lines after end of file are displayed as a single tilde +(~). This option causes lines after end of file to be displayed +as blank lines`, + }, + + { + name: ["-#", "--shift"], + description: `Specifies the default number of positions to scroll horizontally +in the RIGHTARROW and LEFTARROW commands. If the number +specified is zero, it sets the default number of positions to +one half of the screen width. Alternately, the number may be +specified as a fraction of the width of the screen, starting +with a decimal point: .5 is half of the screen width, .3 is +three tenths of the screen width, and so on. If the number is +specified as a fraction, the actual number of scroll positions +is recalculated if the terminal window is resized, so that the +actual scroll remains at the specified fraction of the screen +width`, + }, + + { + name: "--follow-name", + description: `Normally, if the input file is renamed while an F command is +executing, less will continue to display the contents of the +original file despite its name change. If --follow-name is +specified, during an F command less will periodically attempt to +reopen the file by name. If the reopen succeeds and the file is +a different file from the original (which means that a new file +has been created with the same name as the original (now +renamed) file), less will display the contents of that new file`, + }, + { + name: "--incsearch", + description: `Subsequent search commands will be "incremental"; that is, less +will advance to the next line containing the search pattern as +each character of the pattern is typed in`, + }, + + { + name: "--line-num-width", + description: `Sets the minimum width of the line number field when the -N +option is in effect. The default is 7 characters`, + }, + { + name: "--mouse", + description: `Enables mouse input: scrolling the mouse wheel down moves +forward in the file, scrolling the mouse wheel up moves +backwards in the file, and clicking the mouse sets the "#" mark +to the line where the mouse is clicked. The number of lines to +scroll when the wheel is moved can be set by the --wheel-lines +option. Mouse input works only on terminals which support X11 +mouse reporting, and on the Windows version of less`, + }, + { + name: "--MOUSE", + description: `Like --mouse, except the direction scrolled on mouse wheel +movement is reversed`, + }, + { + name: "--no-keypad", + description: `Disables sending the keypad initialization and deinitialization +strings to the terminal. This is sometimes useful if the keypad +strings make the numeric keypad behave in an undesirable manner`, + }, + { + name: "--no-histdups", + description: `This option changes the behavior so that if a search string or +file name is typed in, and the same string is already in the +history list, the existing copy is removed from the history list +before the new one is added. Thus, a given string will appear +only once in the history list. Normally, a string may appear +multiple times`, + }, + { + name: "--rscroll", + description: `This option changes the character used to mark truncated lines. +It may begin with a two-character attribute indicator like +LESSBINFMT does. If there is no attribute indicator, standout +is used. If set to "-", truncated lines are not marked`, + }, + { + name: "--save-marks", + description: `Save marks in the history file, so marks are retained across +different invocations of less`, + }, + { + name: "--status-col-width", + description: `Sets the width of the status column when the -J option is in +effect. The default is 2 characters`, + }, + { + name: "--use-backslash", + description: `This option changes the interpretations of options which follow +this one. After the --use-backslash option, any backslash in an +option string is removed and the following character is taken +literally. This allows a dollar sign to be included in option +strings`, + }, + { + name: "--use-color", + description: `Enables the colored text in various places. The -D option can +be used to change the colors. Colored text works only if the +terminal supports ANSI color escape sequences (as defined in +ECMA-48 SGR; see +https://www.ecma-international.org/publications-and- +standards/standards/ecma-48)`, + }, + { + name: "--wheel-lines", + args: { name: "n" }, + description: `Set the number of lines to scroll when the mouse wheel is rolled`, + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/more.ts b/extensions/terminal-suggest/src/completions/upstream/more.ts new file mode 100644 index 0000000000000..a70c8ee9078d1 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/more.ts @@ -0,0 +1,55 @@ +const completionSpec: Fig.Spec = { + name: "more", + description: "Opposite of less", + options: [ + { + name: ["-d", "--silent"], + description: + "Prompt with '[Press space to continue, 'q' to quit.]', and display '[Press 'h' for instructions.]' instead of ringing the bell when an illegal key is pressed", + }, + { + name: ["-l", "--logical"], + description: "Do not pause after any line containing a ^L (form feed)", + }, + { + name: ["-f", "--no-pause"], + description: "Count logical lines, rather than screen lines", + }, + { + name: ["-p", "--print-over"], + description: "Instead, clear the whole screen and then display the text", + }, + { + name: ["-c", "--clean-print"], + description: + "Instead, paint each screen from the top, clearing the remainder of each line as it is displayed", + }, + { + name: ["-s", "--squeeze"], + description: "Squeeze multiple blank lines into one", + }, + { + name: ["-u", "--plain"], + description: "Silently ignored as backwards compatibility", + }, + { + name: ["-n", "--lines"], + description: "Specify the number of lines per screenful", + args: { name: "n" }, + }, + { + name: "--help", + description: "Display help text", + }, + { + name: ["-V", "--version"], + description: "Display version information", + }, + ], + args: { + isVariadic: true, + template: "filepaths", + }, +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/mv.ts b/extensions/terminal-suggest/src/completions/upstream/mv.ts new file mode 100644 index 0000000000000..bbf98bf49031f --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/mv.ts @@ -0,0 +1,40 @@ +const completionSpec: Fig.Spec = { + name: "mv", + description: "Move & rename files and folders", + args: [ + { + name: "source", + isVariadic: true, + template: ["filepaths", "folders"], + }, + { + name: "target", + template: ["filepaths", "folders"], + }, + ], + options: [ + { + name: "-f", + description: + "Do not prompt for confirmation before overwriting the destination path", + exclusiveOn: ["-i", "-n"], + }, + { + name: "-i", + description: + "Cause mv to write a prompt to standard error before moving a file that would overwrite an existing file", + exclusiveOn: ["-f", "-n"], + }, + { + name: "-n", + description: "Do not overwrite existing file", + exclusiveOn: ["-f", "-i"], + }, + { + name: "-v", + description: "Cause mv to be verbose, showing files after they are moved", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/nano.ts b/extensions/terminal-suggest/src/completions/upstream/nano.ts new file mode 100644 index 0000000000000..6064072e8731c --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/nano.ts @@ -0,0 +1,9 @@ +const completionSpec: Fig.Spec = { + name: "nano", + description: "Nano's ANOther editor, an enhanced free Pico clone", + args: { + template: "filepaths", + }, +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/node.ts b/extensions/terminal-suggest/src/completions/upstream/node.ts new file mode 100644 index 0000000000000..bc261c5affe47 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/node.ts @@ -0,0 +1,505 @@ +// import { filepaths } from "@fig/autocomplete-generators"; + +const completionSpec: Fig.Subcommand = { + name: "node", + description: "Run the node interpreter", + args: { + name: "node script", + isScript: true, + template: 'folders', + // generators: filepaths({ + // extensions: ["mjs", "js", "cjs"], + // editFileSuggestions: { priority: 76 }, + // }), + }, + options: [ + { + name: ["-e", "--eval=..."], + insertValue: "-e '{cursor}'", + description: "Evaluate script", + args: {}, + }, + { + name: "--watch", + description: "Watch input files", + }, + { + name: "--watch-path", + description: "Specify a watch directory or file", + args: { + name: "path", + template: "filepaths", + }, + isRepeatable: true, + }, + { + name: "--watch-preserve-output", + description: + "Disable the clearing of the console when watch mode restarts the process", + dependsOn: ["--watch", "--watch-path"], + }, + { + name: "--env-file", + description: "Specify a file containing environment variables", + args: { + name: "path", + template: "filepaths", + }, + isRepeatable: true, + }, + { + name: ["-p", "--print"], + description: "Evaluate script and print result", + }, + { + name: ["-c", "--check"], + description: "Syntax check script without executing", + }, + { + name: ["-v", "--version"], + description: "Print Node.js version", + }, + { + name: ["-i", "--interactive"], + description: + "Always enter the REPL even if stdin does not appear to be a terminal", + }, + { + name: ["-h", "--help"], + description: "Print node command line options (currently set)", + }, + { + name: "--inspect", + requiresSeparator: true, + args: { + name: "[host:]port", + isOptional: true, + }, + description: "Activate inspector on host:port (default: 127.0.0.1:9229)", + }, + { + name: "--preserve-symlinks", + description: + "Follows symlinks to directories when examining source code and templates for translation strings", + }, + ], + // generateSpec: async (tokens, executeShellCommand) => { + // const isAdonisJsonPresentCommand = "test -f .adonisrc.json"; + // if ( + // ( + // await executeShellCommand({ + // command: "bash", + // args: ["-c", "isAdonisJsonPresentCommand"], + // }) + // ).status === 0 + // ) { + // return { + // name: "node", + // subcommands: [ + // { + // name: "ace", + // description: "Run AdonisJS command-line", + // options: [ + // { + // name: ["-h", "--help"], + // description: "Display AdonisJS Ace help", + // }, + // { + // name: ["-v", "--version"], + // description: "Display AdonisJS version", + // }, + // ], + // subcommands: [ + // { + // name: "build", + // description: + // "Compile project from Typescript to Javascript. Also compiles the frontend assets if using webpack encore", + // options: [ + // { + // name: ["-prod", "--production"], + // description: "Build for production", + // }, + // { + // name: "--assets", + // description: + // "Build frontend assets when webpack encore is installed", + // }, + // { + // name: "--no-assets", + // description: "Disable building assets", + // }, + // { + // name: "--ignore-ts-errors", + // description: + // "Ignore typescript errors and complete the build process", + // }, + // { + // name: "--tsconfig", + // description: + // "Path to the TypeScript project configuration file", + // args: { + // name: "path", + // description: "Path to tsconfig.json", + // }, + // }, + // { + // name: "--encore-args", + // requiresSeparator: true, + // insertValue: "--encore-args='{cursor}'", + // description: + // "CLI options to pass to the encore command line", + // }, + // { + // name: "--client", + // args: { + // name: "name", + // }, + // description: + // "Select the package manager to decide which lock file to copy to the build folder", + // }, + // ], + // }, + // { + // name: ["configure", "invoke"], + // description: "Configure a given AdonisJS package", + // args: { + // name: "name", + // description: "Name of the package you want to configure", + // }, + // subcommands: [ + // { + // name: "@adonisjs/auth", + // description: "Trigger auto configuring auth package", + // }, + // { + // name: "@adonisjs/shield", + // description: "Trigger auto configuring shield package", + // }, + // { + // name: "@adonisjs/redis", + // description: "Trigger auto configuring redis package", + // }, + // { + // name: "@adonisjs/mail", + // description: "Trigger auto configuring mail package", + // }, + // ], + // }, + // { + // name: "repl", + // description: "Start a new REPL session", + // }, + // { + // name: "serve", + // description: + // "Start the AdonisJS HTTP server, along with the file watcher. Also starts the webpack dev server when webpack encore is installed", + // options: [ + // { + // name: "--assets", + // description: + // "Start webpack dev server when encore is installed", + // }, + // { + // name: "--no-assets", + // description: "Disable webpack dev server", + // }, + // { + // name: ["-w", "--watch"], + // description: + // "Watch for file changes and re-start the HTTP server on change", + // }, + // { + // name: ["-p", "--poll"], + // description: + // "Detect file changes by polling files instead of listening to filesystem events", + // }, + // { + // name: "--node-args", + // requiresSeparator: true, + // insertValue: "--node-args='{cursor}'", + // description: "CLI options to pass to the node command line", + // }, + // { + // name: "--encore-args", + // requiresSeparator: true, + // insertValue: "--encore-args='{cursor}'", + // description: + // "CLI options to pass to the encore command line", + // }, + // ], + // }, + // { + // name: "db:seed", + // description: "Execute database seeder files", + // options: [ + // { + // name: ["-c", "--connection"], + // description: + // "Define a custom database connection for the seeders", + // args: { + // name: "name", + // }, + // }, + // { + // name: ["-i", "--interactive"], + // description: "Run seeders in interactive mode", + // }, + // { + // name: ["-f", "--files"], + // args: { + // name: "file", + // isVariadic: true, + // template: "filepaths", + // }, + // description: + // "Define a custom set of seeders files names to run", + // }, + // ], + // }, + // { + // name: "dump:rcfile", + // description: + // "Dump contents of .adonisrc.json file along with defaults", + // }, + // { + // name: "generate:key", + // description: "Generate a new APP_KEY secret", + // }, + // { + // name: "generate:manifest", + // description: + // "Generate ace commands manifest file. Manifest file speeds up commands lookup", + // }, + // { + // name: "list:routes", + // description: "List application routes", + // }, + // { + // name: "make:command", + // description: "Make a new ace command", + // }, + // { + // name: "make:controller", + // description: "Make a new HTTP controller", + // args: { + // name: "name", + // description: "Name of the controller class", + // }, + // options: [ + // { + // name: ["-r", "--resource"], + // description: + // "Add resourceful methods to the controller class", + // }, + // { + // name: ["-e", "--exact"], + // description: + // "Create the controller with the exact name as provided", + // }, + // ], + // }, + // { + // name: "make:exception", + // description: "Make a new custom exception class", + // }, + // { + // name: "make:listener", + // description: "Make a new event listener class", + // }, + // { + // name: "make:mailer", + // description: "Make a new mailer class", + // args: { + // name: "name", + // description: "Mailer class name", + // }, + // }, + // { + // name: "make:middleware", + // description: "Make a new middleware", + // args: { + // name: "name", + // description: "Middleware class name", + // }, + // }, + // { + // name: "make:migration", + // description: "Make a new migration file", + // args: { + // name: "name", + // description: "Name of the migration file", + // }, + // options: [ + // { + // name: "--connection", + // description: + // "The connection flag is used to lookup the directory for the migration file", + // args: { + // name: "name", + // }, + // }, + // { + // name: "--folder", + // description: "Pre-select a migration directory", + // args: { + // name: "name", + // template: "filepaths", + // }, + // }, + // { + // name: "--create", + // description: + // "Define the table name for creating a new table", + // args: { + // name: "name", + // }, + // }, + // { + // name: "--table", + // description: + // "Define the table name for altering an existing table", + // args: { + // name: "name", + // }, + // }, + // ], + // }, + // { + // name: "make:model", + // description: "Make a new Lucid model", + // args: { + // name: "name", + // description: "Name of the model class", + // }, + // options: [ + // { + // name: ["-m", "--migration"], + // description: "Generate the migration for the model", + // }, + // { + // name: ["-c", "--controller"], + // description: "Generate the controller for the model", + // }, + // ], + // }, + // { + // name: "make:prldfile", + // description: "Make a new preload file", + // subcommands: [ + // { + // name: "events", + // description: "Make events preload file", + // }, + // ], + // }, + // { + // name: "make:provider", + // description: "Make a new provider class", + // }, + // { + // name: "make:seeder", + // description: "Make a new Seeder file", + // args: { + // name: "name", + // description: "Name of the seeder class", + // }, + // }, + // { + // name: "make:validator", + // description: "Make a new validator", + // args: { + // name: "name", + // description: "Name of the validator class", + // }, + // options: [ + // { + // name: ["-e", "--exact"], + // description: + // "Create the validator with the exact name as provided", + // }, + // ], + // }, + // { + // name: "make:view", + // description: "Make a new view template", + // args: { + // name: "name", + // description: "Name of the view", + // }, + // options: [ + // { + // name: ["-e", "--exact"], + // description: + // "Create the template file with the exact name as provided", + // }, + // ], + // }, + // { + // name: "migration:rollback", + // description: "Rollback migrations to a given batch number", + // options: [ + // { + // name: ["-c", "--connection"], + // description: "Define a custom database connection", + // args: { + // name: "name", + // }, + // }, + // { + // name: "--force", + // description: + // "Explicitly force to run migrations in production", + // isDangerous: true, + // }, + // { + // name: "--dry-run", + // description: + // "Print SQL queries, instead of running the migrations", + // }, + // { + // name: "--batch", + // args: { + // name: "number", + // description: "Use 0 to rollback to initial state", + // }, + // description: "Define custom batch number for rollback", + // }, + // ], + // }, + // { + // name: "migration:run", + // description: "Run pending migrations", + // options: [ + // { + // name: ["-c", "--connection"], + // description: "Define a custom database connection", + // args: { + // name: "name", + // }, + // }, + // { + // name: "--force", + // description: + // "Explicitly force to run migrations in production", + // isDangerous: true, + // }, + // { + // name: "--dry-run", + // description: + // "Print SQL queries, instead of running the migrations", + // }, + // ], + // }, + // { + // name: "migration:status", + // description: "Check migrations current status", + // }, + // ], + // }, + // ], + // }; + // } + // }, +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/npm.ts b/extensions/terminal-suggest/src/completions/upstream/npm.ts new file mode 100644 index 0000000000000..b48d8126444ca --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/npm.ts @@ -0,0 +1,1608 @@ +function uninstallSubcommand(named: string | string[]): Fig.Subcommand { + return { + name: named, + description: "Uninstall a package", + args: { + name: "package", + generators: dependenciesGenerator, + filterStrategy: "fuzzy", + isVariadic: true, + }, + options: npmUninstallOptions, + }; +} + +const atsInStr = (s: string) => (s.match(/@/g) || []).length; + +export const createNpmSearchHandler = + (keywords?: string[]) => + async ( + context: string[], + executeShellCommand: Fig.ExecuteCommandFunction, + shellContext: Fig.ShellContext + ): Promise => { + const searchTerm = context[context.length - 1]; + if (searchTerm === "") { + return []; + } + // Add optional keyword parameter + const keywordParameter = + keywords && keywords.length > 0 ? `+keywords:${keywords.join(",")}` : ""; + + const queryPackagesUrl = keywordParameter + ? `https://api.npms.io/v2/search?size=20&q=${searchTerm}${keywordParameter}` + : `https://api.npms.io/v2/search/suggestions?q=${searchTerm}&size=20`; + + // Query the API with the package name + const queryPackages = [ + "-s", + "-H", + "Accept: application/json", + queryPackagesUrl, + ]; + // We need to remove the '@' at the end of the searchTerm before querying versions + const queryVersions = [ + "-s", + "-H", + "Accept: application/vnd.npm.install-v1+json", + `https://registry.npmjs.org/${searchTerm.slice(0, -1)}`, + ]; + // If the end of our token is '@', then we want to generate version suggestions + // Otherwise, we want packages + const out = (query: string) => + executeShellCommand({ + command: "curl", + args: query[query.length - 1] === "@" ? queryVersions : queryPackages, + }); + // If our token starts with '@', then a 2nd '@' tells us we want + // versions. + // Otherwise, '@' anywhere else in the string will indicate the same. + const shouldGetVersion = searchTerm.startsWith("@") + ? atsInStr(searchTerm) > 1 + : searchTerm.includes("@"); + + try { + const data = JSON.parse((await out(searchTerm)).stdout); + if (shouldGetVersion) { + // create dist tags suggestions + const versions = Object.entries(data["dist-tags"] || {}).map( + ([key, value]) => ({ + name: key, + description: value, + }) + ) as Fig.Suggestion[]; + // create versions + versions.push( + ...Object.keys(data.versions) + .map((version) => ({ name: version }) as Fig.Suggestion) + .reverse() + ); + return versions; + } + + const results = keywordParameter ? data.results : data; + return results.map((item: any) => ({ + name: item.package.name, + description: item.package.description, + })) as Fig.Suggestion[]; + } catch (error) { + console.error({ error }); + return []; + } + }; + +// GENERATORS +export const npmSearchGenerator: Fig.Generator = { + trigger: (newToken, oldToken) => { + // If the package name starts with '@', we want to trigger when + // the 2nd '@' is typed because we'll need to generate version + // suggetsions + // e.g. @typescript-eslint/types + if (oldToken.startsWith("@")) { + return !(atsInStr(oldToken) > 1 && atsInStr(newToken) > 1); + } + + // If the package name doesn't start with '@', then trigger when + // we see the first '@' so we can generate version suggestions + return !(oldToken.includes("@") && newToken.includes("@")); + }, + getQueryTerm: "@", + cache: { + ttl: 1000 * 60 * 60 * 24 * 2, // 2 days + }, + custom: createNpmSearchHandler(), +}; + +const workspaceGenerator: Fig.Generator = { + // script: "cat $(npm prefix)/package.json", + custom: async (tokens, executeShellCommand) => { + const { stdout: npmPrefix } = await executeShellCommand({ + command: "npm", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: ["prefix"], + }); + + const { stdout: out } = await executeShellCommand({ + command: "cat", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: [`${npmPrefix}/package.json`], + }); + + const suggestions: Fig.Suggestion[] = []; + try { + if (out.trim() == "") { + return suggestions; + } + + const packageContent = JSON.parse(out); + const workspaces = packageContent["workspaces"]; + + if (workspaces) { + for (const workspace of workspaces) { + suggestions.push({ + name: workspace, + description: "Workspaces", + }); + } + } + } catch (e) { + console.log(e); + } + return suggestions; + }, +}; + +/** Generator that lists package.json dependencies */ +export const dependenciesGenerator: Fig.Generator = { + trigger: (newToken) => newToken === "-g" || newToken === "--global", + custom: async function (tokens, executeShellCommand) { + if (!tokens.includes("-g") && !tokens.includes("--global")) { + const { stdout: npmPrefix } = await executeShellCommand({ + command: "npm", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: ["prefix"], + }); + const { stdout: out } = await executeShellCommand({ + command: "cat", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: [`${npmPrefix}/package.json`], + }); + const packageContent = JSON.parse(out); + const dependencies = packageContent["dependencies"] ?? {}; + const devDependencies = packageContent["devDependencies"]; + const optionalDependencies = packageContent["optionalDependencies"] ?? {}; + Object.assign(dependencies, devDependencies, optionalDependencies); + + return Object.keys(dependencies) + .filter((pkgName) => { + const isListed = tokens.some((current) => current === pkgName); + return !isListed; + }) + .map((pkgName) => ({ + name: pkgName, + icon: "πŸ“¦", + description: dependencies[pkgName] + ? "dependency" + : optionalDependencies[pkgName] + ? "optionalDependency" + : "devDependency", + })); + } else { + const { stdout } = await executeShellCommand({ + command: "bash", + args: ["-c", "ls -1 `npm root -g`"], + }); + return stdout.split("\n").map((name) => ({ + name, + icon: "πŸ“¦", + description: "Global dependency", + })); + } + }, +}; + +/** Generator that lists package.json scripts (with the respect to the `fig` field) */ +export const npmScriptsGenerator: Fig.Generator = { + cache: { + strategy: "stale-while-revalidate", + cacheByDirectory: true, + }, + script: [ + "bash", + "-c", + "until [[ -f package.json ]] || [[ $PWD = '/' ]]; do cd ..; done; cat package.json", + ], + postProcess: function (out, [npmClient]) { + if (out.trim() == "") { + return []; + } + + try { + const packageContent = JSON.parse(out); + const scripts = packageContent["scripts"]; + const figCompletions = packageContent["fig"] || {}; + + if (scripts) { + return Object.entries(scripts).map(([scriptName, scriptContents]) => { + const icon = + npmClient === "yarn" + ? "fig://icon?type=yarn" + : "fig://icon?type=npm"; + const customScripts: Fig.Suggestion = figCompletions[scriptName]; + return { + name: scriptName, + icon, + description: scriptContents as string, + priority: 51, + /** + * If there are custom definitions for the scripts + * we want to override the default values + * */ + ...customScripts, + }; + }); + } + } catch (e) { + console.error(e); + } + + return []; + }, +}; + +const globalOption: Fig.Option = { + name: ["-g", "--global"], + description: + "Operates in 'global' mode, so that packages are installed into the prefix folder instead of the current working directory", +}; + +const jsonOption: Fig.Option = { + name: "--json", + description: "Show output in json format", +}; + +const omitOption: Fig.Option = { + name: "--omit", + description: "Dependency types to omit from the installation tree on disk", + args: { + name: "Package type", + default: "dev", + suggestions: ["dev", "optional", "peer"], + }, + isRepeatable: 3, +}; + +const parseableOption: Fig.Option = { + name: ["-p", "--parseable"], + description: + "Output parseable results from commands that write to standard output", +}; + +const longOption: Fig.Option = { + name: ["-l", "--long"], + description: "Show extended information", +}; + +const workSpaceOptions: Fig.Option[] = [ + { + name: ["-w", "--workspace"], + description: + "Enable running a command in the context of the configured workspaces of the current project", + args: { + name: "workspace", + generators: workspaceGenerator, + isVariadic: true, + }, + }, + { + name: ["-ws", "--workspaces"], + description: + "Enable running a command in the context of all the configured workspaces", + }, +]; + +const npmUninstallOptions: Fig.Option[] = [ + { + name: ["-S", "--save"], + description: "Package will be removed from your dependencies", + }, + { + name: ["-D", "--save-dev"], + description: "Package will appear in your `devDependencies`", + }, + { + name: ["-O", "--save-optional"], + description: "Package will appear in your `optionalDependencies`", + }, + { + name: "--no-save", + description: "Prevents saving to `dependencies`", + }, + { + name: "-g", + description: "Uninstall global package", + }, + ...workSpaceOptions, +]; + +const npmListOptions: Fig.Option[] = [ + { + name: ["-a", "-all"], + description: "Show all outdated or installed packages", + }, + jsonOption, + longOption, + parseableOption, + { + name: "--depth", + description: "The depth to go when recursing packages", + args: { name: "depth" }, + }, + { + name: "--link", + description: "Limits output to only those packages that are linked", + }, + { + name: "--package-lock-only", + description: + "Current operation will only use the package-lock.json, ignoring node_modules", + }, + { + name: "--no-unicode", + description: "Uses unicode characters in the tree output", + }, + globalOption, + omitOption, + ...workSpaceOptions, +]; + +const registryOption: Fig.Option = { + name: "--registry", + description: "The base URL of the npm registry", + args: { name: "registry" }, +}; + +const verboseOption: Fig.Option = { + name: "--verbose", + description: "Show extra information", + args: { name: "verbose" }, +}; + +const otpOption: Fig.Option = { + name: "--otp", + description: "One-time password from a two-factor authenticator", + args: { name: "otp" }, +}; + +const ignoreScriptsOption: Fig.Option = { + name: "--ignore-scripts", + description: + "If true, npm does not run scripts specified in package.json files", +}; + +const scriptShellOption: Fig.Option = { + name: "--script-shell", + description: + "The shell to use for scripts run with the npm exec, npm run and npm init commands", + args: { name: "script-shell" }, +}; + +const dryRunOption: Fig.Option = { + name: "--dry-run", + description: + "Indicates that you don't want npm to make any changes and that it should only report what it would have done", +}; + +const completionSpec: Fig.Spec = { + name: "npm", + parserDirectives: { + flagsArePosixNoncompliant: true, + }, + description: "Node package manager", + subcommands: [ + { + name: ["install", "i", "add"], + description: "Install a package and its dependencies", + args: { + name: "package", + isOptional: true, + generators: npmSearchGenerator, + debounce: true, + isVariadic: true, + }, + options: [ + { + name: ["-P", "--save-prod"], + description: + "Package will appear in your `dependencies`. This is the default unless `-D` or `-O` are present", + }, + { + name: ["-D", "--save-dev"], + description: "Package will appear in your `devDependencies`", + }, + { + name: ["-O", "--save-optional"], + description: "Package will appear in your `optionalDependencies`", + }, + { + name: "--no-save", + description: "Prevents saving to `dependencies`", + }, + { + name: ["-E", "--save-exact"], + description: + "Saved dependencies will be configured with an exact version rather than using npm's default semver range operator", + }, + { + name: ["-B", "--save-bundle"], + description: + "Saved dependencies will also be added to your bundleDependencies list", + }, + globalOption, + { + name: "--global-style", + description: + "Causes npm to install the package into your local node_modules folder with the same layout it uses with the global node_modules folder", + }, + { + name: "--legacy-bundling", + description: + "Causes npm to install the package such that versions of npm prior to 1.4, such as the one included with node 0.8, can install the package", + }, + { + name: "--legacy-peer-deps", + description: + "Bypass peerDependency auto-installation. Emulate install behavior of NPM v4 through v6", + }, + { + name: "--strict-peer-deps", + description: + "If set to true, and --legacy-peer-deps is not set, then any conflicting peerDependencies will be treated as an install failure", + }, + { + name: "--no-package-lock", + description: "Ignores package-lock.json files when installing", + }, + registryOption, + verboseOption, + omitOption, + ignoreScriptsOption, + { + name: "--no-audit", + description: + "Submit audit reports alongside the current npm command to the default registry and all registries configured for scopes", + }, + { + name: "--no-bin-links", + description: + "Tells npm to not create symlinks (or .cmd shims on Windows) for package executables", + }, + { + name: "--no-fund", + description: + "Hides the message at the end of each npm install acknowledging the number of dependencies looking for funding", + }, + dryRunOption, + ...workSpaceOptions, + ], + }, + { + name: ["run", "run-script"], + description: "Run arbitrary package scripts", + options: [ + ...workSpaceOptions, + { + name: "--if-present", + description: + "Npm will not exit with an error code when run-script is invoked for a script that isn't defined in the scripts section of package.json", + }, + { + name: "--silent", + description: "", + }, + ignoreScriptsOption, + scriptShellOption, + { + name: "--", + args: { + name: "args", + isVariadic: true, + // TODO: load the spec based on the runned script (see yarn spec `yarnScriptParsedDirectives`) + }, + }, + ], + args: { + name: "script", + description: "Script to run from your package.json", + filterStrategy: "fuzzy", + generators: npmScriptsGenerator, + }, + }, + { + name: "init", + description: "Trigger the initialization", + options: [ + { + name: ["-y", "--yes"], + description: + "Automatically answer 'yes' to any prompts that npm might print on the command line", + }, + { + name: "-w", + description: + "Create the folders and boilerplate expected while also adding a reference to your project workspaces property", + args: { name: "dir" }, + }, + ], + }, + { name: "access", description: "Set access controls on private packages" }, + { + name: ["adduser", "login"], + description: "Add a registry user account", + options: [ + registryOption, + { + name: "--scope", + description: + "Associate an operation with a scope for a scoped registry", + args: { + name: "scope", + description: "Scope name", + }, + }, + ], + }, + { + name: "audit", + description: "Run a security audit", + subcommands: [ + { + name: "fix", + description: + "If the fix argument is provided, then remediations will be applied to the package tree", + options: [ + dryRunOption, + { + name: ["-f", "--force"], + description: + "Removes various protections against unfortunate side effects, common mistakes, unnecessary performance degradation, and malicious input", + isDangerous: true, + }, + ...workSpaceOptions, + ], + }, + ], + options: [ + ...workSpaceOptions, + { + name: "--audit-level", + description: + "The minimum level of vulnerability for npm audit to exit with a non-zero exit code", + args: { + name: "audit", + suggestions: [ + "info", + "low", + "moderate", + "high", + "critical", + "none", + ], + }, + }, + { + name: "--package-lock-only", + description: + "Current operation will only use the package-lock.json, ignoring node_modules", + }, + jsonOption, + omitOption, + ], + }, + { + name: "bin", + description: "Print the folder where npm will install executables", + options: [globalOption], + }, + { + name: ["bugs", "issues"], + description: "Report bugs for a package in a web browser", + args: { + name: "package", + isOptional: true, + generators: npmSearchGenerator, + debounce: true, + isVariadic: true, + }, + options: [ + { + name: "--no-browser", + description: "Display in command line instead of browser", + exclusiveOn: ["--browser"], + }, + { + name: "--browser", + description: + "The browser that is called by the npm bugs command to open websites", + args: { name: "browser" }, + exclusiveOn: ["--no-browser"], + }, + registryOption, + ], + }, + { + name: "cache", + description: "Manipulates packages cache", + subcommands: [ + { + name: "add", + description: "Add the specified packages to the local cache", + }, + { + name: "clean", + description: "Delete all data out of the cache folder", + }, + { + name: "verify", + description: + "Verify the contents of the cache folder, garbage collecting any unneeded data, and verifying the integrity of the cache index and all cached data", + }, + ], + options: [ + { + name: "--cache", + args: { name: "cache" }, + description: "The location of npm's cache directory", + }, + ], + }, + { + name: ["ci", "clean-install", "install-clean"], + description: "Install a project with a clean slate", + options: [ + { + name: "--audit", + description: + 'When "true" submit audit reports alongside the current npm command to the default registry and all registries configured for scopes', + args: { + name: "audit", + suggestions: ["true", "false"], + }, + exclusiveOn: ["--no-audit"], + }, + { + name: "--no-audit", + description: + "Do not submit audit reports alongside the current npm command", + exclusiveOn: ["--audit"], + }, + ignoreScriptsOption, + scriptShellOption, + verboseOption, + registryOption, + ], + }, + { + name: "cit", + description: "Install a project with a clean slate and run tests", + }, + { + name: "clean-install-test", + description: "Install a project with a clean slate and run tests", + }, + { name: "completion", description: "Tab completion for npm" }, + { + name: ["config", "c"], + description: "Manage the npm configuration files", + subcommands: [ + { + name: "set", + description: "Sets the config key to the value", + args: [{ name: "key" }, { name: "value" }], + options: [ + { name: ["-g", "--global"], description: "Sets it globally" }, + ], + }, + { + name: "get", + description: "Echo the config value to stdout", + args: { name: "key" }, + }, + { + name: "list", + description: "Show all the config settings", + options: [ + { name: "-g", description: "Lists globally installed packages" }, + { name: "-l", description: "Also shows defaults" }, + jsonOption, + ], + }, + { + name: "delete", + description: "Deletes the key from all configuration files", + args: { name: "key" }, + }, + { + name: "edit", + description: "Opens the config file in an editor", + options: [ + { name: "--global", description: "Edits the global config" }, + ], + }, + ], + }, + { name: "create", description: "Create a package.json file" }, + { + name: ["dedupe", "ddp"], + description: "Reduce duplication in the package tree", + }, + { + name: "deprecate", + description: "Deprecate a version of a package", + options: [registryOption], + }, + { name: "dist-tag", description: "Modify package distribution tags" }, + { + name: ["docs", "home"], + description: "Open documentation for a package in a web browser", + args: { + name: "package", + isOptional: true, + generators: npmSearchGenerator, + debounce: true, + isVariadic: true, + }, + options: [ + ...workSpaceOptions, + registryOption, + { + name: "--no-browser", + description: "Display in command line instead of browser", + exclusiveOn: ["--browser"], + }, + { + name: "--browser", + description: + "The browser that is called by the npm docs command to open websites", + args: { name: "browser" }, + exclusiveOn: ["--no-browser"], + }, + ], + }, + { + name: "doctor", + description: "Check your npm environment", + options: [registryOption], + }, + { + name: "edit", + description: "Edit an installed package", + options: [ + { + name: "--editor", + description: "The command to run for npm edit or npm config edit", + }, + ], + }, + { + name: "explore", + description: "Browse an installed package", + args: { + name: "package", + filterStrategy: "fuzzy", + generators: dependenciesGenerator, + }, + }, + { name: "fund", description: "Retrieve funding information" }, + { name: "get", description: "Echo the config value to stdout" }, + { + name: "help", + description: "Get help on npm", + args: { + name: "term", + isVariadic: true, + description: "Terms to search for", + }, + options: [ + { + name: "--viewer", + description: "The program to use to view help content", + args: { + name: "viewer", + }, + }, + ], + }, + { + name: "help-search", + description: "Search npm help documentation", + args: { + name: "text", + description: "Text to search for", + }, + options: [longOption], + }, + { name: "hook", description: "Manage registry hooks" }, + { + name: "install-ci-test", + description: "Install a project with a clean slate and run tests", + }, + { name: "install-test", description: "Install package(s) and run tests" }, + { name: "it", description: "Install package(s) and run tests" }, + { + name: "link", + description: "Symlink a package folder", + args: { name: "path", template: "filepaths" }, + }, + { name: "ln", description: "Symlink a package folder" }, + { + name: "logout", + description: "Log out of the registry", + options: [ + registryOption, + { + name: "--scope", + description: + "Associate an operation with a scope for a scoped registry", + args: { + name: "scope", + description: "Scope name", + }, + }, + ], + }, + { + name: ["ls", "list"], + description: "List installed packages", + options: npmListOptions, + args: { name: "[@scope]/pkg", isVariadic: true }, + }, + { + name: "org", + description: "Manage orgs", + subcommands: [ + { + name: "set", + description: "Add a user to an org or manage roles", + args: [ + { + name: "orgname", + description: "Organization name", + }, + { + name: "username", + description: "User name", + }, + { + name: "role", + isOptional: true, + suggestions: ["developer", "admin", "owner"], + }, + ], + options: [registryOption, otpOption], + }, + { + name: "rm", + description: "Remove a user from an org", + args: [ + { + name: "orgname", + description: "Organization name", + }, + { + name: "username", + description: "User name", + }, + ], + options: [registryOption, otpOption], + }, + { + name: "ls", + description: + "List users in an org or see what roles a particular user has in an org", + args: [ + { + name: "orgname", + description: "Organization name", + }, + { + name: "username", + description: "User name", + isOptional: true, + }, + ], + options: [registryOption, otpOption, jsonOption, parseableOption], + }, + ], + }, + { + name: "outdated", + description: "Check for outdated packages", + args: { + name: "[<@scope>/]", + isVariadic: true, + isOptional: true, + }, + options: [ + { + name: ["-a", "-all"], + description: "Show all outdated or installed packages", + }, + jsonOption, + longOption, + parseableOption, + { + name: "-g", + description: "Checks globally", + }, + ...workSpaceOptions, + ], + }, + { + name: ["owner", "author"], + description: "Manage package owners", + subcommands: [ + { + name: "ls", + description: + "List all the users who have access to modify a package and push new versions. Handy when you need to know who to bug for help", + args: { name: "[@scope/]pkg" }, + options: [registryOption], + }, + { + name: "add", + description: + "Add a new user as a maintainer of a package. This user is enabled to modify metadata, publish new versions, and add other owners", + args: [{ name: "user" }, { name: "[@scope/]pkg" }], + options: [registryOption, otpOption], + }, + { + name: "rm", + description: + "Remove a user from the package owner list. This immediately revokes their privileges", + args: [{ name: "user" }, { name: "[@scope/]pkg" }], + options: [registryOption, otpOption], + }, + ], + }, + { + name: "pack", + description: "Create a tarball from a package", + args: { + name: "[<@scope>/]", + }, + options: [ + jsonOption, + dryRunOption, + ...workSpaceOptions, + { + name: "--pack-destination", + description: "Directory in which npm pack will save tarballs", + args: { + name: "pack-destination", + template: ["folders"], + }, + }, + ], + }, + { + name: "ping", + description: "Ping npm registry", + options: [registryOption], + }, + { + name: "pkg", + description: "Manages your package.json", + subcommands: [ + { + name: "get", + description: + "Retrieves a value key, defined in your package.json file. It is possible to get multiple values and values for child fields", + args: { + name: "field", + description: + "Name of the field to get. You can view child fields by separating them with a period", + isVariadic: true, + }, + options: [jsonOption, ...workSpaceOptions], + }, + { + name: "set", + description: + "Sets a value in your package.json based on the field value. It is possible to set multiple values and values for child fields", + args: { + // Format is =. How to achieve this? + name: "field", + description: + "Name of the field to set. You can set child fields by separating them with a period", + isVariadic: true, + }, + options: [ + jsonOption, + ...workSpaceOptions, + { + name: ["-f", "--force"], + description: + "Removes various protections against unfortunate side effects, common mistakes, unnecessary performance degradation, and malicious input. Allow clobbering existing values in npm pkg", + isDangerous: true, + }, + ], + }, + { + name: "delete", + description: "Deletes a key from your package.json", + args: { + name: "key", + description: + "Name of the key to delete. You can delete child fields by separating them with a period", + isVariadic: true, + }, + options: [ + ...workSpaceOptions, + { + name: ["-f", "--force"], + description: + "Removes various protections against unfortunate side effects, common mistakes, unnecessary performance degradation, and malicious input. Allow clobbering existing values in npm pkg", + isDangerous: true, + }, + ], + }, + ], + }, + { + name: "prefix", + description: "Display prefix", + options: [ + { + name: ["-g", "--global"], + description: "Print the global prefix to standard out", + }, + ], + }, + { + name: "profile", + description: "Change settings on your registry profile", + subcommands: [ + { + name: "get", + description: + "Display all of the properties of your profile, or one or more specific properties", + args: { + name: "property", + isOptional: true, + description: "Property name", + }, + options: [registryOption, jsonOption, parseableOption, otpOption], + }, + { + name: "set", + description: "Set the value of a profile property", + args: [ + { + name: "property", + description: "Property name", + suggestions: [ + "email", + "fullname", + "homepage", + "freenode", + "twitter", + "github", + ], + }, + { + name: "value", + description: "Property value", + }, + ], + options: [registryOption, jsonOption, parseableOption, otpOption], + subcommands: [ + { + name: "password", + description: + "Change your password. This is interactive, you'll be prompted for your current password and a new password", + }, + ], + }, + { + name: "enable-2fa", + description: "Enables two-factor authentication", + args: { + name: "mode", + description: + "Mode for two-factor authentication. Defaults to auth-and-writes mode", + isOptional: true, + suggestions: [ + { + name: "auth-only", + description: + "Require an OTP when logging in or making changes to your account's authentication", + }, + { + name: "auth-and-writes", + description: + "Requires an OTP at all the times auth-only does, and also requires one when publishing a module, setting the latest dist-tag, or changing access via npm access and npm owner", + }, + ], + }, + options: [registryOption, otpOption], + }, + { + name: "disable-2fa", + description: "Disables two-factor authentication", + options: [registryOption, otpOption], + }, + ], + }, + { + name: "prune", + description: "Remove extraneous packages", + args: { + name: "[<@scope>/]", + isOptional: true, + }, + options: [ + omitOption, + dryRunOption, + jsonOption, + { + name: "--production", + description: "Remove the packages specified in your devDependencies", + }, + ...workSpaceOptions, + ], + }, + { + name: "publish", + description: "Publish a package", + args: { + name: "tarball|folder", + isOptional: true, + description: + "A url or file path to a gzipped tar archive containing a single folder with a package.json file inside | A folder containing a package.json file", + template: ["folders"], + }, + options: [ + { + name: "--tag", + description: "Registers the published package with the given tag", + args: { name: "tag" }, + }, + ...workSpaceOptions, + { + name: "--access", + description: + "Sets scoped package to be publicly viewable if set to 'public'", + args: { + default: "restricted", + suggestions: ["restricted", "public"], + }, + }, + dryRunOption, + otpOption, + ], + }, + { + name: ["rebuild", "rb"], + description: "Rebuild a package", + args: { + name: "[<@scope>/][@]", + }, + options: [ + globalOption, + ...workSpaceOptions, + ignoreScriptsOption, + { + name: "--no-bin-links", + description: + "Tells npm to not create symlinks (or .cmd shims on Windows) for package executables", + }, + ], + }, + { + name: "repo", + description: "Open package repository page in the browser", + args: { + name: "package", + isOptional: true, + generators: npmSearchGenerator, + debounce: true, + isVariadic: true, + }, + options: [ + ...workSpaceOptions, + { + name: "--no-browser", + description: "Display in command line instead of browser", + exclusiveOn: ["--browser"], + }, + { + name: "--browser", + description: + "The browser that is called by the npm repo command to open websites", + args: { name: "browser" }, + exclusiveOn: ["--no-browser"], + }, + ], + }, + { + name: "restart", + description: "Restart a package", + options: [ + ignoreScriptsOption, + scriptShellOption, + { + name: "--", + args: { + name: "arg", + description: "Arguments to be passed to the restart script", + }, + }, + ], + }, + { + name: "root", + description: "Display npm root", + options: [ + { + name: ["-g", "--global"], + description: + "Print the effective global node_modules folder to standard out", + }, + ], + }, + { + name: ["search", "s", "se", "find"], + description: "Search for packages", + args: { + name: "search terms", + isVariadic: true, + }, + options: [ + longOption, + jsonOption, + { + name: "--color", + description: "Show colors", + args: { + name: "always", + suggestions: ["always"], + description: "Always show colors", + }, + exclusiveOn: ["--no-color"], + }, + { + name: "--no-color", + description: "Do not show colors", + exclusiveOn: ["--color"], + }, + parseableOption, + { + name: "--no-description", + description: "Do not show descriptions", + }, + { + name: "--searchopts", + description: + "Space-separated options that are always passed to search", + args: { + name: "searchopts", + }, + }, + { + name: "--searchexclude", + description: + "Space-separated options that limit the results from search", + args: { + name: "searchexclude", + }, + }, + registryOption, + { + name: "--prefer-online", + description: + "If true, staleness checks for cached data will be forced, making the CLI look for updates immediately even for fresh package data", + exclusiveOn: ["--prefer-offline", "--offline"], + }, + { + name: "--prefer-offline", + description: + "If true, staleness checks for cached data will be bypassed, but missing data will be requested from the server", + exclusiveOn: ["--prefer-online", "--offline"], + }, + { + name: "--offline", + description: + "Force offline mode: no network requests will be done during install", + exclusiveOn: ["--prefer-online", "--prefer-offline"], + }, + ], + }, + { name: "set", description: "Sets the config key to the value" }, + { + name: "set-script", + description: "Set tasks in the scripts section of package.json", + args: [ + { + name: "script", + description: + "Name of the task to be added to the scripts section of package.json", + }, + { + name: "command", + description: "Command to run when script is called", + }, + ], + options: workSpaceOptions, + }, + { + name: "shrinkwrap", + description: "Lock down dependency versions for publication", + }, + { + name: "star", + description: "Mark your favorite packages", + args: { + name: "pkg", + description: "Package to mark as favorite", + }, + options: [ + registryOption, + { + name: "--no-unicode", + description: "Do not use unicode characters in the tree output", + }, + ], + }, + { + name: "stars", + description: "View packages marked as favorites", + args: { + name: "user", + isOptional: true, + description: "View packages marked as favorites by ", + }, + options: [registryOption], + }, + { + name: "start", + description: "Start a package", + options: [ + ignoreScriptsOption, + scriptShellOption, + { + name: "--", + args: { + name: "arg", + description: "Arguments to be passed to the start script", + }, + }, + ], + }, + { + name: "stop", + description: "Stop a package", + options: [ + ignoreScriptsOption, + scriptShellOption, + { + name: "--", + args: { + name: "arg", + description: "Arguments to be passed to the stop script", + }, + }, + ], + }, + { + name: "team", + description: "Manage organization teams and team memberships", + subcommands: [ + { + name: "create", + args: { name: "scope:team" }, + options: [registryOption, otpOption], + }, + { + name: "destroy", + args: { name: "scope:team" }, + options: [registryOption, otpOption], + }, + { + name: "add", + args: [{ name: "scope:team" }, { name: "user" }], + options: [registryOption, otpOption], + }, + { + name: "rm", + args: [{ name: "scope:team" }, { name: "user" }], + options: [registryOption, otpOption], + }, + { + name: "ls", + args: { name: "scope|scope:team" }, + options: [registryOption, jsonOption, parseableOption], + }, + ], + }, + { + name: ["test", "tst", "t"], + description: "Test a package", + options: [ignoreScriptsOption, scriptShellOption], + }, + { + name: "token", + description: "Manage your authentication tokens", + subcommands: [ + { + name: "list", + description: "Shows a table of all active authentication tokens", + options: [jsonOption, parseableOption], + }, + { + name: "create", + description: "Create a new authentication token", + options: [ + { + name: "--read-only", + description: + "This is used to mark a token as unable to publish when configuring limited access tokens with the npm token create command", + }, + { + name: "--cidr", + description: + "This is a list of CIDR address to be used when configuring limited access tokens with the npm token create command", + isRepeatable: true, + args: { + name: "cidr", + }, + }, + ], + }, + { + name: "revoke", + description: + "Immediately removes an authentication token from the registry. You will no longer be able to use it", + args: { name: "idtoken" }, + }, + ], + options: [registryOption, otpOption], + }, + uninstallSubcommand("uninstall"), + uninstallSubcommand(["r", "rm"]), + uninstallSubcommand("un"), + uninstallSubcommand("remove"), + uninstallSubcommand("unlink"), + { + name: "unpublish", + description: "Remove a package from the registry", + args: { + name: "[<@scope>/][@]", + }, + options: [ + dryRunOption, + { + name: ["-f", "--force"], + description: + "Allow unpublishing all versions of a published package. Removes various protections against unfortunate side effects, common mistakes, unnecessary performance degradation, and malicious input", + isDangerous: true, + }, + ...workSpaceOptions, + ], + }, + { + name: "unstar", + description: "Remove an item from your favorite packages", + args: { + name: "pkg", + description: "Package to unmark as favorite", + }, + options: [ + registryOption, + otpOption, + { + name: "--no-unicode", + description: "Do not use unicode characters in the tree output", + }, + ], + }, + { + name: ["update", "upgrade", "up"], + description: "Update a package", + options: [ + { name: "-g", description: "Update global package" }, + { + name: "--global-style", + description: + "Causes npm to install the package into your local node_modules folder with the same layout it uses with the global node_modules folder", + }, + { + name: "--legacy-bundling", + description: + "Causes npm to install the package such that versions of npm prior to 1.4, such as the one included with node 0.8, can install the package", + }, + { + name: "--strict-peer-deps", + description: + "If set to true, and --legacy-peer-deps is not set, then any conflicting peerDependencies will be treated as an install failure", + }, + { + name: "--no-package-lock", + description: "Ignores package-lock.json files when installing", + }, + omitOption, + ignoreScriptsOption, + { + name: "--no-audit", + description: + "Submit audit reports alongside the current npm command to the default registry and all registries configured for scopes", + }, + { + name: "--no-bin-links", + description: + "Tells npm to not create symlinks (or .cmd shims on Windows) for package executables", + }, + { + name: "--no-fund", + description: + "Hides the message at the end of each npm install acknowledging the number of dependencies looking for funding", + }, + { + name: "--save", + description: + "Update the semver values of direct dependencies in your project package.json", + }, + dryRunOption, + ...workSpaceOptions, + ], + }, + { + name: "version", + description: "Bump a package version", + options: [ + ...workSpaceOptions, + jsonOption, + { + name: "--allow-same-version", + description: + "Prevents throwing an error when npm version is used to set the new version to the same value as the current version", + }, + { + name: "--no-commit-hooks", + description: + "Do not run git commit hooks when using the npm version command", + }, + { + name: "--no-git-tag-version", + description: + "Do not tag the commit when using the npm version command", + }, + { + name: "--preid", + description: + 'The "prerelease identifier" to use as a prefix for the "prerelease" part of a semver. Like the rc in 1.2.0-rc.8', + args: { + name: "prerelease-id", + }, + }, + { + name: "--sign-git-tag", + description: + "If set to true, then the npm version command will tag the version using -s to add a signature", + }, + ], + }, + { + name: ["view", "v", "info", "show"], + description: "View registry info", + options: [...workSpaceOptions, jsonOption], + }, + { + name: "whoami", + description: "Display npm username", + options: [registryOption], + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/npx.ts b/extensions/terminal-suggest/src/completions/upstream/npx.ts new file mode 100644 index 0000000000000..4143ed790d1b9 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/npx.ts @@ -0,0 +1,317 @@ +// import autocannon from "./autocannon"; + +export const npxSuggestions: Fig.Suggestion[] = [ + // { + // name: autocannon.name, + // ...("icon" in autocannon && { icon: autocannon.icon }), + // }, + { + name: "vite", + icon: "https://vitejs.dev/logo.svg", + }, + { + name: "babel", + icon: "https://raw.githubusercontent.com/babel/logo/master/babel.png", + }, + { + name: "create-react-native-app", + icon: "https://reactnative.dev/img/pwa/manifest-icon-512.png", + }, + { + name: "react-native", + icon: "https://reactnative.dev/img/pwa/manifest-icon-512.png", + }, + { + name: "tailwindcss", + icon: "https://tailwindcss.com/favicons/favicon-32x32.png", + }, + { + name: "next", + icon: "https://nextjs.org/static/favicon/favicon-16x16.png", + }, + { + name: "nuxi", + icon: "https://raw.githubusercontent.com/nuxt/framework/main/docs/public/icon.png", + }, + { + name: "gltfjsx", + icon: "https://raw.githubusercontent.com/pmndrs/branding/master/logo.svg", + }, + { + name: "prisma", + icon: "https://raw.githubusercontent.com/prisma/docs/main/src/images/favicon-16x16.png", + }, + { + name: "eslint", + icon: "https://raw.githubusercontent.com/eslint/eslint.org/main/src/static/icon-512.png", + }, + { + name: "prettier", + icon: "https://prettier.io/icon.png", + }, + { + name: "tsc", + icon: "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Typescript_logo_2020.svg/240px-Typescript_logo_2020.svg.png", + }, + { + name: "typeorm", + icon: "https://avatars.githubusercontent.com/u/20165699?s=200&v=4", + }, + // { + // name: "fig-teams", + // icon: "https://fig.io/icons/fig-light.png", + // }, + { + name: "@withfig/autocomplete-tools", + icon: "https://fig.io/icons/fig-light.png", + }, + { + name: "create-completion-spec", + icon: "https://fig.io/icons/fig-light.png", + }, + { + name: "@fig/publish-spec-to-team", + icon: "https://fig.io/icons/fig-light.png", + }, + { + name: "fig-teams@latest", + icon: "https://fig.io/icons/fig-light.png", + }, + { + name: "create-next-app", + icon: "https://nextjs.org/static/favicon/favicon-16x16.png", + }, + { + name: "create-t3-app", + icon: "https://create.t3.gg/favicon.svg", + }, + { + name: "create-discord-bot", + icon: "https://discordjs.dev/favicon-32x32.png", + }, + { + name: "create-video", + icon: "https://raw.githubusercontent.com/remotion-dev/remotion/main/packages/docs/static/img/logo-small.png", + }, + { + name: "remotion", + icon: "https://raw.githubusercontent.com/remotion-dev/remotion/main/packages/docs/static/img/logo-small.png", + }, + { + name: "create-remix", + icon: "https://remix.run/favicon-light.1.png", + }, + { + name: "remix", + icon: "https://remix.run/favicon-light.1.png", + }, + { + name: "playwright", + icon: "https://playwright.dev/img/playwright-logo.svg", + }, + { + name: "ignite-cli", + icon: "πŸ”₯", + }, + { + name: "vsce", + }, + { + name: "degit", + icon: "fig://icon?type=git", + }, + { + name: "@preset/cli", + icon: "https://raw.githubusercontent.com/preset/preset/main/.github/assets/logo.svg", + }, + { + name: "mikro-orm", + icon: "https://raw.githubusercontent.com/mikro-orm/mikro-orm/master/docs/static/img/favicon.ico", + }, + { + name: "pod-install", + }, + { + name: "capacitor", + icon: "https://capacitorjs.com/docs/img/meta/favicon.png", + }, + { + name: "cap", + icon: "https://capacitorjs.com/docs/img/meta/favicon.png", + }, + { + name: "@magnolia/cli", + icon: "https://avatars.githubusercontent.com/u/25686615?s=200&v=4", + }, + { + name: "stencil", + icon: "https://stenciljs.com/assets/icon/favicon.ico", + }, + { + name: "swagger-typescript-api", + icon: "https://static1.smartbear.co/swagger/media/assets/swagger_fav.png", + }, + { + name: "sta", + icon: "https://static1.smartbear.co/swagger/media/assets/swagger_fav.png", + }, + { + name: "@wordpress/create-block", + icon: "https://s1.wp.com/i/webclip.png", + }, + { + name: "astro", + icon: "https://astro.build/favicon.svg", + }, + { + name: "ampx", + icon: "https://raw.githubusercontent.com/aws-amplify/docs/refs/heads/main/public/favicon.ico", + }, +]; + +const completionSpec: Fig.Spec = { + name: "npx", + description: "Execute binaries from npm packages", + args: { + name: "command", + isCommand: true, + generators: { + script: [ + "bash", + "-c", + "until [[ -d node_modules/ ]] || [[ $PWD = '/' ]]; do cd ..; done; ls -1 node_modules/.bin/", + ], + postProcess: function (out) { + const cli = [...npxSuggestions].reduce( + (acc: any, { name }) => [...acc, name], + [] + ); + return out + .split("\n") + .filter((name) => !cli.includes(name)) + .map((name) => ({ + name, + icon: "fig://icon?type=command", + loadSpec: name, + })); + }, + }, + suggestions: [...npxSuggestions], + isOptional: true, + }, + + options: [ + { + name: ["--package", "-p"], + description: "Package to be installed", + args: { + name: "package", + }, + }, + { + name: "--cache", + args: { + name: "path", + template: "filepaths", + }, + description: "Location of the npm cache", + }, + { + name: "--always-spawn", + description: "Always spawn a child process to execute the command", + }, + { + name: "-y", + description: "Execute npx command without prompting for confirmation", + }, + { + description: "Skip installation if a package is missing", + name: "--no-install", + }, + { + args: { + name: "path", + template: "filepaths", + }, + description: "Path to user npmrc", + name: "--userconfig", + }, + { + name: ["--call", "-c"], + args: { + name: "script", + }, + description: "Execute string as if inside `npm run-script`", + }, + { + name: ["--shell", "-s"], + description: "Shell to execute the command with, if any", + args: { + name: "shell", + suggestions: [ + { + name: "bash", + }, + { + name: "fish", + }, + { + name: "zsh", + }, + ], + }, + }, + { + args: { + name: "shell-fallback", + suggestions: [ + { + name: "bash", + }, + { + name: "fish", + }, + { + name: "zsh", + }, + ], + }, + name: "--shell-auto-fallback", + description: + 'Generate shell code to use npx as the "command not found" fallback', + }, + { + name: "--ignore-existing", + description: + "Ignores existing binaries in $PATH, or in the localproject. This forces npx to do a temporary install and use the latest version", + }, + { + name: ["--quiet", "-q"], + description: + "Suppress output from npx itself. Subcommands will not be affected", + }, + { + name: "--npm", + args: { + name: "path to binary", + template: "filepaths", + }, + description: "Npm binary to use for internal operations", + }, + { + args: {}, + description: "Extra node argument when calling a node binary", + name: ["--node-arg", "-n"], + }, + { + description: "Show version number", + name: ["--version", "-v"], + }, + { + description: "Show help", + name: ["--help", "-h"], + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/nvm.ts b/extensions/terminal-suggest/src/completions/upstream/nvm.ts new file mode 100644 index 0000000000000..843ffef57de61 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/nvm.ts @@ -0,0 +1,318 @@ +// args +const version: Fig.Arg = { + name: "version", + description: "Node version", + suggestions: [ + { + name: "node", + description: "The latest version of node", + }, + { + name: "iojs", + description: "The latest version of io.js", + }, + { + name: "system", + description: "System-installed version of node", + }, + ], +}; + +const command: Fig.Arg = { + name: "command", + isVariadic: true, +}; + +const args: Fig.Arg = { + name: "args", + isVariadic: true, +}; + +// const pattern: Fig.Arg = { +// name: "pattern", +// }; + +const name: Fig.Arg = { + name: "name", +}; + +const ltsName: Fig.Arg = { + name: "LTS name", +}; + +const colorCodes: Fig.Arg = { + name: "color codes", + description: 'Using format "yMeBg"', +}; + +// options +const noColors: Fig.Option = { + name: "--no-colors", + description: "Suppress colored output", +}; + +const noAlias: Fig.Option = { + name: "--no-alias", + description: "Suppress `nvm alias` output", +}; + +const silent: Fig.Option = { + name: "--silent", + description: "Silences stdout/stderr output", +}; + +const lts: Fig.Option = { + name: "--lts", + description: + "Uses automatic LTS (long-term support) alias `lts/*`, if available", +}; + +const ltsWithName: Fig.Option = { + name: "--lts", + description: "Uses automatic alias for provided LTS line, if available", + args: ltsName, +}; + +const completionSpec: Fig.Spec = { + name: "nvm", + description: "Node Package Manager", + subcommands: [ + { + name: "install", + description: + "Download and install a . Uses .nvmrc if available and version is omitted", + args: { ...version, isOptional: true }, + options: [ + { + name: "-s", + description: "Skip binary download, install from source only", + }, + { + name: "--reinstall-packages-from", + description: + "When installing, reinstall packages installed in ", + args: version, + }, + { + ...lts, + description: + "When installing, only select from LTS (long-term support) versions", + }, + { + ...ltsWithName, + description: + "When installing, only select from versions for a specific LTS line", + }, + { + name: "--skip-default-packages", + description: + "When installing, skip the default-packages file if it exists", + }, + { + name: "--latest-npm", + description: + "After installing, attempt to upgrade to the latest working npm on the given node version", + }, + { + name: "--no-progress", + description: "Disable the progress bar on any downloads", + }, + { + name: "--alias", + description: + "After installing, set the alias specified to the version specified. (same as: nvm alias )", + args: name, + }, + { + name: "--default", + description: + "After installing, set default alias to the version specified. (same as: nvm alias default )", + }, + ], + }, + { + name: "uninstall", + description: "Uninstall a version", + args: version, + options: [ + { + ...lts, + description: + "Uninstall using automatic LTS (long-term support) alias `lts/*`, if available", + }, + { + ...ltsWithName, + description: + "Uninstall using automatic alias for provided LTS line, if available", + }, + ], + }, + { + name: "use", + description: + "Modify PATH to use . Uses .nvmrc if available and version is omitted", + args: { ...version, isOptional: true }, + options: [silent, lts, ltsWithName], + }, + { + name: "exec", + description: + "Run on . Uses .nvmrc if available and version is omitted", + args: [{ ...version, isOptional: true }, command], + options: [silent, lts, ltsWithName], + }, + { + name: "run", + description: + "Run `node` on with as arguments. Uses .nvmrc if available and version is omitted", + args: [{ ...version, isOptional: true }, args], + options: [silent, lts, ltsWithName], + }, + { + name: "current", + description: "Display currently activated version of Node", + }, + { + name: "ls", + description: + "List installed versions, matching a given if provided", + args: version, + options: [noColors, noAlias], + }, + { + name: "ls-remote", + description: + "List remote versions available for install, matching a given if provided", + args: version, + options: [ + { + ...lts, + description: + "When listing, only show LTS (long-term support) versions", + }, + { + ...ltsWithName, + description: + "When listing, only show versions for a specific LTS line", + }, + noColors, + ], + }, + { + name: "version", + description: "Resolve the given description to a single local version", + args: version, + }, + { + name: "version-remote", + description: "Resolve the given description to a single remote version", + args: version, + options: [ + { + ...lts, + description: + "When listing, only show LTS (long-term support) versions", + }, + { + ...ltsWithName, + description: + "When listing, only show versions for a specific LTS line", + }, + ], + }, + { + name: "deactivate", + description: "Undo effects of `nvm` on current shell", + options: [silent], + }, + { + name: "alias", + description: + "Show all aliases beginning with or Set an alias named pointing to ", + args: [ + { + name: "pattern or name", + description: "Pattern or name", + }, + { + name: "version", + isOptional: true, + }, + ], + }, + { + name: "unalias", + description: "Deletes the alias named ", + args: name, + }, + { + name: "install-latest-npm", + description: + "Attempt to upgrade to the latest working `npm` on the current node version", + }, + { + name: "reinstall-packages", + description: + "Reinstall global `npm` packages contained in to current version", + args: version, + }, + { + name: "unload", + description: "Unload `nvm` from shell", + }, + { + name: "which", + description: + "Display path to installed node version. Uses .nvmrc if available and version is omitted", + args: { ...version, isOptional: true }, + subcommands: [ + { + name: "current", + }, + ], + options: [ + { + ...silent, + description: + "Silences stdout/stderr output when a version is omitted", + }, + ], + }, + { + name: "cache", + args: { + suggestions: [ + { + name: "dir", + description: "Display path to the cache directory for nvm", + type: "subcommand", + }, + { + name: "clear", + description: "Empty cache directory for nvm", + type: "subcommand", + }, + ], + }, + }, + { + name: "set-colors", + description: + 'Set five text colors using format "yMeBg". Available when supported', + args: colorCodes, + }, + ], + options: [ + { + name: "--help", + description: "Show help page", + }, + { + name: "--version", + description: "Print out the installed version of nvm", + }, + noColors, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/pnpm.ts b/extensions/terminal-suggest/src/completions/upstream/pnpm.ts new file mode 100644 index 0000000000000..1710549572f14 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/pnpm.ts @@ -0,0 +1,1027 @@ +// GENERATORS + +import { npmScriptsGenerator, npmSearchGenerator } from "./npm"; +import { dependenciesGenerator, nodeClis } from "./yarn"; + +const filterMessages = (out: string): string => { + return out.startsWith("warning:") || out.startsWith("error:") + ? out.split("\n").slice(1).join("\n") + : out; +}; + +const searchBranches: Fig.Generator = { + script: ["git", "branch", "--no-color"], + postProcess: function (out) { + const output = filterMessages(out); + + if (output.startsWith("fatal:")) { + return []; + } + + return output.split("\n").map((elm) => { + let name = elm.trim(); + const parts = elm.match(/\S+/g); + if (parts && parts.length > 1) { + if (parts[0] == "*") { + // Current branch. + return { + name: elm.replace("*", "").trim(), + description: "Current branch", + icon: "⭐️", + }; + } else if (parts[0] == "+") { + // Branch checked out in another worktree. + name = elm.replace("+", "").trim(); + } + } + + return { + name, + description: "Branch", + icon: "fig://icon?type=git", + }; + }); + }, +}; + +const generatorInstalledPackages: Fig.Generator = { + script: ["pnpm", "ls"], + postProcess: function (out) { + /** + * out + * @example + * ``` + * Legend: production dependency, optional only, dev only + * + * /xxxx/xxxx/ (PRIVATE) + * + * dependencies: + * lodash 4.17.21 + * foo link:packages/foo + * + * devDependencies: + * typescript 4.7.4 + * ``` + */ + if (out.includes("ERR_PNPM")) { + return []; + } + + const output = out + .split("\n") + .slice(3) + // remove empty lines, "*dependencies:" lines, local workspace packages (eg: "foo":"workspace:*") + .filter( + (item) => + !!item && + !item.toLowerCase().includes("dependencies") && + !item.includes("link:") + ) + .map((item) => item.replace(/\s/, "@")); // typescript 4.7.4 -> typescript@4.7.4 + + return output.map((pkg) => { + return { + name: pkg, + icon: "fig://icon?type=package", + }; + }); + }, +}; + +const FILTER_OPTION: Fig.Option = { + name: "--filter", + args: { + template: "filepaths", + name: "Filepath / Package", + description: + "To only select packages under the specified directory, you may specify any absolute path, typically in POSIX format", + }, + description: `Filtering allows you to restrict commands to specific subsets of packages. +pnpm supports a rich selector syntax for picking packages by name or by relation. +More details: https://pnpm.io/filtering`, +}; + +/** Options that being appended for `pnpm i` and `add` */ +const INSTALL_BASE_OPTIONS: Fig.Option[] = [ + { + name: "--offline", + description: + "If true, pnpm will use only packages already available in the store. If a package won't be found locally, the installation will fail", + }, + { + name: "--prefer-offline", + description: + "If true, staleness checks for cached data will be bypassed, but missing data will be requested from the server. To force full offline mode, use --offline", + }, + { + name: "--ignore-scripts", + description: + "Do not execute any scripts defined in the project package.json and its dependencies", + }, + { + name: "--reporter", + description: `Allows you to choose the reporter that will log debug info to the terminal about the installation progress`, + args: { + name: "Reporter Type", + suggestions: ["silent", "default", "append-only", "ndjson"], + }, + }, +]; + +/** Base options for pnpm i when run without any arguments */ +const INSTALL_OPTIONS: Fig.Option[] = [ + { + name: ["-P", "--save-prod"], + description: `Pnpm will not install any package listed in devDependencies if the NODE_ENV environment variable is set to production. +Use this flag to instruct pnpm to ignore NODE_ENV and take its production status from this flag instead`, + }, + { + name: ["-D", "--save-dev"], + description: + "Only devDependencies are installed regardless of the NODE_ENV", + }, + { + name: "--no-optional", + description: "OptionalDependencies are not installed", + }, + { + name: "--lockfile-only", + description: + "When used, only updates pnpm-lock.yaml and package.json instead of checking node_modules and downloading dependencies", + }, + { + name: "--frozen-lockfile", + description: + "If true, pnpm doesn't generate a lockfile and fails to install if the lockfile is out of sync with the manifest / an update is needed or no lockfile is present", + }, + { + name: "--use-store-server", + description: + "Starts a store server in the background. The store server will keep running after installation is done. To stop the store server, run pnpm server stop", + }, + { + name: "--shamefully-hoist", + description: + "Creates a flat node_modules structure, similar to that of npm or yarn. WARNING: This is highly discouraged", + }, +]; + +/** Base options for pnpm add */ +const INSTALL_PACKAGE_OPTIONS: Fig.Option[] = [ + { + name: ["-P", "--save-prod"], + description: "Install the specified packages as regular dependencies", + }, + { + name: ["-D", "--save-dev"], + description: "Install the specified packages as devDependencies", + }, + { + name: ["-O", "--save-optional"], + description: "Install the specified packages as optionalDependencies", + }, + { + name: "--no-save", + description: "Prevents saving to `dependencies`", + }, + { + name: ["-E", "--save-exact"], + description: + "Saved dependencies will be configured with an exact version rather than using pnpm's default semver range operator", + }, + { + name: "--save-peer", + description: + "Using --save-peer will add one or more packages to peerDependencies and install them as dev dependencies", + }, + { + name: ["--ignore-workspace-root-check", "-W#"], + description: `Adding a new dependency to the root workspace package fails, unless the --ignore-workspace-root-check or -W flag is used. +For instance, pnpm add debug -W`, + }, + { + name: ["--global", "-g"], + description: `Install a package globally`, + }, + { + name: "--workspace", + description: `Only adds the new dependency if it is found in the workspace`, + }, + FILTER_OPTION, +]; + +// SUBCOMMANDS +const SUBCOMMANDS_MANAGE_DEPENDENCIES: Fig.Subcommand[] = [ + { + name: "add", + description: `Installs a package and any packages that it depends on. By default, any new package is installed as a production dependency`, + args: { + name: "package", + generators: npmSearchGenerator, + debounce: true, + isVariadic: true, + }, + options: [...INSTALL_BASE_OPTIONS, ...INSTALL_PACKAGE_OPTIONS], + }, + { + name: ["install", "i"], + description: `Pnpm install is used to install all dependencies for a project. +In a CI environment, installation fails if a lockfile is present but needs an update. +Inside a workspace, pnpm install installs all dependencies in all the projects. +If you want to disable this behavior, set the recursive-install setting to false`, + async generateSpec(tokens) { + // `pnpm i` with args is an `pnpm add` alias + const hasArgs = + tokens.filter((token) => token.trim() !== "" && !token.startsWith("-")) + .length > 2; + + return { + name: "install", + options: [ + ...INSTALL_BASE_OPTIONS, + ...(hasArgs ? INSTALL_PACKAGE_OPTIONS : INSTALL_OPTIONS), + ], + }; + }, + args: { + name: "package", + isOptional: true, + generators: npmSearchGenerator, + debounce: true, + isVariadic: true, + }, + }, + { + name: ["install-test", "it"], + description: + "Runs pnpm install followed immediately by pnpm test. It takes exactly the same arguments as pnpm install", + options: [...INSTALL_BASE_OPTIONS, ...INSTALL_OPTIONS], + }, + { + name: ["update", "upgrade", "up"], + description: `Pnpm update updates packages to their latest version based on the specified range. +When used without arguments, updates all dependencies. You can use patterns to update specific dependencies`, + args: { + name: "Package", + isOptional: true, + filterStrategy: "fuzzy", + generators: dependenciesGenerator, + isVariadic: true, + }, + options: [ + { + name: ["--recursive", "-r"], + description: + "Concurrently runs update in all subdirectories with a package.json (excluding node_modules)", + }, + { + name: ["--latest", "-L"], + description: + "Ignores the version range specified in package.json. Instead, the version specified by the latest tag will be used (potentially upgrading the packages across major versions)", + }, + { + name: "--global", + description: "Update global packages", + }, + { + name: ["-P", "--save-prod"], + description: `Only update packages in dependencies and optionalDependencies`, + }, + { + name: ["-D", "--save-dev"], + description: "Only update packages in devDependencies", + }, + { + name: "--no-optional", + description: "Don't update packages in optionalDependencies", + }, + { + name: ["--interactive", "-i"], + description: + "Show outdated dependencies and select which ones to update", + }, + { + name: "--workspace", + description: `Tries to link all packages from the workspace. Versions are updated to match the versions of packages inside the workspace. +If specific packages are updated, the command will fail if any of the updated dependencies are not found inside the workspace. For instance, the following command fails if express is not a workspace package: pnpm up -r --workspace express`, + }, + FILTER_OPTION, + ], + }, + { + name: ["remove", "rm", "uninstall", "un"], + description: `Removes packages from node_modules and from the project's package.json`, + args: { + name: "Package", + filterStrategy: "fuzzy", + generators: dependenciesGenerator, + isVariadic: true, + }, + options: [ + { + name: ["--recursive", "-r"], + description: `When used inside a workspace, removes a dependency (or dependencies) from every workspace package. +When used not inside a workspace, removes a dependency (or dependencies) from every package found in subdirectories`, + }, + { + name: "--global", + description: "Remove a global package", + }, + { + name: ["-P", "--save-prod"], + description: `Only remove the dependency from dependencies`, + }, + { + name: ["-D", "--save-dev"], + description: "Only remove the dependency from devDependencies", + }, + { + name: ["--save-optional", "-O"], + description: "Only remove the dependency from optionalDependencies", + }, + FILTER_OPTION, + ], + }, + { + name: ["link", "ln"], + description: `Makes the current local package accessible system-wide, or in another location`, + args: [ + { + name: "Package", + filterStrategy: "fuzzy", + generators: dependenciesGenerator, + isVariadic: true, + }, + { template: "filepaths" }, + ], + options: [ + { + name: ["--dir", "-C"], + description: `Changes the link location to `, + }, + { + name: "--global", + description: + "Links the specified package () from global node_modules to the node_nodules of package from where this command was executed or specified via --dir option", + }, + ], + }, + { + name: "unlink", + description: `Unlinks a system-wide package (inverse of pnpm link). +If called without arguments, all linked dependencies will be unlinked. +This is similar to yarn unlink, except pnpm re-installs the dependency after removing the external link`, + args: [ + { + name: "Package", + filterStrategy: "fuzzy", + generators: dependenciesGenerator, + isVariadic: true, + }, + { template: "filepaths" }, + ], + options: [ + { + name: ["--recursive", "-r"], + description: `Unlink in every package found in subdirectories or in every workspace package, when executed inside a workspace`, + }, + FILTER_OPTION, + ], + }, + { + name: "import", + description: + "Pnpm import generates a pnpm-lock.yaml from an npm package-lock.json (or npm-shrinkwrap.json) file", + }, + { + name: ["rebuild", "rb"], + description: `Rebuild a package`, + args: [ + { + name: "Package", + filterStrategy: "fuzzy", + generators: dependenciesGenerator, + isVariadic: true, + }, + { template: "filepaths" }, + ], + options: [ + { + name: ["--recursive", "-r"], + description: `This command runs the pnpm rebuild command in every package of the monorepo`, + }, + FILTER_OPTION, + ], + }, + { + name: "prune", + description: `Removes unnecessary packages`, + options: [ + { + name: "--prod", + description: `Remove the packages specified in devDependencies`, + }, + { + name: "--no-optional", + description: `Remove the packages specified in optionalDependencies`, + }, + ], + }, + { + name: "fetch", + description: `EXPERIMENTAL FEATURE: Fetch packages from a lockfile into virtual store, package manifest is ignored: https://pnpm.io/cli/fetch`, + options: [ + { + name: "--prod", + description: `Development packages will not be fetched`, + }, + { + name: "--dev", + description: `Only development packages will be fetched`, + }, + ], + }, + { + name: "patch", + description: `This command will cause a package to be extracted in a temporary directory intended to be editable at will`, + args: { + name: "package", + generators: generatorInstalledPackages, + }, + options: [ + { + name: "--edit-dir", + description: `The package that needs to be patched will be extracted to this directory`, + }, + ], + }, + { + name: "patch-commit", + args: { + name: "dir", + }, + description: `Generate a patch out of a directory`, + }, + { + name: "patch-remove", + args: { + name: "package", + isVariadic: true, + // TODO: would be nice to have a generator of all patched packages + }, + }, +]; + +const SUBCOMMANDS_RUN_SCRIPTS: Fig.Subcommand[] = [ + { + name: ["run", "run-script"], + description: "Runs a script defined in the package's manifest file", + args: { + name: "Scripts", + filterStrategy: "fuzzy", + generators: npmScriptsGenerator, + isVariadic: true, + }, + options: [ + { + name: ["-r", "--recursive"], + description: `This runs an arbitrary command from each package's "scripts" object. If a package doesn't have the command, it is skipped. If none of the packages have the command, the command fails`, + }, + { + name: "--if-present", + description: + "You can use the --if-present flag to avoid exiting with a non-zero exit code when the script is undefined. This lets you run potentially undefined scripts without breaking the execution chain", + }, + { + name: "--parallel", + description: + "Completely disregard concurrency and topological sorting, running a given script immediately in all matching packages with prefixed streaming output. This is the preferred flag for long-running processes over many packages, for instance, a lengthy build process", + }, + { + name: "--stream", + description: + "Stream output from child processes immediately, prefixed with the originating package directory. This allows output from different packages to be interleaved", + }, + FILTER_OPTION, + ], + }, + { + name: "exec", + description: `Execute a shell command in scope of a project. +node_modules/.bin is added to the PATH, so pnpm exec allows executing commands of dependencies`, + args: { + name: "Scripts", + filterStrategy: "fuzzy", + generators: dependenciesGenerator, + isVariadic: true, + }, + options: [ + { + name: ["-r", "--recursive"], + description: `Execute the shell command in every project of the workspace. +The name of the current package is available through the environment variable PNPM_PACKAGE_NAME (supported from pnpm v2.22.0 onwards)`, + }, + { + name: "--parallel", + description: + "Completely disregard concurrency and topological sorting, running a given script immediately in all matching packages with prefixed streaming output. This is the preferred flag for long-running processes over many packages, for instance, a lengthy build process", + }, + FILTER_OPTION, + ], + }, + { + name: ["test", "t", "tst"], + description: `Runs an arbitrary command specified in the package's test property of its scripts object. +The intended usage of the property is to specify a command that runs unit or integration testing for your program`, + }, + { + name: "start", + description: `Runs an arbitrary command specified in the package's start property of its scripts object. If no start property is specified on the scripts object, it will attempt to run node server.js as a default, failing if neither are present. +The intended usage of the property is to specify a command that starts your program`, + }, +]; + +const SUBCOMMANDS_REVIEW_DEPS: Fig.Subcommand[] = [ + { + name: "audit", + description: `Checks for known security issues with the installed packages. +If security issues are found, try to update your dependencies via pnpm update. +If a simple update does not fix all the issues, use overrides to force versions that are not vulnerable. +For instance, if lodash@<2.1.0 is vulnerable, use overrides to force lodash@^2.1.0. +Details at: https://pnpm.io/cli/audit`, + options: [ + { + name: "--audit-level", + description: `Only print advisories with severity greater than or equal to `, + args: { + name: "Audit Level", + default: "low", + suggestions: ["low", "moderate", "high", "critical"], + }, + }, + { + name: "--fix", + description: + "Add overrides to the package.json file in order to force non-vulnerable versions of the dependencies", + }, + { + name: "--json", + description: `Output audit report in JSON format`, + }, + { + name: ["--dev", "-D"], + description: `Only audit dev dependencies`, + }, + { + name: ["--prod", "-P"], + description: `Only audit production dependencies`, + }, + { + name: "--no-optional", + description: `Don't audit optionalDependencies`, + }, + { + name: "--ignore-registry-errors", + description: `If the registry responds with a non-200 status code, the process should exit with 0. So the process will fail only if the registry actually successfully responds with found vulnerabilities`, + }, + ], + }, + { + name: ["list", "ls"], + description: `This command will output all the versions of packages that are installed, as well as their dependencies, in a tree-structure. +Positional arguments are name-pattern@version-range identifiers, which will limit the results to only the packages named. For example, pnpm list "babel-*" "eslint-*" semver@5`, + options: [ + { + name: ["--recursive", "-r"], + description: `Perform command on every package in subdirectories or on every workspace package, when executed inside a workspace`, + }, + { + name: "--json", + description: `Log output in JSON format`, + }, + { + name: "--long", + description: `Show extended information`, + }, + { + name: "--parseable", + description: `Outputs package directories in a parseable format instead of their tree view`, + }, + { + name: "--global", + description: `List packages in the global install directory instead of in the current project`, + }, + { + name: "--depth", + description: `Max display depth of the dependency tree. +pnpm ls --depth 0 will list direct dependencies only. pnpm ls --depth -1 will list projects only. Useful inside a workspace when used with the -r option`, + args: { name: "number" }, + }, + { + name: ["--dev", "-D"], + description: `Only list dev dependencies`, + }, + { + name: ["--prod", "-P"], + description: `Only list production dependencies`, + }, + { + name: "--no-optional", + description: `Don't list optionalDependencies`, + }, + FILTER_OPTION, + ], + }, + { + name: "outdated", + description: `Checks for outdated packages. The check can be limited to a subset of the installed packages by providing arguments (patterns are supported)`, + options: [ + { + name: ["--recursive", "-r"], + description: `Check for outdated dependencies in every package found in subdirectories, or in every workspace package when executed inside a workspace`, + }, + { + name: "--long", + description: `Print details`, + }, + { + name: "--global", + description: `List outdated global packages`, + }, + { + name: "--no-table", + description: `Prints the outdated dependencies in a list format instead of the default table. Good for small consoles`, + }, + { + name: "--compatible", + description: `Prints only versions that satisfy specifications in package.json`, + }, + { + name: ["--dev", "-D"], + description: `Only list dev dependencies`, + }, + { + name: ["--prod", "-P"], + description: `Only list production dependencies`, + }, + { + name: "--no-optional", + description: `Doesn't check optionalDependencies`, + }, + ], + }, + { + name: "why", + description: `Shows all packages that depend on the specified package`, + args: { + name: "Scripts", + filterStrategy: "fuzzy", + generators: dependenciesGenerator, + isVariadic: true, + }, + options: [ + { + name: ["--recursive", "-r"], + description: `Show the dependency tree for the specified package on every package in subdirectories or on every workspace package when executed inside a workspace`, + }, + { + name: "--json", + description: `Log output in JSON format`, + }, + { + name: "--long", + description: `Show verbose output`, + }, + { + name: "--parseable", + description: `Show parseable output instead of tree view`, + }, + { + name: "--global", + description: `List packages in the global install directory instead of in the current project`, + }, + { + name: ["--dev", "-D"], + description: `Only display the dependency tree for packages in devDependencies`, + }, + { + name: ["--prod", "-P"], + description: `Only display the dependency tree for packages in dependencies`, + }, + FILTER_OPTION, + ], + }, +]; + +const SUBCOMMANDS_MISC: Fig.Subcommand[] = [ + { + name: "publish", + description: `Publishes a package to the registry. +When publishing a package inside a workspace, the LICENSE file from the root of the workspace is packed with the package (unless the package has a license of its own). +You may override some fields before publish, using the publishConfig field in package.json. You also can use the publishConfig.directory to customize the published subdirectory (usually using third party build tools). +When running this command recursively (pnpm -r publish), pnpm will publish all the packages that have versions not yet published to the registry`, + args: { + name: "Branch", + generators: searchBranches, + }, + options: [ + { + name: "--tag", + description: `Publishes the package with the given tag. By default, pnpm publish updates the latest tag`, + args: { + name: "", + }, + }, + { + name: "--dry-run", + description: `Does everything a publish would do except actually publishing to the registry`, + }, + { + name: "--ignore-scripts", + description: `Ignores any publish related lifecycle scripts (prepublishOnly, postpublish, and the like)`, + }, + { + name: "--no-git-checks", + description: `Don't check if current branch is your publish branch, clean, and up-to-date`, + }, + { + name: "--access", + description: `Tells the registry whether the published package should be public or restricted`, + args: { + name: "Type", + suggestions: ["public", "private"], + }, + }, + { + name: "--force", + description: `Try to publish packages even if their current version is already found in the registry`, + }, + { + name: "--report-summary", + description: `Save the list of published packages to pnpm-publish-summary.json. Useful when some other tooling is used to report the list of published packages`, + }, + FILTER_OPTION, + ], + }, + { + name: ["recursive", "m", "multi", "-r"], + description: `Runs a pnpm command recursively on all subdirectories in the package or every available workspace`, + options: [ + { + name: "--link-workspace-packages", + description: `Link locally available packages in workspaces of a monorepo into node_modules instead of re-downloading them from the registry. This emulates functionality similar to yarn workspaces. +When this is set to deep, local packages can also be linked to subdependencies. +Be advised that it is encouraged instead to use npmrc for this setting, to enforce the same behaviour in all environments. This option exists solely so you may override that if necessary`, + args: { + name: "bool or `deep`", + suggestions: ["dee["], + }, + }, + { + name: "--workspace-concurrency", + description: `Set the maximum number of tasks to run simultaneously. For unlimited concurrency use Infinity`, + args: { name: "" }, + }, + { + name: "--bail", + description: `Stops when a task throws an error`, + }, + { + name: "--no-bail", + description: `Don't stop when a task throws an error`, + }, + { + name: "--sort", + description: `Packages are sorted topologically (dependencies before dependents)`, + }, + { + name: "--no-sort", + description: `Disable packages sorting`, + }, + { + name: "--reverse", + description: `The order of packages is reversed`, + }, + FILTER_OPTION, + ], + }, + { + name: "server", + description: `Manage a store server`, + subcommands: [ + { + name: "start", + description: + "Starts a server that performs all interactions with the store. Other commands will delegate any store-related tasks to this server", + options: [ + { + name: "--background", + description: `Runs the server in the background, similar to daemonizing on UNIX systems`, + }, + { + name: "--network-concurrency", + description: `The maximum number of network requests to process simultaneously`, + args: { name: "number" }, + }, + { + name: "--protocol", + description: `The communication protocol used by the server. When this is set to auto, IPC is used on all systems except for Windows, which uses TCP`, + args: { + name: "Type", + suggestions: ["auto", "tcp", "ipc"], + }, + }, + { + name: "--port", + description: `The port number to use when TCP is used for communication. If a port is specified and the protocol is set to auto, regardless of system type, the protocol is automatically set to use TCP`, + args: { name: "port number" }, + }, + { + name: "--store-dir", + description: `The directory to use for the content addressable store`, + args: { name: "Path", template: "filepaths" }, + }, + { + name: "--lock", + description: `Set to make the package store immutable to external processes while the server is running or not`, + }, + { + name: "--no-lock", + description: `Set to make the package store mutable to external processes while the server is running or not`, + }, + { + name: "--ignore-stop-requests", + description: `Prevents you from stopping the server using pnpm server stop`, + }, + { + name: "--ignore-upload-requests", + description: `Prevents creating a new side effect cache during install`, + }, + ], + }, + { + name: "stop", + description: "Stops the store server", + }, + { + name: "status", + description: "Prints information about the running server", + }, + ], + }, + { + name: "store", + description: "Managing the package store", + subcommands: [ + { + name: "status", + description: `Checks for modified packages in the store. +Returns exit code 0 if the content of the package is the same as it was at the time of unpacking`, + }, + { + name: "add", + description: `Functionally equivalent to pnpm add, +except this adds new packages to the store directly without modifying any projects or files outside of the store`, + }, + { + name: "prune", + description: `Removes orphan packages from the store. +Pruning the store will save disk space, however may slow down future installations involving pruned packages. +Ultimately, it is a safe operation, however not recommended if you have orphaned packages from a package you intend to reinstall. +Please read the FAQ for more information on unreferenced packages and best practices. +Please note that this is prohibited when a store server is running`, + }, + { + name: "path", + description: `Returns the path to the active store directory`, + }, + ], + }, + { + name: "init", + description: + "Creates a basic package.json file in the current directory, if it doesn't exist already", + }, + { + name: "doctor", + description: "Checks for known common issues with pnpm configuration", + }, +]; + +const subcommands = [ + ...SUBCOMMANDS_MANAGE_DEPENDENCIES, + ...SUBCOMMANDS_REVIEW_DEPS, + ...SUBCOMMANDS_RUN_SCRIPTS, + ...SUBCOMMANDS_MISC, +]; + +const recursiveSubcommandsNames = [ + "add", + "exec", + "install", + "list", + "outdated", + "publish", + "rebuild", + "remove", + "run", + "test", + "unlink", + "update", + "why", +]; + +const recursiveSubcommands = subcommands.filter((subcommand) => { + if (Array.isArray(subcommand.name)) { + return subcommand.name.some((name) => + recursiveSubcommandsNames.includes(name) + ); + } + return recursiveSubcommandsNames.includes(subcommand.name); +}); + +// RECURSIVE SUBCOMMAND INDEX +SUBCOMMANDS_MISC[1].subcommands = recursiveSubcommands; + +// common options +const COMMON_OPTIONS: Fig.Option[] = [ + { + name: ["-C", "--dir"], + args: { + name: "path", + template: "folders", + }, + isPersistent: true, + description: + "Run as if pnpm was started in instead of the current working directory", + }, + { + name: ["-w", "--workspace-root"], + args: { + name: "workspace", + }, + isPersistent: true, + description: + "Run as if pnpm was started in the root of the instead of the current working directory", + }, + { + name: ["-h", "--help"], + isPersistent: true, + description: "Output usage information", + }, + { + name: ["-v", "--version"], + description: "Show pnpm's version", + }, +]; + +// SPEC +const completionSpec: Fig.Spec = { + name: "pnpm", + description: "Fast, disk space efficient package manager", + args: { + name: "Scripts", + filterStrategy: "fuzzy", + generators: npmScriptsGenerator, + isVariadic: true, + }, + filterStrategy: "fuzzy", + generateSpec: async (tokens, executeShellCommand) => { + const { script, postProcess } = dependenciesGenerator as Fig.Generator & { + script: string[]; + }; + if (!postProcess) { + return undefined; + } + + const packages = postProcess( + ( + await executeShellCommand({ + command: script[0], + args: script.slice(1), + }) + ).stdout, + tokens + )?.map((e: any) => e.name as string); + if (!packages) { + return undefined; + } + + const subcommands = packages + .filter((name) => nodeClis.has(name)) + .map((name) => ({ + name, + loadSpec: name, + icon: "fig://icon?type=package", + })); + + return { + name: "pnpm", + subcommands, + } as Fig.Spec; + }, + subcommands, + options: COMMON_OPTIONS, +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/ps.ts b/extensions/terminal-suggest/src/completions/upstream/ps.ts new file mode 100644 index 0000000000000..37c34815a8c8b --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/ps.ts @@ -0,0 +1,153 @@ +const completionSpec: Fig.Spec = { + name: "ps", + description: "Report a snapshot of the current processes", + options: [ + { name: ["-A", "-e"], description: "Select all processes" }, + { + name: "-a", + description: "Select all processes except both session leaders", + args: { name: "getsid" }, + }, + { + name: "-d", + description: "Select all processes except session leaders", + }, + { + name: "--deselect", + description: + "Select all processes except those that fulfill the specified conditions", + }, + { + name: "-N", + description: + "Select all processes except those that fulfill the specified conditions (negates the selection)", + }, + { + name: "--pid", + description: "Select by process ID", + args: { name: "pidlist" }, + }, + { + name: "--ppid", + description: + "Select by parent process ID. This selects the processes with a parent process ID in pidlist", + args: { name: "pidlist" }, + }, + { + name: "--sid", + description: "Select by session ID", + args: { name: "sesslist" }, + }, + { + name: "--tty", + description: "Select by terminal", + args: { name: "ttylist" }, + }, + { + name: "U", + description: "Select by effective user ID (EUID) or name", + args: { name: "userlist" }, + }, + { + name: "-U", + description: "Select by real user ID (RUID) or name", + args: { name: "userlist" }, + }, + { + name: "-u", + description: "Select by effective user ID (EUID) or name", + args: { name: "userlist" }, + }, + { + name: "--User", + description: "Select by real user ID (RUID) or name", + args: { name: "userlist" }, + }, + { + name: "--user", + description: "Select by effective user ID (EUID) or name", + args: { name: "userlist" }, + }, + { + name: "-c", + description: "Show different scheduler information for the -l option", + }, + { + name: "--context", + description: "Display security context format (for SE Linux)", + }, + { name: "-f", description: "Do full-format listing" }, + { name: "-F", description: "Extra full format" }, + { + name: ["--format", "-o", "o"], + description: "", + args: { name: "format" }, + isRepeatable: true, + }, + { name: ["-M", "Z"], description: "(for SE Linux)" }, + { name: ["-y", "-l"], description: "" }, + { + name: "--cols", + description: "Set screen width", + args: { name: "n" }, + }, + { + name: "--columns", + description: "Set screen width", + args: { name: "n" }, + }, + { + name: "--cumulative", + description: + "Include some dead child process data (as a sum with the parent)", + }, + { name: "--forest", description: "ASCII art process tree" }, + { name: "-H", description: "Show process hierarchy (forest)" }, + { + name: "--headers", + description: "Repeat header lines, one per page of output", + }, + { + name: "-n", + description: "Set namelist file", + args: { name: "namelist" }, + }, + { + name: "--lines", + description: "Set screen height", + args: { name: "n" }, + }, + { + name: ["--no-headers", "--no-heading"], + description: "Print no header line at all", + }, + { + name: "--rows", + description: "Set screen height", + args: { name: "n" }, + }, + { + name: "--sort", + description: "Specify sorting order", + args: { name: "spec" }, + }, + { + name: "--width", + description: "Set screen width", + args: { name: "n" }, + }, + { + name: "-L", + description: "Show threads, possibly with LWP and NLWP columns", + }, + { + name: "-T", + description: "Show threads, possibly with SPID column", + }, + { name: "--help", description: "Print a help message" }, + { name: "--info", description: "Print debugging info" }, + { name: "--version", description: "Print the procps version" }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/pwd.ts b/extensions/terminal-suggest/src/completions/upstream/pwd.ts new file mode 100644 index 0000000000000..42126db30b7d2 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/pwd.ts @@ -0,0 +1,16 @@ +const completionSpec: Fig.Spec = { + name: "pwd", + description: "Return working directory name", + options: [ + { + name: "-L", + description: "Display the logical current working directory", + }, + { + name: "-P", + description: "Display the physical current working directory", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/python.ts b/extensions/terminal-suggest/src/completions/upstream/python.ts new file mode 100644 index 0000000000000..c9efa79499d2b --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/python.ts @@ -0,0 +1,168 @@ +// import { filepaths } from "@fig/autocomplete-generators"; + +const completionSpec: Fig.Spec = { + name: "python", + description: "Run the python interpreter", + generateSpec: async (tokens, executeShellCommand) => { + const isDjangoManagePyFilePresentCommand = "cat manage.py | grep -q django"; + if ( + ( + await executeShellCommand({ + command: "bash", + args: ["-c", isDjangoManagePyFilePresentCommand], + }) + ).status === 0 + ) { + return { + name: "python", + subcommands: [{ name: "manage.py", loadSpec: "django-admin" }], + }; + } + }, + args: { + name: "python script", + template: "filepaths", + // generators: filepaths({ + // extensions: ["py"], + // editFileSuggestions: { priority: 76 }, + // }), + }, + options: [ + { + name: "-c", + insertValue: "-c '{cursor}'", + description: + "Execute the Python code in command. command can be one or more statements separated by newlines, with significant leading whitespace as in normal module code", + args: { + name: "command", + isCommand: true, + }, + }, + { + name: "-m", + description: "Module", + args: { + name: "python module", + isModule: "python/", + suggestions: ["http.server"], + }, + }, + { + name: ["-?", "-h", "--help"], + description: "Print a short description of all command line options", + }, + { + name: ["-V", "--version"], + description: "Print the Python version number and exit", + }, + { + name: "-b", + description: + "Issue a warning when comparing bytes or bytearray with str or bytes with int. Issue an error when the option is given twice (-bb)", + }, + { + name: "-B", + description: + "If given, Python won’t try to write .pyc files on the import of source modules", + }, + { + name: "--check-hash-based-pycs", + description: + "Control the validation behavior of hash-based .pyc files. See Cached bytecode invalidation", + args: { + suggestions: [ + { name: "default" }, + { name: "always" }, + { name: "never" }, + ], + }, + }, + { + name: "-d", + description: + "Turn on parser debugging output (for expert only, depending on compilation options)", + }, + { + name: "-E", + description: + "Ignore all PYTHON* environment variables, e.g. PYTHONPATH and PYTHONHOME, that might be set", + }, + { + name: "-i", + description: + "When a script is passed as first argument or the -c option is used, enter interactive mode after executing the script or the command, even when sys.stdin does not appear to be a terminal", + }, + { + name: "-I", + description: + "Run Python in isolated mode. This also implies -E and -s. In isolated mode sys.path contains neither the script’s directory nor the user’s site-packages directory", + }, + { + name: "-O", + description: + "Remove assert statements and any code conditional on the value of __debug__", + }, + { + name: "-OO", + description: "Do -O and also discard docstrings", + }, + { + name: "-g", + description: + "Don’t display the copyright and version messages even in interactive mode", + }, + { + name: "-R", + description: + "Turn on hash randomization. This option only has an effect if the PYTHONHASHSEED environment variable is set to 0, since hash randomization is enabled by default", + }, + { + name: "-s", + description: "Don’t add the user site-packages directory to sys.path", + }, + { + name: "-S", + description: + "Disable the import of the module site and the site-dependent manipulations of sys.path that it entails", + }, + { + name: "-u", + description: + "Force the stdout and stderr streams to be unbuffered. This option has no effect on the stdin stream", + }, + { + name: "-v", + description: + "Print a message each time a module is initialized, showing the place (filename or built-in module) from which it is loaded", + }, + { + name: "-W", + description: + "Warning control. Python’s warning machinery by default prints warning messages to sys.stderr", + args: {}, + }, + { + name: "-x", + description: + "Skip the first line of the source, allowing use of non-Unix forms of #!cmd. This is intended for a DOS specific hack only", + }, + { + name: "-X", + description: "Reserved for various implementation-specific options", + args: { + suggestions: [ + { name: "faulthandler" }, + { name: "showrefcount" }, + { name: "tracemalloc" }, + { name: "showalloccount" }, + { name: "importtime" }, + { name: "dev" }, + { name: "utf8" }, + { name: "pycache_prefix=PATH" }, + ], + }, + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/scp.ts b/extensions/terminal-suggest/src/completions/upstream/scp.ts new file mode 100644 index 0000000000000..93da019b68672 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/scp.ts @@ -0,0 +1,241 @@ +import { knownHosts, configHosts } from "./ssh"; + +const completionSpec: Fig.Spec = { + name: "scp", + description: "Copies files or directories between hosts on a network", + args: [ + { + name: "sources", + description: "File or directory, local or remote ([user@]host:[path])", + isVariadic: true, + generators: [ + knownHosts, + configHosts, + { template: ["history", "filepaths", "folders"] }, + ], + }, + { + name: "target", + description: "File or directory, local or remote ([user@]host:[path])", + generators: [ + knownHosts, + configHosts, + { template: ["history", "filepaths", "folders"] }, + ], + }, + ], + options: [ + { + name: "-3", + description: `Copies between two remote hosts are transferred through the local +host. Without this option the data is copied directly between the +two remote hosts. Note that this option disables the progress +meter and selects batch mode for the second host, since scp cannot +ask for passwords or passphrases for both hosts`, + }, + { + name: "-4", + description: "Forces scp to use IPv4 addresses only", + }, + { + name: "-6", + description: "Forces scp to use IPv6 addresses only", + }, + { + name: "-A", + description: + "Allows forwarding of ssh-agent(1) to the remote system. The default is not to forward an authentication agent", + }, + { + name: "-B", + description: + "Selects batch mode (prevents asking for passwords or passphrases)", + }, + { + name: "-C", + description: + "Compression enable. Passes the -C flag to ssh(1) to enable compression", + }, + { + name: "-c", + description: + "Selects the cipher to use for encrypting the data transfer. This option is directly passed to ssh(1)", + args: { + name: "cipher", + description: "The selected cipher specification", + }, + }, + { + name: "-F", + description: + "Specifies an alternative per-user configuration file for ssh. This option is directly passed to ssh(1)", + args: { + name: "ssh_config", + description: "The selected ssh config", + }, + }, + { + name: "-i", + description: + "Selects the file from which the identity (private key) for public key authentication is read. This option is directly passed to ssh(1)", + args: { + name: "identity_file", + description: "Specified identity file", + }, + }, + { + name: "-J", + description: `Connect to the target host by first making an scp connection to the +jump host described by destination and then establishing a TCP +forwarding to the ultimate destination from there. Multiple jump +hops may be specified separated by comma characters. This is a +shortcut to specify a ProxyJump configuration directive. This +option is directly passed to ssh(1)`, + args: { + name: "destination", + description: "Scp destination", + }, + }, + { + name: "-l", + description: "Limits the used bandwidth, specified in Kbit/s", + args: { + name: "limit", + description: "Limit bandwidth in Kbit/s", + }, + }, + { + name: "-o", + description: `Can be used to pass options to ssh in the format used in +ssh_config(5). This is useful for specifying options for which +there is no separate scp command-line flag. For full details of +the options listed below, and their possible values, see +ssh_config(5)`, + args: { + name: "option", + suggestions: [ + { name: "AddressFamily" }, + { name: "BatchMode" }, + { name: "BindAddress" }, + { name: "ChallengeResponseAuthentication" }, + { name: "CheckHostIP" }, + { name: "Cipher" }, + { name: "Ciphers" }, + { name: "ClearAllForwardings" }, + { name: "Compression" }, + { name: "CompressionLevel" }, + { name: "ConnectionAttempts" }, + { name: "ConnectTimeout" }, + { name: "ControlMaster" }, + { name: "ControlPath" }, + { name: "ControlPersist" }, + { name: "DynamicForward" }, + { name: "EscapeChar" }, + { name: "ExitOnForwardFailure" }, + { name: "ForwardAgent" }, + { name: "ForwardX11" }, + { name: "ForwardX11Timeout" }, + { name: "ForwardX11Trusted" }, + { name: "GatewayPorts" }, + { name: "GlobalKnownHostsFile" }, + { name: "GSSAPIAuthentication" }, + { name: "GSSAPIDelegateCredentials" }, + { name: "HashKnownHosts" }, + { name: "Host" }, + { name: "HostbasedAuthentication" }, + { name: "HostKeyAlgorithms" }, + { name: "HostKeyAlias" }, + { name: "HostName" }, + { name: "IdentityFile" }, + { name: "IdentitiesOnly" }, + { name: "IPQoS" }, + { name: "KbdInteractiveAuthentication" }, + { name: "KbdInteractiveDevices" }, + { name: "KexAlgorithms" }, + { name: "LocalCommand" }, + { name: "LocalForward" }, + { name: "LogLevel" }, + { name: "MACs" }, + { name: "NoHostAuthenticationForLocalhost" }, + { name: "NumberOfPasswordPrompts" }, + { name: "PasswordAuthentication" }, + { name: "PermitLocalCommand" }, + { name: "PKCS11Provider" }, + { name: "Port" }, + { name: "PreferredAuthentications" }, + { name: "Protocol" }, + { name: "ProxyCommand" }, + { name: "PubkeyAuthentication" }, + { name: "RekeyLimit" }, + { name: "RequestTTY" }, + { name: "RhostsRSAAuthentication" }, + { name: "RSAAuthentication" }, + { name: "SendEnv" }, + { name: "ServerAliveInterval" }, + { name: "ServerAliveCountMax" }, + { name: "StrictHostKeyChecking" }, + { name: "TCPKeepAlive" }, + { name: "Tunnel" }, + { name: "TunnelDevice" }, + { name: "UsePrivilegedPort" }, + { name: "User" }, + { name: "UserKnownHostsFile" }, + { name: "VerifyHostKeyDNS" }, + { name: "VisualHostKey" }, + { name: "XAuthLocation" }, + ], + }, + }, + { + name: "-P", + description: `Specifies the port to connect to on the remote host. Note that +this option is written with a capital β€˜P’, because -p is already +reserved for preserving the times and modes of the file`, + args: { + name: "port", + }, + }, + { + name: "-p", + description: + "Preserves modification times, access times, and modes from the original file", + }, + { + name: "-q", + description: + "Quiet mode: disables the progress meter as well as warning and diagnostic messages from ssh(1)", + }, + { + name: "-r", + description: + "Recursively copy entire directories. Note that scp follows symbolic links encountered in the tree traversal", + }, + { + name: "-S", + description: + "Name of program to use for the encrypted connection. The program must understand ssh(1) options", + args: { + name: "program", + }, + }, + { + name: "-T", + description: `Disable strict filename checking. By default when copying files +from a remote host to a local directory scp checks that the +received filenames match those requested on the command-line to +prevent the remote end from sending unexpected or unwanted files. +Because of differences in how various operating systems and shells +interpret filename wildcards, these checks may cause wanted files +to be rejected. This option disables these checks at the expense +of fully trusting that the server will not send unexpected +filenames`, + }, + { + name: "-v", + description: + "Verbose mode. Causes scp and ssh(1) to print debugging messages about their progress. This is helpful in debugging connection, authentication, and configuration problems", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/ssh.ts b/extensions/terminal-suggest/src/completions/upstream/ssh.ts new file mode 100644 index 0000000000000..9b0f5bd4e7723 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/ssh.ts @@ -0,0 +1,447 @@ +const knownHostRegex = /(?:[a-zA-Z0-9-]+\.)+[a-zA-Z0-9]+/; // will match numerical IPs as well as domains/subdomains + +const resolveAbsolutePath = ( + path: string, + basePath: string, + home: string +): string => { + if (path.startsWith("/") || path.startsWith("~/") || path === "~") { + return path.replace("~", home); + } + if ( + basePath.startsWith("/") || + basePath.startsWith("~/") || + basePath === "~" + ) { + return ( + basePath.replace("~", home) + + (basePath.replace("~", home).endsWith("/") ? "" : "/") + + path + ); + } + return basePath + (basePath.endsWith("/") ? "" : "/") + path; +}; + +const getConfigLines = async ( + file: string, + executeShellCommand: Fig.ExecuteCommandFunction, + home: string, + basePath: string +) => { + const absolutePath = resolveAbsolutePath(file, basePath, home); + + const { stdout } = await executeShellCommand({ + command: "cat", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: [absolutePath], + }); + const configLines = stdout.split("\n").map((line) => line.trim()); + + // Get list of includes in the config file + const includes = configLines + .filter((line) => line.toLowerCase().startsWith("include ")) + .map((line) => line.split(" ")[1]); + + // Get the lines of every include file + const includeLines: any = await Promise.all( + includes.map((file) => + getConfigLines(file, executeShellCommand, home, basePath) + ) + ); + + // Combine config lines with includes config lines + return [...configLines, ...includeLines.flat()]; +}; + +export const knownHosts: Fig.Generator = { + custom: async (tokens, executeCommand, context) => { + const { stdout } = await executeCommand({ + command: "cat", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: [`${context.environmentVariables["HOME"]}/.ssh/known_hosts`], + }); + + return stdout + .split("\n") + .map((line) => { + const match = knownHostRegex.exec(line); + if (match) { + return String(match); + } + }) + .filter((value, index, self) => value && self.indexOf(value) === index) + .map((knownHost) => ({ + name: (tokens[1].endsWith("@") ? tokens[1] : "") + knownHost, // also suggest when user@ is provided + description: "SSH host", + })); + }, + trigger: "@", +}; + +export const configHosts: Fig.Generator = { + custom: async (tokens, executeShellCommand, context) => { + const configLines = await getConfigLines( + "config", + executeShellCommand, + context.environmentVariables["HOME"], + "~/.ssh" + ); + + return configLines + .filter( + (line: any) => + line.trim().toLowerCase().startsWith("host ") && !line.includes("*") + ) + .map((host: any) => ({ + name: host.split(" ")[1], + description: "SSH host", + priority: 90, + })); + }, +}; + +const completionSpec: Fig.Spec = { + name: "ssh", + description: "Log into a remote machine", + args: { + name: "user@hostname", + description: "Address of remote machine to log into", + generators: [knownHosts, configHosts, { template: "history" }], + }, + options: [ + { + name: "-1", + description: "Forces ssh to try protocol version 1 only", + }, + { + name: "-2", + description: "Forces ssh to try protocol version 2 only", + }, + { + name: "-4", + description: "Forces ssh to use IPv4 addresses only", + }, + { + name: "-6", + description: "Forces ssh to use IPv6 addresses only", + }, + { + name: "-A", + description: "Enables forwarding of the authentication agent connection", + }, + { + name: "-a", + description: "Disables forwarding of the authentication agent connection", + }, + { + name: "-b", + description: + "Use bind_address on the local machine as the source address of the connection", + args: { + name: "bind address", + description: "Source address of the connection", + }, + }, + { + name: "-C", + description: + "Requests compression of all data (including stdin, stdout, stderr, and data for forwarded X11 and TCP connections)", + }, + { + name: "-c", + description: + "Selects the cipher specification for encrypting the session", + args: { + name: "cipher spec", + description: "The selected cipher specification", + }, + }, + { + name: "-D", + description: + "Specifies a local 'dynamic' application-level port forwarding", + args: { + name: "port", + description: "Port of the bind address", + }, + }, + { + name: "-e", + description: + "Sets the escape character for sessions with a pty (default: '~')", + args: { + name: "escape char", + description: "Specified escape character", + }, + }, + { + name: "-F", + description: "Specifies an alternative per-user configuration file", + args: { + name: "configfile", + description: "Path to alternative config file", + template: "filepaths", + }, + }, + { + name: "-f", + description: + "Requests ssh to go to background just before command execution", + }, + { + name: "-g", + description: "Allows remote hosts to connect to local forwarded ports", + }, + { + name: "-I", + description: + "Specify the PKCS#11 shared library ssh should use to communicate with a PKCS#11 token providing the user's private RSA key", + args: { + name: "pkcs11", + }, + }, + { + name: "-i", + description: + "Selects a file from which the identity (private key) for public key authentication is read", + isRepeatable: true, + args: { + name: "identity file", + description: "Path to identity (private key)", + template: "filepaths", + }, + }, + { + name: "-K", + description: + "Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI credentials to the server", + }, + { + name: "-k", + description: + "Disables forwarding (delegation) of GSSAPI credentials to the server", + }, + { + name: "-L", + description: + "Specifies that the given port on the local (client) host is to be forwarded to the given host and port on the remote side", + args: { + name: "port:host:hostport", + description: "Local port, followed by host and host port to forward to", + }, + }, + { + name: "-l", + description: "Specifies the user to log in as on the remote machine", + args: { + name: "login name", + description: "Name of user logging into remote machine", + }, + }, + { + name: "-M", + description: + "Places the ssh client into ``master'' mode for connection sharing", + isRepeatable: true, + }, + { + name: "-m", + description: + "Additionally, for protocol version 2 a comma-separated list of MAC (message authentication code) algorithms can be specified in order of preference", + args: { + name: "mac spec", + }, + }, + { + name: "-N", + description: "Do not execute a remote command", + }, + { + name: "-n", + description: + "Redirects stdin from /dev/null (actually, prevents reading from stdin)", + }, + { + name: "-O", + description: "Control an active connection multiplexing master process", + args: { + name: "ctl cmd", + description: "Command that's passed to the master process", + }, + }, + { + name: "-o", + description: + "Can be used to give options in the format used in the configuration file", + isRepeatable: true, + args: { + name: "option", + description: + "Options that can be specified in the format of the config file", + suggestions: [ + { name: "AddressFamily" }, + { name: "BatchMode" }, + { name: "BindAddress" }, + { name: "ChallengeResponseAuthentication" }, + { name: "CheckHostIP" }, + { name: "Cipher" }, + { name: "Ciphers" }, + { name: "ClearAllForwardings" }, + { name: "Compression" }, + { name: "CompressionLevel" }, + { name: "ConnectionAttempts" }, + { name: "ConnectTimeout" }, + { name: "ControlMaster" }, + { name: "ControlPath" }, + { name: "ControlPersist" }, + { name: "DynamicForward" }, + { name: "EscapeChar" }, + { name: "ExitOnForwardFailure" }, + { name: "ForwardAgent" }, + { name: "ForwardX11" }, + { name: "ForwardX11Timeout" }, + { name: "ForwardX11Trusted" }, + { name: "GatewayPorts" }, + { name: "GlobalKnownHostsFile" }, + { name: "GSSAPIAuthentication" }, + { name: "GSSAPIDelegateCredentials" }, + { name: "HashKnownHosts" }, + { name: "Host" }, + { name: "HostbasedAuthentication" }, + { name: "HostKeyAlgorithms" }, + { name: "HostKeyAlias" }, + { name: "HostName" }, + { name: "IdentityFile" }, + { name: "IdentitiesOnly" }, + { name: "IPQoS" }, + { name: "KbdInteractiveAuthentication" }, + { name: "KbdInteractiveDevices" }, + { name: "KexAlgorithms" }, + { name: "LocalCommand" }, + { name: "LocalForward" }, + { name: "LogLevel" }, + { name: "MACs" }, + { name: "NoHostAuthenticationForLocalhost" }, + { name: "NumberOfPasswordPrompts" }, + { name: "PasswordAuthentication" }, + { name: "PermitLocalCommand" }, + { name: "PKCS11Provider" }, + { name: "Port" }, + { name: "PreferredAuthentications" }, + { name: "Protocol" }, + { name: "ProxyCommand" }, + { name: "PubkeyAuthentication" }, + { name: "RekeyLimit" }, + { name: "RequestTTY" }, + { name: "RhostsRSAAuthentication" }, + { name: "RSAAuthentication" }, + { name: "SendEnv" }, + { name: "ServerAliveInterval" }, + { name: "ServerAliveCountMax" }, + { name: "StrictHostKeyChecking" }, + { name: "TCPKeepAlive" }, + { name: "Tunnel" }, + { name: "TunnelDevice" }, + { name: "UsePrivilegedPort" }, + { name: "User" }, + { name: "UserKnownHostsFile" }, + { name: "VerifyHostKeyDNS" }, + { name: "VisualHostKey" }, + { name: "XAuthLocation" }, + ], + }, + }, + { + name: "-p", + description: "Port to connect to on the remote host", + args: { + name: "port", + description: "Port to connect to", + }, + }, + { + name: "-q", + description: + "Quiet mode. Causes most warning and diagnostic messages to be suppressed", + }, + { + name: "-R", + description: + "Specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side", + args: { + name: "port:host:hostport", + description: "Local port, followed by host and host port to forward to", + }, + }, + { + name: "-S", + description: + "Specifies the location of a control socket for connection sharing, or the string 'none' to disable connection sharing", + args: { + name: "ctl_path", + description: "Location of the control socket", + template: "filepaths", + }, + }, + { + name: "-s", + description: + "May be used to request invocation of a subsystem on the remote system", + }, + { + name: "-T", + description: "Disable pseudo-tty allocation", + }, + { + name: "-t", + description: "Force pseudo-tty allocation", + isRepeatable: true, + }, + { + name: "-V", + description: "Display the version number and exit", + }, + { + name: "-v", + description: + "Verbose mode. Causes ssh to print debugging messages about its progress", + isRepeatable: 3, + }, + { + name: "-W", + description: + "Requests that standard input and output on the client be forwarded to host on port over the secure channel", + args: { + name: "host:port", + description: "Host and port to forward to", + }, + }, + { + name: "-w", + description: + "Requests tunnel device forwarding with the specified tun(4) devices between the client (local_tun) and the server (remote_tun)", + args: { + name: "local tun", + description: "Local device to forward to", + }, + }, + { + name: "-X", + description: "Enables X11 forwarding", + }, + { + name: "-x", + description: "Disables X11 forwarding", + }, + { + name: "-Y", + description: "Enables trusted X11 forwarding", + }, + { + name: "-y", + description: "Send log information using the syslog(3) system module", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/tail.ts b/extensions/terminal-suggest/src/completions/upstream/tail.ts new file mode 100644 index 0000000000000..657c610b37dc6 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/tail.ts @@ -0,0 +1,20 @@ +const completionSpec: Fig.Spec = { + name: "tail", + description: "Display the last part of a file", + args: { + isVariadic: true, + template: "filepaths", + }, + options: [ + { + name: "-f", + description: "Wait for additional data to be appended", + }, + { + name: "-r", + description: "Display in reverse order", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/top.ts b/extensions/terminal-suggest/src/completions/upstream/top.ts new file mode 100644 index 0000000000000..df922164c069c --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/top.ts @@ -0,0 +1,49 @@ +const completionSpec: Fig.Spec = { + name: "top", + description: "Display Linux tasks", + options: [ + { + name: ["-h", "-v"], + description: "Show library version and usage prompt", + }, + { + name: "-b", + description: "Starts top in Batch mode", + args: { + name: "operation", + }, + }, + { + name: "-c", + description: "Starts top with last remembered c state reversed", + args: { + name: "toggle", + }, + }, + { + name: "-i", + description: + "Starts top with the last remembered 'i' state reversed. When this toggle is Off, tasks that are idled or zombied will not be displayed", + args: { + name: "toggle", + }, + }, + { + name: "-s", + description: "Starts top with secure mode forced", + args: { + name: "delay", + }, + }, + { + name: "-pid", + description: "Monitor pids", + args: { + name: "process ids", + isVariadic: true, + }, + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/uname.ts b/extensions/terminal-suggest/src/completions/upstream/uname.ts new file mode 100644 index 0000000000000..e73b9efe39791 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/uname.ts @@ -0,0 +1,36 @@ +const completionSpec: Fig.Spec = { + name: "uname", + description: "Print operating system name", + options: [ + { + name: "-a", + description: "Print all available system information", + }, + { + name: "-m", + description: "Print the machine hardware name", + }, + { + name: "-n", + description: "Print the system hostname", + }, + { + name: "-p", + description: "Print the machine processor architecture name", + }, + { + name: "-r", + description: "Print the operating system release", + }, + { + name: "-s", + description: "Print the operating system name", + }, + { + name: "-v", + description: "Print the operating system version", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/vim.ts b/extensions/terminal-suggest/src/completions/upstream/vim.ts new file mode 100644 index 0000000000000..7e41109f025c2 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/vim.ts @@ -0,0 +1,244 @@ +const completionSpec: Fig.Spec = { + name: "vim", + description: "Vi IMproved, a programmer's text editor", + args: { + template: "filepaths", + // suggestCurrentToken: true, + }, + options: [ + { + name: "-v", + description: "Vi mode (like 'vi')", + }, + { + name: "-e", + description: "Ex mode (like 'ex')", + }, + { + name: "-E", + description: "Improved Ex mode", + }, + { + name: "-s", + description: + "Enable silent mode (when in ex mode), or Read Normal mode commands from file", + args: { + name: "scriptin", + template: "filepaths", + isOptional: true, + }, + }, + { + name: "-d", + description: "Diff mode (like 'vimdiff')", + }, + { + name: "-y", + description: "Easy mode (like 'evim', modeless)", + }, + { + name: "-R", + description: "Readonly mode (like 'view')", + }, + { + name: "-Z", + description: "Restricted mode (like 'rvim')", + }, + { + name: "-m", + description: "Modifications (writing files) not allowed", + }, + { + name: "-M", + description: "Modifications in text not allowed", + }, + { + name: "-b", + description: "Binary mode", + }, + { + name: "-l", + description: "Lisp mode", + }, + { + name: "-C", + description: "Compatible with Vi: 'compatible'", + }, + { + name: "-N", + description: "Not fully Vi compatible: 'nocompatible'", + }, + { + name: "-V", + description: "Be verbose [level N] [log messages to fname]", + args: [ + { + name: "N", + }, + { + name: "fname", + template: "filepaths", + }, + ], + }, + { + name: "-D", + description: "Debugging mode", + }, + { + name: "-n", + description: "No swap file, use memory only", + }, + { + name: "-r", + description: + "Recover crashed session if filename is specified, otherwise list swap files and exit", + args: { + name: "filename", + isOptional: true, + template: "filepaths", + }, + }, + { + name: "-L", + description: "Same as -r", + args: { + name: "filename", + template: "filepaths", + }, + }, + { + name: "-T", + description: "Set terminal type to ", + args: { + name: "terminal", + }, + }, + { + name: "--not-a-term", + description: "Skip warning for input/output not being a terminal", + }, + { + name: "--ttyfail", + description: "Exit if input or output is not a terminal", + }, + { + name: "-u", + description: "Use instead of any .vimrc", + args: { + name: "vimrc", + template: "filepaths", + }, + }, + { + name: "--noplugin", + description: "Don't load plugin scripts", + }, + { + name: "-p", + description: "Open N tab pages (default: one for each file)", + args: { + name: "N", + isOptional: true, + }, + }, + { + name: "-o", + description: "Open N windows (default: one for each file)", + args: { + name: "N", + isOptional: true, + }, + }, + { + name: "-O", + description: "Like -o but split vertically", + args: { + name: "N", + isOptional: true, + }, + }, + { + name: "+", + description: + "Start at end of file, if line number is specified, start at that line", + args: { + name: "lnum", + isOptional: true, + }, + }, + { + name: "--cmd", + description: "Execute before loading any vimrc file", + args: { + name: "command", + isCommand: true, + }, + }, + { + name: "-c", + description: "Execute after loading the first file", + args: { + name: "command", + }, + }, + { + name: "-S", + description: "Source file after loading the first file", + args: { + name: "session", + template: "filepaths", + }, + }, + { + name: "-w", + description: "Append all typed commands to file ", + args: { + name: "scriptout", + template: "filepaths", + }, + }, + { + name: "-W", + description: "Write all typed commands to file ", + args: { + name: "scriptout", + template: "filepaths", + }, + }, + { + name: "-x", + description: "Edit encrypted files", + }, + { + name: "--startuptime", + description: "Write startup timing messages to ", + args: { + name: "file", + template: "filepaths", + }, + }, + { + name: "-i", + description: "Use instead of .viminfo", + args: { + name: "viminfo", + template: "filepaths", + }, + }, + { + name: "--clean", + description: "'nocompatible', Vim defaults, no plugins, no viminfo", + }, + { + name: ["-h", "--help"], + description: "Print Help message and exit", + }, + { + name: "--version", + description: "Print version information and exit", + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/wget.ts b/extensions/terminal-suggest/src/completions/upstream/wget.ts new file mode 100644 index 0000000000000..fd8442d9e8aac --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/wget.ts @@ -0,0 +1,604 @@ +const completionSpec: Fig.Spec = { + name: "wget", + description: "A non-interactive network retriever", + args: { + isVariadic: true, + name: "url", + description: "The url(s) to retrieve", + }, + options: [ + { + name: ["-V", "--version"], + description: "Display the version of Wget and exit", + }, + { name: ["-h", "--help"], description: "Print this help" }, + { + name: ["-b", "--background"], + description: "Go to background after startup", + }, + { + name: ["-e", "--execute=COMMAND"], + description: "Execute a `.wgetrc'-style command", + }, + { name: ["-o", "--output-file=FILE"], description: "Log messages to FILE" }, + { + name: ["-a", "--append-output=FILE"], + description: "Append messages to FILE", + }, + { name: ["-q", "--quiet"], description: "Quiet (no output)" }, + { + name: ["-v", "--verbose"], + description: "Be verbose (this is the default)", + }, + { + name: ["-nv", "--no-verbose"], + description: "Turn off verboseness, without being quiet", + }, + { + name: "--report-speed=TYPE", + description: "Output bandwidth as TYPE. TYPE can be bits", + }, + { + name: ["-i", "--input-file=FILE"], + description: "Download URLs found in local or external FILE", + }, + { name: ["-F", "--force-html"], description: "Treat input file as HTML" }, + { + name: ["-B", "--base=URL"], + description: "Resolves HTML input-file links (-i -F) relative to URL", + }, + { name: "--config=FILE", description: "Specify config file to use" }, + { name: "--no-config", description: "Do not read any config file" }, + { + name: "--rejected-log=FILE", + description: "Log reasons for URL rejection to FILE", + }, + { + name: ["-t", "--tries=NUMBER"], + description: "Set number of retries to NUMBER (0 unlimits)", + }, + { + name: "--retry-connrefused", + description: "Retry even if connection is refused", + }, + { + name: "--retry-on-http-error", + description: "Comma-separated list of HTTP errors to retry", + }, + { + name: ["-O", "--output-document=FILE"], + description: "Write documents to FILE", + }, + { + name: ["-nc", "--no-clobber"], + description: + "Skip downloads that would download to existing files (overwriting them)", + }, + { + name: "--no-netrc", + description: "Don't try to obtain credentials from .netrc", + }, + { + name: ["-c", "--continue"], + description: "Resume getting a partially-downloaded file", + }, + { + name: "--start-pos=OFFSET", + description: "Start downloading from zero-based position OFFSET", + }, + { name: "--progress=TYPE", description: "Select progress gauge type" }, + { + name: "--show-progress", + description: "Display the progress bar in any verbosity mode", + }, + { + name: ["-N", "--timestamping"], + description: "Don't re-retrieve files unless newer than local", + }, + { name: ["-S", "--server-response"], description: "Print server response" }, + { name: "--spider", description: "Don't download anything" }, + { + name: ["-T", "--timeout=SECONDS"], + description: "Set all timeout values to SECONDS", + }, + { + name: "--dns-timeout=SECS", + description: "Set the DNS lookup timeout to SECS", + }, + { + name: "--connect-timeout=SECS", + description: "Set the connect timeout to SECS", + }, + { + name: "--read-timeout=SECS", + description: "Set the read timeout to SECS", + }, + { + name: ["-w", "--wait=SECONDS"], + description: "Wait SECONDS between retrievals", + }, + { + name: "--waitretry=SECONDS", + description: "Wait 1..SECONDS between retries of a retrieval", + }, + { + name: "--random-wait", + description: "Wait from 0.5*WAIT...1.5*WAIT secs between retrievals", + }, + { name: "--no-proxy", description: "Explicitly turn off proxy" }, + { + name: ["-Q", "--quota=NUMBER"], + description: "Set retrieval quota to NUMBER", + }, + { + name: "--bind-address=ADDRESS", + description: "Bind to ADDRESS (hostname or IP) on local host", + }, + { name: "--limit-rate=RATE", description: "Limit download rate to RATE" }, + { name: "--no-dns-cache", description: "Disable caching DNS lookups" }, + { + name: "--restrict-file-names=OS", + description: "Restrict chars in file names to ones OS allows", + }, + { + name: "--ignore-case", + description: "Ignore case when matching files/directories", + }, + { + name: ["-4", "--inet4-only"], + description: "Connect only to IPv4 addresses", + }, + { + name: ["-6", "--inet6-only"], + description: "Connect only to IPv6 addresses", + }, + { + name: "--user=USER", + description: "Set both ftp and http user to USER", + }, + { + name: "--password=PASS", + description: "Set both ftp and http password to PASS", + }, + { name: "--ask-password", description: "Prompt for passwords" }, + { name: "--no-iri", description: "Turn off IRI support" }, + { + name: "--local-encoding=ENC", + description: "Use ENC as the local encoding for IRIs", + }, + { + name: "--remote-encoding=ENC", + description: "Use ENC as the default remote encoding", + }, + { name: "--unlink", description: "Remove file before clobber" }, + { + name: "--xattr", + description: "Turn on storage of metadata in extended file attributes", + }, + { + name: ["-nd", "--no-directories"], + description: "Don't create directories", + }, + { + name: ["-x", "--force-directories"], + description: "Force creation of directories", + }, + { + name: ["-nH", "--no-host-directories"], + description: "Don't create host directories", + }, + { + name: "--protocol-directories", + description: "Use protocol name in directories", + }, + { + name: ["-P", "--directory-prefix=PREFIX"], + description: "Save files to PREFIX/", + }, + { + name: "--cut-dirs=NUMBER", + description: "Ignore NUMBER remote directory components", + }, + { name: "--http-user=USER", description: "Set http user to USER" }, + { + name: "--http-password=PASS", + description: "Set http password to PASS", + }, + { name: "--no-cache", description: "Disallow server-cached data" }, + { + name: ["-E", "--adjust-extension"], + description: "Save HTML/CSS documents with proper extensions", + }, + { + name: "--ignore-length", + description: "Ignore 'Content-Length' header field", + }, + { + name: "--header=STRING", + description: "Insert STRING among the headers", + }, + { + name: "--compression=TYPE", + description: + "Choose compression, one of auto, gzip and none. (default: none)", + }, + { + name: "--max-redirect", + description: "Maximum redirections allowed per page", + }, + { name: "--proxy-user=USER", description: "Set USER as proxy username" }, + { + name: "--proxy-password=PASS", + description: "Set PASS as proxy password", + }, + { + name: "--referer=URL", + description: "Include 'Referer: URL' header in HTTP request", + }, + { name: "--save-headers", description: "Save the HTTP headers to file" }, + { + name: ["-U", "--user-agent=AGENT"], + description: "Identify as AGENT instead of Wget/VERSION", + }, + { + name: "--no-http-keep-alive", + description: "Disable HTTP keep-alive (persistent connections)", + }, + { name: "--no-cookies", description: "Don't use cookies" }, + { + name: "--load-cookies=FILE", + description: "Load cookies from FILE before session", + }, + { + name: "--save-cookies=FILE", + description: "Save cookies to FILE after session", + }, + { + name: "--keep-session-cookies", + description: "Load and save session (non-permanent) cookies", + }, + { + name: "--post-data=STRING", + description: "Use the POST method; send STRING as the data", + }, + { + name: "--post-file=FILE", + description: "Use the POST method; send contents of FILE", + }, + { + name: "--method=HTTPMethod", + description: 'Use method "HTTPMethod" in the request', + }, + { + name: "--body-data=STRING", + description: "Send STRING as data. --method MUST be set", + }, + { + name: "--body-file=FILE", + description: "Send contents of FILE. --method MUST be set", + }, + { + name: "--content-on-error", + description: "Output the received content on server errors", + }, + { + name: "--secure-protocol=PR", + description: "Choose secure protocol, one of auto, SSLv2,", + }, + { name: "--https-only", description: "Only follow secure HTTPS links" }, + { + name: "--no-check-certificate", + description: "Don't validate the server's certificate", + }, + { name: "--certificate=FILE", description: "Client certificate file" }, + { + name: "--certificate-type=TYPE", + description: "Client certificate type, PEM or DER", + }, + { name: "--private-key=FILE", description: "Private key file" }, + { + name: "--private-key-type=TYPE", + description: "Private key type, PEM or DER", + }, + { + name: "--ca-certificate=FILE", + description: "File with the bundle of CAs", + }, + { + name: "--ca-directory=DIR", + description: "Directory where hash list of CAs is stored", + }, + { name: "--crl-file=FILE", description: "File with bundle of CRLs" }, + { + name: "--ciphers=STR", + description: + "Set the priority string (GnuTLS) or cipher list string (OpenSSL) directly", + }, + { name: ["-r", "--recursive"], description: "Specify recursive download" }, + { + name: ["-l", "--level=NUMBER"], + description: "Maximum recursion depth (inf or 0 for infinite)", + }, + { + name: "--delete-after", + description: "Delete files locally after downloading them", + }, + { + name: ["-k", "--convert-links"], + description: "Make links in downloaded HTML or CSS point to local files", + }, + { + name: ["-K", "--backup-converted"], + description: "Before converting file X, back up as X.orig", + }, + { + name: ["-m", "--mirror"], + description: "Shortcut for -N -r -l inf --no-remove-listing", + }, + { + name: ["-p", "--page-requisites"], + description: "Get all images, etc. needed to display HTML page", + }, + { + name: ["-A", "--accept=LIST"], + description: "Comma-separated list of accepted extensions", + }, + { + name: ["-R", "--reject=LIST"], + description: "Comma-separated list of rejected extensions", + }, + { + name: "--accept-regex=REGEX", + description: "Regex matching accepted URLs", + }, + { + name: "--reject-regex=REGEX", + description: "Regex matching rejected URLs", + }, + { name: "--regex-type=TYPE", description: "Regex type (posix)" }, + { + name: ["-D", "--domains=LIST"], + description: "Comma-separated list of accepted domains", + }, + { + name: "--exclude-domains=LIST", + description: "Comma-separated list of rejected domains", + }, + { + name: "--follow-ftp", + description: "Follow FTP links from HTML documents", + }, + { + name: "--follow-tags=LIST", + description: "Comma-separated list of followed HTML tags", + }, + { + name: "--ignore-tags=LIST", + description: "Comma-separated list of ignored HTML tags", + }, + { + name: ["-H", "--span-hosts"], + description: "Go to foreign hosts when recursive", + }, + { name: ["-L", "--relative"], description: "Follow relative links only" }, + { + name: ["-I", "--include-directories=LIST"], + description: "List of allowed directories", + }, + { + name: ["-X", "--exclude-directories=LIST"], + description: "List of excluded directories", + }, + { + name: ["-np", "--no-parent"], + description: "Don't ascend to the parent directory", + }, + ], +}; + +// GNU Wget 1.20.3, a non-interactive network retriever. +// Usage: wget [OPTION]... [URL]... + +// Mandatory arguments to long options are mandatory for short options too. + +// Startup: +// -V, --version display the version of Wget and exit +// -h, --help print this help +// -b, --background go to background after startup +// -e, --execute=COMMAND execute a `.wgetrc'-style command + +// Logging and input file: +// -o, --output-file=FILE log messages to FILE +// -a, --append-output=FILE append messages to FILE +// -q, --quiet quiet (no output) +// -v, --verbose be verbose (this is the default) +// -nv, --no-verbose turn off verboseness, without being quiet +// --report-speed=TYPE output bandwidth as TYPE. TYPE can be bits +// -i, --input-file=FILE download URLs found in local or external FILE +// -F, --force-html treat input file as HTML +// -B, --base=URL resolves HTML input-file links (-i -F) +// relative to URL +// --config=FILE specify config file to use +// --no-config do not read any config file +// --rejected-log=FILE log reasons for URL rejection to FILE + +// Download: +// -t, --tries=NUMBER set number of retries to NUMBER (0 unlimits) +// --retry-connrefused retry even if connection is refused +// --retry-on-http-error=ERRORS comma-separated list of HTTP errors to retry +// -O, --output-document=FILE write documents to FILE +// -nc, --no-clobber skip downloads that would download to +// existing files (overwriting them) +// --no-netrc don't try to obtain credentials from .netrc +// -c, --continue resume getting a partially-downloaded file +// --start-pos=OFFSET start downloading from zero-based position OFFSET +// --progress=TYPE select progress gauge type +// --show-progress display the progress bar in any verbosity mode +// -N, --timestamping don't re-retrieve files unless newer than +// local +// --no-if-modified-since don't use conditional if-modified-since get +// requests in timestamping mode +// --no-use-server-timestamps don't set the local file's timestamp by +// the one on the server +// -S, --server-response print server response +// --spider don't download anything +// -T, --timeout=SECONDS set all timeout values to SECONDS +// --dns-timeout=SECS set the DNS lookup timeout to SECS +// --connect-timeout=SECS set the connect timeout to SECS +// --read-timeout=SECS set the read timeout to SECS +// -w, --wait=SECONDS wait SECONDS between retrievals +// --waitretry=SECONDS wait 1..SECONDS between retries of a retrieval +// --random-wait wait from 0.5*WAIT...1.5*WAIT secs between retrievals +// --no-proxy explicitly turn off proxy +// -Q, --quota=NUMBER set retrieval quota to NUMBER +// --bind-address=ADDRESS bind to ADDRESS (hostname or IP) on local host +// --limit-rate=RATE limit download rate to RATE +// --no-dns-cache disable caching DNS lookups +// --restrict-file-names=OS restrict chars in file names to ones OS allows +// --ignore-case ignore case when matching files/directories +// -4, --inet4-only connect only to IPv4 addresses +// -6, --inet6-only connect only to IPv6 addresses +// --prefer-family=FAMILY connect first to addresses of specified family, +// one of IPv6, IPv4, or none +// --user=USER set both ftp and http user to USER +// --password=PASS set both ftp and http password to PASS +// --ask-password prompt for passwords +// --use-askpass=COMMAND specify credential handler for requesting +// username and password. If no COMMAND is +// specified the WGET_ASKPASS or the SSH_ASKPASS +// environment variable is used. +// --no-iri turn off IRI support +// --local-encoding=ENC use ENC as the local encoding for IRIs +// --remote-encoding=ENC use ENC as the default remote encoding +// --unlink remove file before clobber +// --xattr turn on storage of metadata in extended file attributes + +// Directories: +// -nd, --no-directories don't create directories +// -x, --force-directories force creation of directories +// -nH, --no-host-directories don't create host directories +// --protocol-directories use protocol name in directories +// -P, --directory-prefix=PREFIX save files to PREFIX/.. +// --cut-dirs=NUMBER ignore NUMBER remote directory components + +// HTTP options: +// --http-user=USER set http user to USER +// --http-password=PASS set http password to PASS +// --no-cache disallow server-cached data +// --default-page=NAME change the default page name (normally +// this is 'index.html'.) +// -E, --adjust-extension save HTML/CSS documents with proper extensions +// --ignore-length ignore 'Content-Length' header field +// --header=STRING insert STRING among the headers +// --compression=TYPE choose compression, one of auto, gzip and none. (default: none) +// --max-redirect maximum redirections allowed per page +// --proxy-user=USER set USER as proxy username +// --proxy-password=PASS set PASS as proxy password +// --referer=URL include 'Referer: URL' header in HTTP request +// --save-headers save the HTTP headers to file +// -U, --user-agent=AGENT identify as AGENT instead of Wget/VERSION +// --no-http-keep-alive disable HTTP keep-alive (persistent connections) +// --no-cookies don't use cookies +// --load-cookies=FILE load cookies from FILE before session +// --save-cookies=FILE save cookies to FILE after session +// --keep-session-cookies load and save session (non-permanent) cookies +// --post-data=STRING use the POST method; send STRING as the data +// --post-file=FILE use the POST method; send contents of FILE +// --method=HTTPMethod use method "HTTPMethod" in the request +// --body-data=STRING send STRING as data. --method MUST be set +// --body-file=FILE send contents of FILE. --method MUST be set +// --content-disposition honor the Content-Disposition header when +// choosing local file names (EXPERIMENTAL) +// --content-on-error output the received content on server errors +// --auth-no-challenge send Basic HTTP authentication information +// without first waiting for the server's +// challenge + +// HTTPS (SSL/TLS) options: +// --secure-protocol=PR choose secure protocol, one of auto, SSLv2, +// SSLv3, TLSv1, TLSv1_1, TLSv1_2 and PFS +// --https-only only follow secure HTTPS links +// --no-check-certificate don't validate the server's certificate +// --certificate=FILE client certificate file +// --certificate-type=TYPE client certificate type, PEM or DER +// --private-key=FILE private key file +// --private-key-type=TYPE private key type, PEM or DER +// --ca-certificate=FILE file with the bundle of CAs +// --ca-directory=DIR directory where hash list of CAs is stored +// --crl-file=FILE file with bundle of CRLs +// --pinnedpubkey=FILE/HASHES Public key (PEM/DER) file, or any number +// of base64 encoded sha256 hashes preceded by +// 'sha256//' and separated by ';', to verify +// peer against +// --random-file=FILE file with random data for seeding the SSL PRNG + +// --ciphers=STR Set the priority string (GnuTLS) or cipher list string (OpenSSL) directly. +// Use with care. This option overrides --secure-protocol. +// The format and syntax of this string depend on the specific SSL/TLS engine. +// HSTS options: +// --no-hsts disable HSTS +// --hsts-file path of HSTS database (will override default) + +// FTP options: +// --ftp-user=USER set ftp user to USER +// --ftp-password=PASS set ftp password to PASS +// --no-remove-listing don't remove '.listing' files +// --no-glob turn off FTP file name globbing +// --no-passive-ftp disable the "passive" transfer mode +// --preserve-permissions preserve remote file permissions +// --retr-symlinks when recursing, get linked-to files (not dir) + +// FTPS options: +// --ftps-implicit use implicit FTPS (default port is 990) +// --ftps-resume-ssl resume the SSL/TLS session started in the control connection when +// opening a data connection +// --ftps-clear-data-connection cipher the control channel only; all the data will be in plaintext +// --ftps-fallback-to-ftp fall back to FTP if FTPS is not supported in the target server +// WARC options: +// --warc-file=FILENAME save request/response data to a .warc.gz file +// --warc-header=STRING insert STRING into the warcinfo record +// --warc-max-size=NUMBER set maximum size of WARC files to NUMBER +// --warc-cdx write CDX index files +// --warc-dedup=FILENAME do not store records listed in this CDX file +// --no-warc-compression do not compress WARC files with GZIP +// --no-warc-digests do not calculate SHA1 digests +// --no-warc-keep-log do not store the log file in a WARC record +// --warc-tempdir=DIRECTORY location for temporary files created by the +// WARC writer + +// Recursive download: +// -r, --recursive specify recursive download +// -l, --level=NUMBER maximum recursion depth (inf or 0 for infinite) +// --delete-after delete files locally after downloading them +// -k, --convert-links make links in downloaded HTML or CSS point to +// local files +// --convert-file-only convert the file part of the URLs only (usually known as the basename) +// --backups=N before writing file X, rotate up to N backup files +// -K, --backup-converted before converting file X, back up as X.orig +// -m, --mirror shortcut for -N -r -l inf --no-remove-listing +// -p, --page-requisites get all images, etc. needed to display HTML page +// --strict-comments turn on strict (SGML) handling of HTML comments + +// Recursive accept/reject: +// -A, --accept=LIST comma-separated list of accepted extensions +// -R, --reject=LIST comma-separated list of rejected extensions +// --accept-regex=REGEX regex matching accepted URLs +// --reject-regex=REGEX regex matching rejected URLs +// --regex-type=TYPE regex type (posix) +// -D, --domains=LIST comma-separated list of accepted domains +// --exclude-domains=LIST comma-separated list of rejected domains +// --follow-ftp follow FTP links from HTML documents +// --follow-tags=LIST comma-separated list of followed HTML tags +// --ignore-tags=LIST comma-separated list of ignored HTML tags +// -H, --span-hosts go to foreign hosts when recursive +// -L, --relative follow relative links only +// -I, --include-directories=LIST list of allowed directories +// --trust-server-names use the name specified by the redirection +// URL's last component +// -X, --exclude-directories=LIST list of excluded directories +// -np, --no-parent don't ascend to the parent directory + +// Email bug reports, questions, discussions to +// and/or open issues at https://savannah.gnu.org/bugs/?func=additem&group=wget. + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/upstream/yarn.ts b/extensions/terminal-suggest/src/completions/upstream/yarn.ts new file mode 100644 index 0000000000000..a3de493a1b3bb --- /dev/null +++ b/extensions/terminal-suggest/src/completions/upstream/yarn.ts @@ -0,0 +1,1674 @@ +import { npmScriptsGenerator, npmSearchGenerator } from "./npm"; + +export const yarnScriptParserDirectives: Fig.Arg["parserDirectives"] = { + alias: async (token, executeShellCommand) => { + const npmPrefix = await executeShellCommand({ + command: "npm", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: ["prefix"], + }); + if (npmPrefix.status !== 0) { + throw new Error("npm prefix command failed"); + } + const packageJson = await executeShellCommand({ + command: "cat", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: [`${npmPrefix.stdout.trim()}/package.json`], + }); + const script: string = JSON.parse(packageJson.stdout).scripts?.[token]; + if (!script) { + throw new Error(`Script not found: '${token}'`); + } + return script; + }, +}; + +export const nodeClis = new Set([ + "vue", + "vite", + "nuxt", + "react-native", + "degit", + "expo", + "jest", + "next", + "electron", + "prisma", + "eslint", + "prettier", + "tsc", + "typeorm", + "babel", + "remotion", + "autocomplete-tools", + "redwood", + "rw", + "create-completion-spec", + "publish-spec-to-team", + "capacitor", + "cap", +]); + +// generate global package list from global package.json file +const getGlobalPackagesGenerator: Fig.Generator = { + custom: async (tokens, executeCommand, generatorContext) => { + const { stdout: yarnGlobalDir } = await executeCommand({ + command: "yarn", + args: ["global", "dir"], + }); + + const { stdout } = await executeCommand({ + command: "cat", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: [`${yarnGlobalDir.trim()}/package.json`], + }); + + if (stdout.trim() == "") return []; + + try { + const packageContent = JSON.parse(stdout); + const dependencyScripts = packageContent["dependencies"] || {}; + const devDependencyScripts = packageContent["devDependencies"] || {}; + const dependencies = [ + ...Object.keys(dependencyScripts), + ...Object.keys(devDependencyScripts), + ]; + + const filteredDependencies = dependencies.filter( + (dependency) => !tokens.includes(dependency) + ); + + return filteredDependencies.map((dependencyName) => ({ + name: dependencyName, + icon: "πŸ“¦", + })); + } catch (e) { } + + return []; + }, +}; + +// generate package list of direct and indirect dependencies +const allDependenciesGenerator: Fig.Generator = { + script: ["yarn", "list", "--depth=0", "--json"], + postProcess: (out) => { + if (out.trim() == "") return []; + + try { + const packageContent = JSON.parse(out); + const dependencies = packageContent.data.trees; + return dependencies.map((dependency: { name: string }) => ({ + name: dependency.name.split("@")[0], + icon: "πŸ“¦", + })); + } catch (e) { } + return []; + }, +}; + +const configList: Fig.Generator = { + script: ["yarn", "config", "list"], + postProcess: function (out) { + if (out.trim() == "") { + return []; + } + + try { + const startIndex = out.indexOf("{"); + const endIndex = out.indexOf("}"); + let output = out.substring(startIndex, endIndex + 1); + // TODO: fix hacky code + // reason: JSON parse was not working without double quotes + output = output + .replace(/\'/gi, '"') + .replace("lastUpdateCheck", '"lastUpdateCheck"') + .replace("registry", '"lastUpdateCheck"'); + const configObject = JSON.parse(output); + if (configObject) { + return Object.keys(configObject).map((key) => ({ name: key })); + } + } catch (e) { } + + return []; + }, +}; + +export const dependenciesGenerator: Fig.Generator = { + script: [ + "bash", + "-c", + "until [[ -f package.json ]] || [[ $PWD = '/' ]]; do cd ..; done; cat package.json", + ], + postProcess: function (out, context = []) { + if (out.trim() === "") { + return []; + } + + try { + const packageContent = JSON.parse(out); + const dependencies = packageContent["dependencies"] ?? {}; + const devDependencies = packageContent["devDependencies"]; + const optionalDependencies = packageContent["optionalDependencies"] ?? {}; + Object.assign(dependencies, devDependencies, optionalDependencies); + + return Object.keys(dependencies) + .filter((pkgName) => { + const isListed = context.some((current) => current === pkgName); + return !isListed; + }) + .map((pkgName) => ({ + name: pkgName, + icon: "πŸ“¦", + description: dependencies[pkgName] + ? "dependency" + : optionalDependencies[pkgName] + ? "optionalDependency" + : "devDependency", + })); + } catch (e) { + console.error(e); + return []; + } + }, +}; + +const commonOptions: Fig.Option[] = [ + { name: ["-s", "--silent"], description: "Skip Yarn console logs" }, + { + name: "--no-default-rc", + description: + "Prevent Yarn from automatically detecting yarnrc and npmrc files", + }, + { + name: "--use-yarnrc", + description: + "Specifies a yarnrc file that Yarn should use (.yarnrc only, not .npmrc) (default: )", + args: { name: "path", template: "filepaths" }, + }, + { + name: "--verbose", + description: "Output verbose messages on internal operations", + }, + { + name: "--offline", + description: + "Trigger an error if any required dependencies are not available in local cache", + }, + { + name: "--prefer-offline", + description: + "Use network only if dependencies are not available in local cache", + }, + { + name: ["--enable-pnp", "--pnp"], + description: "Enable the Plug'n'Play installation", + }, + { + name: "--json", + description: "Format Yarn log messages as lines of JSON", + }, + { + name: "--ignore-scripts", + description: "Don't run lifecycle scripts", + }, + { name: "--har", description: "Save HAR output of network traffic" }, + { name: "--ignore-platform", description: "Ignore platform checks" }, + { name: "--ignore-engines", description: "Ignore engines check" }, + { + name: "--ignore-optional", + description: "Ignore optional dependencies", + }, + { + name: "--force", + description: + "Install and build packages even if they were built before, overwrite lockfile", + }, + { + name: "--skip-integrity-check", + description: "Run install without checking if node_modules is installed", + }, + { + name: "--check-files", + description: "Install will verify file tree of packages for consistency", + }, + { + name: "--no-bin-links", + description: "Don't generate bin links when setting up packages", + }, + { name: "--flat", description: "Only allow one version of a package" }, + { + name: ["--prod", "--production"], + description: + "Instruct Yarn to ignore NODE_ENV and take its production-or-not status from this flag instead", + }, + { + name: "--no-lockfile", + description: "Don't read or generate a lockfile", + }, + { name: "--pure-lockfile", description: "Don't generate a lockfile" }, + { + name: "--frozen-lockfile", + description: "Don't generate a lockfile and fail if an update is needed", + }, + { + name: "--update-checksums", + description: "Update package checksums from current repository", + }, + { + name: "--link-duplicates", + description: "Create hardlinks to the repeated modules in node_modules", + }, + { + name: "--link-folder", + description: "Specify a custom folder to store global links", + args: { name: "path", template: "folders" }, + }, + { + name: "--global-folder", + description: "Specify a custom folder to store global packages", + args: { name: "path", template: "folders" }, + }, + { + name: "--modules-folder", + description: + "Rather than installing modules into the node_modules folder relative to the cwd, output them here", + args: { name: "path", template: "folders" }, + }, + { + name: "--preferred-cache-folder", + description: "Specify a custom folder to store the yarn cache if possible", + args: { name: "path", template: "folders" }, + }, + { + name: "--cache-folder", + description: + "Specify a custom folder that must be used to store the yarn cache", + args: { name: "path", template: "folders" }, + }, + { + name: "--mutex", + description: "Use a mutex to ensure only one yarn instance is executing", + args: { name: "type[:specifier]" }, + }, + { + name: "--emoji", + description: "Enables emoji in output", + args: { + default: "true", + suggestions: ["true", "false"], + }, + }, + { + name: "--cwd", + description: "Working directory to use", + args: { name: "cwd", template: "folders" }, + }, + { + name: ["--proxy", "--https-proxy"], + description: "", + args: { name: "host" }, + }, + { + name: "--registry", + description: "Override configuration registry", + args: { name: "url" }, + }, + { name: "--no-progress", description: "Disable progress bar" }, + { + name: "--network-concurrency", + description: "Maximum number of concurrent network requests", + args: { name: "number" }, + }, + { + name: "--network-timeout", + description: "TCP timeout for network requests", + args: { name: "milliseconds" }, + }, + { + name: "--non-interactive", + description: "Do not show interactive prompts", + }, + { + name: "--scripts-prepend-node-path", + description: "Prepend the node executable dir to the PATH in scripts", + }, + { + name: "--no-node-version-check", + description: + "Do not warn when using a potentially unsupported Node version", + }, + { + name: "--focus", + description: + "Focus on a single workspace by installing remote copies of its sibling workspaces", + }, + { + name: "--otp", + description: "One-time password for two factor authentication", + args: { name: "otpcode" }, + }, +]; + +export const createCLIsGenerator: Fig.Generator = { + script: function (context) { + if (context[context.length - 1] === "") return undefined; + const searchTerm = "create-" + context[context.length - 1]; + return [ + "curl", + "-s", + "-H", + "Accept: application/json", + `https://api.npms.io/v2/search?q=${searchTerm}&size=20`, + ]; + }, + cache: { + ttl: 100 * 24 * 60 * 60 * 3, // 3 days + }, + postProcess: function (out) { + try { + return JSON.parse(out).results.map( + (item: any) => + ({ + name: item.package.name.substring(7), + description: item.package.description, + }) as Fig.Suggestion + ) as Fig.Suggestion[]; + } catch (e) { + return []; + } + }, +}; + +const completionSpec: Fig.Spec = { + name: "yarn", + description: "Manage packages and run scripts", + generateSpec: async (tokens, executeShellCommand) => { + const binaries = ( + await executeShellCommand({ + command: "bash", + args: [ + "-c", + `until [[ -d node_modules/ ]] || [[ $PWD = '/' ]]; do cd ..; done; ls -1 node_modules/.bin/`, + ], + }) + ).stdout.split("\n"); + + const subcommands = binaries + .filter((name) => nodeClis.has(name)) + .map((name) => ({ + name: name, + loadSpec: name === "rw" ? "redwood" : name, + icon: "fig://icon?type=package", + })); + + return { + name: "yarn", + subcommands, + } as Fig.Spec; + }, + args: { + generators: npmScriptsGenerator, + filterStrategy: "fuzzy", + parserDirectives: yarnScriptParserDirectives, + isOptional: true, + isCommand: true, + }, + options: [ + { + name: "--disable-pnp", + description: "Disable the Plug'n'Play installation", + }, + { + name: "--emoji", + description: "Enable emoji in output (default: true)", + args: { + name: "bool", + suggestions: [{ name: "true" }, { name: "false" }], + }, + }, + { + name: ["--enable-pnp", "--pnp"], + description: "Enable the Plug'n'Play installation", + }, + { + name: "--flat", + description: "Only allow one version of a package", + }, + { + name: "--focus", + description: + "Focus on a single workspace by installing remote copies of its sibling workspaces", + }, + { + name: "--force", + description: + "Install and build packages even if they were built before, overwrite lockfile", + }, + { + name: "--frozen-lockfile", + description: "Don't generate a lockfile and fail if an update is needed", + }, + { + name: "--global-folder", + description: "Specify a custom folder to store global packages", + args: { + template: "folders", + }, + }, + { + name: "--har", + description: "Save HAR output of network traffic", + }, + { + name: "--https-proxy", + description: "", + args: { + name: "path", + suggestions: [{ name: "https://" }], + }, + }, + { + name: "--ignore-engines", + description: "Ignore engines check", + }, + { + name: "--ignore-optional", + description: "Ignore optional dependencies", + }, + { + name: "--ignore-platform", + description: "Ignore platform checks", + }, + { + name: "--ignore-scripts", + description: "Don't run lifecycle scripts", + }, + { + name: "--json", + description: + "Format Yarn log messages as lines of JSON (see jsonlines.org)", + }, + { + name: "--link-duplicates", + description: "Create hardlinks to the repeated modules in node_modules", + }, + { + name: "--link-folder", + description: "Specify a custom folder to store global links", + args: { + template: "folders", + }, + }, + { + name: "--modules-folder", + description: + "Rather than installing modules into the node_modules folder relative to the cwd, output them here", + args: { + template: "folders", + }, + }, + { + name: "--mutex", + description: "Use a mutex to ensure only one yarn instance is executing", + args: [ + { + name: "type", + suggestions: [{ name: ":" }], + }, + { + name: "specifier", + suggestions: [{ name: ":" }], + }, + ], + }, + { + name: "--network-concurrency", + description: "Maximum number of concurrent network requests", + args: { + name: "number", + }, + }, + { + name: "--network-timeout", + description: "TCP timeout for network requests", + args: { + name: "milliseconds", + }, + }, + { + name: "--no-bin-links", + description: "Don't generate bin links when setting up packages", + }, + { + name: "--no-default-rc", + description: + "Prevent Yarn from automatically detecting yarnrc and npmrc files", + }, + { + name: "--no-lockfile", + description: "Don't read or generate a lockfile", + }, + { + name: "--non-interactive", + description: "Do not show interactive prompts", + }, + { + name: "--no-node-version-check", + description: + "Do not warn when using a potentially unsupported Node version", + }, + { + name: "--no-progress", + description: "Disable progress bar", + }, + { + name: "--offline", + description: + "Trigger an error if any required dependencies are not available in local cache", + }, + { + name: "--otp", + description: "One-time password for two factor authentication", + args: { + name: "otpcode", + }, + }, + { + name: "--prefer-offline", + description: + "Use network only if dependencies are not available in local cache", + }, + { + name: "--preferred-cache-folder", + description: + "Specify a custom folder to store the yarn cache if possible", + args: { + template: "folders", + }, + }, + { + name: ["--prod", "--production"], + description: "", + args: {}, + }, + { + name: "--proxy", + description: "", + args: { + name: "host", + }, + }, + { + name: "--pure-lockfile", + description: "Don't generate a lockfile", + }, + { + name: "--registry", + description: "Override configuration registry", + args: { + name: "url", + }, + }, + { + name: ["-s", "--silent"], + description: + "Skip Yarn console logs, other types of logs (script output) will be printed", + }, + { + name: "--scripts-prepend-node-path", + description: "Prepend the node executable dir to the PATH in scripts", + args: { + suggestions: [{ name: "true" }, { name: "false" }], + }, + }, + { + name: "--skip-integrity-check", + description: "Run install without checking if node_modules is installed", + }, + { + name: "--strict-semver", + description: "", + }, + ...commonOptions, + { + name: ["-v", "--version"], + description: "Output the version number", + }, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + subcommands: [ + { + name: "add", + description: "Installs a package and any packages that it depends on", + args: { + name: "package", + generators: npmSearchGenerator, + debounce: true, + isVariadic: true, + }, + options: [ + ...commonOptions, + { + name: ["-W", "--ignore-workspace-root-check"], + description: "Required to run yarn add inside a workspace root", + }, + { + name: ["-D", "--dev"], + description: "Save package to your `devDependencies`", + }, + { + name: ["-P", "--peer"], + description: "Save package to your `peerDependencies`", + }, + { + name: ["-O", "--optional"], + description: "Save package to your `optionalDependencies`", + }, + { + name: ["-E", "--exact"], + description: "Install exact version", + dependsOn: ["--latest"], + }, + { + name: ["-T", "--tilde"], + description: + "Install most recent release with the same minor version", + }, + { + name: ["-A", "--audit"], + description: "Run vulnerability audit on installed packages", + }, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "audit", + description: + "Perform a vulnerability audit against the installed packages", + options: [ + { + name: "--summary", + description: "Only print the summary", + }, + { + name: "--groups", + description: + "Only audit dependencies from listed groups. Default: devDependencies, dependencies, optionalDependencies", + args: { + name: "group_name", + isVariadic: true, + }, + }, + { + name: "--level", + description: + "Only print advisories with severity greater than or equal to one of the following: info|low|moderate|high|critical. Default: info", + args: { + name: "severity", + suggestions: [ + { name: "info" }, + { name: "low" }, + { name: "moderate" }, + { name: "high" }, + { name: "critical" }, + ], + }, + }, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "autoclean", + description: + "Cleans and removes unnecessary files from package dependencies", + options: [ + { + name: ["-h", "--help"], + description: "Output usage information", + }, + { + name: ["-i", "--init"], + description: + "Creates the .yarnclean file if it does not exist, and adds the default entries", + }, + { + name: ["-f", "--force"], + description: "If a .yarnclean file exists, run the clean process", + }, + ], + }, + { + name: "bin", + description: "Displays the location of the yarn bin folder", + options: [ + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "cache", + description: "Yarn cache list will print out every cached package", + options: [ + ...commonOptions, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + subcommands: [ + { + name: "clean", + description: "Clear global cache", + }, + { + name: "dir", + description: "Print yarn’s global cache path", + }, + { + name: "list", + description: "Print out every cached package", + options: [ + { + name: "--pattern", + description: "Filter cached packages by pattern", + args: { + name: "pattern", + }, + }, + ], + }, + ], + }, + { + name: "config", + description: "Configure yarn", + options: [ + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + subcommands: [ + { + name: "set", + description: "Sets the config key to a certain value", + options: [ + { + name: ["-g", "--global"], + description: "Set global config", + }, + ], + }, + { + name: "get", + description: "Print the value for a given key", + args: { + generators: configList, + }, + }, + { + name: "delete", + description: "Deletes a given key from the config", + args: { + generators: configList, + }, + }, + { + name: "list", + description: "Displays the current configuration", + }, + ], + }, + { + name: "create", + description: "Creates new projects from any create-* starter kits", + args: { + name: "cli", + generators: createCLIsGenerator, + loadSpec: async (token) => ({ + name: "create-" + token, + type: "global", + }), + isCommand: true, + }, + options: [ + ...commonOptions, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "exec", + description: "", + options: [ + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "generate-lock-entry", + description: "Generates a lock file entry", + options: [ + { + name: "--use-manifest", + description: + "Specify which manifest file to use for generating lock entry", + args: { + template: "filepaths", + }, + }, + { + name: "--resolved", + description: "Generate from <*.tgz>#", + args: { + template: "filepaths", + }, + }, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "global", + description: "Manage yarn globally", + subcommands: [ + { + name: "add", + description: "Install globally packages on your operating system", + args: { + name: "package", + generators: npmSearchGenerator, + debounce: true, + isVariadic: true, + }, + }, + { + name: "bin", + description: "Displays the location of the yarn global bin folder", + }, + { + name: "dir", + description: + "Displays the location of the global installation folder", + }, + { + name: "ls", + description: "List globally installed packages (deprecated)", + }, + { + name: "list", + description: "List globally installed packages", + }, + { + name: "remove", + description: "Remove globally installed packages", + args: { + name: "package", + filterStrategy: "fuzzy", + generators: getGlobalPackagesGenerator, + isVariadic: true, + }, + options: [ + ...commonOptions, + { + name: ["-W", "--ignore-workspace-root-check"], + description: + "Required to run yarn remove inside a workspace root", + }, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "upgrade", + description: "Upgrade globally installed packages", + options: [ + ...commonOptions, + { + name: ["-S", "--scope"], + description: "Upgrade packages under the specified scope", + args: { name: "scope" }, + }, + { + name: ["-L", "--latest"], + description: "List the latest version of packages", + }, + { + name: ["-E", "--exact"], + description: + "Install exact version. Only used when --latest is specified", + dependsOn: ["--latest"], + }, + { + name: ["-P", "--pattern"], + description: "Upgrade packages that match pattern", + args: { name: "pattern" }, + }, + { + name: ["-T", "--tilde"], + description: + "Install most recent release with the same minor version. Only used when --latest is specified", + }, + { + name: ["-C", "--caret"], + description: + "Install most recent release with the same major version. Only used when --latest is specified", + dependsOn: ["--latest"], + }, + { + name: ["-A", "--audit"], + description: "Run vulnerability audit on installed packages", + }, + { name: ["-h", "--help"], description: "Output usage information" }, + ], + }, + { + name: "upgrade-interactive", + description: + "Display the outdated packages before performing any upgrade", + options: [ + { + name: "--latest", + description: "Use the version tagged latest in the registry", + }, + ], + }, + ], + options: [ + ...commonOptions, + { + name: "--prefix", + description: "Bin prefix to use to install binaries", + args: { + name: "prefix", + }, + }, + { + name: "--latest", + description: "Bin prefix to use to install binaries", + }, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "help", + description: "Output usage information", + }, + { + name: "import", + description: "Generates yarn.lock from an npm package-lock.json file", + }, + { + name: "info", + description: "Show information about a package", + }, + { + name: "init", + description: "Interactively creates or updates a package.json file", + options: [ + ...commonOptions, + { + name: ["-y", "--yes"], + description: "Use default options", + }, + { + name: ["-p", "--private"], + description: "Use default options and private true", + }, + { + name: ["-i", "--install"], + description: "Install a specific Yarn release", + args: { + name: "version", + }, + }, + { + name: "-2", + description: "Generates the project using Yarn 2", + }, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "install", + description: "Install all the dependencies listed within package.json", + options: [ + ...commonOptions, + { + name: ["-A", "--audit"], + description: "Run vulnerability audit on installed packages", + }, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "licenses", + description: "", + subcommands: [ + { + name: "list", + description: "List licenses for installed packages", + }, + { + name: "generate-disclaimer", + description: "List of licenses from all the packages", + }, + ], + }, + { + name: "link", + description: "Symlink a package folder during development", + args: { + isOptional: true, + name: "package", + }, + options: [ + ...commonOptions, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "list", + description: "Lists all dependencies for the current working directory", + options: [ + { + name: "--depth", + description: "Restrict the depth of the dependencies", + }, + { + name: "--pattern", + description: "Filter the list of dependencies by the pattern", + }, + ], + }, + { + name: "login", + description: "Store registry username and email", + }, + { + name: "logout", + description: "Clear registry username and email", + }, + { + name: "node", + description: "", + }, + { + name: "outdated", + description: "Checks for outdated package dependencies", + options: [ + ...commonOptions, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "owner", + description: "Manage package owners", + subcommands: [ + { + name: "list", + description: "Lists all of the owners of a package", + args: { + name: "package", + }, + }, + { + name: "add", + description: "Adds the user as an owner of the package", + args: { + name: "package", + }, + }, + { + name: "remove", + description: "Removes the user as an owner of the package", + args: [ + { + name: "user", + }, + { + name: "package", + }, + ], + }, + ], + }, + { + name: "pack", + description: "Creates a compressed gzip archive of package dependencies", + options: [ + { + name: "--filename", + description: + "Creates a compressed gzip archive of package dependencies and names the file filename", + }, + ], + }, + { + name: "policies", + description: "Defines project-wide policies for your project", + subcommands: [ + { + name: "set-version", + description: "Will download the latest stable release", + options: [ + { + name: "--rc", + description: "Download the latest rc release", + }, + ], + }, + ], + }, + { + name: "publish", + description: "Publishes a package to the npm registry", + args: { name: "Tarball or Folder", template: "folders" }, + options: [ + ...commonOptions, + { name: ["-h", "--help"], description: "Output usage information" }, + { + name: "--major", + description: "Auto-increment major version number", + }, + { + name: "--minor", + description: "Auto-increment minor version number", + }, + { + name: "--patch", + description: "Auto-increment patch version number", + }, + { + name: "--premajor", + description: "Auto-increment premajor version number", + }, + { + name: "--preminor", + description: "Auto-increment preminor version number", + }, + { + name: "--prepatch", + description: "Auto-increment prepatch version number", + }, + { + name: "--prerelease", + description: "Auto-increment prerelease version number", + }, + { + name: "--preid", + description: "Add a custom identifier to the prerelease", + args: { name: "preid" }, + }, + { + name: "--message", + description: "Message", + args: { name: "message" }, + }, + { name: "--no-git-tag-version", description: "No git tag version" }, + { + name: "--no-commit-hooks", + description: "Bypass git hooks when committing new version", + }, + { name: "--access", description: "Access", args: { name: "access" } }, + { name: "--tag", description: "Tag", args: { name: "tag" } }, + ], + }, + { + name: "remove", + description: "Remove installed package", + args: { + filterStrategy: "fuzzy", + generators: dependenciesGenerator, + isVariadic: true, + }, + options: [ + ...commonOptions, + { + name: ["-W", "--ignore-workspace-root-check"], + description: "Required to run yarn remove inside a workspace root", + }, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + ], + }, + { + name: "run", + description: "Runs a defined package script", + options: [ + ...commonOptions, + { name: ["-h", "--help"], description: "Output usage information" }, + ], + args: [ + { + name: "script", + description: "Script to run from your package.json", + generators: npmScriptsGenerator, + filterStrategy: "fuzzy", + parserDirectives: yarnScriptParserDirectives, + isCommand: true, + }, + { + name: "env", + suggestions: ["env"], + description: "Lists environment variables available to scripts", + isOptional: true, + }, + ], + }, + { + name: "tag", + description: "Add, remove, or list tags on a package", + }, + { + name: "team", + description: "Maintain team memberships", + subcommands: [ + { + name: "create", + description: "Create a new team", + args: { + name: "", + }, + }, + { + name: "destroy", + description: "Destroys an existing team", + args: { + name: "", + }, + }, + { + name: "add", + description: "Add a user to an existing team", + args: [ + { + name: "", + }, + { + name: "", + }, + ], + }, + { + name: "remove", + description: "Remove a user from a team they belong to", + args: { + name: " ", + }, + }, + { + name: "list", + description: + "If performed on an organization name, will return a list of existing teams under that organization. If performed on a team, it will instead return a list of all users belonging to that particular team", + args: { + name: "|", + }, + }, + ], + }, + { + name: "unlink", + description: "Unlink a previously created symlink for a package", + }, + { + name: "unplug", + description: "", + }, + { + name: "upgrade", + description: + "Upgrades packages to their latest version based on the specified range", + args: { + name: "package", + generators: dependenciesGenerator, + filterStrategy: "fuzzy", + isVariadic: true, + isOptional: true, + }, + options: [ + ...commonOptions, + { + name: ["-S", "--scope"], + description: "Upgrade packages under the specified scope", + args: { name: "scope" }, + }, + { + name: ["-L", "--latest"], + description: "List the latest version of packages", + }, + { + name: ["-E", "--exact"], + description: + "Install exact version. Only used when --latest is specified", + dependsOn: ["--latest"], + }, + { + name: ["-P", "--pattern"], + description: "Upgrade packages that match pattern", + args: { name: "pattern" }, + }, + { + name: ["-T", "--tilde"], + description: + "Install most recent release with the same minor version. Only used when --latest is specified", + }, + { + name: ["-C", "--caret"], + description: + "Install most recent release with the same major version. Only used when --latest is specified", + dependsOn: ["--latest"], + }, + { + name: ["-A", "--audit"], + description: "Run vulnerability audit on installed packages", + }, + { name: ["-h", "--help"], description: "Output usage information" }, + ], + }, + { + name: "upgrade-interactive", + description: "Upgrades packages in interactive mode", + options: [ + { + name: "--latest", + description: "Use the version tagged latest in the registry", + }, + ], + }, + { + name: "version", + description: "Update version of your package", + options: [ + ...commonOptions, + { name: ["-h", "--help"], description: "Output usage information" }, + { + name: "--new-version", + description: "New version", + args: { name: "version" }, + }, + { + name: "--major", + description: "Auto-increment major version number", + }, + { + name: "--minor", + description: "Auto-increment minor version number", + }, + { + name: "--patch", + description: "Auto-increment patch version number", + }, + { + name: "--premajor", + description: "Auto-increment premajor version number", + }, + { + name: "--preminor", + description: "Auto-increment preminor version number", + }, + { + name: "--prepatch", + description: "Auto-increment prepatch version number", + }, + { + name: "--prerelease", + description: "Auto-increment prerelease version number", + }, + { + name: "--preid", + description: "Add a custom identifier to the prerelease", + args: { name: "preid" }, + }, + { + name: "--message", + description: "Message", + args: { name: "message" }, + }, + { name: "--no-git-tag-version", description: "No git tag version" }, + { + name: "--no-commit-hooks", + description: "Bypass git hooks when committing new version", + }, + { name: "--access", description: "Access", args: { name: "access" } }, + { name: "--tag", description: "Tag", args: { name: "tag" } }, + ], + }, + { + name: "versions", + description: + "Displays version information of the currently installed Yarn, Node.js, and its dependencies", + }, + { + name: "why", + description: "Show information about why a package is installed", + args: { + name: "package", + filterStrategy: "fuzzy", + generators: allDependenciesGenerator, + }, + options: [ + ...commonOptions, + { + name: ["-h", "--help"], + description: "Output usage information", + }, + { + name: "--peers", + description: + "Print the peer dependencies that match the specified name", + }, + { + name: ["-R", "--recursive"], + description: + "List, for each workspace, what are all the paths that lead to the dependency", + }, + ], + }, + { + name: "workspace", + description: "Manage workspace", + filterStrategy: "fuzzy", + generateSpec: async (_tokens, executeShellCommand) => { + const version = ( + await executeShellCommand({ + command: "yarn", + // eslint-disable-next-line @withfig/fig-linter/no-useless-arrays + args: ["--version"], + }) + ).stdout; + const isYarnV1 = version.startsWith("1."); + + const getWorkspacesDefinitionsV1 = async () => { + const { stdout } = await executeShellCommand({ + command: "yarn", + args: ["workspaces", "info"], + }); + + const startJson = stdout.indexOf("{"); + const endJson = stdout.lastIndexOf("}"); + + return Object.entries( + JSON.parse(stdout.slice(startJson, endJson + 1)) as Record< + string, + { location: string } + > + ).map(([name, { location }]) => ({ + name, + location, + })); + }; + + // For yarn >= 2.0.0 + const getWorkspacesDefinitionsVOther = async () => { + // yarn workspaces list --json + const out = ( + await executeShellCommand({ + command: "yarn", + args: ["workspaces", "list", "--json"], + }) + ).stdout; + return out.split("\n").map((line) => JSON.parse(line.trim())); + }; + + try { + const workspacesDefinitions = isYarnV1 + ? // transform Yarn V1 output to array of workspaces like Yarn V2 + await getWorkspacesDefinitionsV1() + : // in yarn v>=2.0.0, workspaces definitions are a list of JSON lines + await getWorkspacesDefinitionsVOther(); + + const subcommands: Fig.Subcommand[] = workspacesDefinitions.map( + ({ name, location }: { name: string; location: string }) => ({ + name, + description: "Workspaces", + args: { + name: "script", + generators: { + cache: { + strategy: "stale-while-revalidate", + ttl: 60_000, // 60s + }, + script: ["cat", `${location}/package.json`], + postProcess: function (out: string) { + if (out.trim() == "") { + return []; + } + try { + const packageContent = JSON.parse(out); + const scripts = packageContent["scripts"]; + if (scripts) { + return Object.keys(scripts).map((script) => ({ + name: script, + })); + } + } catch (e) { } + return []; + }, + }, + }, + }) + ); + + return { + name: "workspace", + subcommands, + }; + } catch (e) { + console.error(e); + } + return { name: "workspaces" }; + }, + }, + { + name: "workspaces", + description: "Show information about your workspaces", + options: [ + { + name: "subcommand", + description: "", + args: { + suggestions: [{ name: "info" }, { name: "run" }], + }, + }, + { + name: "flags", + description: "", + }, + ], + }, + { + name: "set", + description: "Set global Yarn options", + subcommands: [ + { + name: "resolution", + description: "Enforce a package resolution", + args: [ + { + name: "descriptor", + description: + "A descriptor for the package, in the form of 'lodash@npm:^1.2.3'", + }, + { + name: "resolution", + description: "The version of the package to resolve", + }, + ], + options: [ + { + name: ["-s", "--save"], + description: + "Persist the resolution inside the top-level manifest", + }, + ], + }, + { + name: "version", + description: "Lock the Yarn version used by the project", + args: { + name: "version", + description: + "Use the specified version, which can also be a Yarn 2 build (e.g 2.0.0-rc.30) or a Yarn 1 build (e.g 1.22.1)", + template: "filepaths", + suggestions: [ + { + name: "from-sources", + insertValue: "from sources", + }, + "latest", + "canary", + "classic", + "self", + ], + }, + options: [ + { + name: "--only-if-needed", + description: + "Only lock the Yarn version if it isn't already locked", + }, + ], + }, + ], + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/constants.ts b/extensions/terminal-suggest/src/constants.ts index cde47bec13db3..8f04abc5fe639 100644 --- a/extensions/terminal-suggest/src/constants.ts +++ b/extensions/terminal-suggest/src/constants.ts @@ -4,13 +4,48 @@ *--------------------------------------------------------------------------------------------*/ export const upstreamSpecs = [ - 'echo', 'ls', + 'echo', 'mkdir', 'rm', 'rmdir', 'touch', - 'git' + 'pwd', + 'brew', + 'cp', + 'mv', + 'cat', + 'less', + 'more', + 'head', + 'tail', + 'nano', + 'vim', + 'chmod', + 'chown', + 'uname', + 'top', + 'df', + 'du', + 'ps', + 'kill', + 'killall', + 'curl', + 'wget', + 'ssh', + 'scp', + 'apt', + 'grep', + 'find', + + 'git', + 'npm', + 'yarn', + 'python', + 'pnpm', + 'node', + 'nvm', + 'npx', ]; diff --git a/extensions/terminal-suggest/src/terminalSuggestMain.ts b/extensions/terminal-suggest/src/terminalSuggestMain.ts index cf60eb2696ccb..51e1f12be1331 100644 --- a/extensions/terminal-suggest/src/terminalSuggestMain.ts +++ b/extensions/terminal-suggest/src/terminalSuggestMain.ts @@ -260,6 +260,9 @@ export async function collectCompletionItemResult(command: Command, parsedArgume continue; } const generatedItems = generator.postProcess(output, command.tokens.map(e => e.text)); + if (!generatedItems) { + continue; + } for (const generatedItem of generatedItems) { if (!generatedItem) { continue;