Repository: neovim
Issue: Options refactor roadmap
Labels: refactor,options

The Neovim options code is an incomprehensible mess filled with code duplication, special logic for every option, multiple code paths for the same thing, lack of generalization, etc. This makes Neovim options difficult to maintain, and even more difficult to extend, which has been a blocker towards the addition of new option types (e.g. Callback, Array, Dictionary).

This is a roadmap for refactoring Neovim options to be more extensible and maintainable. This is not an absolutely concrete roadmap and each item is subject to change, further additions and deletions may also be made at any time.

- [ ] Unify interfaces for options.
  - [x] Implement a single type to represent any option value. #23850
  - [x] Unify `do_set_option_value` and `set_option_value` codepaths. #25394
  - [ ] Unify interfaces for number, boolean and string options.
    - [x] Unify interfaces for setting number and boolean options. #25394
    - [x] Unify interfaces for setting number/boolean and string options. #25674
    - [x] Unify separate interfaces for setting string options (e.g. `set_string_option_direct`, `set_string_option_global`, etc.). #26970
    - [ ] Remove functions specific to string options (e.g. `free_string_option`, `clear_string_option`, `check_string_option`) and replace them with something more general.
    - [x] Unify `put_set(num|bool|string)`. #30993
    - [x] Use `OptVal` for option `def_val`. #26691 
  - [x] Unify `get_option_value` and `get_option_value_strict` if possible. #30974
  - [ ] Use a struct for option variables and make it so that the option index can be used to directly access the variable, instead of having to manually hardcode a variable for each option. #31084
  - [x] Replace `p_force_on` and `p_force_off` with an `immutable` property for options. #26209
  - [x] Unify `enable_if = false`, `immutable` and `hidden` into just `immutable. #28400
  - [ ] Give TTY options their own indices to avoid having to use their names.
- [x] Replace option flag macros with enum values. #30961
- [x] Remove `P_ALLOCED` and always allocate option values. #30917
- [x] Check if `OPT_FREE` is necessary and remove it if it isn't. #26963
- [x] Refactor `set_option_default`.  #26691
- [x] Remove logic for platform-specific options (`shellslash` / `completeslash`). #28400
- [ ] Allow setting options for any context (buffer/window/etc.) without having to temporarily switch the context. #31112
- [ ] Autogenerate option metadata.
  - [x] Replace `.indir` and `PV_*` macros with autogenerated option indices for each scope. #31066
  - [x] Option flags. #31089
  - [x] Valid values for options. #31089
  - [ ] Global option variables. #31084
  - [ ] Buffer/window option variables. #31084
  - [ ] Make it possible to directly access an option's variable at any scope through the option's index. #31084
- [ ] Revamp option scopes. #29314
  - [x] Allow options to support an arbitrary amount of scopes. #31066
  - [ ] Remove `OPT_LOCAL` and `OPT_GLOBAL`
- [ ] Use a separate flag indicate if an option is set at any scope, instead of using arbitrary values for each option. This would also mean that boolean options no longer need to be represented using tri-states and instead can be actual booleans.
- [ ] Use `bool` type for boolean option variables, instead of `int`.
- [ ] Use reference counted strings for string options.
- [ ] Remove `empty_string_option`.
- [x] Replace `P_(NUM|BOOL|STRING)` flags with `kOptValType*` and move type flags to a separate variable from other option flags. #26512
- [ ] Fix the behavior of `winbar` and make it possible to unset winbar for a single window. #18660
- [ ] Convert `kOptFlagFunc` to a separate option type for callback options, instead of having them be shoehorned into string options. #18997
- [ ] Add support for Array and Dictionary options.
- [ ] Convert all list-like or map-like string options to Array / Dictionary options.
- [ ] Add a dict-based configuration format for complicated options such as `winbar`, `tabline`, `statusline`, etc.