*dev_vimpatch.txt*          Nvim

                            NVIM REFERENCE MANUAL

Merging patches from Vim                                    *dev-vimpatch*


Nvim was forked from Vim 7.4.160; it is kept up-to-date with relevant Vim
patches in order to avoid duplicate work. Run `vim-patch.sh` to see the status
of Vim patches: >bash
    ./scripts/vim-patch.sh -l
<
Everyone is welcome to create a |dev-vimpatch-pr| for relevant Vim patches,
but some types of patches are |dev-vimpatch-na|. See |dev-vimpatch-quickstart|
to get started immediately.


                                         Type |gO| to see the table of contents.

==============================================================================
QUICKSTART                                           *dev-vimpatch-quickstart*

1. Pull the Nvim source: >bash
     git clone https://github.com/neovim/neovim.git
2. Run `./scripts/vim-patch.sh -l` to see the list of missing Vim patches.
3. Choose a patch from the list (usually the oldest one), e.g. `8.0.0123`.
   - Check for open vim-patch PRs
     https://github.com/neovim/neovim/pulls?q=is%3Apr+is%3Aopen+label%3Avim-patch.
4. Run `./scripts/vim-patch.sh -p 8.0.0123`
5. Follow the instructions given by the script.

NOTES

- It's strongly recommended to work on the oldest missing patch, because
  later patches might depend on the changes.
- Use `git log --grep` or `git log -G` to search the Nvim/Vim source history
  (even deleted code). E.g. to find `reset_option_was_set`: >bash

    git log -p -G reset_option_was_set
<
- Pass `git log` options like `--grep` and `-G` to `./scripts/vim-patch.sh -L`
  to filter unmerged Vim patches E.g. to find `+quickfix` patches: >bash

    ./scripts/vim-patch.sh -L --grep quickfix -- src
<
==============================================================================
PULL REQUESTS                                                *dev-vimpatch-pr*

Note: vim-patch.sh automates these steps for you. Use it!

- Install `gh` (https://cli.github.com/) if you want to use `vim-patch.sh` to
  create PRs automatically
- The pull request title should include `vim-patch:8.x.xxxx` (no whitespace)
- The commit message
  https://github.com/neovim/neovim/commit/4ccf1125ff569eccfc34abc4ad794044c5ab7455
  should include:
    - A token indicating the Vim patch number, formatted as follows:
      `vim-patch:8.0.0123` (no whitespace)
    - A URL pointing to the Vim commit:
      https://github.com/vim/vim/commit/c8020ee825b9d9196b1329c0e097424576fc9b3a
    - The original Vim commit message, including author

Reviewers: hint for reviewing `runtime/` patches
https://github.com/neovim/neovim/pull/1744#issuecomment-68202876

==============================================================================
NA (NOT APPLICABLE) PATCHES                                  *dev-vimpatch-na*

Most Vim patches are not applicable to Nvim. If you find NA patches, visit an
the latest "version.c: update" pull request
https://github.com/neovim/neovim/pulls?q=is%3Apr+author%3Aapp%2Fgithub-actions+version.c+is%3Aopen
and mention the NA patches in a comment (please edit/update one comment,
rather than adding a new comment for each patch).

Or if there is no open `version.c: update` pull request, include NA patches in
a commit message in this format:
>
    vim-patch:<version-or-commit>
    vim-patch:<version-or-commit>
    ...
<
where `<version-or-commit>` is a valid Vim version (like `8.0.0123`) or
commit-id (SHA). Each patch is on a separate line.

Example: https://github.com/neovim/neovim/commit/00f60c2ce78fc1280e93d5a36bc7b2267d5f4ac6

------------------------------------------------------------------------------
HOW TO DECIDE IF A VIM-PATCH IS WANTED

Legacy Vim is becoming much less relevant to Nvim: we expect to decline the
majority of their patches. Thus this is an "allow-list" instead of
a "deny-list". Generally, only modules explicitly noted in the "OWNED BY VIM"
list below, are in-scope; everything else should be marked "N/A".

OWNED BY VIM

- quickfix
- regex
- runtime files

Everything else is owned by Nvim. Most of Vim's "bug fixes" for e.g.
buffer/window behavior, or the events/autocmds subysytem, or "getchar" (input
engine), just aren't relevant to Nvim anymore, because we've significantly
enhanced and redesigned those subsystems to make them simpler.

UNWANTED VIM-PATCHES

- "channel"
- "job"
- "modelinestrict" https://github.com/neovim/neovim/issues/38985
- "tabpanel"
- "terminal"
- Vim9script features, and anything related to `:scriptversion`. (Nvim
  supports Vimscript version 1 only.)
- Fixes for build warnings.
- GUI-related changes.
- Most new Vimscript functions or Ex commands (with rare exceptions).

==============================================================================
VERSION.C                                             *dev-vimpatch-version.c*

The list of Vim patches in `src/nvim/version.c` is automatically updated
https://github.com/neovim/neovim/pull/7780 based on the presence of
`vim-patch:xxx` tokens in the Nvim git log.

- Don't update `src/nvim/version.c` yourself.
    - `scripts/vim-patch.sh -p` intentionally omits `version.c` to avoid merge
      conflicts and save time when porting a patch.
- The automation script (`scripts/vimpatch.lua`) only recognizes tokens like
  `vim-patch:8.0.1206`, not `vim-patch:<hash>`.

==============================================================================
CODE DIFFERENCES                                           *dev-vimpatch-diff*

The following functions have been removed or deprecated in favor of newer
alternatives. See `memory.c`
https://github.com/neovim/neovim/blob/master/src/nvim/memory.c for more
information.
>
  -----------------------------------------------------------------------
  Deprecated or removed                                 Replacement
  -----------------------------------------------------------------------
  vim_free                                                 xfree
  VIM_CLEAR(&foo)                                    XFREE_CLEAR(foo)
  malloc alloc lalloc lalloc_id ALLOC_ONE                 xmalloc
  calloc lalloc_clear                                     xcalloc
  realloc vim_realloc                                    xrealloc
  mch_memmove                                             memmove
  vim_memset copy_chars copy_spaces                       memset
  vim_strbyte                                             strchr
  vim_strncpy strncpy                               xstrlcpy/xmemcpyz
  vim_strcat strncat                                     xstrlcat
  VIM_ISWHITE                                          ascii_iswhite
  IS_WHITE_OR_NUL                                  ascii_iswhite_or_nul
  IS_WHITE_NL_OR_NUL                              ascii_iswhite_nl_or_nul
  vim_isalpha                                           mb_isalpha
  vim_isNormalIDc                                      ascii_isident
  vim_islower vim_isupper                          mb_islower mb_isupper
  vim_tolower vim_toupper                          mb_tolower mb_toupper
  mb_ptr2len                                           utfc_ptr2len
  mb_ptr2len_len                                     utfc_ptr2len_len
  mb_char2len                                          utf_char2len
  mb_char2bytes                                       utf_char2bytes
  mb_ptr2cells                                         utf_ptr2cells
  mb_ptr2cells_len                                   utf_ptr2cells_len
  mb_char2cells                                       utf_char2cells
  mb_off2cells                                         utf_off2cells
  mb_ptr2char                                          utf_ptr2char
  mb_head_off                                          utf_head_off
  mb_tail_off                                          utf_cp_bounds
  mb_strnicmp2                                         utf_strnicmp
  MB_STRNICMP2                                         utf_strnicmp
  mb_lefthalve                                        grid_lefthalve
  mb_fix_col                                           grid_fix_col
  utf_off2cells                                       grid_off2cells
  ml_get_curline                                    get_cursor_line_ptr
  ml_get_cursor                                     get_cursor_pos_ptr
  ml_get_curline_len                                get_cursor_line_len
  ml_get_cursor_len                                 get_cursor_pos_len
  screen_char                                             ui_line
  screen_line                                        grid_put_linebuf
  screen_* (most functions)                               grid_*
  update_prepare, update_finish #9484                  removed; use update_screen only
  ARRAY_LENGTH                                          ARRAY_SIZE
  vim_strsave_escape_csi                           vim_strsave_escape_ks
  vim_unescape_csi                                    vim_unescape_ks
  gettail                                                path_tail
  mch_isFullName                                     path_is_absolute
  script_do_profile                                    profile_init

  -----------------------------------------------------------------------
<
Make sure to note the difference between `utf_` and `utfc_` when replacing
`mb_` functions. Also indirect call syntax `(*mb_ptr2len)(...)` should be
replaced with an ordinary function call `utfc_ptr2len(...)`.
>
  -----------------------------------------------------------------------
  Data type    Format (Vim source)     Portable format (Nvim source)
  ------------ ----------------------- ----------------------------------
  long long    "%lld"                  "%" PRId64
  size_t       "%ld"                   "%zu"
  linenr_T     "%ld"                   "%" PRIdLINENR
  -----------------------------------------------------------------------
<
- See also: https://github.com/neovim/neovim/pull/1729#discussion_r22423779
- Vim's `ga_init2` was renamed to `ga_init` and the original `ga_init` is
  gone.
- "Old style" Vim tests (`src/testdir/*.in`) should be converted to Lua tests
  (see #1286 https://github.com/neovim/neovim/issues/1286 and #1328
  https://github.com/neovim/neovim/pull/1328). See Checklist for migrating
  legacy tests
  https://github.com/neovim/neovim/blob/master/test/README.md#checklist-for-migrating-legacy-tests.
    - However, please do not convert "new style" Vim tests
      (`src/testdir/*.vim`) to Lua. The "new style" Vim tests are faster than
      the old ones, and converting them takes time and effort better spent
      elsewhere. Just copy them to `test/old/testdir/*.vim`.
- Conditions that check `enc_utf8` or `has_mbyte` are obsolete (only the
  "true" case is applicable).
    - `enc_utf8` and `has_mbyte` macros were removed in
      https://github.com/neovim/neovim/pull/13293
- Check for `CSI` in typeahead buffer is only necessary in Vim with
  `FEAT_GUI`. `CSI` does not have a special meaning in typeahead buffer in
  Nvim. (also see https://github.com/neovim/neovim/pull/16936)

==============================================================================
LIST MANAGEMENT                                       *dev-vimpatch-list-impl*

Management of lists (types `list_T` and `listitem_T` from vim) was changed in
https://github.com/neovim/neovim/pull/7708/. There is a lint against the "old"
usage, but here are the most important changes.

Declarations for the table

- `list_T list`: a list
- `listitem_T li`: an item of `list`
- `int val` a value for `lv_copyID`

>
  --------------------------------------------------------------------------------------
  Old                             New                                  Comment
  ------------------------------- ------------------------------------------------------
  list->lv_first                  tv_list_first(list)
  list->lv_last                   tv_list_last(list)
  li->li_next                     TV_LIST_ITEM_NEXT(list, li)          To be avoided if possible, must use list which li belongs to.
  li->li_prev                     TV_LIST_ITEM_PREV(list, li)          To be avoided if possible, must use list which li belongs to.
                                  Suggestion by @ZyX-l:                Use TV_LIST_ITER or indexing instead of the previous two calls.
  list->lv_len                    tv_list_len(list)
  list->lv_lock                   tv_list_locked(list)
  &li->li_tv                      TV_LIST_ITEM_TV(li)
  list->lv_refcount++             tv_list_ref(list)
  val = list->lv_copyID           val = tv_list_copyid(list)
  list->lv_copyID = val           tv_list_set_copyid(list, val)

  for (li = list->lv_first;       TV_LIST_ITER_CONST(list, li,         Use TV_LIST_ITER(...) if you need to
  li != NULL && another_cond;     { if (another_cond) {break;} code})  modify list items (note: assigning copyID is also modification and this happens
  li = li->li_next) code                                               always when recursively traversing a list).

  --------------------------------------------------------------------------------------
<
For more details and some more advanced usage, see `typval.h` and `typval.c`.

==============================================================================
DOCUMENTATION DIFFERENCES                                   *dev-vimpatch-doc*

The following should be removed from all imported documentation, and not be
used in new documentation:

- `{Only when compiled with ...}`: the vast majority of features have been
  made non-optional (see https://github.com/neovim/neovim/wiki/Introduction)

==============================================================================
FILETYPE DETECTION                                     *dev-vimpatch-filetype*

Nvim's filetype detection behavior matches Vim, but is implemented as part of
|vim.filetype| (see `$VIMRUNTIME/lua/vim/filetype.lua`). The logic is encoded in
three tables, listed in order of precedence (the first match is returned):
1. `filename` for literal full path or basename lookup;
2. `pattern` for matching filenames or paths against |lua-pattern|s, optimized
   for fast lookup;
3. `extension` for literal extension lookup.

Logic that requires checking file contents or buffer variables is implemented
in `$VIMRUNTIME/lua/vim/filetype/detect.lua`.

When porting filetype patches from Vim, keep the following in mind:

Prefer explicit filenames or extensions over patterns, especially for case
insensitive matches (see https://github.com/neovim/neovim/pull/29800): >
    "*[mM]akefile" regex -> "makefile", "Makefile" filenames
    "*.js\c"       regex -> "js", "jS", "Js", "jS" extensions

Pattern matching has several differences:
- It is done using explicit Lua patterns without implicit anchoring instead
  of Vim regexes: >
    "*/debian/changelog" -> "/debian/changelog$"
    "*/bind/db.*"        -> "/bind/db%."
<
- Filetype patterns are grouped by their parent pattern to improve matching
  performance: If the parent pattern does not match, skip testing all child
  patterns. Note that unlike leaf patterns, parent patterns do not have
  special matching behaviour if they contain a `/`.

  When adding a new filetype with pattern matching, consider the following:
  - If there is already a group with appropriate parent pattern, use it.
  - If there can be a fast and specific enough pattern to group at least 3
    filetype patterns, add it as a separate grouped entry.

  New parent patterns should be
  - fast: rule of thumb is that it should be a short explicit string
  (i.e. no quantifiers or character sets);
  - specific: rules of thumb, in order:
    - full directory name (e.g., `"/etc/"`, `"/log/"`);
    - part of a rare enough directory name (e.g., `"/conf"`, `"git/"`);
    - string rarely used in real full paths (e.g., `"nginx"`).

  Example:
  - Filetype pattern: `".*/etc/a2ps/.*%.cfg"`
  - Good parents: `"/etc/"` or `"%.cfg$"`
  - Bad parents: `"%."` (fast but not specific) or `"/a2ps/.*%."` (specific
    but slow)

  When modifying an existing regular pattern, make sure that it still fits its
  group.

vim:tw=78:ts=8:et:ft=help:norl:
