VS Code extension - programmatically find keybindings
Asked Answered
W

2

7

When programming a vscode extension... Is there a programmatic way to find the keybinding for a provided command?

I would like to be able to see if a user has updated the key mapping from default for a command so that the UI can display the up-to-date binding. (and if not, look up the default binding)

Here are the APIs I've looked into so far:

  • vscode.workspace.getConfiguration() - I cannot determine how to access the keybindings.json file / perform a lookup.

  • vscode.extensions.getExtension(name/id) allows access to the package.json, but not the command or keybinding override.

  • vscode.getCommands does not provide access to the keybinding values either...

Wilbur answered 18/11, 2016 at 16:41 Comment(0)
H
3

You can get keybinding values from the keybindings.json file using NodeJS.

keybindings.json path on diferrent systems:

Windows: %APPDATA%\Code\User\keybindings.json
Mac: $HOME/Library/Application Support/Code/User/keybindings.json
Linux: $HOME/.config/Code/User/keybindings.json

To build the path you'll need to get Environment variables using process.env.{variableName}.

For example for MacOS it'll be:

var process = require('process');
//...
var keybindingsPath = process.env.HOME + "/Library/Application Support/Code/User/keybindings.json";

vscode.workspace.openTextDocument(keybindingsPath).then((document) => {
    let text = document.getText();
    //then use this JSON file for your needs
    //...
});
Holleyholli answered 30/12, 2016 at 13:33 Comment(3)
NB: VSC profile folder location can be specified by parameters, i.e. outside the system user profile folder, see https://mcmap.net/q/302856/-launch-vsc-with-clean-or-custom-profileSkimmia
For portable version it's process.env.VSCODE_PORTABLE + "/user-data/User/keybindings.json"Helix
Now, how do we parse that JSON file? We can't use JSON.parse() because it's non-standard - json with commentsHelix
H
0

Inspired by @nikita-kunevich answer Here is a code I use in autoit extension.

First it gets default keybindings from package.json, then it parses keybindings.json via JSON5 library (can't use JSON.parse() because file may contain comments) and replaces default keys with new keys.

//get keybindings
const keybindings = new Promise(resolve => {
  //default keybindings
  const data = require("../package.json").contributes.keybindings.reduce((a,b)=>(a[b.command]=b.key,a),{});
  const parse = list => {
    for(let i = 0; i < list.length; i++) {
      if (list[i].command in data)
        data[list[i].command] = list[i].key;
    }
    for(let i in data) {
      //capitalize first letter
      data[i] = data[i].replace(/\w+/g, w => (w.substring(0,1).toUpperCase()) + w.substring(1));
      //add spaces around "+"
      // data[i] = data[i].replace(/\+/g, " $& ");
    }

    Object.assign(keybindings, data);
    resolve(data);
  };
  const path = {
    windows: process.env.APPDATA + "/Code",
    macos: process.env.HOME + "/Library/Application Support/Code",
    linux: process.env.HOME + "/config/Code"
  }[{
    aix: "linux",
    darwin: "macos",
    freebsd: "linux",
    linux: "linux",
    openbsd: "linux",
    sunos: "linux",
    win32: "windows"
  }[process.platform]||"windows"];
  const file = ((process.env.VSCODE_PORTABLE ? process.env.VSCODE_PORTABLE + "/user-data/User/" : path) + "/User/keybindings.json")
    .replace(/\//g, process.platform == "win32" ? "\\" : "/");

  //read file
  workspace.openTextDocument(file).then(doc => {
    //we can't use JSON.parse() because file may contain comments
    const JSON5 = require("json5").default;
    parse(JSON5.parse(doc.getText()));
  }).catch(er => {
    parse([]);
  });
});

To install JSON5 package use:

npm install json5

Usage:

keybindings.then(list => {
  console.log(list);
});
Helix answered 30/9, 2022 at 5:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.