2

In package.json you can add a command to the File Explorer context menu.

In File Explorer you can select multiple files but my command only gets the last selected file URI as argument.

Can I get a list of all the selected files in the File Explorer?

rioV8
  • 24,506
  • 3
  • 32
  • 49

1 Answers1

1

You could look at my extension Find and Transform to see how I parse multiple files when an explorer context menu command is triggered. [There is some extra code in there because that command can be triggered by a keybinding or explorer/editor/tab menus so they have to be handled differently.]

let contextMenuCommandFile = vscode.commands.registerCommand('find-and-transform.searchInFile', async (...commandArgs) => {

    let args = {};

    if (commandArgs?.length === 1 && !(commandArgs[0] instanceof vscode.Uri)) {   // if from keybinding
      let argsArray = Object.entries(commandArgs[0]).filter(arg => {
        return searchCommands.getKeys().includes(arg[0]);
      });
      Object.assign(args, Object.fromEntries(argsArray));
    }

    args.filesToInclude = await parseCommands.parseArgs(commandArgs, "file");
    args.triggerSearch = true;
        searchCommands.useSearchPanel(args);
    });

    context.subscriptions.push(contextMenuCommandFile);

You might be missing this async (...commandArgs) => { to get all available passed arguments into an array.

...commandArgs will be of length 1 if coming from a keybinding and length 2 if trigggered from the context menu no matter how many files were selected in the Explorer before right-clicking on one and choosing the command.

commandArgs[0] is the single file (i.e., the last file) on which I right-clicked.
commandsArgs[1] is itself an array of all the selected files in the explorer.

I then send that commandArgs array to be parsed (since I just need a comma-separated list of the files selected) to parseCommands.parseArgs() [okay, strangely-named function!).

The operative bit there is:

    else if (commandArgs[1][0] instanceof vscode.Uri) {              // explorer/context
      for (const resource of commandArgs[1]) {
        const thisResource = vscode.workspace.asRelativePath(resource.fsPath);
        resources += `${ thisResource }, `;
      }
      resources = resources.substring(0, resources.length - 2);  // strip ', ' off end
      return resources;
    }

multiple files selected in explorer menu


It would probably be better to use:

vscode.commands.registerCommand('find-and-transform.searchInFile', async (contextSelection: vscode.Uri, allSelections: vscode.Uri[]) => {

which splits the ...commandArgs from above into its constituent parts: the item right-clicked on contextSelection and the array of all selections allSelections. Then you don't need notation like commandArgs[1] to refer to all the selections but could use the simpler allSelections.

Thanks to @PeterWone at https://stackoverflow.com/a/75533230/836330.

Mark
  • 143,421
  • 24
  • 428
  • 436
  • Ah, that pesky `...`, I program to much Python, you can simply the result string: `return commandArgs[1].map(r => vscode.workspace.asRelativePath(r.fsPath)).join(', ');` – rioV8 Dec 11 '21 at 10:43