rioV8
rioV8

Reputation: 28633

How to get the Multi Selected files from the File Explorer in an extension command

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?

Upvotes: 2

Views: 1469

Answers (1)

Mark
Mark

Reputation: 180785

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.

Upvotes: 1

Related Questions