Is there a way to introspect the mainmenu?

hiya lads

I’m trying to customize the mainmenu in a notebook-based application
So far I’ve been able to remove quite a few of the menu entries, but am failing with a few remaining ones

For these entries in the menu that I can’t seem to disable, the command names that I find in the code don’t seem to trigger, for example these

    { "commands" : "jupyter-notebook:open-lab", "disabled": true},
    { "commands" : "jupyter-notebook:open-nbclassic", "disabled": true},


        "id": "jp-mainmenu-settings",
        "items": [
          { "command": "terminal:increase-font", "disabled": true},
          { "command": "terminal:decrease-font", "disabled": true},
          { "command": "terminal:set-theme", "disabled": true}

do not change the behaviour

so I was wondering if there’d be a simple way to kind of dump the mainmenu with the commands actually used in there so I’d stop trying to blindly guess the command names that I need to use…

fyi my current settings are here

thanks in advance !

If entries are added programatically rather than by schema these cannot be be disabled via schema I think (the cusomization via schema is rather recent so some places/extensions were not yet migrated, and in a few places it does not makes much sense to migrate). But the dump of all menu command is JSON Settings Editor if this helps:

thanks @krassowski for this insight, which sheds some light on an otherwise rather surprising behaviour :slight_smile:

How can I get rid of these sticky menu entries then ?

1 Like

You have two options:

  1. Open a PR moving the menu definition out of the code into the settings schema
  2. Use private attributes of IMainMenu to force remove these menus (not recommended but should work if you need to do this in an older version)

For (1) it would for example be moving this group:

Both the (settings) schema-based and API-based definition of menus is documented in Common Extension Points — JupyterLab 4.1.0a2 documentation

It could be that there was a reason for not moving some settings out, but I think that in this case it could have been an omission (possibly worth checking by opening an issue first/asking on gitter - if not one replies quickly go for a PR).

1 Like

before I go down this road though, I have a couple more comments/questions to share

  • I had spotted the section on Common Extension Points, but I’d like to point out it’s vastly concerned with adding new stuff, and not so much about removing stuff, which is my primary objective here - I take it a few words on that would come in handy, especially as indeed seems to mention only add* operations
  • iiuc you’re saying that I can’t use settings to disable entries created through the API; but could I use the API to cancel them then ? honestly in my case if I could use something like mainMenu.removeAllEntriesInCategory("terminal"), I’m making it up but I mean something that filters out all commands that start with terminal:, when then my life would be so much easier (or similar operations to cancel one specific command, or based or a regexp, etc…)

many thanks

I’d like to also add that removing the other group that I first mentioned, i.e.

    { "commands" : "jupyter-notebook:open-lab", "disabled": true},
    { "commands" : "jupyter-notebook:open-nbclassic", "disabled": true},

is more crucial to my app, and so maybe I’d like to start with that one as far as possible :slight_smile:

well, that is what I had in mind by saing “private attributes of IMainMenu” because while lumino Menu does allow to acess/remove specific items, the public API of IMainMenu does not expose these methods (you can still use them - which requires a bit of poking to find out how - but it is not officially supported and might break in the future)


By the looks of it is defined in schema so should just work:

This is likely an issue in Jupyter Notebook but then in context of other problems with using a menu in the toolbar it was recently proposed that this switcher should be reimplemented using a different approach (Change the interface switcher widget · Issue #7137 · jupyter/notebook · GitHub).

What you could do right now is just disable the interface switcher in your custom application:

indeed, I could eventually get rid of the “Open in…” entries using this

          { "command": "jupyter-notebook:open-notebook", "disabled": true, "args": { "isMenu": true}},
          { "command": "jupyter-notebook:open-lab", "disabled": true, "args": { "isMenu": true}},

worth being outlined maybe, for others who would run into this, without the "args": { "isMenu": true} thing, the menu remains; it came as a surprise because (1) it seemed more natural to disable based on the command only, and (2) what does it mean for these entries to be tagged as "args": { "isMenu": true} in the first place ?

in any case, thanks a million @krassowski as usual for your helpful insights :slight_smile:

I think it does argument (args) comparison because a single command can be used in the menu multiple times. For example imagine a command zoom which has

   label: (args) => `Zoom x${args.factor} times`

it could be used with args: {factor: 1.5} and args: {factor: 2} resultin to two menu items with labels Zoom x1.5 times and Zoom x2 times.

A PR adding a clarification to the docs would certainly be welcome.

Also, there should probably be a warning when user tries to disable a menu entry which does not match the existing ones.

bingo, that nailed it this time :sparkler:
and for the record this goes into package.json
this approach is much more effective indeed :slight_smile: