aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/autoload/man.vim344
-rw-r--r--runtime/doc/eval.txt47
-rw-r--r--runtime/doc/filetype.txt51
-rw-r--r--runtime/doc/usr_12.txt19
-rw-r--r--runtime/doc/vim_diff.txt1
-rw-r--r--runtime/ftplugin/man.vim73
-rw-r--r--runtime/macros/justify.vim319
-rw-r--r--runtime/pack/dist/opt/justify/plugin/justify.vim316
-rw-r--r--runtime/plugin/man.vim13
-rw-r--r--runtime/syntax/man.vim90
-rw-r--r--scripts/genoptions.lua7
-rw-r--r--src/nvim/buffer_defs.h5
-rw-r--r--src/nvim/eval.c32
-rw-r--r--src/nvim/fileio.c20
-rw-r--r--src/nvim/message.c7
-rw-r--r--src/nvim/option.c42
-rw-r--r--src/nvim/option.h23
-rw-r--r--src/nvim/options.lua10
-rw-r--r--src/nvim/os/stdpaths.c26
-rw-r--r--src/nvim/po/af.po4
-rw-r--r--src/nvim/po/ca.po4
-rw-r--r--src/nvim/po/cs.cp1250.po4
-rw-r--r--src/nvim/po/cs.po4
-rw-r--r--src/nvim/po/en_GB.po4
-rw-r--r--src/nvim/po/eo.po4
-rw-r--r--src/nvim/po/es.po6
-rw-r--r--src/nvim/po/fi.po4
-rw-r--r--src/nvim/po/fr.po4
-rw-r--r--src/nvim/po/ga.po5
-rw-r--r--src/nvim/po/it.po4
-rw-r--r--src/nvim/po/ja.euc-jp.po4
-rw-r--r--src/nvim/po/ja.po4
-rw-r--r--src/nvim/po/ja.sjis.po4
-rw-r--r--src/nvim/po/ko.UTF-8.po4
-rw-r--r--src/nvim/po/ko.po4
-rw-r--r--src/nvim/po/nb.po5
-rw-r--r--src/nvim/po/nl.po4
-rw-r--r--src/nvim/po/no.po5
-rw-r--r--src/nvim/po/pl.UTF-8.po4
-rw-r--r--src/nvim/po/pl.cp1250.po4
-rw-r--r--src/nvim/po/pl.po4
-rw-r--r--src/nvim/po/ru.cp1251.po6
-rw-r--r--src/nvim/po/ru.po6
-rw-r--r--src/nvim/po/sk.cp1250.po4
-rw-r--r--src/nvim/po/sk.po4
-rw-r--r--src/nvim/po/uk.cp1251.po4
-rw-r--r--src/nvim/po/uk.po4
-rw-r--r--src/nvim/po/vi.po5
-rw-r--r--src/nvim/po/zh_CN.UTF-8.po4
-rw-r--r--src/nvim/po/zh_CN.cp936.po4
-rw-r--r--src/nvim/po/zh_CN.po4
-rw-r--r--src/nvim/po/zh_TW.UTF-8.po6
-rw-r--r--src/nvim/po/zh_TW.po6
-rw-r--r--src/nvim/shada.c2
-rw-r--r--src/nvim/testdir/Makefile1
-rw-r--r--src/nvim/testdir/test_window_id.vim71
-rw-r--r--src/nvim/version.c6
-rw-r--r--src/nvim/window.c93
-rw-r--r--test/functional/helpers.lua38
-rw-r--r--test/functional/options/defaults_spec.lua182
-rw-r--r--third-party/cmake/BuildLuarocks.cmake2
61 files changed, 1220 insertions, 770 deletions
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 0dfcc424e2..a3632a10c3 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -1,137 +1,285 @@
-let s:man_tag_depth = 0
-let s:man_sect_arg = ''
-let s:man_find_arg = '-w'
+" Maintainer: Anmol Sethi <anmol@aubble.com>
+" Ensure Vim is not recursively invoked (man-db does this)
+" by forcing man to use cat as the pager.
+" More info here http://comments.gmane.org/gmane.editors.vim.devel/29085
+if &shell =~# 'fish$'
+ let s:man_cmd = 'man -P cat ^/dev/null'
+else
+ let s:man_cmd = 'man -P cat 2>/dev/null'
+endif
+
+let s:man_find_arg = "-w"
+
+" TODO(nhooyr) I do not think completion will work on SunOS because I'm not sure if `man -l`
+" displays the list of directories that are searched by man for manpages.
+" I also do not think Solaris supports the '-P' flag used above and uses only $PAGER.
try
- if !has('win32') && $OSTYPE !~? 'cygwin\|linux' && system('uname -s') =~? 'SunOS' && system('uname -r') =~? '^5'
- let s:man_sect_arg = '-s'
+ if !has('win32') && $OSTYPE !~? 'cygwin\|linux' && system('uname -s') =~? 'SunOS' && system('uname -r') =~# '^5'
let s:man_find_arg = '-l'
endif
catch /E145:/
" Ignore the error in restricted mode
endtry
-" Load man page {page} from {section}
-" call man#get_page([{section}, ]{page})
-function man#get_page(...) abort
- let invoked_from_man = (&filetype ==# 'man')
-
- if a:0 == 0
- echoerr 'argument required'
+" We need count and count1 to ensure the section was explicitly set
+" by the user. count defaults to 0 which is a valid section and
+" count1 defaults to 1 which is also a valid section. Only when they
+" are equal was the count explicitly set.
+function! man#open_page(count, count1, ...) abort
+ if a:0 > 2
+ call s:error('too many arguments')
+ return
+ elseif a:0 ==# 0
+ call s:error('missing argument')
+ return
+ elseif a:0 ==# 1
+ let ref = a:1
+ else
+ " We combine the name and sect into a manpage reference so that all
+ " verification/extraction can be kept in a single function.
+ " If a:2 is a reference as well, that is fine because it is the only
+ " reference that will match.
+ let ref = a:2.'('.a:1.')'
+ endif
+ try
+ let [sect, name] = s:extract_sect_and_name_ref(ref)
+ if a:count ==# a:count1
+ " user explicitly set a count
+ let sect = string(a:count)
+ endif
+ let [sect, name] = s:verify_exists(sect, name)
+ catch
+ call s:error(v:exception)
return
- elseif a:0 > 2
- echoerr 'too many arguments'
+ endtry
+ call s:push_tag()
+ let bufname = 'man://'.name.(empty(sect)?'':'('.sect.')')
+ let found_man = s:find_man()
+ if getbufvar(bufname, 'manwidth') ==# s:manwidth()
+ if found_man
+ silent execute 'buf' bufnr(bufname)
+ else
+ execute 'split' bufname
+ endif
+ keepjumps 1
return
endif
+ if found_man
+ noautocmd execute 'edit' bufname
+ else
+ noautocmd execute 'split' bufname
+ endif
+ call s:read_page(sect, name)
+endfunction
- let sect = get(a:000, 0)
- let page = get(a:000, 1, sect)
+function! man#read_page(ref) abort
+ try
+ let [sect, name] = s:extract_sect_and_name_ref(a:ref)
+ let [sect, name] = s:verify_exists(sect, name)
+ catch
+ call s:error(v:exception)
+ return
+ endtry
+ call s:read_page(sect, name)
+endfunction
- let [page, sect] = s:parse_page_and_section(sect, page)
+function! s:read_page(sect, name) abort
+ setlocal modifiable
+ setlocal noreadonly
+ keepjumps %delete _
+ let b:manwidth = s:manwidth()
+ silent execute 'read!env MANWIDTH='.b:manwidth s:man_cmd s:man_args(a:sect, a:name)
+ " remove all the backspaced text
+ silent execute 'keeppatterns keepjumps %substitute,.\b,,e'.(&gdefault?'':'g')
+ while getline(1) =~# '^\s*$'
+ silent keepjumps 1delete _
+ endwhile
+ setlocal filetype=man
+endfunction
- if !empty(sect) && s:find_page(sect, page) == 0
- let sect = ''
+" attempt to extract the name and sect out of 'name(sect)'
+" otherwise just return the largest string of valid characters in ref
+function! s:extract_sect_and_name_ref(ref) abort
+ if a:ref[0] ==# '-' " try ':Man -pandoc' with this disabled.
+ throw 'manpage name starts with ''-'''
endif
-
- if s:find_page(sect, page) == 0
- echo 'No manual entry for '.page
- return
+ let ref = matchstr(a:ref, '[^()]\+([^()]\+)')
+ if empty(ref)
+ let name = matchstr(a:ref, '[^()]\+')
+ if empty(name)
+ throw 'manpage reference contains only parantheses'
+ endif
+ return ['', name]
endif
+ let left = split(ref, '(')
+ " see ':Man 3X curses' on why tolower.
+ " TODO(nhooyr) Not sure if this is portable across OSs
+ " but I have not seen a single uppercase section.
+ return [tolower(split(left[1], ')')[0]), left[0]]
+endfunction
- exec 'let s:man_tag_buf_'.s:man_tag_depth.' = '.bufnr('%')
- exec 'let s:man_tag_lin_'.s:man_tag_depth.' = '.line('.')
- exec 'let s:man_tag_col_'.s:man_tag_depth.' = '.col('.')
- let s:man_tag_depth = s:man_tag_depth + 1
-
- let editcmd = 'edit'
- " Use an existing 'man' window, else open a new one.
- if &filetype !=# 'man'
- let thiswin = winnr()
- wincmd b
- if winnr() > 1
- exec thiswin . 'wincmd w'
- while 1
- if &filetype ==# 'man'
- break
- endif
- wincmd w
- if thiswin == winnr()
- break
- endif
- endwhile
+function! s:verify_exists(sect, name) abort
+ let path = system(s:man_cmd.' '.s:man_find_arg.' '.s:man_args(a:sect, a:name))
+ if path !~# '^\/'
+ if empty(a:sect)
+ throw 'no manual entry for '.a:name
endif
-
- if &filetype !=# 'man'
- let editcmd = 'tabnew'
+ let path = system(s:man_cmd.' '.s:man_find_arg.' '.shellescape(a:name))
+ if path !~# '^\/'
+ throw 'no manual entry for '.a:name.'('.a:sect.') or '.a:name
endif
endif
+ if a:name =~# '\/'
+ " We do not need to extract the section/name from the path if the name is
+ " just a path.
+ return ['', a:name]
+ endif
+ " We need to extract the section from the path because sometimes
+ " the actual section of the manpage is more specific than the section
+ " we provided to `man`. Try ':Man 3 App::CLI'.
+ " Also on linux, it seems that the name is case insensitive. So if one does
+ " ':Man PRIntf', we still want the name of the buffer to be 'printf' or
+ " whatever the correct capitilization is.
+ return s:extract_sect_and_name_path(path[:len(path)-2])
+endfunction
- silent exec editcmd.' man://'.page.(empty(sect)?'':'('.sect.')')
+let s:tag_stack = []
- setlocal modifiable
- silent keepjumps norm! 1G"_dG
- if empty($MANWIDTH)
- let $MANWIDTH = winwidth(0)
+function! s:push_tag() abort
+ let s:tag_stack += [{
+ \ 'buf': bufnr('%'),
+ \ 'lnum': line('.'),
+ \ 'col': col('.'),
+ \ }]
+endfunction
+
+function! man#pop_tag() abort
+ if !empty(s:tag_stack)
+ let tag = remove(s:tag_stack, -1)
+ execute tag['buf'].'b'
+ call cursor(tag['lnum'], tag['col'])
endif
- silent exec 'r!/usr/bin/man '.s:cmd(sect, page).' | col -b'
- " Remove blank lines from top and bottom.
- while getline(1) =~# '^\s*$'
- silent keepjumps 1delete _
- endwhile
- while getline('$') =~# '^\s*$'
- silent keepjumps $delete _
- endwhile
- setlocal nomodified
- setlocal filetype=man
+endfunction
- if invoked_from_man || editcmd ==# 'tabnew'
- call s:set_window_local_options()
+" extracts the name and sect out of 'path/name.sect'
+function! s:extract_sect_and_name_path(path) abort
+ let tail = fnamemodify(a:path, ':t')
+ if a:path =~# '\.\%([glx]z\|bz2\|lzma\|Z\)$' " valid extensions
+ let tail = fnamemodify(tail, ':r')
endif
+ let sect = matchstr(tail, '\.\zs[^.]\+$')
+ let name = matchstr(tail, '^.\+\ze\.[^.]\+$')
+ return [sect, name]
endfunction
-function s:set_window_local_options() abort
- setlocal colorcolumn=0 foldcolumn=0 nonumber
- setlocal nolist norelativenumber nofoldenable
+function! s:find_man() abort
+ if &filetype ==# 'man'
+ return 1
+ endif
+ let thiswin = winnr()
+ while 1
+ wincmd w
+ if &filetype ==# 'man'
+ return 1
+ elseif thiswin ==# winnr()
+ return 0
+ endif
+ endwhile
endfunction
-function man#pop_page() abort
- if s:man_tag_depth > 0
- let s:man_tag_depth = s:man_tag_depth - 1
- exec "let s:man_tag_buf=s:man_tag_buf_".s:man_tag_depth
- exec "let s:man_tag_lin=s:man_tag_lin_".s:man_tag_depth
- exec "let s:man_tag_col=s:man_tag_col_".s:man_tag_depth
- exec s:man_tag_buf."b"
- exec s:man_tag_lin
- exec "norm! ".s:man_tag_col."|"
- exec "unlet s:man_tag_buf_".s:man_tag_depth
- exec "unlet s:man_tag_lin_".s:man_tag_depth
- exec "unlet s:man_tag_col_".s:man_tag_depth
- unlet s:man_tag_buf s:man_tag_lin s:man_tag_col
+function! s:manwidth() abort
+ " The reason for respecting $MANWIDTH even if it is wider/smaller than the
+ " current window is that the current window might only be temporarily
+ " narrow/wide. Since we don't reflow, we should just assume the
+ " user knows what they're doing and respect $MANWIDTH.
+ if empty($MANWIDTH)
+ " If $MANWIDTH is not set, we do not assign directly to $MANWIDTH because
+ " then $MANWIDTH will always stay the same value as we only use
+ " winwidth(0) when $MANWIDTH is empty. Instead we set it locally for the command.
+ return winwidth(0)
endif
+ return $MANWIDTH
endfunction
-" Expects a string like 'access' or 'access(2)'.
-function s:parse_page_and_section(sect, str) abort
- try
- let [page, sect] = matchlist(a:str, '\v\C([-.[:alnum:]_]+)%(\(([-.[:alnum:]_]+)\))?')[1:2]
- if empty(sect)
- let sect = a:sect
- endif
- catch
- echoerr 'man.vim: failed to parse: "'.a:str.'"'
- endtry
+function! s:man_args(sect, name) abort
+ if empty(a:sect)
+ return shellescape(a:name)
+ endif
+ " The '-s' flag is very useful.
+ " We do not need to worry about stuff like 'printf(echo)'
+ " (two manpages would be interpreted by man without -s)
+ " We do not need to check if the sect starts with '-'
+ " Lastly, the 3pcap section on macOS doesn't work without -s
+ return '-s '.shellescape(a:sect).' '.shellescape(a:name)
+endfunction
- return [page, sect]
+function! s:error(msg) abort
+ redraw
+ echohl ErrorMsg
+ echon 'man.vim: ' a:msg
+ echohl None
endfunction
-function s:cmd(sect, page) abort
- if !empty(a:sect)
- return s:man_sect_arg.' '.a:sect.' '.a:page
+let s:mandirs = join(split(system(s:man_cmd.' '.s:man_find_arg), ':\|\n'), ',')
+
+" see s:extract_sect_and_name_ref on why tolower(sect)
+function! man#complete(arg_lead, cmd_line, cursor_pos) abort
+ let args = split(a:cmd_line)
+ let l = len(args)
+ if l > 3
+ return
+ elseif l ==# 1
+ let name = ''
+ let sect = ''
+ elseif a:arg_lead =~# '^[^()]\+([^()]*$'
+ " cursor (|) is at ':Man printf(|' or ':Man 1 printf(|'
+ " The later is is allowed because of ':Man pri<TAB>'.
+ " It will offer 'priclass.d(1m)' even though section is specified as 1.
+ let tmp = split(a:arg_lead, '(')
+ let name = tmp[0]
+ let sect = tolower(get(tmp, 1, ''))
+ elseif args[1] !~# '^[^()]\+$'
+ " cursor (|) is at ':Man 3() |' or ':Man (3|' or ':Man 3() pri|'
+ " or ':Man 3() pri |'
+ return
+ elseif l ==# 2
+ if empty(a:arg_lead)
+ " cursor (|) is at ':Man 1 |'
+ let name = ''
+ let sect = tolower(args[1])
+ else
+ " cursor (|) is at ':Man pri|'
+ if a:arg_lead =~# '\/'
+ " if the name is a path, complete files
+ " TODO(nhooyr) why does this complete the last one automatically
+ return glob(a:arg_lead.'*', 0, 1)
+ endif
+ let name = a:arg_lead
+ let sect = ''
+ endif
+ elseif a:arg_lead !~# '^[^()]\+$'
+ " cursor (|) is at ':Man 3 printf |' or ':Man 3 (pr)i|'
+ return
+ else
+ " cursor (|) is at ':Man 3 pri|'
+ let name = a:arg_lead
+ let sect = tolower(args[1])
endif
- return a:page
+ " We remove duplicates incase the same manpage in different languages was found.
+ return uniq(sort(map(globpath(s:mandirs,'man?/'.name.'*.'.sect.'*', 0, 1), 's:format_candidate(v:val, sect)'), 'i'))
endfunction
-function s:find_page(sect, page) abort
- let where = system('/usr/bin/man '.s:man_find_arg.' '.s:cmd(a:sect, a:page))
- return (where =~# '^ */')
+function! s:format_candidate(c, sect) abort
+ if a:c =~# '\.\%(pdf\|in\)$' " invalid extensions
+ return
+ endif
+ let [sect, name] = s:extract_sect_and_name_path(a:c)
+ if sect ==# a:sect
+ return name
+ elseif sect =~# a:sect.'[^.]\+$'
+ " We include the section if the user provided section is a prefix
+ " of the actual section.
+ return name.'('.sect.')'
+ endif
endfunction
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index de1ced160c..3fa5474a7e 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -754,13 +754,23 @@ expressions are referring to the same |List| or |Dictionary| instance. A copy
of a |List| is different from the original |List|. When using "is" without
a |List| or a |Dictionary| it is equivalent to using "equal", using "isnot"
equivalent to using "not equal". Except that a different type means the
-values are different: "4 == '4'" is true, "4 is '4'" is false and "0 is []" is
-false and not an error. "is#"/"isnot#" and "is?"/"isnot?" can be used to match
-and ignore case.
+values are different: >
+ echo 4 == '4'
+ 1
+ echo 4 is '4'
+ 0
+ echo 0 is []
+ 0
+"is#"/"isnot#" and "is?"/"isnot?" can be used to match and ignore case.
When comparing a String with a Number, the String is converted to a Number,
-and the comparison is done on Numbers. This means that "0 == 'x'" is TRUE,
-because 'x' converted to a Number is zero.
+and the comparison is done on Numbers. This means that: >
+ echo 0 == 'x'
+ 1
+because 'x' converted to a Number is zero. However: >
+ echo 0 == 'x'
+ 0
+Inside a List or Dictionary this conversion is not used.
When comparing two Strings, this is done with strcmp() or stricmp(). This
results in the mathematical difference (comparing byte values), not
@@ -2138,6 +2148,10 @@ values({dict}) List values in {dict}
virtcol({expr}) Number screen column of cursor or mark
visualmode([expr]) String last visual mode used
wildmenumode() Number whether 'wildmenu' mode is active
+win_getid( [{win} [, {tab}]]) Number get window ID for {win} in {tab}
+win_gotoid( {expr}) Number go to window with ID {expr}
+win_id2tabwin( {expr}) List get tab window nr from window ID
+win_id2win( {expr}) Number get window nr from window ID
winbufnr({nr}) Number buffer number of window {nr}
wincol() Number window column of the cursor
winheight({nr}) Number height of window {nr}
@@ -7192,6 +7206,29 @@ wildmenumode() *wildmenumode()*
(Note, this needs the 'wildcharm' option set appropriately).
+win_getid([{win} [, {tab}]]) *win_getid()*
+ Get the window ID for the specified window.
+ When {win} is missing use the current window.
+ With {win} this is the window number. The top window has
+ number 1.
+ Without {tab} use the current tab, otherwise the tab with
+ number {tab}. The first tab has number one.
+ Return zero if the window cannot be found.
+
+win_gotoid({expr}) *win_gotoid()*
+ Go to window with ID {expr}. This may also change the current
+ tabpage.
+ Return 1 if successful, 0 if the window cannot be found.
+
+win_id2tabwin({expr} *win_id2tabwin()*
+ Return a list with the tab number and window number of window
+ with ID {expr}: [tabnr, winnr].
+ Return [0, 0] if the window cannot be found.
+
+win_id2win({expr}) *win_id2win()*
+ Return the window number of window with ID {expr}.
+ Return 0 if the window cannot be found in the current tabpage.
+
*winbufnr()*
winbufnr({nr}) The result is a Number, which is the number of the buffer
associated with window {nr}. When {nr} is zero, the number of
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index 76aa3a50ce..92ed9de369 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -500,7 +500,7 @@ Options:
avoid that a Subject line with "Vim:" in it will cause an
error message.
'textwidth' is set to 72. This is often recommended for e-mail.
-'formatoptions' is set to break text lines and to repeat the comment leader
+'formatoptions' is set to break text lines and to repeat the comment leader
in new lines, so that a leading ">" for quotes is repeated.
You can also format quoted text with |gq|.
@@ -512,37 +512,40 @@ Local mappings:
MAN *ft-man-plugin* *:Man* *man.vim*
-Displays a manual page in a nice way. Also see the user manual
-|find-manpage|.
+View manpages in Nvim. Supports highlighting, autocompletion, locales, and
+navigation. See also |find-manpage|.
-To start using the ":Man" command before any manual page was loaded, source
-this script from your startup vimrc file: >
+To use Nvim as a manpager:
- runtime ftplugin/man.vim
-
-Options:
-'iskeyword' the '.' character is added to be able to use CTRL-] on the
- manual page name.
+ export MANPAGER="nvim -c 'set ft=man' -"
Commands:
-Man {name} Display the manual page for {name} in a window.
-Man {number} {name}
- Display the manual page for {name} in a section {number}.
-
-Global mapping:
-<Leader>K Displays the manual page for the word under the cursor.
+Man {name} Display the manpage for {name} in a window.
+Man {sect} {name} Display the manpage for {name} and section {sect}.
+Man {name}({sect}) Alternate syntax which auto-completes the section.
+Man {sect} {name}({sect}) Used during completion to show the real section of
+ when the provided section is a prefix, e.g. 1m vs 1.
+Man {path} Open the manpage specified by path. Use "./" if it
+ is in the current directory.
+
+Global Mappings:
+<Plug>(Man) Jump to the manpage for the <cWORD> under the
+ cursor in a new tab. Takes a count for the section.
Local mappings:
-CTRL-] Jump to the manual page for the word under the cursor.
-CTRL-T Jump back to the previous manual page.
-q Same as ":quit"
+K
+CTRL-] Jump to the manpage for the <cWORD> under the
+ cursor. Takes a count for the section.
+CTRL-T Jump back to the previous manpage.
+q Close the window.
-To enable folding use this: >
- let g:ft_man_folding_enable = 1
-If you do not like the default folding, use an autocommand to add your desired
-folding style instead. For example: >
- autocmd FileType man setlocal foldmethod=indent foldenable
+Variables:
+g:no_man_maps Do not create mappings in manpage buffers.
+g:ft_man_folding_enable Fold manpages with foldmethod=indent foldnestmax=1.
+If you do not like the default folding, use an autocommand to add your desired
+folding style instead. For example: >
+ :autocmd FileType man setlocal foldmethod=indent foldenable
PDF *ft-pdf-plugin*
diff --git a/runtime/doc/usr_12.txt b/runtime/doc/usr_12.txt
index 237abae55f..169d886e78 100644
--- a/runtime/doc/usr_12.txt
+++ b/runtime/doc/usr_12.txt
@@ -237,19 +237,8 @@ simple way: Move the cursor to the word you want to find help on and press >
K
-Vim will run the external "man" program on the word. If the man page is
-found, it is displayed. This uses the normal pager to scroll through the text
-(mostly the "more" program). When you get to the end pressing <Enter> will
-get you back into Vim.
-
-A disadvantage is that you can't see the man page and the text you are working
-on at the same time. There is a trick to make the man page appear in a Vim
-window. First, load the man filetype plugin: >
-
- :runtime! ftplugin/man.vim
-
-Put this command in your vimrc file if you intend to do this often. Now you
-can use the ":Man" command to open a window on a man page: >
+Nvim will run |:Man| on the word. If the man page is found, it is displayed.
+You can also use the |:Man| command to open a window on a man page: >
:Man csh
@@ -267,7 +256,7 @@ window.
To display a man page for the word under the cursor, use this: >
- \K
+ K
(If you redefined the <Leader>, use it instead of the backslash).
For example, you want to know the return value of "strstr()" while editing
@@ -275,7 +264,7 @@ this line:
if ( strstr (input, "aap") == ) ~
-Move the cursor to somewhere on "strstr" and type "\K". A window will open
+Move the cursor to somewhere on "strstr" and type "K". A window will open
to display the man page for strstr().
==============================================================================
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 937ed9e8ba..47380428b0 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -96,6 +96,7 @@ Options:
Commands:
|:CheckHealth|
+ |:Man| has many improvements, including auto-completion
Functions:
|execute()| works with |:redir|
diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim
index 04ab539fb1..614e1cb161 100644
--- a/runtime/ftplugin/man.vim
+++ b/runtime/ftplugin/man.vim
@@ -1,41 +1,60 @@
-" Vim filetype plugin file
-" Language: man
-" Maintainer: SungHyun Nam <goweol@gmail.com>
+" Maintainer: Anmol Sethi <anmol@aubble.com>
+" Previous Maintainer: SungHyun Nam <goweol@gmail.com>
-if has('vim_starting') && &filetype !=# 'man'
- finish
-endif
-
-" Only do this when not done yet for this buffer
if exists('b:did_ftplugin')
finish
endif
let b:did_ftplugin = 1
-" Ensure Vim is not recursively invoked (man-db does this)
-" when doing ctrl-[ on a man page reference.
-if exists('$MANPAGER')
- let $MANPAGER = ''
-endif
-
-setlocal iskeyword+=\.,-,(,)
-
-setlocal buftype=nofile noswapfile
-setlocal nomodifiable readonly bufhidden=hide nobuflisted tabstop=8
+let s:pager = 0
-if !exists("g:no_plugin_maps") && !exists("g:no_man_maps")
- nnoremap <silent> <buffer> <C-]> :call man#get_page(v:count, expand('<cword>'))<CR>
- nnoremap <silent> <buffer> <C-T> :call man#pop_page()<CR>
- nnoremap <silent> <nowait><buffer> q <C-W>c
- if &keywordprg !=# ':Man'
- nnoremap <silent> <buffer> K :call man#get_page(v:count, expand('<cword>'))<CR>
+if has('vim_starting')
+ let s:pager = 1
+ " remove all those backspaces
+ silent execute 'keeppatterns keepjumps %substitute,.\b,,e'.(&gdefault?'':'g')
+ if getline(1) =~# '^\s*$'
+ silent keepjumps 1delete _
+ else
+ keepjumps 1
endif
+ " This is not perfect. See `man glDrawArraysInstanced`. Since the title is
+ " all caps it is impossible to tell what the original capitilization was.
+ execute 'file man://'.tolower(matchstr(getline(1), '^\S\+'))
endif
-if exists('g:ft_man_folding_enable') && (g:ft_man_folding_enable == 1)
- setlocal foldmethod=indent foldnestmax=1 foldenable
+setlocal buftype=nofile
+setlocal noswapfile
+setlocal bufhidden=hide
+setlocal nomodified
+setlocal readonly
+setlocal nomodifiable
+setlocal noexpandtab
+setlocal tabstop=8
+setlocal softtabstop=8
+setlocal shiftwidth=8
+
+setlocal nonumber
+setlocal norelativenumber
+setlocal foldcolumn=0
+setlocal colorcolumn=0
+setlocal nolist
+setlocal nofoldenable
+
+if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
+ nmap <silent> <buffer> <C-]> <Plug>(Man)
+ nmap <silent> <buffer> K <Plug>(Man)
+ if s:pager
+ nnoremap <silent> <buffer> <nowait> q :q<CR>
+ else
+ nnoremap <silent> <buffer> <nowait> q <C-W>c
+ endif
endif
-let b:undo_ftplugin = 'setlocal iskeyword<'
+if get(g:, 'ft_man_folding_enable', 0)
+ setlocal foldenable
+ setlocal foldmethod=indent
+ setlocal foldnestmax=1
+endif
+let b:undo_ftplugin = ''
" vim: set sw=2:
diff --git a/runtime/macros/justify.vim b/runtime/macros/justify.vim
index 4ef3bf95fa..011a911401 100644
--- a/runtime/macros/justify.vim
+++ b/runtime/macros/justify.vim
@@ -1,316 +1,3 @@
-" Function to left and right align text.
-"
-" Written by: Preben "Peppe" Guldberg <c928400@student.dtu.dk>
-" Created: 980806 14:13 (or around that time anyway)
-" Revised: 001103 00:36 (See "Revisions" below)
-
-
-" function Justify( [ textwidth [, maxspaces [, indent] ] ] )
-"
-" Justify() will left and right align a line by filling in an
-" appropriate amount of spaces. Extra spaces are added to existing
-" spaces starting from the right side of the line. As an example, the
-" following documentation has been justified.
-"
-" The function takes the following arguments:
-
-" textwidth argument
-" ------------------
-" If not specified, the value of the 'textwidth' option is used. If
-" 'textwidth' is zero a value of 80 is used.
-"
-" Additionally the arguments 'tw' and '' are accepted. The value of
-" 'textwidth' will be used. These are handy, if you just want to specify
-" the maxspaces argument.
-
-" maxspaces argument
-" ------------------
-" If specified, alignment will only be done, if the longest space run
-" after alignment is no longer than maxspaces.
-"
-" An argument of '' is accepted, should the user like to specify all
-" arguments.
-"
-" To aid user defined commands, negative values are accepted aswell.
-" Using a negative value specifies the default behaviour: any length of
-" space runs will be used to justify the text.
-
-" indent argument
-" ---------------
-" This argument specifies how a line should be indented. The default is
-" to keep the current indentation.
-"
-" Negative values: Keep current amount of leading whitespace.
-" Positive values: Indent all lines with leading whitespace using this
-" amount of whitespace.
-"
-" Note that the value 0, needs to be quoted as a string. This value
-" leads to a left flushed text.
-"
-" Additionally units of 'shiftwidth'/'sw' and 'tabstop'/'ts' may be
-" added. In this case, if the value of indent is positive, the amount of
-" whitespace to be added will be multiplied by the value of the
-" 'shiftwidth' and 'tabstop' settings. If these units are used, the
-" argument must be given as a string, eg. Justify('','','2sw').
-"
-" If the values of 'sw' or 'tw' are negative, they are treated as if
-" they were 0, which means that the text is flushed left. There is no
-" check if a negative number prefix is used to change the sign of a
-" negative 'sw' or 'ts' value.
-"
-" As with the other arguments, '' may be used to get the default
-" behaviour.
-
-
-" Notes:
-"
-" If the line, adjusted for space runs and leading/trailing whitespace,
-" is wider than the used textwidth, the line will be left untouched (no
-" whitespace removed). This should be equivalent to the behaviour of
-" :left, :right and :center.
-"
-" If the resulting line is shorter than the used textwidth it is left
-" untouched.
-"
-" All space runs in the line are truncated before the alignment is
-" carried out.
-"
-" If you have set 'noexpandtab', :retab! is used to replace space runs
-" with whitespace using the value of 'tabstop'. This should be
-" conformant with :left, :right and :center.
-"
-" If joinspaces is set, an extra space is added after '.', '?' and '!'.
-" If 'cpooptions' include 'j', extra space is only added after '.'.
-" (This may on occasion conflict with maxspaces.)
-
-
-" Related mappings:
-"
-" Mappings that will align text using the current text width, using at
-" most four spaces in a space run and keeping current indentation.
-nmap _j :%call Justify('tw',4)<CR>
-vmap _j :call Justify('tw',4)<CR>
-"
-" Mappings that will remove space runs and format lines (might be useful
-" prior to aligning the text).
-nmap ,gq :%s/\s\+/ /g<CR>gq1G
-vmap ,gq :s/\s\+/ /g<CR>gvgq
-
-
-" User defined command:
-"
-" The following is an ex command that works as a shortcut to the Justify
-" function. Arguments to Justify() can be added after the command.
-com! -range -nargs=* Justify <line1>,<line2>call Justify(<f-args>)
-"
-" The following commands are all equivalent:
-"
-" 1. Simplest use of Justify():
-" :call Justify()
-" :Justify
-"
-" 2. The _j mapping above via the ex command:
-" :%Justify tw 4
-"
-" 3. Justify visualised text at 72nd column while indenting all
-" previously indented text two shiftwidths
-" :'<,'>call Justify(72,'','2sw')
-" :'<,'>Justify 72 -1 2sw
-"
-" This documentation has been justified using the following command:
-":se et|kz|1;/^" function Justify(/+,'z-g/^" /s/^" //|call Justify(70,3)|s/^/" /
-
-" Revisions:
-" 001103: If 'joinspaces' was set, calculations could be wrong.
-" Tabs at start of line could also lead to errors.
-" Use setline() instead of "exec 's/foo/bar/' - safer.
-" Cleaned up the code a bit.
-"
-" Todo: Convert maps to the new script specific form
-
-" Error function
-function! Justify_error(message)
- echohl Error
- echo "Justify([tw, [maxspaces [, indent]]]): " . a:message
- echohl None
-endfunction
-
-
-" Now for the real thing
-function! Justify(...) range
-
- if a:0 > 3
- call Justify_error("Too many arguments (max 3)")
- return 1
- endif
-
- " Set textwidth (accept 'tw' and '' as arguments)
- if a:0 >= 1
- if a:1 =~ '^\(tw\)\=$'
- let tw = &tw
- elseif a:1 =~ '^\d\+$'
- let tw = a:1
- else
- call Justify_error("tw must be a number (>0), '' or 'tw'")
- return 2
- endif
- else
- let tw = &tw
- endif
- if tw == 0
- let tw = 80
- endif
-
- " Set maximum number of spaces between WORDs
- if a:0 >= 2
- if a:2 == ''
- let maxspaces = tw
- elseif a:2 =~ '^-\d\+$'
- let maxspaces = tw
- elseif a:2 =~ '^\d\+$'
- let maxspaces = a:2
- else
- call Justify_error("maxspaces must be a number or ''")
- return 3
- endif
- else
- let maxspaces = tw
- endif
- if maxspaces <= 1
- call Justify_error("maxspaces should be larger than 1")
- return 4
- endif
-
- " Set the indentation style (accept sw and ts units)
- let indent_fix = ''
- if a:0 >= 3
- if (a:3 == '') || a:3 =~ '^-[1-9]\d*\(shiftwidth\|sw\|tabstop\|ts\)\=$'
- let indent = -1
- elseif a:3 =~ '^-\=0\(shiftwidth\|sw\|tabstop\|ts\)\=$'
- let indent = 0
- elseif a:3 =~ '^\d\+\(shiftwidth\|sw\|tabstop\|ts\)\=$'
- let indent = substitute(a:3, '\D', '', 'g')
- elseif a:3 =~ '^\(shiftwidth\|sw\|tabstop\|ts\)$'
- let indent = 1
- else
- call Justify_error("indent: a number with 'sw'/'ts' unit")
- return 5
- endif
- if indent >= 0
- while indent > 0
- let indent_fix = indent_fix . ' '
- let indent = indent - 1
- endwhile
- let indent_sw = 0
- if a:3 =~ '\(shiftwidth\|sw\)'
- let indent_sw = &sw
- elseif a:3 =~ '\(tabstop\|ts\)'
- let indent_sw = &ts
- endif
- let indent_fix2 = ''
- while indent_sw > 0
- let indent_fix2 = indent_fix2 . indent_fix
- let indent_sw = indent_sw - 1
- endwhile
- let indent_fix = indent_fix2
- endif
- else
- let indent = -1
- endif
-
- " Avoid substitution reports
- let save_report = &report
- set report=1000000
-
- " Check 'joinspaces' and 'cpo'
- if &js == 1
- if &cpo =~ 'j'
- let join_str = '\(\. \)'
- else
- let join_str = '\([.!?!] \)'
- endif
- endif
-
- let cur = a:firstline
- while cur <= a:lastline
-
- let str_orig = getline(cur)
- let save_et = &et
- set et
- exec cur . "retab"
- let &et = save_et
- let str = getline(cur)
-
- let indent_str = indent_fix
- let indent_n = strlen(indent_str)
- " Shall we remember the current indentation
- if indent < 0
- let indent_orig = matchstr(str_orig, '^\s*')
- if strlen(indent_orig) > 0
- let indent_str = indent_orig
- let indent_n = strlen(matchstr(str, '^\s*'))
- endif
- endif
-
- " Trim trailing, leading and running whitespace
- let str = substitute(str, '\s\+$', '', '')
- let str = substitute(str, '^\s\+', '', '')
- let str = substitute(str, '\s\+', ' ', 'g')
- let str_n = strdisplaywidth(str)
-
- " Possible addition of space after punctuation
- if exists("join_str")
- let str = substitute(str, join_str, '\1 ', 'g')
- endif
- let join_n = strdisplaywidth(str) - str_n
-
- " Can extraspaces be added?
- " Note that str_n may be less than strlen(str) [joinspaces above]
- if strdisplaywidth(str) <= tw - indent_n && str_n > 0
- " How many spaces should be added
- let s_add = tw - str_n - indent_n - join_n
- let s_nr = strlen(substitute(str, '\S', '', 'g') ) - join_n
- let s_dup = s_add / s_nr
- let s_mod = s_add % s_nr
-
- " Test if the changed line fits with tw
- if 0 <= (str_n + (maxspaces - 1)*s_nr + indent_n) - tw
-
- " Duplicate spaces
- while s_dup > 0
- let str = substitute(str, '\( \+\)', ' \1', 'g')
- let s_dup = s_dup - 1
- endwhile
-
- " Add extra spaces from the end
- while s_mod > 0
- let str = substitute(str, '\(\(\s\+\S\+\)\{' . s_mod . '}\)$', ' \1', '')
- let s_mod = s_mod - 1
- endwhile
-
- " Indent the line
- if indent_n > 0
- let str = substitute(str, '^', indent_str, '' )
- endif
-
- " Replace the line
- call setline(cur, str)
-
- " Convert to whitespace
- if &et == 0
- exec cur . 'retab!'
- endif
-
- endif " Change of line
- endif " Possible change
-
- let cur = cur + 1
- endwhile
-
- norm ^
-
- let &report = save_report
-
-endfunction
-
-" EOF vim: tw=78 ts=8 sw=4 sts=4 noet ai
+" Load the justify package.
+" For those users who were loading the justify plugin from here.
+packadd justify
diff --git a/runtime/pack/dist/opt/justify/plugin/justify.vim b/runtime/pack/dist/opt/justify/plugin/justify.vim
new file mode 100644
index 0000000000..4ef3bf95fa
--- /dev/null
+++ b/runtime/pack/dist/opt/justify/plugin/justify.vim
@@ -0,0 +1,316 @@
+" Function to left and right align text.
+"
+" Written by: Preben "Peppe" Guldberg <c928400@student.dtu.dk>
+" Created: 980806 14:13 (or around that time anyway)
+" Revised: 001103 00:36 (See "Revisions" below)
+
+
+" function Justify( [ textwidth [, maxspaces [, indent] ] ] )
+"
+" Justify() will left and right align a line by filling in an
+" appropriate amount of spaces. Extra spaces are added to existing
+" spaces starting from the right side of the line. As an example, the
+" following documentation has been justified.
+"
+" The function takes the following arguments:
+
+" textwidth argument
+" ------------------
+" If not specified, the value of the 'textwidth' option is used. If
+" 'textwidth' is zero a value of 80 is used.
+"
+" Additionally the arguments 'tw' and '' are accepted. The value of
+" 'textwidth' will be used. These are handy, if you just want to specify
+" the maxspaces argument.
+
+" maxspaces argument
+" ------------------
+" If specified, alignment will only be done, if the longest space run
+" after alignment is no longer than maxspaces.
+"
+" An argument of '' is accepted, should the user like to specify all
+" arguments.
+"
+" To aid user defined commands, negative values are accepted aswell.
+" Using a negative value specifies the default behaviour: any length of
+" space runs will be used to justify the text.
+
+" indent argument
+" ---------------
+" This argument specifies how a line should be indented. The default is
+" to keep the current indentation.
+"
+" Negative values: Keep current amount of leading whitespace.
+" Positive values: Indent all lines with leading whitespace using this
+" amount of whitespace.
+"
+" Note that the value 0, needs to be quoted as a string. This value
+" leads to a left flushed text.
+"
+" Additionally units of 'shiftwidth'/'sw' and 'tabstop'/'ts' may be
+" added. In this case, if the value of indent is positive, the amount of
+" whitespace to be added will be multiplied by the value of the
+" 'shiftwidth' and 'tabstop' settings. If these units are used, the
+" argument must be given as a string, eg. Justify('','','2sw').
+"
+" If the values of 'sw' or 'tw' are negative, they are treated as if
+" they were 0, which means that the text is flushed left. There is no
+" check if a negative number prefix is used to change the sign of a
+" negative 'sw' or 'ts' value.
+"
+" As with the other arguments, '' may be used to get the default
+" behaviour.
+
+
+" Notes:
+"
+" If the line, adjusted for space runs and leading/trailing whitespace,
+" is wider than the used textwidth, the line will be left untouched (no
+" whitespace removed). This should be equivalent to the behaviour of
+" :left, :right and :center.
+"
+" If the resulting line is shorter than the used textwidth it is left
+" untouched.
+"
+" All space runs in the line are truncated before the alignment is
+" carried out.
+"
+" If you have set 'noexpandtab', :retab! is used to replace space runs
+" with whitespace using the value of 'tabstop'. This should be
+" conformant with :left, :right and :center.
+"
+" If joinspaces is set, an extra space is added after '.', '?' and '!'.
+" If 'cpooptions' include 'j', extra space is only added after '.'.
+" (This may on occasion conflict with maxspaces.)
+
+
+" Related mappings:
+"
+" Mappings that will align text using the current text width, using at
+" most four spaces in a space run and keeping current indentation.
+nmap _j :%call Justify('tw',4)<CR>
+vmap _j :call Justify('tw',4)<CR>
+"
+" Mappings that will remove space runs and format lines (might be useful
+" prior to aligning the text).
+nmap ,gq :%s/\s\+/ /g<CR>gq1G
+vmap ,gq :s/\s\+/ /g<CR>gvgq
+
+
+" User defined command:
+"
+" The following is an ex command that works as a shortcut to the Justify
+" function. Arguments to Justify() can be added after the command.
+com! -range -nargs=* Justify <line1>,<line2>call Justify(<f-args>)
+"
+" The following commands are all equivalent:
+"
+" 1. Simplest use of Justify():
+" :call Justify()
+" :Justify
+"
+" 2. The _j mapping above via the ex command:
+" :%Justify tw 4
+"
+" 3. Justify visualised text at 72nd column while indenting all
+" previously indented text two shiftwidths
+" :'<,'>call Justify(72,'','2sw')
+" :'<,'>Justify 72 -1 2sw
+"
+" This documentation has been justified using the following command:
+":se et|kz|1;/^" function Justify(/+,'z-g/^" /s/^" //|call Justify(70,3)|s/^/" /
+
+" Revisions:
+" 001103: If 'joinspaces' was set, calculations could be wrong.
+" Tabs at start of line could also lead to errors.
+" Use setline() instead of "exec 's/foo/bar/' - safer.
+" Cleaned up the code a bit.
+"
+" Todo: Convert maps to the new script specific form
+
+" Error function
+function! Justify_error(message)
+ echohl Error
+ echo "Justify([tw, [maxspaces [, indent]]]): " . a:message
+ echohl None
+endfunction
+
+
+" Now for the real thing
+function! Justify(...) range
+
+ if a:0 > 3
+ call Justify_error("Too many arguments (max 3)")
+ return 1
+ endif
+
+ " Set textwidth (accept 'tw' and '' as arguments)
+ if a:0 >= 1
+ if a:1 =~ '^\(tw\)\=$'
+ let tw = &tw
+ elseif a:1 =~ '^\d\+$'
+ let tw = a:1
+ else
+ call Justify_error("tw must be a number (>0), '' or 'tw'")
+ return 2
+ endif
+ else
+ let tw = &tw
+ endif
+ if tw == 0
+ let tw = 80
+ endif
+
+ " Set maximum number of spaces between WORDs
+ if a:0 >= 2
+ if a:2 == ''
+ let maxspaces = tw
+ elseif a:2 =~ '^-\d\+$'
+ let maxspaces = tw
+ elseif a:2 =~ '^\d\+$'
+ let maxspaces = a:2
+ else
+ call Justify_error("maxspaces must be a number or ''")
+ return 3
+ endif
+ else
+ let maxspaces = tw
+ endif
+ if maxspaces <= 1
+ call Justify_error("maxspaces should be larger than 1")
+ return 4
+ endif
+
+ " Set the indentation style (accept sw and ts units)
+ let indent_fix = ''
+ if a:0 >= 3
+ if (a:3 == '') || a:3 =~ '^-[1-9]\d*\(shiftwidth\|sw\|tabstop\|ts\)\=$'
+ let indent = -1
+ elseif a:3 =~ '^-\=0\(shiftwidth\|sw\|tabstop\|ts\)\=$'
+ let indent = 0
+ elseif a:3 =~ '^\d\+\(shiftwidth\|sw\|tabstop\|ts\)\=$'
+ let indent = substitute(a:3, '\D', '', 'g')
+ elseif a:3 =~ '^\(shiftwidth\|sw\|tabstop\|ts\)$'
+ let indent = 1
+ else
+ call Justify_error("indent: a number with 'sw'/'ts' unit")
+ return 5
+ endif
+ if indent >= 0
+ while indent > 0
+ let indent_fix = indent_fix . ' '
+ let indent = indent - 1
+ endwhile
+ let indent_sw = 0
+ if a:3 =~ '\(shiftwidth\|sw\)'
+ let indent_sw = &sw
+ elseif a:3 =~ '\(tabstop\|ts\)'
+ let indent_sw = &ts
+ endif
+ let indent_fix2 = ''
+ while indent_sw > 0
+ let indent_fix2 = indent_fix2 . indent_fix
+ let indent_sw = indent_sw - 1
+ endwhile
+ let indent_fix = indent_fix2
+ endif
+ else
+ let indent = -1
+ endif
+
+ " Avoid substitution reports
+ let save_report = &report
+ set report=1000000
+
+ " Check 'joinspaces' and 'cpo'
+ if &js == 1
+ if &cpo =~ 'j'
+ let join_str = '\(\. \)'
+ else
+ let join_str = '\([.!?!] \)'
+ endif
+ endif
+
+ let cur = a:firstline
+ while cur <= a:lastline
+
+ let str_orig = getline(cur)
+ let save_et = &et
+ set et
+ exec cur . "retab"
+ let &et = save_et
+ let str = getline(cur)
+
+ let indent_str = indent_fix
+ let indent_n = strlen(indent_str)
+ " Shall we remember the current indentation
+ if indent < 0
+ let indent_orig = matchstr(str_orig, '^\s*')
+ if strlen(indent_orig) > 0
+ let indent_str = indent_orig
+ let indent_n = strlen(matchstr(str, '^\s*'))
+ endif
+ endif
+
+ " Trim trailing, leading and running whitespace
+ let str = substitute(str, '\s\+$', '', '')
+ let str = substitute(str, '^\s\+', '', '')
+ let str = substitute(str, '\s\+', ' ', 'g')
+ let str_n = strdisplaywidth(str)
+
+ " Possible addition of space after punctuation
+ if exists("join_str")
+ let str = substitute(str, join_str, '\1 ', 'g')
+ endif
+ let join_n = strdisplaywidth(str) - str_n
+
+ " Can extraspaces be added?
+ " Note that str_n may be less than strlen(str) [joinspaces above]
+ if strdisplaywidth(str) <= tw - indent_n && str_n > 0
+ " How many spaces should be added
+ let s_add = tw - str_n - indent_n - join_n
+ let s_nr = strlen(substitute(str, '\S', '', 'g') ) - join_n
+ let s_dup = s_add / s_nr
+ let s_mod = s_add % s_nr
+
+ " Test if the changed line fits with tw
+ if 0 <= (str_n + (maxspaces - 1)*s_nr + indent_n) - tw
+
+ " Duplicate spaces
+ while s_dup > 0
+ let str = substitute(str, '\( \+\)', ' \1', 'g')
+ let s_dup = s_dup - 1
+ endwhile
+
+ " Add extra spaces from the end
+ while s_mod > 0
+ let str = substitute(str, '\(\(\s\+\S\+\)\{' . s_mod . '}\)$', ' \1', '')
+ let s_mod = s_mod - 1
+ endwhile
+
+ " Indent the line
+ if indent_n > 0
+ let str = substitute(str, '^', indent_str, '' )
+ endif
+
+ " Replace the line
+ call setline(cur, str)
+
+ " Convert to whitespace
+ if &et == 0
+ exec cur . 'retab!'
+ endif
+
+ endif " Change of line
+ endif " Possible change
+
+ let cur = cur + 1
+ endwhile
+
+ norm ^
+
+ let &report = save_report
+
+endfunction
+
+" EOF vim: tw=78 ts=8 sw=4 sts=4 noet ai
diff --git a/runtime/plugin/man.vim b/runtime/plugin/man.vim
index 8e5062a209..12762f1854 100644
--- a/runtime/plugin/man.vim
+++ b/runtime/plugin/man.vim
@@ -1,6 +1,15 @@
-if get(g:, 'loaded_man', 0)
+" Maintainer: Anmol Sethi <anmol@aubble.com>
+
+if exists('g:loaded_man')
finish
endif
let g:loaded_man = 1
-command! -count=0 -nargs=+ Man call man#get_page(<count>, <f-args>)
+command! -count=0 -complete=customlist,man#complete -nargs=* Man call man#open_page(v:count, v:count1, <f-args>)
+
+nnoremap <silent> <Plug>(Man) :<C-U>call man#open_page(v:count, v:count1, &filetype ==# 'man' ? expand('<cWORD>') : expand('<cword>'))<CR>
+
+augroup man
+ autocmd!
+ autocmd BufReadCmd man://* call man#read_page(matchstr(expand('<amatch>'), 'man://\zs.*'))
+augroup END
diff --git a/runtime/syntax/man.vim b/runtime/syntax/man.vim
index fbc1847e6e..5dd41b3af5 100644
--- a/runtime/syntax/man.vim
+++ b/runtime/syntax/man.vim
@@ -1,67 +1,37 @@
-" Vim syntax file
-" Language: Man page
-" Maintainer: SungHyun Nam <goweol@gmail.com>
-" Previous Maintainer: Gautam H. Mudunuri <gmudunur@informatica.com>
-" Version Info:
-" Last Change: 2015 Nov 24
+" Maintainer: Anmol Sethi <anmol@aubble.com>
+" Previous Maintainer: SungHyun Nam <goweol@gmail.com>
-" Additional highlighting by Johannes Tanzler <johannes.tanzler@aon.at>:
-" * manSubHeading
-" * manSynopsis (only for sections 2 and 3)
-
-" For version 5.x: Clear all syntax items
-" For version 6.x: Quit when a syntax file was already loaded
-if version < 600
- syntax clear
-elseif exists("b:current_syntax")
+if exists('b:current_syntax')
finish
endif
-" Get the CTRL-H syntax to handle backspaced text
-if version >= 600
- runtime! syntax/ctrlh.vim
-else
- source <sfile>:p:h/ctrlh.vim
-endif
-
-syn case ignore
-syn match manReference "\f\+([1-9][a-z]\=)"
-syn match manTitle "^\f\+([0-9]\+[a-z]\=).*"
-syn match manSectionHeading "^[a-z][a-z -]*[a-z]$"
-syn match manSubHeading "^\s\{3\}[a-z][a-z -]*[a-z]$"
-syn match manOptionDesc "^\s*[+-][a-z0-9]\S*"
-syn match manLongOptionDesc "^\s*--[a-z0-9-]\S*"
-" syn match manHistory "^[a-z].*last change.*$"
-
-if getline(1) =~ '^[a-zA-Z_]\+([23])'
- syntax include @cCode <sfile>:p:h/c.vim
- syn match manCFuncDefinition display "\<\h\w*\>\s*("me=e-1 contained
- syn region manSynopsis start="^SYNOPSIS"hs=s+8 end="^\u\+\s*$"me=e-12 keepend contains=manSectionHeading,@cCode,manCFuncDefinition
-endif
-
-
-" Define the default highlighting.
-" For version 5.7 and earlier: only when not done already
-" For version 5.8 and later: only when an item doesn't have highlighting yet
-if version >= 508 || !exists("did_man_syn_inits")
- if version < 508
- let did_man_syn_inits = 1
- command -nargs=+ HiLink hi link <args>
- else
- command -nargs=+ HiLink hi def link <args>
- endif
-
- HiLink manTitle Title
- HiLink manSectionHeading Statement
- HiLink manOptionDesc Constant
- HiLink manLongOptionDesc Constant
- HiLink manReference PreProc
- HiLink manSubHeading Function
- HiLink manCFuncDefinition Function
-
- delcommand HiLink
+syntax case ignore
+syntax match manReference display '[^()[:space:]]\+([0-9nx][a-z]*)'
+syntax match manSectionHeading display '^\%(\S.*\)\=\S$'
+syntax match manTitle display '^\%1l.*$'
+syntax match manSubHeading display '^ \{3\}\S.*$'
+syntax match manOptionDesc display '^\s\+\%(+\|--\=\)\S\+'
+
+highlight default link manTitle Title
+highlight default link manSectionHeading Statement
+highlight default link manOptionDesc Constant
+highlight default link manReference PreProc
+highlight default link manSubHeading Function
+
+if getline(1) =~# '^[^()[:space:]]\+([23].*'
+ syntax include @c $VIMRUNTIME/syntax/c.vim
+ syntax match manCFuncDefinition display '\<\h\w*\>\ze\(\s\|\n\)*(' contained
+ syntax region manSynopsis start='^\%(
+ \SYNOPSIS\|
+ \SYNTAX\|
+ \SINTASSI\|
+ \SKŁADNIA\|
+ \СИНТАКСИС\|
+ \書式\)$' end='^\%(\S.*\)\=\S$' keepend contains=manSectionHeading,@c,manCFuncDefinition
+ highlight default link manCFuncDefinition Function
endif
-let b:current_syntax = "man"
+" Prevent everything else from matching the last line
+execute 'syntax match manFooter display "^\%'.line('$').'l.*$"'
-" vim:ts=8 sts=2 sw=2:
+let b:current_syntax = 'man'
diff --git a/scripts/genoptions.lua b/scripts/genoptions.lua
index da53d010bd..9f7d94969d 100644
--- a/scripts/genoptions.lua
+++ b/scripts/genoptions.lua
@@ -57,9 +57,14 @@ local get_flags = function(o)
add_flag(redraw_flags[r_flag])
end
end
+ if o.expand then
+ add_flag('P_EXPAND')
+ if o.expand == 'nodefault' then
+ add_flag('P_NO_DEF_EXP')
+ end
+ end
for _, flag_desc in ipairs({
{'alloced'},
- {'expand'},
{'nodefault'},
{'no_mkrc'},
{'vi_def'},
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index b515c4e1e4..46687f344c 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -937,8 +937,9 @@ struct matchitem {
*/
struct window_S {
uint64_t handle;
- buf_T *w_buffer; /* buffer we are a window into (used
- often, keep it the first item!) */
+ int w_id; ///< unique window ID
+ buf_T *w_buffer; ///< buffer we are a window into (used
+ ///< often, keep it the first item!)
synblock_T *w_s; /* for :ownsyntax */
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a5333d74be..7839a7f645 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6987,6 +6987,10 @@ static struct fst {
{ "virtcol", 1, 1, f_virtcol },
{ "visualmode", 0, 1, f_visualmode },
{ "wildmenumode", 0, 0, f_wildmenumode },
+ { "win_getid", 0, 2, f_win_getid },
+ { "win_gotoid", 1, 1, f_win_gotoid },
+ { "win_id2tabwin", 1, 1, f_win_id2tabwin },
+ { "win_id2win", 1, 1, f_win_id2win },
{ "winbufnr", 1, 1, f_winbufnr },
{ "wincol", 0, 0, f_wincol },
{ "winheight", 1, 1, f_winheight },
@@ -17150,6 +17154,32 @@ static void f_wildmenumode(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = 1;
}
+/// "win_getid()" function
+static void f_win_getid(typval_T *argvars, typval_T *rettv)
+{
+ rettv->vval.v_number = win_getid(argvars);
+}
+
+/// "win_gotoid()" function
+static void f_win_gotoid(typval_T *argvars, typval_T *rettv)
+{
+ rettv->vval.v_number = win_gotoid(argvars);
+}
+
+/// "win_id2tabwin()" function
+static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
+{
+ if (rettv_list_alloc(rettv) != FAIL) {
+ win_id2tabwin(argvars, rettv->vval.v_list);
+ }
+}
+
+/// "win_id2win()" function
+static void f_win_id2win(typval_T *argvars, typval_T *rettv)
+{
+ rettv->vval.v_number = win_id2win(argvars);
+}
+
/*
* "winbufnr(nr)" function
*/
@@ -18437,7 +18467,7 @@ static void init_tv(typval_T *varp)
* caller of incompatible types: it sets *denote to TRUE if "denote"
* is not NULL or returns -1 otherwise.
*/
-static long get_tv_number(typval_T *varp)
+long get_tv_number(typval_T *varp)
{
int error = FALSE;
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 154558b332..3b598bd64b 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -493,22 +493,14 @@ readfile (
curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
}
- /*
- * Check readonly by trying to open the file for writing.
- * If this fails, we know that the file is readonly.
- */
- file_readonly = FALSE;
+ // Check readonly.
+ file_readonly = false;
if (!read_buffer && !read_stdin) {
- if (!newfile || readonlymode) {
- file_readonly = TRUE;
- } else if ((fd = os_open((char *)fname, O_RDWR, 0)) < 0) {
- // opening in readwrite mode failed => file is readonly
- file_readonly = TRUE;
- }
- if (file_readonly == TRUE) {
- // try to open readonly
- fd = os_open((char *)fname, O_RDONLY, 0);
+ if (!newfile || readonlymode || !(perm & 0222)
+ || !os_file_is_writable((char *)fname)) {
+ file_readonly = true;
}
+ fd = os_open((char *)fname, O_RDONLY, 0);
}
if (fd < 0) { /* cannot open at all */
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 3c310ed309..725c6b080a 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -702,16 +702,9 @@ int delete_first_msg(void)
void ex_messages(exarg_T *eap)
{
struct msg_hist *p;
- const char *s;
msg_hist_off = TRUE;
- s = os_getenv("LANG");
- if (s)
- msg_attr((char_u *)
- _("Messages maintainer: Bram Moolenaar <Bram@vim.org>"),
- hl_attr(HLF_T));
-
for (p = first_msg_hist; p != NULL && !got_int; p = p->next)
if (p->msg != NULL)
msg_attr(p->msg, p->attr);
diff --git a/src/nvim/option.c b/src/nvim/option.c
index de53b0b1f4..6baf8c65ce 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -236,6 +236,7 @@ typedef struct vimoption {
#define P_NO_ML 0x2000000U ///< not allowed in modeline
#define P_CURSWANT 0x4000000U ///< update curswant required; not needed
///< when there is a redraw flag
+#define P_NO_DEF_EXP 0x8000000U ///< Do not expand default value.
#define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \
@@ -676,15 +677,18 @@ void set_init_1(void)
#endif
false);
- char *backupdir = stdpaths_user_data_subpath("backup", 0);
+ char *backupdir = stdpaths_user_data_subpath("backup", 0, true);
const size_t backupdir_len = strlen(backupdir);
backupdir = xrealloc(backupdir, backupdir_len + 3);
memmove(backupdir + 2, backupdir, backupdir_len + 1);
memmove(backupdir, ".,", 2);
- set_string_default("viewdir", stdpaths_user_data_subpath("view", 0), true);
+ set_string_default("viewdir", stdpaths_user_data_subpath("view", 0, true),
+ true);
set_string_default("backupdir", backupdir, true);
- set_string_default("directory", stdpaths_user_data_subpath("swap", 2), true);
- set_string_default("undodir", stdpaths_user_data_subpath("undo", 0), true);
+ set_string_default("directory", stdpaths_user_data_subpath("swap", 2, true),
+ true);
+ set_string_default("undodir", stdpaths_user_data_subpath("undo", 0, true),
+ true);
// Set default for &runtimepath. All necessary expansions are performed in
// this function.
set_runtimepath_default();
@@ -726,6 +730,9 @@ void set_init_1(void)
* default.
*/
for (opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
+ if (options[opt_idx].flags & P_NO_DEF_EXP) {
+ continue;
+ }
char *p;
if ((options[opt_idx].flags & P_GETTEXT)
&& options[opt_idx].var != NULL) {
@@ -1473,16 +1480,19 @@ do_set (
* default value was already expanded, only
* required when an environment variable was set
* later */
- if (newval == NULL)
+ new_value_alloced = true;
+ if (newval == NULL) {
newval = empty_option;
- else {
+ } else if (!(options[opt_idx].flags | P_NO_DEF_EXP)) {
s = option_expand(opt_idx, newval);
- if (s == NULL)
+ if (s == NULL) {
s = newval;
+ }
newval = vim_strsave(s);
+ } else {
+ newval = (char_u *)xstrdup((char *)newval);
}
- new_value_alloced = TRUE;
- } else if (nextchar == '<') { /* set to global val */
+ } else if (nextchar == '<') { // set to global val
newval = vim_strsave(*(char_u **)get_varp_scope(
&(options[opt_idx]), OPT_GLOBAL));
new_value_alloced = TRUE;
@@ -2020,13 +2030,15 @@ static char_u *option_expand(int opt_idx, char_u *val)
if (!(options[opt_idx].flags & P_EXPAND) || options[opt_idx].var == NULL)
return NULL;
- /* If val is longer than MAXPATHL no meaningful expansion can be done,
- * expand_env() would truncate the string. */
- if (val != NULL && STRLEN(val) > MAXPATHL)
- return NULL;
-
- if (val == NULL)
+ if (val == NULL) {
val = *(char_u **)options[opt_idx].var;
+ }
+
+ // If val is longer than MAXPATHL no meaningful expansion can be done,
+ // expand_env() would truncate the string.
+ if (val == NULL || STRLEN(val) > MAXPATHL) {
+ return NULL;
+ }
/*
* Expanding this with NameBuff, expand_env() must not be passed IObuff.
diff --git a/src/nvim/option.h b/src/nvim/option.h
index 5c2b2662b5..3a43b859a8 100644
--- a/src/nvim/option.h
+++ b/src/nvim/option.h
@@ -6,17 +6,18 @@
#define BCO_ALWAYS 2 /* always copy the options */
#define BCO_NOHELP 4 /* don't touch the help related options */
-/*
- * "flags" values for option-setting functions.
- * When OPT_GLOBAL and OPT_LOCAL are both missing, set both local and global
- * values, get local value.
- */
-#define OPT_FREE 1 /* free old value if it was allocated */
-#define OPT_GLOBAL 2 /* use global value */
-#define OPT_LOCAL 4 /* use local value */
-#define OPT_MODELINE 8 /* option in modeline */
-#define OPT_WINONLY 16 /* only set window-local options */
-#define OPT_NOWIN 32 /* don't set window-local options */
+/// Flags for option-setting functions
+///
+/// When OPT_GLOBAL and OPT_LOCAL are both missing, set both local and global
+/// values, get local value.
+typedef enum {
+ OPT_FREE = 1, ///< Free old value if it was allocated.
+ OPT_GLOBAL = 2, ///< Use global value.
+ OPT_LOCAL = 4, ///< Use local value.
+ OPT_MODELINE = 8, ///< Option in modeline.
+ OPT_WINONLY = 16, ///< Only set window-local options.
+ OPT_NOWIN = 32, ///< Don’t set window-local options.
+} OptionFlags;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "option.h.generated.h"
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index d19af4f73f..060ec8c1e1 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -165,7 +165,7 @@ return {
deny_duplicates=true,
secure=true,
vi_def=true,
- expand=true,
+ expand='nodefault',
varname='p_bdir',
defaults={if_true={vi=''}}
},
@@ -616,7 +616,7 @@ return {
deny_duplicates=true,
secure=true,
vi_def=true,
- expand=true,
+ expand='nodefault',
varname='p_dir',
defaults={if_true={vi=''}}
},
@@ -1891,7 +1891,7 @@ return {
deny_duplicates=true,
secure=true,
vi_def=true,
- expand=true,
+ expand='nodefault',
varname='p_rtp',
defaults={if_true={vi=''}}
},
@@ -2507,7 +2507,7 @@ return {
deny_duplicates=true,
secure=true,
vi_def=true,
- expand=true,
+ expand='nodefault',
varname='p_udir',
defaults={if_true={vi=''}}
},
@@ -2568,7 +2568,7 @@ return {
type='string', scope={'global'},
secure=true,
vi_def=true,
- expand=true,
+ expand='nodefault',
varname='p_vdir',
defaults={if_true={vi=''}}
},
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index 81ceb919c4..10b3f4c091 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -100,18 +100,30 @@ char *stdpaths_user_conf_subpath(const char *fname)
///
/// @param[in] fname New component of the path.
/// @param[in] trailing_pathseps Amount of trailing path separators to add.
+/// @param[in] escape_commas If true, all commas will be escaped.
///
-/// @return [allocated] `$XDG_DATA_HOME/nvim/{fname}`
+/// @return [allocated] `$XDG_DATA_HOME/nvim/{fname}`.
char *stdpaths_user_data_subpath(const char *fname,
- const size_t trailing_pathseps)
+ const size_t trailing_pathseps,
+ const bool escape_commas)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
char *ret = concat_fnames_realloc(get_xdg_home(kXDGDataHome), fname, true);
- if (trailing_pathseps) {
- const size_t len = strlen(ret);
- ret = xrealloc(ret, len + trailing_pathseps + 1);
- memset(ret + len, PATHSEP, trailing_pathseps);
- ret[len + trailing_pathseps] = NUL;
+ const size_t len = strlen(ret);
+ const size_t numcommas = (escape_commas ? memcnt(ret, ',', len) : 0);
+ if (numcommas || trailing_pathseps) {
+ ret = xrealloc(ret, len + trailing_pathseps + numcommas + 1);
+ for (size_t i = 0 ; i < len + numcommas ; i++) {
+ if (ret[i] == ',') {
+ memmove(ret + i + 1, ret + i, len - i + numcommas);
+ ret[i] = '\\';
+ i++;
+ }
+ }
+ if (trailing_pathseps) {
+ memset(ret + len + numcommas, PATHSEP, trailing_pathseps);
+ }
+ ret[len + trailing_pathseps + numcommas] = NUL;
}
return ret;
}
diff --git a/src/nvim/po/af.po b/src/nvim/po/af.po
index 6bb93b9e02..8f06ed178c 100644
--- a/src/nvim/po/af.po
+++ b/src/nvim/po/af.po
@@ -4305,10 +4305,6 @@ msgstr "rel %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Ongeldige registernaam: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Boodskappe onderhouers: Danie Roux en Jean Jordaan <droux@tuks.co.za>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Onderbreek: "
diff --git a/src/nvim/po/ca.po b/src/nvim/po/ca.po
index 79434cfdcd..2b0d7611d0 100644
--- a/src/nvim/po/ca.po
+++ b/src/nvim/po/ca.po
@@ -4293,10 +4293,6 @@ msgstr "lnia %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: El nom de registre no s vlid: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Traducci dels missatges: Ernest Adrogu <eadrogue@gmx.net>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Interrupci: "
diff --git a/src/nvim/po/cs.cp1250.po b/src/nvim/po/cs.cp1250.po
index 1e62034317..339dfe6ae5 100644
--- a/src/nvim/po/cs.cp1250.po
+++ b/src/nvim/po/cs.cp1250.po
@@ -4378,10 +4378,6 @@ msgstr "dek %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: '%s' nen ppustn jmno registru"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Sprvce zprv: Bram Moolenaar <Bram@vim.org>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Peruen: "
diff --git a/src/nvim/po/cs.po b/src/nvim/po/cs.po
index dd7016fedb..5c19eecf32 100644
--- a/src/nvim/po/cs.po
+++ b/src/nvim/po/cs.po
@@ -4378,10 +4378,6 @@ msgstr "dek %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: '%s' nen ppustn jmno registru"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Sprvce zprv: Bram Moolenaar <Bram@vim.org>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Peruen: "
diff --git a/src/nvim/po/en_GB.po b/src/nvim/po/en_GB.po
index b4b38e11e3..41e4cd895d 100644
--- a/src/nvim/po/en_GB.po
+++ b/src/nvim/po/en_GB.po
@@ -4128,10 +4128,6 @@ msgstr ""
msgid "E354: Invalid register name: '%s'"
msgstr ""
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Messages maintainer: Mike Williams <mrw@eandem.co.uk>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr ""
diff --git a/src/nvim/po/eo.po b/src/nvim/po/eo.po
index 6bc76506ae..153eacc7b8 100644
--- a/src/nvim/po/eo.po
+++ b/src/nvim/po/eo.po
@@ -4295,10 +4295,6 @@ msgstr "linio %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Nevalida nomo de reĝistro: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Flegado de mesaĝoj: Dominique PELLÉ <dominique.pelle@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Interrompo: "
diff --git a/src/nvim/po/es.po b/src/nvim/po/es.po
index 8a9c86e88d..9a3bfa6894 100644
--- a/src/nvim/po/es.po
+++ b/src/nvim/po/es.po
@@ -4377,12 +4377,6 @@ msgstr "línea %4ld"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Nombre de registro no válido: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ""
-"Traducción: Proyecto vim-doc-es <http://www.assembla.com/wiki/show/vim-doc-"
-"es>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Interrupción: "
diff --git a/src/nvim/po/fi.po b/src/nvim/po/fi.po
index d4082135aa..6dfaa78a77 100644
--- a/src/nvim/po/fi.po
+++ b/src/nvim/po/fi.po
@@ -4275,10 +4275,6 @@ msgstr "rivi %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Virheellinen rekisterin nimi: %s"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Knnksen yllpitj: Flammie Pirinen <flammie@iki.fi>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Keskeytys: "
diff --git a/src/nvim/po/fr.po b/src/nvim/po/fr.po
index 41efd5c5e3..a16a939117 100644
--- a/src/nvim/po/fr.po
+++ b/src/nvim/po/fr.po
@@ -4479,10 +4479,6 @@ msgid "E354: Invalid register name: '%s'"
msgstr "E354: Nom de registre invalide : '%s'"
# DB - todo : mettre jour ?
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Maintenance des messages : Dominique Pell <dominique.pelle@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Interruption : "
diff --git a/src/nvim/po/ga.po b/src/nvim/po/ga.po
index f7117c6e86..d94b788449 100644
--- a/src/nvim/po/ga.po
+++ b/src/nvim/po/ga.po
@@ -4286,11 +4286,6 @@ msgstr "lne %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Ainm neamhbhail tabhaill: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ""
-"Cothaitheoir na dteachtaireachta: Kevin P. Scannell <scannell@slu.edu>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Idirbhriseadh: "
diff --git a/src/nvim/po/it.po b/src/nvim/po/it.po
index 084102da60..119a8f02ff 100644
--- a/src/nvim/po/it.po
+++ b/src/nvim/po/it.po
@@ -4294,10 +4294,6 @@ msgstr "riga %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Nome registro non valido: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Manutentore messaggi: Vlad Sandrini <marco@sandrini.biz>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Interruzione: "
diff --git a/src/nvim/po/ja.euc-jp.po b/src/nvim/po/ja.euc-jp.po
index 85042e3506..e8d60d4438 100644
--- a/src/nvim/po/ja.euc-jp.po
+++ b/src/nvim/po/ja.euc-jp.po
@@ -4258,10 +4258,6 @@ msgstr " %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: ̵ʥ쥸̾: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "ܸå/ƽ: ¼ Ϻ <koron.kaoriya@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr ": "
diff --git a/src/nvim/po/ja.po b/src/nvim/po/ja.po
index 0326f33bb5..fd3690f9bf 100644
--- a/src/nvim/po/ja.po
+++ b/src/nvim/po/ja.po
@@ -4257,10 +4257,6 @@ msgstr "行 %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: 無効なレジスタ名: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "日本語メッセージ翻訳/監修: 村岡 太郎 <koron.kaoriya@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "割込み: "
diff --git a/src/nvim/po/ja.sjis.po b/src/nvim/po/ja.sjis.po
index 16a5d2ce36..c9fd35292c 100644
--- a/src/nvim/po/ja.sjis.po
+++ b/src/nvim/po/ja.sjis.po
@@ -4261,10 +4261,6 @@ msgstr "s %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: ȃWX^: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "{ꃁbZ[W|/ďC: Y <koron.kaoriya@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr ": "
diff --git a/src/nvim/po/ko.UTF-8.po b/src/nvim/po/ko.UTF-8.po
index 149286eda8..3ed659208b 100644
--- a/src/nvim/po/ko.UTF-8.po
+++ b/src/nvim/po/ko.UTF-8.po
@@ -4224,10 +4224,6 @@ msgstr "%4ld 줄:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: 잘못된 레지스터 이름: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "메시지 관리자: Bram Moolenaar <Bram@vim.org>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "중단: "
diff --git a/src/nvim/po/ko.po b/src/nvim/po/ko.po
index b6aaf37bbb..e97e90642c 100644
--- a/src/nvim/po/ko.po
+++ b/src/nvim/po/ko.po
@@ -4224,10 +4224,6 @@ msgstr "%4ld :"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: ߸ ̸: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "޽ : Bram Moolenaar <Bram@vim.org>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "ߴ: "
diff --git a/src/nvim/po/nb.po b/src/nvim/po/nb.po
index ce635e098c..76e42ddcd6 100644
--- a/src/nvim/po/nb.po
+++ b/src/nvim/po/nb.po
@@ -4275,11 +4275,6 @@ msgstr "linje %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Ugyldig registernavn: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ""
-"Vedlikeholder for norsk oversettelse: yvind A. Holm <sunny@sunbase.org>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Avbryt: "
diff --git a/src/nvim/po/nl.po b/src/nvim/po/nl.po
index ea609c0f69..6013b847cb 100644
--- a/src/nvim/po/nl.po
+++ b/src/nvim/po/nl.po
@@ -4282,10 +4282,6 @@ msgstr "regel %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr ""
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Vertaald door: Erwin Poeze <erwin.poeze@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr ""
diff --git a/src/nvim/po/no.po b/src/nvim/po/no.po
index ce635e098c..76e42ddcd6 100644
--- a/src/nvim/po/no.po
+++ b/src/nvim/po/no.po
@@ -4275,11 +4275,6 @@ msgstr "linje %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Ugyldig registernavn: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ""
-"Vedlikeholder for norsk oversettelse: yvind A. Holm <sunny@sunbase.org>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Avbryt: "
diff --git a/src/nvim/po/pl.UTF-8.po b/src/nvim/po/pl.UTF-8.po
index 68cb9e72d5..2536efb422 100644
--- a/src/nvim/po/pl.UTF-8.po
+++ b/src/nvim/po/pl.UTF-8.po
@@ -4243,10 +4243,6 @@ msgstr "wiersz %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Niewłaściwa nazwa rejestru: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Opiekun komunikatów: Mikołaj Machowski <mikmach@wp.pl>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Przerwanie: "
diff --git a/src/nvim/po/pl.cp1250.po b/src/nvim/po/pl.cp1250.po
index 3fcdbfb87d..30835637d0 100644
--- a/src/nvim/po/pl.cp1250.po
+++ b/src/nvim/po/pl.cp1250.po
@@ -4243,10 +4243,6 @@ msgstr "wiersz %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Niewaciwa nazwa rejestru: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Opiekun komunikatw: Mikoaj Machowski <mikmach@wp.pl>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Przerwanie: "
diff --git a/src/nvim/po/pl.po b/src/nvim/po/pl.po
index 2a2d12daac..c5734f0c49 100644
--- a/src/nvim/po/pl.po
+++ b/src/nvim/po/pl.po
@@ -4243,10 +4243,6 @@ msgstr "wiersz %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Niewaciwa nazwa rejestru: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Opiekun komunikatw: Mikoaj Machowski <mikmach@wp.pl>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Przerwanie: "
diff --git a/src/nvim/po/ru.cp1251.po b/src/nvim/po/ru.cp1251.po
index 29e8c83ee6..b1005bd0e6 100644
--- a/src/nvim/po/ru.cp1251.po
+++ b/src/nvim/po/ru.cp1251.po
@@ -4283,12 +4283,6 @@ msgstr " %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: : '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ""
-" : <vrr@users.sourceforge."
-"net>, <alyoshin.s@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr ": "
diff --git a/src/nvim/po/ru.po b/src/nvim/po/ru.po
index c8146e8c47..2511ef2c46 100644
--- a/src/nvim/po/ru.po
+++ b/src/nvim/po/ru.po
@@ -4281,12 +4281,6 @@ msgstr "строка %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Недопустимое имя регистра: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ""
-"Перевод сообщений на русский язык: Василий Рагозин <vrr@users.sourceforge."
-"net>, Сергей Алёшин <alyoshin.s@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Прерывание: "
diff --git a/src/nvim/po/sk.cp1250.po b/src/nvim/po/sk.cp1250.po
index e3b7508cdc..b1b0bb6ade 100644
--- a/src/nvim/po/sk.cp1250.po
+++ b/src/nvim/po/sk.cp1250.po
@@ -4273,10 +4273,6 @@ msgstr "riadok %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: '%s' nie je prstupn meno registru"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Sprvca prekladu: Lubomir Host <rajo@platon.sk>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Preruenie: "
diff --git a/src/nvim/po/sk.po b/src/nvim/po/sk.po
index 53f8a7b911..206e3e3ef6 100644
--- a/src/nvim/po/sk.po
+++ b/src/nvim/po/sk.po
@@ -4273,10 +4273,6 @@ msgstr "riadok %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: '%s' nie je prstupn meno registru"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Sprvca prekladu: Lubomir Host <rajo@platon.sk>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Preruenie: "
diff --git a/src/nvim/po/uk.cp1251.po b/src/nvim/po/uk.cp1251.po
index 2c6f3423ae..0b5668cfc5 100644
--- a/src/nvim/po/uk.cp1251.po
+++ b/src/nvim/po/uk.cp1251.po
@@ -4362,10 +4362,6 @@ msgstr " %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: : '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ": <sakhnik@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr ": "
diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po
index eaa3a5bfa9..73d43b14c5 100644
--- a/src/nvim/po/uk.po
+++ b/src/nvim/po/uk.po
@@ -4362,10 +4362,6 @@ msgstr "рядок %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Неправильна назва регістру: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Українізація: Анатолій Сахнік <sakhnik@gmail.com>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Перервано: "
diff --git a/src/nvim/po/vi.po b/src/nvim/po/vi.po
index a720510426..49c6765843 100644
--- a/src/nvim/po/vi.po
+++ b/src/nvim/po/vi.po
@@ -4311,11 +4311,6 @@ msgstr "dòng %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: Tên sổ đăng ký không cho phép: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ""
-"Bản dịch các thông báo sang tiếng Việt: Phan Vĩnh Thịnh <teppi@vnlinux.org>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "Gián đoạn: "
diff --git a/src/nvim/po/zh_CN.UTF-8.po b/src/nvim/po/zh_CN.UTF-8.po
index 82b895d9d6..e88efed8e3 100644
--- a/src/nvim/po/zh_CN.UTF-8.po
+++ b/src/nvim/po/zh_CN.UTF-8.po
@@ -4264,10 +4264,6 @@ msgstr "第 %4ld 行:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: 无效的寄存器名: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "简体中文消息维护者: Yuheng Xie <elephant@linux.net.cn>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "已中断: "
diff --git a/src/nvim/po/zh_CN.cp936.po b/src/nvim/po/zh_CN.cp936.po
index cf66010c71..e5351cc22a 100644
--- a/src/nvim/po/zh_CN.cp936.po
+++ b/src/nvim/po/zh_CN.cp936.po
@@ -4265,10 +4265,6 @@ msgstr " %4ld :"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: ЧļĴ: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Ϣά: Yuheng Xie <elephant@linux.net.cn>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "ж: "
diff --git a/src/nvim/po/zh_CN.po b/src/nvim/po/zh_CN.po
index 254ebbce6b..6cc4dd42ac 100644
--- a/src/nvim/po/zh_CN.po
+++ b/src/nvim/po/zh_CN.po
@@ -4265,10 +4265,6 @@ msgstr " %4ld :"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: ЧļĴ: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr "Ϣά: Yuheng Xie <elephant@linux.net.cn>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "ж: "
diff --git a/src/nvim/po/zh_TW.UTF-8.po b/src/nvim/po/zh_TW.UTF-8.po
index 79e09c83d1..da86d80c27 100644
--- a/src/nvim/po/zh_TW.UTF-8.po
+++ b/src/nvim/po/zh_TW.UTF-8.po
@@ -4304,12 +4304,6 @@ msgstr "行 %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: 暫存器名稱錯誤: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ""
-"正體中文訊息維護者: Francis S.Lin <piaip@csie.ntu.edu."
-"tw>, Cecil Sheng <b7506022@csie.ntu.edu.tw>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "已中斷: "
diff --git a/src/nvim/po/zh_TW.po b/src/nvim/po/zh_TW.po
index 07d510c0c6..977f18086e 100644
--- a/src/nvim/po/zh_TW.po
+++ b/src/nvim/po/zh_TW.po
@@ -4296,12 +4296,6 @@ msgstr " %4ld:"
msgid "E354: Invalid register name: '%s'"
msgstr "E354: ȦsWٿ~: '%s'"
-#: ../message.c:745
-msgid "Messages maintainer: Bram Moolenaar <Bram@vim.org>"
-msgstr ""
-"餤T@: Francis S.Lin <piaip@csie.ntu.edu."
-"tw>, Cecil Sheng <b7506022@csie.ntu.edu.tw>"
-
#: ../message.c:986
msgid "Interrupt: "
msgstr "w_: "
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index b5921eb810..fe62f06e59 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -1524,7 +1524,7 @@ static const char *shada_get_default_file(void)
FUNC_ATTR_WARN_UNUSED_RESULT
{
if (default_shada_file == NULL) {
- char *shada_dir = stdpaths_user_data_subpath("shada", 0);
+ char *shada_dir = stdpaths_user_data_subpath("shada", 0, false);
default_shada_file = concat_fnames_realloc(shada_dir, "main.shada", true);
}
return default_shada_file;
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 9a0bba83fe..4979aae57a 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -39,6 +39,7 @@ NEW_TESTS = \
test_timers.res \
test_viml.res \
test_visual.res \
+ test_window_id.res \
test_alot.res
SCRIPTS_GUI := test16.out
diff --git a/src/nvim/testdir/test_window_id.vim b/src/nvim/testdir/test_window_id.vim
new file mode 100644
index 0000000000..b9e9f45c49
--- /dev/null
+++ b/src/nvim/testdir/test_window_id.vim
@@ -0,0 +1,71 @@
+" Test using the window ID.
+
+func Test_win_getid()
+ edit one
+ let id1 = win_getid()
+ split two
+ let id2 = win_getid()
+ split three
+ let id3 = win_getid()
+ tabnew
+ edit four
+ let id4 = win_getid()
+ split five
+ let id5 = win_getid()
+ tabnext
+
+ wincmd w
+ call assert_equal("two", expand("%"))
+ call assert_equal(id2, win_getid())
+ let nr2 = winnr()
+ wincmd w
+ call assert_equal("one", expand("%"))
+ call assert_equal(id1, win_getid())
+ let nr1 = winnr()
+ wincmd w
+ call assert_equal("three", expand("%"))
+ call assert_equal(id3, win_getid())
+ let nr3 = winnr()
+ tabnext
+ call assert_equal("five", expand("%"))
+ call assert_equal(id5, win_getid())
+ let nr5 = winnr()
+ wincmd w
+ call assert_equal("four", expand("%"))
+ call assert_equal(id4, win_getid())
+ let nr4 = winnr()
+ tabnext
+
+ exe nr1 . "wincmd w"
+ call assert_equal(id1, win_getid())
+ exe nr2 . "wincmd w"
+ call assert_equal(id2, win_getid())
+ exe nr3 . "wincmd w"
+ call assert_equal(id3, win_getid())
+ tabnext
+ exe nr4 . "wincmd w"
+ call assert_equal(id4, win_getid())
+ exe nr5 . "wincmd w"
+ call assert_equal(id5, win_getid())
+
+ call win_gotoid(id2)
+ call assert_equal("two", expand("%"))
+ call win_gotoid(id4)
+ call assert_equal("four", expand("%"))
+ call win_gotoid(id1)
+ call assert_equal("one", expand("%"))
+ call win_gotoid(id5)
+ call assert_equal("five", expand("%"))
+
+ call assert_equal(0, win_id2win(9999))
+ call assert_equal(nr5, win_id2win(id5))
+ call assert_equal(0, win_id2win(id1))
+ tabnext
+ call assert_equal(nr1, win_id2win(id1))
+
+ call assert_equal([0, 0], win_id2tabwin(9999))
+ call assert_equal([1, nr2], win_id2tabwin(id2))
+ call assert_equal([2, nr4], win_id2tabwin(id4))
+
+ only!
+endfunc
diff --git a/src/nvim/version.c b/src/nvim/version.c
index d6b051a511..aa337f9fae 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -604,7 +604,7 @@ static int included_patches[] = {
1676,
1675,
// 1674 NA
- // 1673,
+ 1673,
// 1672 NA
// 1671,
// 1670,
@@ -674,7 +674,7 @@ static int included_patches[] = {
// 1606,
// 1605,
// 1604,
- // 1603,
+ 1603,
// 1602 NA
// 1601 NA
// 1600 NA
@@ -720,7 +720,7 @@ static int included_patches[] = {
// 1560 NA
// 1559,
// 1558,
- // 1557,
+ 1557,
// 1556 NA
// 1555 NA
1554,
diff --git a/src/nvim/window.c b/src/nvim/window.c
index e267d493bf..350b54d595 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -3683,6 +3683,8 @@ win_T *buf_jump_open_tab(buf_T *buf)
return NULL;
}
+static int last_win_id = 0;
+
/*
* Allocate a window structure and link it in the window list when "hidden" is
* FALSE.
@@ -3695,6 +3697,7 @@ static win_T *win_alloc(win_T *after, int hidden)
win_T *new_wp = xcalloc(1, sizeof(win_T));
handle_register_window(new_wp);
win_alloc_lines(new_wp);
+ new_wp->w_id = ++last_win_id;
/* init w: variables */
new_wp->w_vars = dict_alloc();
@@ -5674,3 +5677,93 @@ static bool frame_check_width(frame_T *topfrp, int width)
}
return true;
}
+
+int win_getid(typval_T *argvars)
+{
+ if (argvars[0].v_type == VAR_UNKNOWN) {
+ return curwin->w_id;
+ }
+ int winnr = get_tv_number(&argvars[0]);
+ win_T *wp;
+ if (winnr > 0) {
+ if (argvars[1].v_type == VAR_UNKNOWN) {
+ wp = firstwin;
+ } else {
+ tabpage_T *tp;
+ int tabnr = get_tv_number(&argvars[1]);
+ for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
+ if (--tabnr == 0) {
+ break;
+ }
+ }
+ if (tp == NULL) {
+ return -1;
+ }
+ wp = tp->tp_firstwin;
+ }
+ for ( ; wp != NULL; wp = wp->w_next) {
+ if (--winnr == 0) {
+ return wp->w_id;
+ }
+ }
+ }
+ return 0;
+}
+
+int win_gotoid(typval_T *argvars)
+{
+ win_T *wp;
+ tabpage_T *tp;
+ int id = get_tv_number(&argvars[0]);
+
+ for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
+ for (wp = tp == curtab ? firstwin : tp->tp_firstwin;
+ wp != NULL; wp = wp->w_next) {
+ if (wp->w_id == id) {
+ goto_tabpage_win(tp, wp);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+void win_id2tabwin(typval_T *argvars, list_T *list)
+{
+ win_T *wp;
+ tabpage_T *tp;
+ int winnr = 1;
+ int tabnr = 1;
+ int id = get_tv_number(&argvars[0]);
+
+ for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
+ for (wp = tp == curtab ? firstwin : tp->tp_firstwin;
+ wp != NULL; wp = wp->w_next) {
+ if (wp->w_id == id) {
+ list_append_number(list, tabnr);
+ list_append_number(list, winnr);
+ return;
+ }
+ winnr++;
+ }
+ tabnr++;
+ winnr = 1;
+ }
+ list_append_number(list, 0);
+ list_append_number(list, 0);
+}
+
+int win_id2win(typval_T *argvars)
+{
+ win_T *wp;
+ int nr = 1;
+ int id = get_tv_number(&argvars[0]);
+
+ for (wp = firstwin; wp != NULL; wp = wp->w_next) {
+ if (wp->w_id == id) {
+ return nr;
+ }
+ nr++;
+ }
+ return 0;
+}
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 02109d0889..6f43ec817c 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -216,17 +216,47 @@ local function merge_args(...)
return argv
end
-local function spawn(argv, merge)
- local child_stream = ChildProcessStream.spawn(merge and merge_args(prepend_argv, argv) or argv)
+local function spawn(argv, merge, env)
+ local child_stream = ChildProcessStream.spawn(
+ merge and merge_args(prepend_argv, argv) or argv,
+ env)
return Session.new(child_stream)
end
local function clear(...)
local args = {unpack(nvim_argv)}
- for _, arg in ipairs({...}) do
+ local new_args
+ local env = nil
+ local opts = select(1, ...)
+ if type(opts) == 'table' then
+ if opts.env then
+ local env_tbl = {}
+ for k, v in pairs(opts.env) do
+ assert(type(k) == 'string')
+ assert(type(v) == 'string')
+ env_tbl[k] = v
+ end
+ for _, k in ipairs({
+ 'HOME',
+ 'ASAN_OPTIONS',
+ 'LD_LIBRARY_PATH', 'PATH',
+ 'NVIM_LOG_FILE',
+ }) do
+ env_tbl[k] = os.getenv(k)
+ end
+ env = {}
+ for k, v in pairs(env_tbl) do
+ env[#env + 1] = k .. '=' .. v
+ end
+ end
+ new_args = opts.args or {}
+ else
+ new_args = {...}
+ end
+ for _, arg in ipairs(new_args) do
table.insert(args, arg)
end
- set_session(spawn(args))
+ set_session(spawn(args, nil, env))
end
local function insert(...)
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index a36939b0bd..8eec6ad8bf 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -1,7 +1,12 @@
local helpers = require('test.functional.helpers')(after_each)
+
local Screen = require('test.functional.ui.screen')
-local eval, eq = helpers.eval, helpers.eq
+
+local meths = helpers.meths
local execute = helpers.execute
+local clear = helpers.clear
+local eval = helpers.eval
+local eq = helpers.eq
local function init_session(...)
local args = { helpers.nvim_prog, '-i', 'NONE', '--embed',
@@ -77,4 +82,179 @@ describe('startup defaults', function()
end)
end)
+describe('XDG-based defaults', function()
+ -- Need to be in separate describe() block to not run clear() twice.
+ -- Do not put before_each() here for the same reasons.
+ describe('with too long XDG variables', function()
+ before_each(function()
+ clear({env={
+ XDG_CONFIG_HOME=('/x'):rep(4096),
+ XDG_CONFIG_DIRS=(('/a'):rep(2048)
+ .. ':' .. ('/b'):rep(2048)
+ .. (':/c'):rep(512)),
+ XDG_DATA_HOME=('/X'):rep(4096),
+ XDG_DATA_DIRS=(('/A'):rep(2048)
+ .. ':' .. ('/B'):rep(2048)
+ .. (':/C'):rep(512)),
+ }})
+ end)
+
+ it('are correctly set', function()
+ eq((('/x'):rep(4096) .. '/nvim'
+ .. ',' .. ('/a'):rep(2048) .. '/nvim'
+ .. ',' .. ('/b'):rep(2048) .. '/nvim'
+ .. (',' .. '/c/nvim'):rep(512)
+ .. ',' .. ('/X'):rep(4096) .. '/nvim/site'
+ .. ',' .. ('/A'):rep(2048) .. '/nvim/site'
+ .. ',' .. ('/B'):rep(2048) .. '/nvim/site'
+ .. (',' .. '/C/nvim/site'):rep(512)
+ .. ',' .. eval('$VIMRUNTIME')
+ .. (',' .. '/C/nvim/site/after'):rep(512)
+ .. ',' .. ('/B'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. ('/A'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. ('/X'):rep(4096) .. '/nvim/site/after'
+ .. (',' .. '/c/nvim/after'):rep(512)
+ .. ',' .. ('/b'):rep(2048) .. '/nvim/after'
+ .. ',' .. ('/a'):rep(2048) .. '/nvim/after'
+ .. ',' .. ('/x'):rep(4096) .. '/nvim/after'
+ ), meths.get_option('runtimepath'))
+ meths.command('set runtimepath&')
+ meths.command('set backupdir&')
+ meths.command('set directory&')
+ meths.command('set undodir&')
+ meths.command('set viewdir&')
+ eq((('/x'):rep(4096) .. '/nvim'
+ .. ',' .. ('/a'):rep(2048) .. '/nvim'
+ .. ',' .. ('/b'):rep(2048) .. '/nvim'
+ .. (',' .. '/c/nvim'):rep(512)
+ .. ',' .. ('/X'):rep(4096) .. '/nvim/site'
+ .. ',' .. ('/A'):rep(2048) .. '/nvim/site'
+ .. ',' .. ('/B'):rep(2048) .. '/nvim/site'
+ .. (',' .. '/C/nvim/site'):rep(512)
+ .. ',' .. eval('$VIMRUNTIME')
+ .. (',' .. '/C/nvim/site/after'):rep(512)
+ .. ',' .. ('/B'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. ('/A'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. ('/X'):rep(4096) .. '/nvim/site/after'
+ .. (',' .. '/c/nvim/after'):rep(512)
+ .. ',' .. ('/b'):rep(2048) .. '/nvim/after'
+ .. ',' .. ('/a'):rep(2048) .. '/nvim/after'
+ .. ',' .. ('/x'):rep(4096) .. '/nvim/after'
+ ), meths.get_option('runtimepath'))
+ eq('.,' .. ('/X'):rep(4096) .. '/nvim/backup',
+ meths.get_option('backupdir'))
+ eq(('/X'):rep(4096) .. '/nvim/swap//', meths.get_option('directory'))
+ eq(('/X'):rep(4096) .. '/nvim/undo', meths.get_option('undodir'))
+ eq(('/X'):rep(4096) .. '/nvim/view', meths.get_option('viewdir'))
+ end)
+ end)
+
+ describe('with XDG variables that can be expanded', function()
+ before_each(function()
+ clear({env={
+ XDG_CONFIG_HOME='$XDG_DATA_HOME',
+ XDG_CONFIG_DIRS='$XDG_DATA_DIRS',
+ XDG_DATA_HOME='$XDG_CONFIG_HOME',
+ XDG_DATA_DIRS='$XDG_CONFIG_DIRS',
+ }})
+ end)
+
+ it('are not expanded', function()
+ eq(('$XDG_DATA_HOME/nvim'
+ .. ',$XDG_DATA_DIRS/nvim'
+ .. ',$XDG_CONFIG_HOME/nvim/site'
+ .. ',$XDG_CONFIG_DIRS/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',$XDG_CONFIG_DIRS/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/nvim/site/after'
+ .. ',$XDG_DATA_DIRS/nvim/after'
+ .. ',$XDG_DATA_HOME/nvim/after'
+ ), meths.get_option('runtimepath'))
+ meths.command('set runtimepath&')
+ meths.command('set backupdir&')
+ meths.command('set directory&')
+ meths.command('set undodir&')
+ meths.command('set viewdir&')
+ eq(('$XDG_DATA_HOME/nvim'
+ .. ',$XDG_DATA_DIRS/nvim'
+ .. ',$XDG_CONFIG_HOME/nvim/site'
+ .. ',$XDG_CONFIG_DIRS/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',$XDG_CONFIG_DIRS/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/nvim/site/after'
+ .. ',$XDG_DATA_DIRS/nvim/after'
+ .. ',$XDG_DATA_HOME/nvim/after'
+ ), meths.get_option('runtimepath'))
+ eq('.,$XDG_CONFIG_HOME/nvim/backup', meths.get_option('backupdir'))
+ eq('$XDG_CONFIG_HOME/nvim/swap//', meths.get_option('directory'))
+ eq('$XDG_CONFIG_HOME/nvim/undo', meths.get_option('undodir'))
+ eq('$XDG_CONFIG_HOME/nvim/view', meths.get_option('viewdir'))
+ meths.command('set all&')
+ eq(('$XDG_DATA_HOME/nvim'
+ .. ',$XDG_DATA_DIRS/nvim'
+ .. ',$XDG_CONFIG_HOME/nvim/site'
+ .. ',$XDG_CONFIG_DIRS/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',$XDG_CONFIG_DIRS/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/nvim/site/after'
+ .. ',$XDG_DATA_DIRS/nvim/after'
+ .. ',$XDG_DATA_HOME/nvim/after'
+ ), meths.get_option('runtimepath'))
+ eq('.,$XDG_CONFIG_HOME/nvim/backup', meths.get_option('backupdir'))
+ eq('$XDG_CONFIG_HOME/nvim/swap//', meths.get_option('directory'))
+ eq('$XDG_CONFIG_HOME/nvim/undo', meths.get_option('undodir'))
+ eq('$XDG_CONFIG_HOME/nvim/view', meths.get_option('viewdir'))
+ end)
+ end)
+
+ describe('with commas', function()
+ before_each(function()
+ clear({env={
+ XDG_CONFIG_HOME=', , ,',
+ XDG_CONFIG_DIRS=',-,-,:-,-,-',
+ XDG_DATA_HOME=',=,=,',
+ XDG_DATA_DIRS=',≡,≡,:≡,≡,≡',
+ }})
+ end)
+ it('are escaped properly', function()
+ eq(('\\, \\, \\,/nvim'
+ .. ',\\,-\\,-\\,/nvim'
+ .. ',-\\,-\\,-/nvim'
+ .. ',\\,=\\,=\\,/nvim/site'
+ .. ',\\,≡\\,≡\\,/nvim/site'
+ .. ',≡\\,≡\\,≡/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',≡\\,≡\\,≡/nvim/site/after'
+ .. ',\\,≡\\,≡\\,/nvim/site/after'
+ .. ',\\,=\\,=\\,/nvim/site/after'
+ .. ',-\\,-\\,-/nvim/after'
+ .. ',\\,-\\,-\\,/nvim/after'
+ .. ',\\, \\, \\,/nvim/after'
+ ), meths.get_option('runtimepath'))
+ meths.command('set runtimepath&')
+ meths.command('set backupdir&')
+ meths.command('set directory&')
+ meths.command('set undodir&')
+ meths.command('set viewdir&')
+ eq(('\\, \\, \\,/nvim'
+ .. ',\\,-\\,-\\,/nvim'
+ .. ',-\\,-\\,-/nvim'
+ .. ',\\,=\\,=\\,/nvim/site'
+ .. ',\\,≡\\,≡\\,/nvim/site'
+ .. ',≡\\,≡\\,≡/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',≡\\,≡\\,≡/nvim/site/after'
+ .. ',\\,≡\\,≡\\,/nvim/site/after'
+ .. ',\\,=\\,=\\,/nvim/site/after'
+ .. ',-\\,-\\,-/nvim/after'
+ .. ',\\,-\\,-\\,/nvim/after'
+ .. ',\\, \\, \\,/nvim/after'
+ ), meths.get_option('runtimepath'))
+ eq('.,\\,=\\,=\\,/nvim/backup', meths.get_option('backupdir'))
+ eq('\\,=\\,=\\,/nvim/swap//', meths.get_option('directory'))
+ eq('\\,=\\,=\\,/nvim/undo', meths.get_option('undodir'))
+ eq('\\,=\\,=\\,/nvim/view', meths.get_option('viewdir'))
+ end)
+ end)
+end)
diff --git a/third-party/cmake/BuildLuarocks.cmake b/third-party/cmake/BuildLuarocks.cmake
index effe01b814..daf39ec271 100644
--- a/third-party/cmake/BuildLuarocks.cmake
+++ b/third-party/cmake/BuildLuarocks.cmake
@@ -159,7 +159,7 @@ if(USE_BUNDLED_BUSTED)
add_custom_command(OUTPUT ${HOSTDEPS_LIB_DIR}/luarocks/rocks/nvim-client
COMMAND ${LUAROCKS_BINARY}
- ARGS build https://raw.githubusercontent.com/neovim/lua-client/0.0.1-24/nvim-client-0.0.1-24.rockspec ${LUAROCKS_BUILDARGS}
+ ARGS build https://raw.githubusercontent.com/neovim/lua-client/0.0.1-25/nvim-client-0.0.1-25.rockspec ${LUAROCKS_BUILDARGS}
DEPENDS luv)
add_custom_target(nvim-client
DEPENDS ${HOSTDEPS_LIB_DIR}/luarocks/rocks/nvim-client)