diff options
-rw-r--r-- | .github/ISSUE_TEMPLATE/bug_report.yml | 9 | ||||
-rw-r--r-- | .github/workflows/squash-typos.yml | 32 | ||||
-rw-r--r-- | CONTRIBUTING.md | 8 | ||||
-rw-r--r-- | runtime/doc/help.txt | 18 | ||||
-rw-r--r-- | runtime/doc/lsp.txt | 6 | ||||
-rw-r--r-- | runtime/doc/map.txt | 1 | ||||
-rw-r--r-- | runtime/doc/options.txt | 7 | ||||
-rw-r--r-- | runtime/filetype.vim | 3 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 8 | ||||
-rw-r--r-- | scripts/squash_typos.py | 148 | ||||
-rw-r--r-- | src/nvim/api/buffer.c | 1 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 7 | ||||
-rw-r--r-- | src/nvim/indent.c | 28 | ||||
-rw-r--r-- | src/nvim/option.c | 24 | ||||
-rw-r--r-- | src/nvim/testdir/test_breakindent.vim | 123 | ||||
-rw-r--r-- | src/nvim/testdir/test_filetype.vim | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_usercommands.vim | 42 | ||||
-rw-r--r-- | src/nvim/window.c | 2 | ||||
-rw-r--r-- | test/functional/api/command_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 6 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 128 |
22 files changed, 557 insertions, 50 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 9890636aea..e9384c1982 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -45,16 +45,25 @@ body: description: | Steps to reproduce using `nvim -u NORC` and/or `nvim -u NONE` (please test both). If you are reporting build failures, please list the exact sequence of steps including all CMake flags (if any). + validations: + required: true - type: input attributes: label: "Vim" description: "Does Vim behave differently when called with `vim -u DEFAULTS`? (Please add the specific version, including patch level, of Vim that you tested.)" + validations: + required: true - type: textarea attributes: label: "Expected behavior" description: "A description of the behavior you expected. May optionally include logs, images, or videos." + validations: + required: true + - type: textarea attributes: label: "Actual behavior" + validations: + required: true diff --git a/.github/workflows/squash-typos.yml b/.github/workflows/squash-typos.yml new file mode 100644 index 0000000000..6f5e24a9b6 --- /dev/null +++ b/.github/workflows/squash-typos.yml @@ -0,0 +1,32 @@ +name: Squash Typo Pull Requests + +on: + pull_request: + types: labeled +concurrency: + group: ${{ github.workflow }} +jobs: + build: + if: github.event.label.name == 'typo' + runs-on: ubuntu-latest + + permissions: + contents: write + pull-requests: write + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + ref: master + - uses: actions/setup-python@v2 + + - name: Setup git config + run: | + git config --global user.name 'marvim' + git config --global user.email 'marvim@users.noreply.github.com' + + - run: python scripts/squash_typos.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 366892b522..56b200050f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -89,17 +89,19 @@ the VCS/git logs more valuable. The general structure of a commit message is as - Prefix the commit subject with one of the following _types_: - `build`: all changes related to the build system (involving scripts, configurations or tools) and package dependencies. - `ci`: all changes related to the continuous integration and deployment system - involving scripts, configurations or tools. - - `docs`: all documentation changes. This includes both external documentation intended for end users as well as internal documentation intended for developers. + - `docs`: all documentation changes. This includes both external documentation for users as well as internal documentation for developers. - `feat`: new abilities or functionality. - `fix`: a bug fix. - `perf`: performance improvements. - - `refactor`: modification of the code base which neither adds a feature nor fixes a bug - such as removing redundant code, simplifying the code, renaming variables, etc. + - `refactor`: modification of the code base which neither adds a feature nor fixes a bug - such as removing redundant code, simplifying code, renaming variables, etc. - `revert`: revert previous commits. - `test`: all changes related to tests such as refactoring existing tests or adding new tests. - `vim-patch`: all patches from upstream Vim. The commit messages for patches has [slightly different rules](https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-Vim#pull-requests) as not to interfere with existing scripts. - `chore`: Lastly, if none of the types above fits you may use `chore` as the type. -- Append optional scope to _type_ if possible: `(lsp)`, `(treesitter)` or `(float/windows)`. +- Append optional scope to _type_ such as `(lsp)`, `(treesitter)`, `(float)`, ... + +- The _description_ shouldn't start with a capital letter or end in a period. - Try to keep the first line under 72 characters. diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 8b096ff28b..353058ec03 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -130,6 +130,7 @@ Advanced editing ~ |eval.txt| expression evaluation, conditional commands |fold.txt| hide (fold) ranges of lines |lua.txt| Lua API +|api.txt| Nvim API via RPC, Lua and VimL Special issues ~ |testing.txt| testing Vim and Vim scripts @@ -137,14 +138,15 @@ Special issues ~ |remote.txt| using Vim as a server or client Programming language support ~ -|indent.txt| automatic indenting for C and other languages -|lsp.txt| Language Server Protocol (LSP) -|syntax.txt| syntax highlighting -|filetype.txt| settings done specifically for a type of file -|quickfix.txt| commands for a quick edit-compile-fix cycle -|ft_ada.txt| Ada (the programming language) support -|ft_rust.txt| Filetype plugin for Rust -|ft_sql.txt| about the SQL filetype plugin +|indent.txt| automatic indenting for C and other languages +|lsp.txt| Language Server Protocol (LSP) +|treesitter.txt| tree-sitter library for incremental parsing of buffers +|syntax.txt| syntax highlighting +|filetype.txt| settings done specifically for a type of file +|quickfix.txt| commands for a quick edit-compile-fix cycle +|ft_ada.txt| Ada (the programming language) support +|ft_rust.txt| Filetype plugin for Rust +|ft_sql.txt| about the SQL filetype plugin Language support ~ |digraph.txt| list of available digraphs diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 9624f582a9..7e589c095b 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -1805,6 +1805,9 @@ apply_text_edits({text_edits}, {bufnr}) {text_edits} (table) list of `TextEdit` objects {buf_nr} (number) Buffer id + See also: ~ + https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit + *vim.lsp.util.apply_workspace_edit()* apply_workspace_edit({workspace_edit}) Applies a `WorkspaceEdit` . @@ -1833,6 +1836,9 @@ buf_highlight_references({bufnr}, {references}) {references} List of `DocumentHighlight` objects to highlight + See also: ~ + https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight + buf_lines({bufnr}) *vim.lsp.util.buf_lines()* TODO: Documentation diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 10d503e180..64c0d96aed 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1306,6 +1306,7 @@ completion can be enabled: -complete=highlight highlight groups -complete=history :history suboptions -complete=locale locale names (as output of locale -a) + -complete=lua Lua expression -complete=mapclear buffer argument -complete=mapping mapping name -complete=menu menus diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index f55ec62b77..f0ce15ac0f 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1038,7 +1038,12 @@ A jump table for the options with a short description can be found at |Q_op|. continuation (positive). sbr Display the 'showbreak' value before applying the additional indent. - The default value for min is 20 and shift is 0. + list:{n} Adds an additional indent for lines that match a + numbered or bulleted list (using the + 'formatlistpat' setting). + list:-1 Uses the length of a match with 'formatlistpat' + for indentation. + The default value for min is 20, shift and list is 0. *'browsedir'* *'bsdir'* 'browsedir' 'bsdir' string (default: "last") diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 40d7e8be08..f012c7cb4b 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1519,6 +1519,9 @@ au BufNewFile,BufRead *.sbt setf sbt " Scilab au BufNewFile,BufRead *.sci,*.sce setf scilab +" scdoc +au BufNewFile,BufRead *.scd setf scdoc + " SCSS au BufNewFile,BufRead *.scss setf scss diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 4c3ceaf503..d682fdc17e 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -240,6 +240,7 @@ end --- Applies a list of text edits to a buffer. --@param text_edits (table) list of `TextEdit` objects --@param buf_nr (number) Buffer id +---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit function M.apply_text_edits(text_edits, bufnr) if not next(text_edits) then return end if not api.nvim_buf_is_loaded(bufnr) then @@ -972,7 +973,7 @@ function M.make_floating_popup_options(width, height, opts) row = -get_border_size(opts).height end - if vim.fn.wincol() + width <= api.nvim_get_option('columns') then + if vim.fn.wincol() + width + (opts.offset_x or 0) <= api.nvim_get_option('columns') then anchor = anchor..'W' col = 0 else @@ -1483,6 +1484,7 @@ do --[[ References ]] --- --@param bufnr buffer id --@param references List of `DocumentHighlight` objects to highlight + ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight function M.buf_highlight_references(bufnr, references) validate { bufnr = {bufnr, 'n', true} } for _, reference in ipairs(references) do @@ -1717,14 +1719,14 @@ end function M.trim_empty_lines(lines) local start = 1 for i = 1, #lines do - if #lines[i] > 0 then + if lines[i] ~= nil and #lines[i] > 0 then start = i break end end local finish = 1 for i = #lines, 1, -1 do - if #lines[i] > 0 then + if lines[i] ~= nil and #lines[i] > 0 then finish = i break end diff --git a/scripts/squash_typos.py b/scripts/squash_typos.py new file mode 100644 index 0000000000..e7ee2e24a8 --- /dev/null +++ b/scripts/squash_typos.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python +""" + +This script squashes a PR tagged with the "typo" label into a single, dedicated +"squash PR". + +""" + +import subprocess +import os +import re + + +def get_authors_and_emails_from_pr(): + """ + + For a given PR number, returns all contributing authors and their emails + for that PR. This includes co-authors, meaning that if two authors are + credited for a single commit, which is possible with GitHub, then both will + get credited. + + """ + + # Get a list of all authors involved in the pull request (including co-authors). + authors = subprocess.check_output( + ["gh", "pr", "view", "--json", "commits", "--jq", ".[][].authors.[].name"], + text=True, + ).splitlines() + + # Get a list of emails of the aforementioned authors. + emails = subprocess.check_output( + ["gh", "pr", "view", "--json", "commits", "--jq", ".[][].authors.[].email"], + text=True, + ).splitlines() + + return [(author, mail) for author, mail in zip(authors, emails)] + + +def rebase_onto_pr(pr, squash_branch): + """ + + Add all commits from PR into current branch. This is done by rebasing + current branch onto the PR. + + """ + + # Check out the pull request. + subprocess.call(["gh", "pr", "checkout", pr]) + + pr_branch_name = subprocess.check_output( + ["git", "branch", "--show-current"], text=True + ).strip() + + # Change back to the original branch. + subprocess.call(["git", "switch", squash_branch]) + + # Rebase onto the pull request, aka include the commits in the pull + # request in the current branch. + subprocess.call(["git", "rebase", pr_branch_name]) + + +def squash_all_commits(): + """ + + Squash all commits into a single commit. Credit all authors by name and + email. + + """ + + authors_and_emails = get_authors_and_emails_from_pr() + subprocess.call(["git", "reset", "--soft", f"{os.environ['GITHUB_BASE_REF']}"]) + + authors_and_emails = sorted(set(authors_and_emails)) + commit_message_coauthors = "\n" + "\n".join( + [f"Co-authored-by: {i[0]} <{i[1]}>" for i in authors_and_emails] + ) + subprocess.call( + ["git", "commit", "-m", "chore: typo fixes", "-m", commit_message_coauthors] + ) + + +def force_push(branch): + gh_actor = os.environ["GITHUB_ACTOR"] + gh_token = os.environ["GITHUB_TOKEN"] + gh_repo = os.environ["GITHUB_REPOSITORY"] + subprocess.call( + [ + "git", + "push", + "--force", + f"https://{gh_actor}:{gh_token}@github.com/{gh_repo}", + branch, + ] + ) + + +def main(): + squash_branch = "marvim/squash-typos" + all_pr_urls = "" + + pr_number = re.sub(r"\D", "", os.environ["GITHUB_REF"]) + + show_ref_output = subprocess.check_output(["git", "show-ref"], text=True).strip() + + if squash_branch in show_ref_output: + subprocess.call( + ["git", "checkout", "-b", squash_branch, f"origin/{squash_branch}"] + ) + squash_branch_exists = True + + all_pr_urls += subprocess.check_output( + ["gh", "pr", "view", "--json", "body", "--jq", ".body"], text=True + ) + else: + subprocess.call(["git", "checkout", "-b", squash_branch]) + squash_branch_exists = False + + all_pr_urls += subprocess.check_output( + ["gh", "pr", "view", pr_number, "--json", "url", "--jq", ".url"], text=True + ).strip() + + rebase_onto_pr(pr_number, squash_branch) + force_push(squash_branch) + + subprocess.call(["gh", "pr", "close", pr_number]) + + squash_all_commits() + force_push(squash_branch) + + if not squash_branch_exists: + subprocess.call( + [ + "gh", + "pr", + "create", + "--fill", + "--head", + squash_branch, + "--title", + "Dedicated PR for all typo fixes.", + ] + ) + + subprocess.call(["gh", "pr", "edit", "--add-label", "typo", "--body", all_pr_urls]) + + +if __name__ == "__main__": + main() diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 77cff0cb4f..878ffdf06f 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1486,7 +1486,6 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { - api_set_error(err, kErrorTypeValidation, "Invalid buffer id"); return 0; } diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index ec6d5a3955..b03d69a04c 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1395,6 +1395,7 @@ struct window_S { int w_briopt_min; // minimum width for breakindent int w_briopt_shift; // additional shift for breakindent bool w_briopt_sbr; // sbr in 'briopt' + int w_briopt_list; // additional indent for lists // transform a pointer to a "onebuf" option into a "allbuf" option #define GLOBAL_WO(p) ((char *)p + sizeof(winopt_T)) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index d10ecf5c7f..3afcd9ec5a 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5514,6 +5514,9 @@ invalid_count: return OK; } +static char e_complete_used_without_nargs[] = N_( + "E1208: -complete used without -nargs"); + /* * ":command ..." */ @@ -5565,10 +5568,10 @@ static void ex_command(exarg_T *eap) uc_list(name, end - name); } else if (!ASCII_ISUPPER(*name)) { EMSG(_("E183: User defined commands must start with an uppercase letter")); - return; } else if (name_len <= 4 && STRNCMP(name, "Next", name_len) == 0) { EMSG(_("E841: Reserved name, cannot be used for user defined command")); - return; + } else if (compl > 0 && (argt & EX_EXTRA) == 0) { + EMSG(_(e_complete_used_without_nargs)); } else { uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg, addr_type_arg, eap->forceit); diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 6364ca2ff4..a6df0e97e6 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -433,7 +433,7 @@ int get_number_indent(linenr_T lnum) // Return appropriate space number for breakindent, taking influencing // parameters into account. Window must be specified, since it is not // necessarily always the current one. -int get_breakindent_win(win_T *wp, const char_u *line) +int get_breakindent_win(win_T *wp, char_u *line) FUNC_ATTR_NONNULL_ALL { static int prev_indent = 0; // Cached indent value. @@ -463,12 +463,32 @@ int get_breakindent_win(win_T *wp, const char_u *line) } bri = prev_indent + wp->w_briopt_shift; + // Add offset for number column, if 'n' is in 'cpoptions' + bri += win_col_off2(wp); + + // add additional indent for numbered lists + if (wp->w_briopt_list != 0) { + regmatch_T regmatch = { + .regprog = vim_regcomp(curbuf->b_p_flp, + RE_MAGIC + RE_STRING + RE_AUTO + RE_STRICT), + }; + + if (regmatch.regprog != NULL) { + if (vim_regexec(®match, line, 0)) { + if (wp->w_briopt_list > 0) { + bri += wp->w_briopt_list; + } else { + bri = (int)(*regmatch.endp - *regmatch.startp); + } + } + vim_regfree(regmatch.regprog); + } + } + // indent minus the length of the showbreak string if (wp->w_briopt_sbr) { - bri -= vim_strsize(p_sbr); + bri -= vim_strsize(get_showbreak_value(wp)); } - // Add offset for number column, if 'n' is in 'cpoptions' - bri += win_col_off2(wp); // never indent past left window margin if (bri < 0) { diff --git a/src/nvim/option.c b/src/nvim/option.c index a4b33118cf..0595776f79 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1408,22 +1408,19 @@ int do_set( *errbuf = NUL; i = getdigits_int(&arg, true, 0); if (i & 1) { - STRCAT(errbuf, "b,"); + STRLCAT(errbuf, "b,", sizeof(errbuf)); } if (i & 2) { - STRCAT(errbuf, "s,"); + STRLCAT(errbuf, "s,", sizeof(errbuf)); } if (i & 4) { - STRCAT(errbuf, "h,l,"); + STRLCAT(errbuf, "h,l,", sizeof(errbuf)); } if (i & 8) { - STRCAT(errbuf, "<,>,"); + STRLCAT(errbuf, "<,>,", sizeof(errbuf)); } if (i & 16) { - STRCAT(errbuf, "[,],"); - } - if (*errbuf != NUL) { // remove trailing , - errbuf[STRLEN(errbuf) - 1] = NUL; + STRLCAT(errbuf, "[,],", sizeof(errbuf)); } save_arg = arg; arg = errbuf; @@ -7429,6 +7426,7 @@ static bool briopt_check(win_T *wp) int bri_shift = 0; int bri_min = 20; bool bri_sbr = false; + int bri_list = 0; char_u *p = wp->w_p_briopt; while (*p != NUL) @@ -7448,6 +7446,9 @@ static bool briopt_check(win_T *wp) { p += 3; bri_sbr = true; + } else if (STRNCMP(p, "list:", 5) == 0) { + p += 5; + bri_list = (int)getdigits(&p, false, 0); } if (*p != ',' && *p != NUL) { return false; @@ -7460,6 +7461,7 @@ static bool briopt_check(win_T *wp) wp->w_briopt_shift = bri_shift; wp->w_briopt_min = bri_min; wp->w_briopt_sbr = bri_sbr; + wp->w_briopt_list = bri_list; return true; } @@ -7672,6 +7674,12 @@ int win_signcol_configured(win_T *wp, int *is_fixed) return ret; } +// Get the local or global value of 'showbreak'. +char_u *get_showbreak_value(win_T *win FUNC_ATTR_UNUSED) +{ + return p_sbr; +} + /// Get window or buffer local options dict_T *get_winbuf_options(const int bufopt) FUNC_ATTR_WARN_UNUSED_RESULT diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim index ff5029b889..5542746a04 100644 --- a/src/nvim/testdir/test_breakindent.vim +++ b/src/nvim/testdir/test_breakindent.vim @@ -16,6 +16,10 @@ func s:screen_lines(lnum, width) abort return ScreenLines([a:lnum, a:lnum + 2], a:width) endfunc +func s:screen_lines2(lnums, lnume, width) abort + return ScreenLines([a:lnums, a:lnume], a:width) +endfunc + func! s:compare_lines(expect, actual) call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) endfunc @@ -745,4 +749,123 @@ func Test_breakindent20_cpo_n_nextpage() call s:close_windows('set breakindent& briopt& cpo& number&') endfunc +func Test_breakindent20_list() + call s:test_windows('setl breakindent breakindentopt= linebreak') + " default: + call setline(1, [' 1. Congress shall make no law', + \ ' 2.) Congress shall make no law', + \ ' 3.] Congress shall make no law']) + norm! 1gg + redraw! + let lines = s:screen_lines2(1, 6, 20) + let expect = [ + \ " 1. Congress ", + \ "shall make no law ", + \ " 2.) Congress ", + \ "shall make no law ", + \ " 3.] Congress ", + \ "shall make no law ", + \ ] + call s:compare_lines(expect, lines) + " set mininum indent + setl briopt=min:5 + redraw! + let lines = s:screen_lines2(1, 6, 20) + let expect = [ + \ " 1. Congress ", + \ " shall make no law ", + \ " 2.) Congress ", + \ " shall make no law ", + \ " 3.] Congress ", + \ " shall make no law ", + \ ] + call s:compare_lines(expect, lines) + " set additional handing indent + setl briopt+=list:4 + redraw! + let expect = [ + \ " 1. Congress ", + \ " shall make no ", + \ " law ", + \ " 2.) Congress ", + \ " shall make no ", + \ " law ", + \ " 3.] Congress ", + \ " shall make no ", + \ " law ", + \ ] + let lines = s:screen_lines2(1, 9, 20) + call s:compare_lines(expect, lines) + + " reset linebreak option + " Note: it indents by one additional + " space, because of the leading space. + setl linebreak&vim list listchars=eol:$,space:_ + redraw! + let expect = [ + \ "__1.__Congress_shall", + \ " _make_no_law$ ", + \ "__2.)_Congress_shall", + \ " _make_no_law$ ", + \ "__3.]_Congress_shall", + \ " _make_no_law$ ", + \ ] + let lines = s:screen_lines2(1, 6, 20) + call s:compare_lines(expect, lines) + + " check formatlistpat indent + setl briopt=min:5,list:-1 + setl linebreak list&vim listchars&vim + let &l:flp = '^\s*\d\+\.\?[\]:)}\t ]\s*' + redraw! + let expect = [ + \ " 1. Congress ", + \ " shall make no ", + \ " law ", + \ " 2.) Congress ", + \ " shall make no ", + \ " law ", + \ " 3.] Congress ", + \ " shall make no ", + \ " law ", + \ ] + let lines = s:screen_lines2(1, 9, 20) + call s:compare_lines(expect, lines) + " check formatlistpat indent with different list levels + let &l:flp = '^\s*\*\+\s\+' + redraw! + %delete _ + call setline(1, ['* Congress shall make no law', + \ '*** Congress shall make no law', + \ '**** Congress shall make no law']) + norm! 1gg + let expect = [ + \ "* Congress shall ", + \ " make no law ", + \ "*** Congress shall ", + \ " make no law ", + \ "**** Congress shall ", + \ " make no law ", + \ ] + let lines = s:screen_lines2(1, 6, 20) + call s:compare_lines(expect, lines) + + " check formatlistpat indent with different list level + " showbreak and sbr + setl briopt=min:5,sbr,list:-1,shift:2 + setl showbreak=> + redraw! + let expect = [ + \ "* Congress shall ", + \ "> make no law ", + \ "*** Congress shall ", + \ "> make no law ", + \ "**** Congress shall ", + \ "> make no law ", + \ ] + let lines = s:screen_lines2(1, 6, 20) + call s:compare_lines(expect, lines) + call s:close_windows('set breakindent& briopt& linebreak& list& listchars& showbreak&') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 18b810e63f..4ab58cd084 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -431,6 +431,7 @@ let s:filename_checks = { \ 'scilab': ['file.sci', 'file.sce'], \ 'screen': ['.screenrc', 'screenrc'], \ 'sexplib': ['file.sexp'], + \ 'scdoc': ['file.scd'], \ 'scss': ['file.scss'], \ 'sd': ['file.sd'], \ 'sdc': ['file.sdc'], diff --git a/src/nvim/testdir/test_usercommands.vim b/src/nvim/testdir/test_usercommands.vim index 4621207d19..29e578ac6d 100644 --- a/src/nvim/testdir/test_usercommands.vim +++ b/src/nvim/testdir/test_usercommands.vim @@ -238,6 +238,8 @@ func Test_CmdErrors() call assert_fails('com! -complete=custom DoCmd :', 'E467:') call assert_fails('com! -complete=customlist DoCmd :', 'E467:') call assert_fails('com! -complete=behave,CustomComplete DoCmd :', 'E468:') + call assert_fails('com! -complete=file DoCmd :', 'E1208:') + call assert_fails('com! -nargs=0 -complete=file DoCmd :', 'E1208:') call assert_fails('com! -nargs=x DoCmd :', 'E176:') call assert_fails('com! -count=1 -count=2 DoCmd :', 'E177:') call assert_fails('com! -count=x DoCmd :', 'E178:') @@ -306,27 +308,33 @@ func Test_CmdCompletion() call feedkeys(":com DoC\<C-A>\<C-B>\"\<CR>", 'tx') call assert_equal('"com DoC', @:) - com! -complete=behave DoCmd : + com! -nargs=1 -complete=behave DoCmd : call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx') call assert_equal('"DoCmd mswin xterm', @:) - " This does not work. Why? - "call feedkeys(":DoCmd x\<C-A>\<C-B>\"\<CR>", 'tx') - "call assert_equal('"DoCmd xterm', @:) - - com! -complete=custom,CustomComplete DoCmd : + com! -nargs=* -complete=custom,CustomComplete DoCmd : call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx') call assert_equal('"DoCmd January February Mars', @:) - com! -complete=customlist,CustomCompleteList DoCmd : + com! -nargs=? -complete=customlist,CustomCompleteList DoCmd : call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx') call assert_equal('"DoCmd Monday Tuesday Wednesday', @:) - com! -complete=custom,CustomCompleteList DoCmd : + com! -nargs=+ -complete=custom,CustomCompleteList DoCmd : call assert_fails("call feedkeys(':DoCmd \<C-D>', 'tx')", 'E730:') - com! -complete=customlist,CustomComp DoCmd : + com! -nargs=+ -complete=customlist,CustomComp DoCmd : call assert_fails("call feedkeys(':DoCmd \<C-D>', 'tx')", 'E117:') + + " custom completion without a function + com! -nargs=? -complete=custom, DoCmd + call assert_beeps("call feedkeys(':DoCmd \t', 'tx')") + + " custom completion failure with the wrong function + com! -nargs=? -complete=custom,min DoCmd + call assert_fails("call feedkeys(':DoCmd \t', 'tx')", 'E118:') + + delcom DoCmd endfunc func CallExecute(A, L, P) @@ -459,21 +467,21 @@ func Test_command_list() \ execute('command DoCmd')) " Test with various -complete= argument values (non-exhaustive list) - command! -complete=arglist DoCmd : + command! -nargs=1 -complete=arglist DoCmd : call assert_equal("\n Name Args Address Complete Definition" - \ .. "\n DoCmd 0 arglist :", + \ .. "\n DoCmd 1 arglist :", \ execute('command DoCmd')) - command! -complete=augroup DoCmd : + command! -nargs=* -complete=augroup DoCmd : call assert_equal("\n Name Args Address Complete Definition" - \ .. "\n DoCmd 0 augroup :", + \ .. "\n DoCmd * augroup :", \ execute('command DoCmd')) - command! -complete=custom,CustomComplete DoCmd : + command! -nargs=? -complete=custom,CustomComplete DoCmd : call assert_equal("\n Name Args Address Complete Definition" - \ .. "\n DoCmd 0 custom :", + \ .. "\n DoCmd ? custom :", \ execute('command DoCmd')) - command! -complete=customlist,CustomComplete DoCmd : + command! -nargs=+ -complete=customlist,CustomComplete DoCmd : call assert_equal("\n Name Args Address Complete Definition" - \ .. "\n DoCmd 0 customlist :", + \ .. "\n DoCmd + customlist :", \ execute('command DoCmd')) " Test with various -narg= argument values. diff --git a/src/nvim/window.c b/src/nvim/window.c index be2e1d282f..fe6ab5af55 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -677,7 +677,7 @@ void win_set_minimal_style(win_T *wp) } // signcolumn: use 'auto' - if (wp->w_p_scl[0] != 'a') { + if (wp->w_p_scl[0] != 'a' || STRLEN(wp->w_p_scl) >= 8) { xfree(wp->w_p_scl); wp->w_p_scl = (char_u *)xstrdup("auto"); } diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua index e6a9e11fd9..37331d11c7 100644 --- a/test/functional/api/command_spec.lua +++ b/test/functional/api/command_spec.lua @@ -53,7 +53,7 @@ describe('nvim_get_commands', function() end) it('gets various command attributes', function() - local cmd0 = { addr='arguments', bang=false, bar=false, complete='dir', complete_arg=NIL, count='10', definition='pwd <args>', name='TestCmd', nargs='0', range='10', register=false, script_id=0, } + local cmd0 = { addr='arguments', bang=false, bar=false, complete='dir', complete_arg=NIL, count='10', definition='pwd <args>', name='TestCmd', nargs='1', range='10', register=false, script_id=0, } local cmd1 = { addr=NIL, bang=false, bar=false, complete='custom', complete_arg='ListUsers', count=NIL, definition='!finger <args>', name='Finger', nargs='+', range=NIL, register=false, script_id=1, } local cmd2 = { addr=NIL, bang=true, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R2_foo(<q-args>)', name='Cmd2', nargs='*', range=NIL, register=false, script_id=2, } local cmd3 = { addr=NIL, bang=false, bar=true, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R3_ohyeah()', name='Cmd3', nargs='0', range=NIL, register=false, script_id=3, } @@ -62,7 +62,7 @@ describe('nvim_get_commands', function() command -complete=custom,ListUsers -nargs=+ Finger !finger <args> ]]) eq({Finger=cmd1}, meths.get_commands({builtin=false})) - command('command -complete=dir -addr=arguments -count=10 TestCmd pwd <args>') + command('command -nargs=1 -complete=dir -addr=arguments -count=10 TestCmd pwd <args>') eq({Finger=cmd1, TestCmd=cmd0}, meths.get_commands({builtin=false})) source([[ diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index b77a285379..863176bfa9 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -1954,6 +1954,12 @@ describe('LSP', function() end) end) + describe('lsp.util.trim.trim_empty_lines', function() + it('properly trims empty lines', function() + eq({{"foo", "bar"}}, exec_lua[[ return vim.lsp.util.trim_empty_lines({{ "foo", "bar" }, nil}) ]]) + end) + end) + describe('lsp.util.get_effective_tabstop', function() local function test_tabstop(tabsize, softtabstop) exec_lua(string.format([[ diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 61ed0a65b0..51ee922d23 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -620,6 +620,134 @@ describe('float window', function() end end) + it("would not break 'minimal' style with signcolumn=auto:[min]-[max]", function() + command('set number') + command('set signcolumn=auto:1-3') + command('set colorcolumn=1') + command('set cursorline') + command('set foldcolumn=1') + command('hi NormalFloat guibg=#333333') + feed('ix<cr>y<cr><esc>gg') + local win = meths.open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10, style='minimal'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + {19: }{20: 1 }{22:^x}{21: }| + {19: }{14: 2 }{22:y} | + {19: }{14: 3 }{22: } | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + {15:x }| + {15:y }| + {15: }| + {15: }| + ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}} + else + screen:expect{grid=[[ + {19: }{20: 1 }{22:^x}{21: }| + {19: }{14: 2 }{22:y} | + {19: }{14: 3 }{22: } {15:x } | + {0:~ }{15:y }{0: }| + {0:~ }{15: }{0: }| + {0:~ }{15: }{0: }| + | + ]]} + end + + command('sign define piet1 text=𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄ texthl=Search') + command('sign place 1 line=1 name=piet1 buffer=1') + -- signcolumn=auto:1-3 still works if there actually are signs + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + {19: }{17:𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄}{20: 1 }{22:^x}{21: }| + {19: }{14: 2 }{22:y} | + {19: }{14: 3 }{22: } | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + {17:𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄}{15:x }| + {19: }{15:y }| + {19: }{15: }| + {15: }| + ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}} + + else + screen:expect([[ + {19: }{17:𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄}{20: 1 }{22:^x}{21: }| + {19: }{14: 2 }{22:y} | + {19: }{14: 3 }{22: } {17:𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄}{15:x } | + {0:~ }{19: }{15:y }{0: }| + {0:~ }{19: }{15: }{0: }| + {0:~ }{15: }{0: }| + | + ]]) + end + command('sign unplace 1 buffer=1') + + local buf = meths.create_buf(false, true) + meths.win_set_buf(win, buf) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + {19: }{20: 1 }{22:^x}{21: }| + {19: }{14: 2 }{22:y} | + {19: }{14: 3 }{22: } | + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + {15: }| + {15: }| + {15: }| + {15: }| + ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}} + else + screen:expect([[ + {19: }{20: 1 }{22:^x}{21: }| + {19: }{14: 2 }{22:y} | + {19: }{14: 3 }{22: } {15: } | + {0:~ }{15: }{0: }| + {0:~ }{15: }{0: }| + {0:~ }{15: }{0: }| + | + ]]) + end + end) + it('can have border', function() local buf = meths.create_buf(false, false) meths.buf_set_lines(buf, 0, -1, true, {' halloj! ', |