biosbob
biosbob

Reputation: 311

Get focused Explorer folder or file in an extension when command triggered by a shortcut, not by context menu

A follow-on to this question: How to get file name or path in vscode extension when user right click on file in explorer/context?

My command expects to receive the uri to the item selected with a right-click; and in fact it does if I invoke the command by choosing it from the context menu....

If, however, I bind a shortcut key to this command (and correctly set the "when" context to only activate when explorer has focus) I do not receive the uri; that parameter is undefined.

Obviously there are plenty of "built-in" commands ("Reveal in File Explorer" -- Shift+Alt+R) that function they way I would like my own to command operate.

What's the trick to getting the uri to my own command when invoked with a keyboard shortcut?

Upvotes: 2

Views: 2754

Answers (2)

Mark
Mark

Reputation: 180795

There is a hint in a related issue: Get selected file/folder in the Explorer view.

It is suggested to use

vscode.commands.executeCommand('copyFilePath');

see https://github.com/Microsoft/vscode/issues/3553#issuecomment-438969485

so I investigated that and it can work like this:

async function activate(context) {

   let createFile = vscode.commands.registerCommand('folder-operations.createFile', async (folder) => {

    // use this if triggered by a menu item,
    let newUri = folder;  // folder will be undefined when triggered by keybinding

     if (!folder) {                       // so triggered by a keybinding
       await vscode.commands.executeCommand('copyFilePath');
       folder = await vscode.env.clipboard.readText();  // returns a string

       // see note below for parsing multiple files/folders
       newUri = await vscode.Uri.file(folder);          // make it a Uri 
     }

     createFileOpen(newUri);                 // use in some function  
  });
  context.subscriptions.push(createFile);
}

NOTE :

This works when multiple folders or files are selected as well. Then folder = await vscode.env.clipboard.readText(); will return something like (on W10):

"C:\\Users\\Mark\\OneDrive\\Test Bed\\zip\r\nC:\\Users\\Mark\\OneDrive\\Test Bed\\zipMultiple"

when two folders, zip and zipMultiple in this case, are selected and then the keybinding is triggered for the folder-operations.createFile command. So you would have to parse/split that string to get the two folders selected. Same with multiple files.



Using some keybinding:

{
  "key": "shift+alt+c",
  "command": "folder-operations.createFile",
  "when": "explorerResourceIsFolder && filesExplorerFocus"
}

Now this will work when some folder is focused in the Explorer and you trigger your keybinding. Demo creating a new file by keybinding:

get folder path in an extension via a keybinding

Upvotes: 2

rioV8
rioV8

Reputation: 28643

The arguments you get with your keybindings.json defined key binding is the args property of the key binding.

In VSC the key bindings are defined different. The command is a function of the key binding and it gets special arguments.

In file src/vs/workbench/contrib/files/electron-browser/fileActions.contribution.ts

const REVEAL_IN_OS_COMMAND_ID = 'revealFileInOS';

KeybindingsRegistry.registerCommandAndKeybindingRule({
  id: REVEAL_IN_OS_COMMAND_ID,
  weight: KeybindingWeight.WorkbenchContrib,
  when: EditorContextKeys.focus.toNegated(),
  primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R,
  win: {
    primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_R
  },
  handler: (accessor: ServicesAccessor, resource: URI | object) => {
    const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService), accessor.get(IExplorerService));
    revealResourcesInOS(resources, accessor.get(IElectronService), accessor.get(INotificationService), accessor.get(IWorkspaceContextService));
  }
});

In extensions we can't get an object that has the focus.

So the extension has no way of getting the "TreeView" of the File Explorer.

vscode.window also does not allow us to get to some of the GUI elements.

Upvotes: 0

Related Questions