Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support per-window "global" values for local-to-window options #697

Merged

Conversation

citizenmatt
Copy link
Member

When an option is set in Vim with :set, Vim will set the local/effective value of the option and also sets a global value. When opening a new window or editing a new buffer in the current window, Vim will (re)initialise options by copying the global value to the new window's effective options. This means last-write-wins. For non-user-visible (local-to-buffer) options such as 'fileencoding' this makes sense - the user sees the behaviour set with the last write, regardless of which window it was actually set in. For user-visible options such as 'relativenumber', this is less intuitive. The user will expect to see the same value as currently used in the current/opening window, not the last globally set value (ignoring explicitly local values set with :setlocal). In order to do this, Vim's local-to-window options maintain a per-window "global" value rather than an application wide global value (as used by local-to-buffer options).

This PR adds support for per-window "global" values for local-to-window options to IdeaVim. It can be seen in action by setting different values of the 'relativenumber' local-to-window option and using that to open new windows. IdeaVim will open the new window based on the settings in the current window, so the same look-and-feel of the opening window is maintained, similar to Vim.

This behaviour will be used by all local-to-window options, including the 'wrap' option, which will be added next - user-visible options will be correctly copied to a new window, from the opening window, providing Vim compatible, intuitive option values.

It also:

  • Treats the preview tab and "reuse unmodified tabs" as opening in the same window, and initalises options correctly - as though Vim had used :edit {file}. (IntelliJ implements preview tabs and reusing tabs by simply opening a new tab and closing the previous tab). The previous PR already implemented initialising new windows from the current/opening window.
  • Create a "fallback" window that is used to evaluate the ~/.ideavimrc file. This is used to capture option state and apply it to the first opened editor. Vim will initialise vimrc files in the context of the initial window and buffer, and now IdeaVim will do so too, even if there are no editors open at the time of IDE startup, or if plugin initialisation is delayed. This can be seen by the use of setlocal in ~/.ideavimrc.
  • Updates the "fallback" window's option state when the last editor is closed. The next editor to open is initialised from the fallback window, and therefore maintains the per-window "global" options of the last closed window. I.e. the new editor will look like the last closed window. This mimics the behaviour of Vim, which always has at least one open window - closing the last and opening a new editor is like Vim editing a new buffer in the current ("last") window.
  • Changes OptionAccessScope.GLOBAL from a singleton object to also requiring a VimEditor instance, like LOCAL and EFFECTIVE. This is necessary to be able to access per-window "global" values of local-to-window options. It is possible to pass null as this editor, but this is only valid when accessing global options and only applicable if an editor isn't available. Generally speaking, you should always pass an editor to GLOBAL.
  • Minor refactorings such as renaming OptionScope to OptionAccessScope to avoid confusion with OptionDeclaredScope, and fixing some minor implementation details of adding/removing values from string and string list options.

Getting the effective IJ options would allow access to Vim global and IJ global, but not Vim effective. IntelliJ specific options are now a separate hierarchy, so the Vim effective and IJ effective accessors now simply access all Vim or all IJ options.
For local-to-window options
Subsequent initialisation will be treated like EDIT
This is primarily to avoid instantiating inactive extensions when
resetting all options back to default values, which sets extensions
inactive.
It applies to global and local options, but not to global-local. The
notifications for global-local options are already complex, as they can
be reacting to changes to both the global and local value, and only
notifying editors that are affected.
@citizenmatt
Copy link
Member Author

Just pushed an extra commit to only notify changes for options that have actually changed. This is primarily to avoid instantiating extensions when resetting the extension's option – it will instantiate the extension just to mark it inactive.

@AlexPl292 AlexPl292 merged commit 585b815 into JetBrains:master Sep 11, 2023
3 checks passed
@AlexPl292
Copy link
Member

Awesome work! Merged, thank you!

@citizenmatt citizenmatt deleted the feature/per-window-global-options branch September 11, 2023 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants