diff --git a/nsis/gvim.nsi b/nsis/gvim.nsi index 649c6950dd..c32a8868f6 100644 --- a/nsis/gvim.nsi +++ b/nsis/gvim.nsi @@ -347,6 +347,9 @@ Section "$(str_section_exe)" id_section_exe File /oname=gvim.exe ${VIMSRC}\gvim_ole.exe !if /FileExists "${VIMSRC}\vim${BIT}.dll" File ${VIMSRC}\vim${BIT}.dll +!endif +!if /FileExists "${VIMRT}\libsodium.dll" + File ${VIMRT}\libsodium.dll !endif File /oname=install.exe ${VIMSRC}\installw32.exe File /oname=uninstall.exe ${VIMSRC}\uninstallw32.exe diff --git a/runtime/autoload/dist/script.vim b/runtime/autoload/dist/script.vim new file mode 100644 index 0000000000..b926f31566 --- /dev/null +++ b/runtime/autoload/dist/script.vim @@ -0,0 +1,426 @@ +vim9script + +# Vim function for detecting a filetype from the file contents. +# Invoked from "scripts.vim" in 'runtimepath' +# +# Maintainer: Bram Moolenaar +# Last Change: 2022 Feb 13 + +export def DetectFiletype() + var line1 = getline(1) + if line1[0] == '#' && line1[1] == '!' + # File that starts with "#!". + DetectFromHashBang(line1) + else + # File does not start with "#!". + DetectFromText(line1) + endif +enddef + +# Called for a script that has "#!" in the first line. +def DetectFromHashBang(firstline: string) + var line1 = firstline + + # Check for a line like "#!/usr/bin/env {options} bash". Turn it into + # "#!/usr/bin/bash" to make matching easier. + # Recognize only a few {options} that are commonly used. + if line1 =~ '^#!\s*\S*\' + name = substitute(line1, '^#!.*\\s\+\(\i\+\).*', '\1', '') + elseif line1 =~ '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)' + name = substitute(line1, '^#!\s*\([^/\\ ]*\>\).*', '\1', '') + else + name = substitute(line1, '^#!\s*\S*[/\\]\(\i\+\).*', '\1', '') + endif + + # tcl scripts may have #!/bin/sh in the first line and "exec wish" in the + # third line. Suggested by Steven Atkinson. + if getline(3) =~ '^exec wish' + name = 'wish' + endif + + # Bourne-like shell scripts: bash bash2 ksh ksh93 sh + if name =~ '^\(bash\d*\|\|ksh\d*\|sh\)\>' + call dist#ft#SetFileTypeSH(line1) + + # csh scripts + elseif name =~ '^csh\>' + if exists("g:filetype_csh") + call dist#ft#SetFileTypeShell(g:filetype_csh) + else + call dist#ft#SetFileTypeShell("csh") + endif + + # tcsh scripts + elseif name =~ '^tcsh\>' + call dist#ft#SetFileTypeShell("tcsh") + + # Z shell scripts + elseif name =~ '^zsh\>' + set ft=zsh + + # TCL scripts + elseif name =~ '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>' + set ft=tcl + + # Expect scripts + elseif name =~ '^expect\>' + set ft=expect + + # Gnuplot scripts + elseif name =~ '^gnuplot\>' + set ft=gnuplot + + # Makefiles + elseif name =~ 'make\>' + set ft=make + + # Pike + elseif name =~ '^pike\%(\>\|[0-9]\)' + set ft=pike + + # Lua + elseif name =~ 'lua' + set ft=lua + + # Perl + elseif name =~ 'perl' + set ft=perl + + # PHP + elseif name =~ 'php' + set ft=php + + # Python + elseif name =~ 'python' + set ft=python + + # Groovy + elseif name =~ '^groovy\>' + set ft=groovy + + # Raku + elseif name =~ 'raku' + set ft=raku + + # Ruby + elseif name =~ 'ruby' + set ft=ruby + + # JavaScript + elseif name =~ 'node\(js\)\=\>\|js\>' || name =~ 'rhino\>' + set ft=javascript + + # BC calculator + elseif name =~ '^bc\>' + set ft=bc + + # sed + elseif name =~ 'sed\>' + set ft=sed + + # OCaml-scripts + elseif name =~ 'ocaml' + set ft=ocaml + + # Awk scripts; also finds "gawk" + elseif name =~ 'awk\>' + set ft=awk + + # Website MetaLanguage + elseif name =~ 'wml' + set ft=wml + + # Scheme scripts + elseif name =~ 'scheme' + set ft=scheme + + # CFEngine scripts + elseif name =~ 'cfengine' + set ft=cfengine + + # Erlang scripts + elseif name =~ 'escript' + set ft=erlang + + # Haskell + elseif name =~ 'haskell' + set ft=haskell + + # Scala + elseif name =~ 'scala\>' + set ft=scala + + # Clojure + elseif name =~ 'clojure' + set ft=clojure + + # Free Pascal + elseif name =~ 'instantfpc\>' + set ft=pascal + + # Fennel + elseif name =~ 'fennel\>' + set ft=fennel + + # MikroTik RouterOS script + elseif name =~ 'rsc\>' + set ft=routeros + + # Fish shell + elseif name =~ 'fish\>' + set ft=fish + + # Gforth + elseif name =~ 'gforth\>' + set ft=forth + + endif +enddef + + +# Called for a script that does not have "#!" in the first line. +def DetectFromText(line1: string) + var line2 = getline(2) + var line3 = getline(3) + var line4 = getline(4) + var line5 = getline(5) + + # Bourne-like shell scripts: sh ksh bash bash2 + if line1 =~ '^:$' + call dist#ft#SetFileTypeSH(line1) + + # Z shell scripts + elseif line1 =~ '^#compdef\>' + || line1 =~ '^#autoload\>' + || "\n" .. line1 .. "\n" .. line2 .. "\n" .. line3 .. + "\n" .. line4 .. "\n" .. line5 + =~ '\n\s*emulate\s\+\%(-[LR]\s\+\)\=[ckz]\=sh\>' + set ft=zsh + + # ELM Mail files + elseif line1 =~ '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$' + set ft=mail + + # Mason + elseif line1 =~ '^<[%&].*>' + set ft=mason + + # Vim scripts (must have '" vim' as the first line to trigger this) + elseif line1 =~ '^" *[vV]im$' + set ft=vim + + # libcxx and libstdc++ standard library headers like "iostream" do not have + # an extension, recognize the Emacs file mode. + elseif line1 =~? '-\*-.*C++.*-\*-' + set ft=cpp + + # MOO + elseif line1 =~ '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$' + set ft=moo + + # Diff file: + # - "diff" in first line (context diff) + # - "Only in " in first line + # - "--- " in first line and "+++ " in second line (unified diff). + # - "*** " in first line and "--- " in second line (context diff). + # - "# It was generated by makepatch " in the second line (makepatch diff). + # - "Index: " in the first line (CVS file) + # - "=== ", line of "=", "---", "+++ " (SVK diff) + # - "=== ", "--- ", "+++ " (bzr diff, common case) + # - "=== (removed|added|renamed|modified)" (bzr diff, alternative) + # - "# HG changeset patch" in first line (Mercurial export format) + elseif line1 =~ '^\(diff\>\|Only in \|\d\+\(,\d\+\)\=[cda]\d\+\>\|# It was generated by makepatch \|Index:\s\+\f\+\r\=$\|===== \f\+ \d\+\.\d\+ vs edited\|==== //\f\+#\d\+\|# HG changeset patch\)' + || (line1 =~ '^--- ' && line2 =~ '^+++ ') + || (line1 =~ '^\* looking for ' && line2 =~ '^\* comparing to ') + || (line1 =~ '^\*\*\* ' && line2 =~ '^--- ') + || (line1 =~ '^=== ' && ((line2 =~ '^=\{66\}' && line3 =~ '^--- ' && line4 =~ '^+++') || (line2 =~ '^--- ' && line3 =~ '^+++ '))) + || (line1 =~ '^=== \(removed\|added\|renamed\|modified\)') + set ft=diff + + # PostScript Files (must have %!PS as the first line, like a2ps output) + elseif line1 =~ '^%![ \t]*PS' + set ft=postscr + + # M4 scripts: Guess there is a line that starts with "dnl". + elseif line1 =~ '^\s*dnl\>' + || line2 =~ '^\s*dnl\>' + || line3 =~ '^\s*dnl\>' + || line4 =~ '^\s*dnl\>' + || line5 =~ '^\s*dnl\>' + set ft=m4 + + # AmigaDos scripts + elseif $TERM == "amiga" && (line1 =~ "^;" || line1 =~? '^\.bra') + set ft=amiga + + # SiCAD scripts (must have procn or procd as the first line to trigger this) + elseif line1 =~? '^ *proc[nd] *$' + set ft=sicad + + # Purify log files start with "**** Purify" + elseif line1 =~ '^\*\*\*\* Purify' + set ft=purifylog + + # XML + elseif line1 =~ '' + set ft=xml + + # XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN") + elseif line1 =~ '\' + set ft=html + + # PDF + elseif line1 =~ '^%PDF-' + set ft=pdf + + # XXD output + elseif line1 =~ '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} ' + set ft=xxd + + # RCS/CVS log output + elseif line1 =~ '^RCS file:' || line2 =~ '^RCS file:' + set ft=rcslog + + # CVS commit + elseif line2 =~ '^CVS:' || getline("$") =~ '^CVS: ' + set ft=cvs + + # Prescribe + elseif line1 =~ '^!R!' + set ft=prescribe + + # Send-pr + elseif line1 =~ '^SEND-PR:' + set ft=sendpr + + # SNNS files + elseif line1 =~ '^SNNS network definition file' + set ft=snnsnet + elseif line1 =~ '^SNNS pattern definition file' + set ft=snnspat + elseif line1 =~ '^SNNS result file' + set ft=snnsres + + # Virata + elseif line1 =~ '^%.\{-}[Vv]irata' + || line2 =~ '^%.\{-}[Vv]irata' + || line3 =~ '^%.\{-}[Vv]irata' + || line4 =~ '^%.\{-}[Vv]irata' + || line5 =~ '^%.\{-}[Vv]irata' + set ft=virata + + # Strace + elseif line1 =~ '[0-9:.]* *execve(' || line1 =~ '^__libc_start_main' + set ft=strace + + # VSE JCL + elseif line1 =~ '^\* $$ JOB\>' || line1 =~ '^// *JOB\>' + set ft=vsejcl + + # TAK and SINDA + elseif line4 =~ 'K & K Associates' || line2 =~ 'TAK 2000' + set ft=takout + elseif line3 =~ 'S Y S T E M S I M P R O V E D ' + set ft=sindaout + elseif getline(6) =~ 'Run Date: ' + set ft=takcmp + elseif getline(9) =~ 'Node File 1' + set ft=sindacmp + + # DNS zone files + elseif line1 .. line2 .. line3 .. line4 =~ '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA' + set ft=bindzone + + # BAAN + elseif line1 =~ '|\*\{1,80}' && line2 =~ 'VRC ' + || line2 =~ '|\*\{1,80}' && line3 =~ 'VRC ' + set ft=baan + + # Valgrind + elseif line1 =~ '^==\d\+== valgrind' || line3 =~ '^==\d\+== Using valgrind' + set ft=valgrind + + # Go docs + elseif line1 =~ '^PACKAGE DOCUMENTATION$' + set ft=godoc + + # Renderman Interface Bytestream + elseif line1 =~ '^##RenderMan' + set ft=rib + + # Scheme scripts + elseif line1 =~ 'exec\s\+\S*scheme' || line2 =~ 'exec\s\+\S*scheme' + set ft=scheme + + # Git output + elseif line1 =~ '^\(commit\|tree\|object\) \x\{40,\}\>\|^tag \S\+$' + set ft=git + + # Gprof (gnu profiler) + elseif line1 == 'Flat profile:' + && line2 == '' + && line3 =~ '^Each sample counts as .* seconds.$' + set ft=gprof + + # Erlang terms + # (See also: http://www.gnu.org/software/emacs/manual/html_node/emacs/Choosing-Modes.html#Choosing-Modes) + elseif line1 =~? '-\*-.*erlang.*-\*-' + set ft=erlang + + # YAML + elseif line1 =~ '^%YAML' + set ft=yaml + + # MikroTik RouterOS script + elseif line1 =~ '^#.*by RouterOS.*$' + set ft=routeros + + # Sed scripts + # #ncomment is allowed but most likely a false positive so require a space + # before any trailing comment text + elseif line1 =~ '^#n\%($\|\s\)' + set ft=sed + + else + var lnum = 1 + while getline(lnum) =~ "^? " && lnum < line("$") + lnum += 1 + endwhile + if getline(lnum) =~ '^Index:\s\+\f\+$' + # CVS diff + set ft=diff + + # locale input files: Formal Definitions of Cultural Conventions + # filename must be like en_US, fr_FR@euro or en_US.UTF-8 + elseif expand("%") =~ '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_' + lnum = 1 + while lnum < 100 && lnum < line("$") + if getline(lnum) =~ '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$' + setf fdcc + break + endif + lnum += 1 + endwhile + endif + endif +enddef diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 37126ad955..fe1f12cb06 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1547,6 +1547,9 @@ au BufNewFile,BufRead *.r,*.R call dist#ft#FTr() " Remind au BufNewFile,BufRead .reminders,*.remind,*.rem setf remind +" ReScript +au BufNewFile,BufRead *.res,*.resi setf rescript + " Resolv.conf au BufNewFile,BufRead resolv.conf setf resolv diff --git a/runtime/scripts.vim b/runtime/scripts.vim index dd47f65ba0..9f9c0655c7 100644 --- a/runtime/scripts.vim +++ b/runtime/scripts.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types in scripts " " Maintainer: Bram Moolenaar -" Last change: 2021 Jan 22 +" Last change: 2022 Feb 13 " This file is called by an autocommand for every file that has just been " loaded into a buffer. It checks if the type of file can be recognized by @@ -12,7 +12,7 @@ " =~? instead. Do not use =~ anywhere. -" Only do the rest when the FileType autocommand has not been triggered yet. +" Bail out when a FileType autocommand has already set the filetype. if did_filetype() finish endif @@ -26,422 +26,5 @@ if exists("myscriptsfile") && filereadable(expand(myscriptsfile)) endif endif -" Line continuation is used here, remove 'C' from 'cpoptions' -let s:cpo_save = &cpo -set cpo&vim - -let s:line1 = getline(1) - -if s:line1 =~# "^#!" - " A script that starts with "#!". - - " Check for a line like "#!/usr/bin/env {options} bash". Turn it into - " "#!/usr/bin/bash" to make matching easier. - " Recognize only a few {options} that are commonly used. - if s:line1 =~# '^#!\s*\S*\' - let s:name = substitute(s:line1, '^#!.*\\s\+\(\i\+\).*', '\1', '') - elseif s:line1 =~# '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)' - let s:name = substitute(s:line1, '^#!\s*\([^/\\ ]*\>\).*', '\1', '') - else - let s:name = substitute(s:line1, '^#!\s*\S*[/\\]\(\i\+\).*', '\1', '') - endif - - " tcl scripts may have #!/bin/sh in the first line and "exec wish" in the - " third line. Suggested by Steven Atkinson. - if getline(3) =~# '^exec wish' - let s:name = 'wish' - endif - - " Bourne-like shell scripts: bash bash2 ksh ksh93 sh - if s:name =~# '^\(bash\d*\|\|ksh\d*\|sh\)\>' - call dist#ft#SetFileTypeSH(s:line1) " defined in filetype.vim - - " csh scripts - elseif s:name =~# '^csh\>' - if exists("g:filetype_csh") - call dist#ft#SetFileTypeShell(g:filetype_csh) - else - call dist#ft#SetFileTypeShell("csh") - endif - - " tcsh scripts - elseif s:name =~# '^tcsh\>' - call dist#ft#SetFileTypeShell("tcsh") - - " Z shell scripts - elseif s:name =~# '^zsh\>' - set ft=zsh - - " TCL scripts - elseif s:name =~# '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>' - set ft=tcl - - " Expect scripts - elseif s:name =~# '^expect\>' - set ft=expect - - " Gnuplot scripts - elseif s:name =~# '^gnuplot\>' - set ft=gnuplot - - " Makefiles - elseif s:name =~# 'make\>' - set ft=make - - " Pike - elseif s:name =~# '^pike\%(\>\|[0-9]\)' - set ft=pike - - " Lua - elseif s:name =~# 'lua' - set ft=lua - - " Perl - elseif s:name =~# 'perl' - set ft=perl - - " PHP - elseif s:name =~# 'php' - set ft=php - - " Python - elseif s:name =~# 'python' - set ft=python - - " Groovy - elseif s:name =~# '^groovy\>' - set ft=groovy - - " Raku - elseif s:name =~# 'raku' - set ft=raku - - " Ruby - elseif s:name =~# 'ruby' - set ft=ruby - - " JavaScript - elseif s:name =~# 'node\(js\)\=\>\|js\>' || s:name =~# 'rhino\>' - set ft=javascript - - " BC calculator - elseif s:name =~# '^bc\>' - set ft=bc - - " sed - elseif s:name =~# 'sed\>' - set ft=sed - - " OCaml-scripts - elseif s:name =~# 'ocaml' - set ft=ocaml - - " Awk scripts; also finds "gawk" - elseif s:name =~# 'awk\>' - set ft=awk - - " Website MetaLanguage - elseif s:name =~# 'wml' - set ft=wml - - " Scheme scripts - elseif s:name =~# 'scheme' - set ft=scheme - - " CFEngine scripts - elseif s:name =~# 'cfengine' - set ft=cfengine - - " Erlang scripts - elseif s:name =~# 'escript' - set ft=erlang - - " Haskell - elseif s:name =~# 'haskell' - set ft=haskell - - " Scala - elseif s:name =~# 'scala\>' - set ft=scala - - " Clojure - elseif s:name =~# 'clojure' - set ft=clojure - - " Free Pascal - elseif s:name =~# 'instantfpc\>' - set ft=pascal - - " Fennel - elseif s:name =~# 'fennel\>' - set ft=fennel - - " MikroTik RouterOS script - elseif s:name =~# 'rsc\>' - set ft=routeros - - " Fish shell - elseif s:name =~# 'fish\>' - set ft=fish - - " Gforth - elseif s:name =~# 'gforth\>' - set ft=forth - - endif - unlet s:name - -else - " File does not start with "#!". - - let s:line2 = getline(2) - let s:line3 = getline(3) - let s:line4 = getline(4) - let s:line5 = getline(5) - - " Bourne-like shell scripts: sh ksh bash bash2 - if s:line1 =~# '^:$' - call dist#ft#SetFileTypeSH(s:line1) " defined in filetype.vim - - " Z shell scripts - elseif s:line1 =~# '^#compdef\>' || s:line1 =~# '^#autoload\>' || - \ "\n".s:line1."\n".s:line2."\n".s:line3."\n".s:line4."\n".s:line5 =~# '\n\s*emulate\s\+\%(-[LR]\s\+\)\=[ckz]\=sh\>' - set ft=zsh - - " ELM Mail files - elseif s:line1 =~# '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$' - set ft=mail - - " Mason - elseif s:line1 =~# '^<[%&].*>' - set ft=mason - - " Vim scripts (must have '" vim' as the first line to trigger this) - elseif s:line1 =~# '^" *[vV]im$' - set ft=vim - - " libcxx and libstdc++ standard library headers like "iostream" do not have - " an extension, recognize the Emacs file mode. - elseif s:line1 =~? '-\*-.*C++.*-\*-' - set ft=cpp - - " MOO - elseif s:line1 =~# '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$' - set ft=moo - - " Diff file: - " - "diff" in first line (context diff) - " - "Only in " in first line - " - "--- " in first line and "+++ " in second line (unified diff). - " - "*** " in first line and "--- " in second line (context diff). - " - "# It was generated by makepatch " in the second line (makepatch diff). - " - "Index: " in the first line (CVS file) - " - "=== ", line of "=", "---", "+++ " (SVK diff) - " - "=== ", "--- ", "+++ " (bzr diff, common case) - " - "=== (removed|added|renamed|modified)" (bzr diff, alternative) - " - "# HG changeset patch" in first line (Mercurial export format) - elseif s:line1 =~# '^\(diff\>\|Only in \|\d\+\(,\d\+\)\=[cda]\d\+\>\|# It was generated by makepatch \|Index:\s\+\f\+\r\=$\|===== \f\+ \d\+\.\d\+ vs edited\|==== //\f\+#\d\+\|# HG changeset patch\)' - \ || (s:line1 =~# '^--- ' && s:line2 =~# '^+++ ') - \ || (s:line1 =~# '^\* looking for ' && s:line2 =~# '^\* comparing to ') - \ || (s:line1 =~# '^\*\*\* ' && s:line2 =~# '^--- ') - \ || (s:line1 =~# '^=== ' && ((s:line2 =~# '^=\{66\}' && s:line3 =~# '^--- ' && s:line4 =~# '^+++') || (s:line2 =~# '^--- ' && s:line3 =~# '^+++ '))) - \ || (s:line1 =~# '^=== \(removed\|added\|renamed\|modified\)') - set ft=diff - - " PostScript Files (must have %!PS as the first line, like a2ps output) - elseif s:line1 =~# '^%![ \t]*PS' - set ft=postscr - - " M4 scripts: Guess there is a line that starts with "dnl". - elseif s:line1 =~# '^\s*dnl\>' - \ || s:line2 =~# '^\s*dnl\>' - \ || s:line3 =~# '^\s*dnl\>' - \ || s:line4 =~# '^\s*dnl\>' - \ || s:line5 =~# '^\s*dnl\>' - set ft=m4 - - " AmigaDos scripts - elseif $TERM == "amiga" - \ && (s:line1 =~# "^;" || s:line1 =~? '^\.bra') - set ft=amiga - - " SiCAD scripts (must have procn or procd as the first line to trigger this) - elseif s:line1 =~? '^ *proc[nd] *$' - set ft=sicad - - " Purify log files start with "**** Purify" - elseif s:line1 =~# '^\*\*\*\* Purify' - set ft=purifylog - - " XML - elseif s:line1 =~# '' - set ft=xml - - " XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN") - elseif s:line1 =~# '\' - set ft=html - - " PDF - elseif s:line1 =~# '^%PDF-' - set ft=pdf - - " XXD output - elseif s:line1 =~# '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} ' - set ft=xxd - - " RCS/CVS log output - elseif s:line1 =~# '^RCS file:' || s:line2 =~# '^RCS file:' - set ft=rcslog - - " CVS commit - elseif s:line2 =~# '^CVS:' || getline("$") =~# '^CVS: ' - set ft=cvs - - " Prescribe - elseif s:line1 =~# '^!R!' - set ft=prescribe - - " Send-pr - elseif s:line1 =~# '^SEND-PR:' - set ft=sendpr - - " SNNS files - elseif s:line1 =~# '^SNNS network definition file' - set ft=snnsnet - elseif s:line1 =~# '^SNNS pattern definition file' - set ft=snnspat - elseif s:line1 =~# '^SNNS result file' - set ft=snnsres - - " Virata - elseif s:line1 =~# '^%.\{-}[Vv]irata' - \ || s:line2 =~# '^%.\{-}[Vv]irata' - \ || s:line3 =~# '^%.\{-}[Vv]irata' - \ || s:line4 =~# '^%.\{-}[Vv]irata' - \ || s:line5 =~# '^%.\{-}[Vv]irata' - set ft=virata - - " Strace - elseif s:line1 =~# '[0-9:.]* *execve(' || s:line1 =~# '^__libc_start_main' - set ft=strace - - " VSE JCL - elseif s:line1 =~# '^\* $$ JOB\>' || s:line1 =~# '^// *JOB\>' - set ft=vsejcl - - " TAK and SINDA - elseif s:line4 =~# 'K & K Associates' || s:line2 =~# 'TAK 2000' - set ft=takout - elseif s:line3 =~# 'S Y S T E M S I M P R O V E D ' - set ft=sindaout - elseif getline(6) =~# 'Run Date: ' - set ft=takcmp - elseif getline(9) =~# 'Node File 1' - set ft=sindacmp - - " DNS zone files - elseif s:line1.s:line2.s:line3.s:line4 =~# '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA' - set ft=bindzone - - " BAAN - elseif s:line1 =~# '|\*\{1,80}' && s:line2 =~# 'VRC ' - \ || s:line2 =~# '|\*\{1,80}' && s:line3 =~# 'VRC ' - set ft=baan - - " Valgrind - elseif s:line1 =~# '^==\d\+== valgrind' || s:line3 =~# '^==\d\+== Using valgrind' - set ft=valgrind - - " Go docs - elseif s:line1 =~# '^PACKAGE DOCUMENTATION$' - set ft=godoc - - " Renderman Interface Bytestream - elseif s:line1 =~# '^##RenderMan' - set ft=rib - - " Scheme scripts - elseif s:line1 =~# 'exec\s\+\S*scheme' || s:line2 =~# 'exec\s\+\S*scheme' - set ft=scheme - - " Git output - elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40,\}\>\|^tag \S\+$' - set ft=git - - " Gprof (gnu profiler) - elseif s:line1 == 'Flat profile:' - \ && s:line2 == '' - \ && s:line3 =~# '^Each sample counts as .* seconds.$' - set ft=gprof - - " Erlang terms - " (See also: http://www.gnu.org/software/emacs/manual/html_node/emacs/Choosing-Modes.html#Choosing-Modes) - elseif s:line1 =~? '-\*-.*erlang.*-\*-' - set ft=erlang - - " YAML - elseif s:line1 =~# '^%YAML' - set ft=yaml - - " MikroTik RouterOS script - elseif s:line1 =~# '^#.*by RouterOS.*$' - set ft=routeros - - " Sed scripts - " #ncomment is allowed but most likely a false positive so require a space - " before any trailing comment text - elseif s:line1 =~# '^#n\%($\|\s\)' - set ft=sed - - " CVS diff - else - let s:lnum = 1 - while getline(s:lnum) =~# "^? " && s:lnum < line("$") - let s:lnum += 1 - endwhile - if getline(s:lnum) =~# '^Index:\s\+\f\+$' - set ft=diff - - " locale input files: Formal Definitions of Cultural Conventions - " filename must be like en_US, fr_FR@euro or en_US.UTF-8 - elseif expand("%") =~# '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_' - let s:lnum = 1 - while s:lnum < 100 && s:lnum < line("$") - if getline(s:lnum) =~# '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$' - setf fdcc - break - endif - let s:lnum += 1 - endwhile - endif - unlet s:lnum - - endif - - unlet s:line2 s:line3 s:line4 s:line5 - -endif - -" Restore 'cpoptions' -let &cpo = s:cpo_save - -unlet s:cpo_save s:line1 +" The main code is in a compiled function for speed. +call dist#script#DetectFiletype() diff --git a/src/Makefile b/src/Makefile index 569f91e49d..ac162143d8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4262,7 +4262,7 @@ objects/vim9script.o: vim9script.c vim.h protodef.h auto/config.h feature.h \ objects/vim9type.o: vim9type.c vim.h protodef.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ - proto.h globals.h errors.h + proto.h globals.h errors.h vim9.h objects/viminfo.o: viminfo.c vim.h protodef.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ diff --git a/src/cmdexpand.c b/src/cmdexpand.c index 45db2e742f..b1fe1a6904 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -50,6 +50,9 @@ sort_func_compare(const void *s1, const void *s2) return STRCMP(p1, p2); } +/* + * Escape special characters in the cmdline completion matches. + */ static void ExpandEscape( expand_T *xp, @@ -350,6 +353,189 @@ int cmdline_compl_startcol(void) } #endif +/* + * Get the next or prev cmdline completion match. The index of the match is set + * in 'p_findex' + */ + static char_u * +get_next_or_prev_match( + int mode, + expand_T *xp, + int *p_findex, + char_u *orig_save) +{ + int findex = *p_findex; + + if (xp->xp_numfiles <= 0) + return NULL; + + if (mode == WILD_PREV) + { + if (findex == -1) + findex = xp->xp_numfiles; + --findex; + } + else // mode == WILD_NEXT + ++findex; + + // When wrapping around, return the original string, set findex to + // -1. + if (findex < 0) + { + if (orig_save == NULL) + findex = xp->xp_numfiles - 1; + else + findex = -1; + } + if (findex >= xp->xp_numfiles) + { + if (orig_save == NULL) + findex = 0; + else + findex = -1; + } +#ifdef FEAT_WILDMENU + if (compl_match_array) + { + compl_selected = findex; + cmdline_pum_display(); + } + else if (p_wmnu) + win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files, + findex, cmd_showtail); +#endif + *p_findex = findex; + + if (findex == -1) + return vim_strsave(orig_save); + + return vim_strsave(xp->xp_files[findex]); +} + +/* + * Start the command-line expansion and get the matches. + */ + static char_u * +ExpandOne_start(int mode, expand_T *xp, char_u *str, int options) +{ + int non_suf_match; // number without matching suffix + int i; + char_u *ss = NULL; + + // Do the expansion. + if (ExpandFromContext(xp, str, &xp->xp_numfiles, &xp->xp_files, + options) == FAIL) + { +#ifdef FNAME_ILLEGAL + // Illegal file name has been silently skipped. But when there + // are wildcards, the real problem is that there was no match, + // causing the pattern to be added, which has illegal characters. + if (!(options & WILD_SILENT) && (options & WILD_LIST_NOTFOUND)) + semsg(_(e_no_match_str_2), str); +#endif + } + else if (xp->xp_numfiles == 0) + { + if (!(options & WILD_SILENT)) + semsg(_(e_no_match_str_2), str); + } + else + { + // Escape the matches for use on the command line. + ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options); + + // Check for matching suffixes in file names. + if (mode != WILD_ALL && mode != WILD_ALL_KEEP + && mode != WILD_LONGEST) + { + if (xp->xp_numfiles) + non_suf_match = xp->xp_numfiles; + else + non_suf_match = 1; + if ((xp->xp_context == EXPAND_FILES + || xp->xp_context == EXPAND_DIRECTORIES) + && xp->xp_numfiles > 1) + { + // More than one match; check suffix. + // The files will have been sorted on matching suffix in + // expand_wildcards, only need to check the first two. + non_suf_match = 0; + for (i = 0; i < 2; ++i) + if (match_suffix(xp->xp_files[i])) + ++non_suf_match; + } + if (non_suf_match != 1) + { + // Can we ever get here unless it's while expanding + // interactively? If not, we can get rid of this all + // together. Don't really want to wait for this message + // (and possibly have to hit return to continue!). + if (!(options & WILD_SILENT)) + emsg(_(e_too_many_file_names)); + else if (!(options & WILD_NO_BEEP)) + beep_flush(); + } + if (!(non_suf_match != 1 && mode == WILD_EXPAND_FREE)) + ss = vim_strsave(xp->xp_files[0]); + } + } + + return ss; +} + +/* + * Return the longest common part in the list of cmdline completion matches. + */ + static char_u * +find_longest_match(expand_T *xp, int options) +{ + long_u len; + int mb_len = 1; + int c0, ci; + int i; + char_u *ss; + + for (len = 0; xp->xp_files[0][len]; len += mb_len) + { + if (has_mbyte) + { + mb_len = (*mb_ptr2len)(&xp->xp_files[0][len]); + c0 =(* mb_ptr2char)(&xp->xp_files[0][len]); + } + else + c0 = xp->xp_files[0][len]; + for (i = 1; i < xp->xp_numfiles; ++i) + { + if (has_mbyte) + ci =(* mb_ptr2char)(&xp->xp_files[i][len]); + else + ci = xp->xp_files[i][len]; + if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES + || xp->xp_context == EXPAND_FILES + || xp->xp_context == EXPAND_SHELLCMD + || xp->xp_context == EXPAND_BUFFERS)) + { + if (MB_TOLOWER(c0) != MB_TOLOWER(ci)) + break; + } + else if (c0 != ci) + break; + } + if (i < xp->xp_numfiles) + { + if (!(options & WILD_NO_BEEP)) + vim_beep(BO_WILD); + break; + } + } + + ss = alloc(len + 1); + if (ss) + vim_strncpy(ss, xp->xp_files[0], (size_t)len); + + return ss; +} + /* * Do wildcard expansion on the string 'str'. * Chars that should not be expanded must be preceded with a backslash. @@ -371,6 +557,10 @@ int cmdline_compl_startcol(void) * mode = WILD_ALL: return all matches concatenated * mode = WILD_LONGEST: return longest matched part * mode = WILD_ALL_KEEP: get all matches, keep matches + * mode = WILD_APPLY: apply the item selected in the cmdline completion + * popup menu and close the menu. + * mode = WILD_CANCEL: cancel and close the cmdline completion popup and + * use the original text. * * options = WILD_LIST_NOTFOUND: list entries without a match * options = WILD_HOME_REPLACE: do home_replace() for buffer names @@ -399,55 +589,10 @@ ExpandOne( int orig_saved = FALSE; int i; long_u len; - int non_suf_match; // number without matching suffix // first handle the case of using an old match if (mode == WILD_NEXT || mode == WILD_PREV) - { - if (xp->xp_numfiles > 0) - { - if (mode == WILD_PREV) - { - if (findex == -1) - findex = xp->xp_numfiles; - --findex; - } - else // mode == WILD_NEXT - ++findex; - - // When wrapping around, return the original string, set findex to - // -1. - if (findex < 0) - { - if (orig_save == NULL) - findex = xp->xp_numfiles - 1; - else - findex = -1; - } - if (findex >= xp->xp_numfiles) - { - if (orig_save == NULL) - findex = 0; - else - findex = -1; - } -#ifdef FEAT_WILDMENU - if (compl_match_array) - { - compl_selected = findex; - cmdline_pum_display(); - } - else if (p_wmnu) - win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files, - findex, cmd_showtail); -#endif - if (findex == -1) - return vim_strsave(orig_save); - return vim_strsave(xp->xp_files[findex]); - } - else - return NULL; - } + return get_next_or_prev_match(mode, xp, &findex, orig_save); if (mode == WILD_CANCEL) ss = vim_strsave(orig_save ? orig_save : (char_u *)""); @@ -473,108 +618,13 @@ ExpandOne( orig_save = orig; orig_saved = TRUE; - // Do the expansion. - if (ExpandFromContext(xp, str, &xp->xp_numfiles, &xp->xp_files, - options) == FAIL) - { -#ifdef FNAME_ILLEGAL - // Illegal file name has been silently skipped. But when there - // are wildcards, the real problem is that there was no match, - // causing the pattern to be added, which has illegal characters. - if (!(options & WILD_SILENT) && (options & WILD_LIST_NOTFOUND)) - semsg(_(e_no_match_str_2), str); -#endif - } - else if (xp->xp_numfiles == 0) - { - if (!(options & WILD_SILENT)) - semsg(_(e_no_match_str_2), str); - } - else - { - // Escape the matches for use on the command line. - ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options); - - // Check for matching suffixes in file names. - if (mode != WILD_ALL && mode != WILD_ALL_KEEP - && mode != WILD_LONGEST) - { - if (xp->xp_numfiles) - non_suf_match = xp->xp_numfiles; - else - non_suf_match = 1; - if ((xp->xp_context == EXPAND_FILES - || xp->xp_context == EXPAND_DIRECTORIES) - && xp->xp_numfiles > 1) - { - // More than one match; check suffix. - // The files will have been sorted on matching suffix in - // expand_wildcards, only need to check the first two. - non_suf_match = 0; - for (i = 0; i < 2; ++i) - if (match_suffix(xp->xp_files[i])) - ++non_suf_match; - } - if (non_suf_match != 1) - { - // Can we ever get here unless it's while expanding - // interactively? If not, we can get rid of this all - // together. Don't really want to wait for this message - // (and possibly have to hit return to continue!). - if (!(options & WILD_SILENT)) - emsg(_(e_too_many_file_names)); - else if (!(options & WILD_NO_BEEP)) - beep_flush(); - } - if (!(non_suf_match != 1 && mode == WILD_EXPAND_FREE)) - ss = vim_strsave(xp->xp_files[0]); - } - } + ss = ExpandOne_start(mode, xp, str, options); } // Find longest common part if (mode == WILD_LONGEST && xp->xp_numfiles > 0) { - int mb_len = 1; - int c0, ci; - - for (len = 0; xp->xp_files[0][len]; len += mb_len) - { - if (has_mbyte) - { - mb_len = (*mb_ptr2len)(&xp->xp_files[0][len]); - c0 =(* mb_ptr2char)(&xp->xp_files[0][len]); - } - else - c0 = xp->xp_files[0][len]; - for (i = 1; i < xp->xp_numfiles; ++i) - { - if (has_mbyte) - ci =(* mb_ptr2char)(&xp->xp_files[i][len]); - else - ci = xp->xp_files[i][len]; - if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES - || xp->xp_context == EXPAND_FILES - || xp->xp_context == EXPAND_SHELLCMD - || xp->xp_context == EXPAND_BUFFERS)) - { - if (MB_TOLOWER(c0) != MB_TOLOWER(ci)) - break; - } - else if (c0 != ci) - break; - } - if (i < xp->xp_numfiles) - { - if (!(options & WILD_NO_BEEP)) - vim_beep(BO_WILD); - break; - } - } - - ss = alloc(len + 1); - if (ss) - vim_strncpy(ss, xp->xp_files[0], (size_t)len); + ss = find_longest_match(xp, options); findex = -1; // next p_wc gets first one } @@ -1077,58 +1127,17 @@ set_expand_context(expand_T *xp) } /* - * This is all pretty much copied from do_one_cmd(), with all the extra stuff - * we don't need/want deleted. Maybe this could be done better if we didn't - * repeat all this stuff. The only problem is that they may not stay - * perfectly compatible with each other, but then the command line syntax - * probably won't change that much -- webb. + * Sets the index of a built-in or user defined command 'cmd' in eap->cmdidx. + * For user defined commands, the completion context is set in 'xp' and the + * completion flags in 'complp'. + * + * Returns a pointer to the text after the command or NULL for failure. */ static char_u * -set_one_cmd_context( - expand_T *xp, - char_u *buff) // buffer for command string +set_cmd_index(char_u *cmd, exarg_T *eap, expand_T *xp, int *complp) { - char_u *p; - char_u *cmd, *arg; - int len = 0; - exarg_T ea; - int compl = EXPAND_NOTHING; - int delim; - int forceit = FALSE; - int usefilter = FALSE; // filter instead of file name - - ExpandInit(xp); - xp->xp_pattern = buff; - xp->xp_line = buff; - xp->xp_context = EXPAND_COMMANDS; // Default until we get past command - ea.argt = 0; - - // 1. skip comment lines and leading space, colons or bars - for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++) - ; - xp->xp_pattern = cmd; - - if (*cmd == NUL) - return NULL; - if (*cmd == '"') // ignore comment lines - { - xp->xp_context = EXPAND_NOTHING; - return NULL; - } - - // 3. Skip over the range to find the command. - cmd = skip_range(cmd, TRUE, &xp->xp_context); - xp->xp_pattern = cmd; - if (*cmd == NUL) - return NULL; - if (*cmd == '"') - { - xp->xp_context = EXPAND_NOTHING; - return NULL; - } - - if (*cmd == '|' || *cmd == '\n') - return cmd + 1; // There's another command + char_u *p = NULL; + int len = 0; // Isolate the command and search for it in the command table. // Exceptions: @@ -1137,7 +1146,7 @@ set_one_cmd_context( // - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' if (*cmd == 'k' && cmd[1] != 'e') { - ea.cmdidx = CMD_k; + eap->cmdidx = CMD_k; p = cmd + 1; } else @@ -1168,7 +1177,7 @@ set_one_cmd_context( return NULL; } - ea.cmdidx = excmd_get_cmdidx(cmd, len); + eap->cmdidx = excmd_get_cmdidx(cmd, len); if (cmd[0] >= 'A' && cmd[0] <= 'Z') while (ASCII_ISALNUM(*p) || *p == '*') // Allow * wild card @@ -1180,262 +1189,172 @@ set_one_cmd_context( if (*p == NUL && ASCII_ISALNUM(p[-1])) return NULL; - if (ea.cmdidx == CMD_SIZE) + if (eap->cmdidx == CMD_SIZE) { if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) { - ea.cmdidx = CMD_substitute; + eap->cmdidx = CMD_substitute; p = cmd + 1; } else if (cmd[0] >= 'A' && cmd[0] <= 'Z') { - ea.cmd = cmd; - p = find_ucmd(&ea, p, NULL, xp, &compl); + eap->cmd = cmd; + p = find_ucmd(eap, p, NULL, xp, complp); if (p == NULL) - ea.cmdidx = CMD_SIZE; // ambiguous user command + eap->cmdidx = CMD_SIZE; // ambiguous user command } } - if (ea.cmdidx == CMD_SIZE) + if (eap->cmdidx == CMD_SIZE) { // Not still touching the command and it was an illegal one xp->xp_context = EXPAND_UNSUCCESSFUL; return NULL; } - xp->xp_context = EXPAND_NOTHING; // Default now that we're past command + return p; +} - if (*p == '!') // forced commands +/* + * Set the completion context for a command argument with wild card characters. + */ + static void +set_context_for_wildcard_arg( + exarg_T *eap, + char_u *arg, + int usefilter, + expand_T *xp, + int *complp) +{ + char_u *p; + int c; + int in_quote = FALSE; + char_u *bow = NULL; // Beginning of word + int len = 0; + + // Allow spaces within back-quotes to count as part of the argument + // being expanded. + xp->xp_pattern = skipwhite(arg); + p = xp->xp_pattern; + while (*p != NUL) { - forceit = TRUE; - ++p; - } - - // 6. parse arguments - if (!IS_USER_CMDIDX(ea.cmdidx)) - ea.argt = excmd_get_argt(ea.cmdidx); - - arg = skipwhite(p); - - // Skip over ++argopt argument - if ((ea.argt & EX_ARGOPT) && *arg != NUL && STRNCMP(arg, "++", 2) == 0) - { - p = arg; - while (*p && !vim_isspace(*p)) - MB_PTR_ADV(p); - arg = skipwhite(p); - } - - if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) - { - if (*arg == '>') // append - { - if (*++arg == '>') - ++arg; - arg = skipwhite(arg); - } - else if (*arg == '!' && ea.cmdidx == CMD_write) // :w !filter - { - ++arg; - usefilter = TRUE; - } - } - - if (ea.cmdidx == CMD_read) - { - usefilter = forceit; // :r! filter if forced - if (*arg == '!') // :r !filter - { - ++arg; - usefilter = TRUE; - } - } - - if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) - { - while (*arg == *cmd) // allow any number of '>' or '<' - ++arg; - arg = skipwhite(arg); - } - - // Does command allow "+command"? - if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') - { - // Check if we're in the +command - p = arg + 1; - arg = skip_cmd_arg(arg, FALSE); - - // Still touching the command after '+'? - if (*arg == NUL) - return p; - - // Skip space(s) after +command to get to the real argument - arg = skipwhite(arg); - } - - - // Check for '|' to separate commands and '"' to start comments. - // Don't do this for ":read !cmd" and ":write !cmd". - if ((ea.argt & EX_TRLBAR) && !usefilter) - { - p = arg; - // ":redir @" is not the start of a comment - if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"') - p += 2; - while (*p) - { - if (*p == Ctrl_V) - { - if (p[1] != NUL) - ++p; - } - else if ( (*p == '"' && !(ea.argt & EX_NOTRLCOM)) - || *p == '|' || *p == '\n') - { - if (*(p - 1) != '\\') - { - if (*p == '|' || *p == '\n') - return p + 1; - return NULL; // It's a comment - } - } - MB_PTR_ADV(p); - } - } - - if (!(ea.argt & EX_EXTRA) && *arg != NUL - && vim_strchr((char_u *)"|\"", *arg) == NULL) - // no arguments allowed but there is something - return NULL; - - // Find start of last argument (argument just before cursor): - p = buff; - xp->xp_pattern = p; - len = (int)STRLEN(buff); - while (*p && p < buff + len) - { - if (*p == ' ' || *p == TAB) - { - // argument starts after a space - xp->xp_pattern = ++p; - } + if (has_mbyte) + c = mb_ptr2char(p); else + c = *p; + if (c == '\\' && p[1] != NUL) + ++p; + else if (c == '`') { - if (*p == '\\' && *(p + 1) != NUL) - ++p; // skip over escaped character - MB_PTR_ADV(p); - } - } - - if (ea.argt & EX_XFILE) - { - int c; - int in_quote = FALSE; - char_u *bow = NULL; // Beginning of word - - // Allow spaces within back-quotes to count as part of the argument - // being expanded. - xp->xp_pattern = skipwhite(arg); - p = xp->xp_pattern; - while (*p != NUL) - { - if (has_mbyte) - c = mb_ptr2char(p); - else - c = *p; - if (c == '\\' && p[1] != NUL) - ++p; - else if (c == '`') + if (!in_quote) { - if (!in_quote) - { - xp->xp_pattern = p; - bow = p + 1; - } - in_quote = !in_quote; + xp->xp_pattern = p; + bow = p + 1; } - // An argument can contain just about everything, except - // characters that end the command and white space. - else if (c == '|' || c == '\n' || c == '"' || (VIM_ISWHITE(c) + in_quote = !in_quote; + } + // An argument can contain just about everything, except + // characters that end the command and white space. + else if (c == '|' || c == '\n' || c == '"' || (VIM_ISWHITE(c) #ifdef SPACE_IN_FILENAME - && (!(ea.argt & EX_NOSPC) || usefilter) + && (!(eap->argt & EX_NOSPC) || usefilter) #endif )) + { + len = 0; // avoid getting stuck when space is in 'isfname' + while (*p != NUL) { - len = 0; // avoid getting stuck when space is in 'isfname' - while (*p != NUL) - { - if (has_mbyte) - c = mb_ptr2char(p); - else - c = *p; - if (c == '`' || vim_isfilec_or_wc(c)) - break; - if (has_mbyte) - len = (*mb_ptr2len)(p); - else - len = 1; - MB_PTR_ADV(p); - } - if (in_quote) - bow = p; + if (has_mbyte) + c = mb_ptr2char(p); else - xp->xp_pattern = p; - p -= len; - } - MB_PTR_ADV(p); - } - - // If we are still inside the quotes, and we passed a space, just - // expand from there. - if (bow != NULL && in_quote) - xp->xp_pattern = bow; - xp->xp_context = EXPAND_FILES; - - // For a shell command more chars need to be escaped. - if (usefilter || ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal) - { -#ifndef BACKSLASH_IN_FILENAME - xp->xp_shell = TRUE; -#endif - // When still after the command name expand executables. - if (xp->xp_pattern == skipwhite(arg)) - xp->xp_context = EXPAND_SHELLCMD; - } - - // Check for environment variable. - if (*xp->xp_pattern == '$') - { - for (p = xp->xp_pattern + 1; *p != NUL; ++p) - if (!vim_isIDc(*p)) + c = *p; + if (c == '`' || vim_isfilec_or_wc(c)) break; - if (*p == NUL) - { - xp->xp_context = EXPAND_ENV_VARS; - ++xp->xp_pattern; - // Avoid that the assignment uses EXPAND_FILES again. - if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST) - compl = EXPAND_ENV_VARS; - } - } - // Check for user names. - if (*xp->xp_pattern == '~') - { - for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) - ; - // Complete ~user only if it partially matches a user name. - // A full match ~user will be replaced by user's home - // directory i.e. something like ~user -> /home/user/ - if (*p == NUL && p > xp->xp_pattern + 1 - && match_user(xp->xp_pattern + 1) >= 1) - { - xp->xp_context = EXPAND_USER; - ++xp->xp_pattern; + if (has_mbyte) + len = (*mb_ptr2len)(p); + else + len = 1; + MB_PTR_ADV(p); } + if (in_quote) + bow = p; + else + xp->xp_pattern = p; + p -= len; } + MB_PTR_ADV(p); } - // 6. Switch on command name. - switch (ea.cmdidx) + // If we are still inside the quotes, and we passed a space, just + // expand from there. + if (bow != NULL && in_quote) + xp->xp_pattern = bow; + xp->xp_context = EXPAND_FILES; + + // For a shell command more chars need to be escaped. + if (usefilter || eap->cmdidx == CMD_bang || eap->cmdidx == CMD_terminal) + { +#ifndef BACKSLASH_IN_FILENAME + xp->xp_shell = TRUE; +#endif + // When still after the command name expand executables. + if (xp->xp_pattern == skipwhite(arg)) + xp->xp_context = EXPAND_SHELLCMD; + } + + // Check for environment variable. + if (*xp->xp_pattern == '$') + { + for (p = xp->xp_pattern + 1; *p != NUL; ++p) + if (!vim_isIDc(*p)) + break; + if (*p == NUL) + { + xp->xp_context = EXPAND_ENV_VARS; + ++xp->xp_pattern; + // Avoid that the assignment uses EXPAND_FILES again. + if (*complp != EXPAND_USER_DEFINED && *complp != EXPAND_USER_LIST) + *complp = EXPAND_ENV_VARS; + } + } + // Check for user names. + if (*xp->xp_pattern == '~') + { + for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) + ; + // Complete ~user only if it partially matches a user name. + // A full match ~user will be replaced by user's home + // directory i.e. something like ~user -> /home/user/ + if (*p == NUL && p > xp->xp_pattern + 1 + && match_user(xp->xp_pattern + 1) >= 1) + { + xp->xp_context = EXPAND_USER; + ++xp->xp_pattern; + } + } +} + +/* + * Set the completion context in 'xp' for command 'cmd' with index 'cmdidx'. + * The argument to the command is 'arg' and the argument flags is 'argt'. + * For user-defined commands and for environment variables, 'compl' has the + * completion type. + * Returns a pointer to the next command. Returns NULL if there is no next + * command. + */ + static char_u * +set_context_by_cmdname( + char_u *cmd, + cmdidx_T cmdidx, + char_u *arg, + long argt, + int compl, + expand_T *xp, + int forceit) +{ + char_u *p; + int delim; + + switch (cmdidx) { case CMD_find: case CMD_sfind: @@ -1658,7 +1577,7 @@ set_one_cmd_context( case CMD_lexpr: case CMD_laddexpr: case CMD_lgetexpr: - set_context_for_expression(xp, arg, ea.cmdidx); + set_context_for_expression(xp, arg, cmdidx); break; case CMD_unlet: @@ -1696,7 +1615,7 @@ set_one_cmd_context( case CMD_cscope: case CMD_lcscope: case CMD_scscope: - set_context_in_cscope_cmd(xp, arg, ea.cmdidx); + set_context_in_cscope_cmd(xp, arg, cmdidx); break; #endif #ifdef FEAT_SIGNS @@ -1730,7 +1649,7 @@ set_one_cmd_context( if (compl != EXPAND_NOTHING) { // EX_XFILE: file names are handled above - if (!(ea.argt & EX_XFILE)) + if (!(argt & EX_XFILE)) { #ifdef FEAT_MENU if (compl == EXPAND_MENUS) @@ -1769,7 +1688,7 @@ set_one_cmd_context( case CMD_tmap: case CMD_tnoremap: case CMD_xmap: case CMD_xnoremap: return set_context_in_map_cmd(xp, cmd, arg, forceit, - FALSE, FALSE, ea.cmdidx); + FALSE, FALSE, cmdidx); case CMD_unmap: case CMD_nunmap: case CMD_vunmap: @@ -1781,7 +1700,7 @@ set_one_cmd_context( case CMD_tunmap: case CMD_xunmap: return set_context_in_map_cmd(xp, cmd, arg, forceit, - FALSE, TRUE, ea.cmdidx); + FALSE, TRUE, cmdidx); case CMD_mapclear: case CMD_nmapclear: case CMD_vmapclear: @@ -1800,12 +1719,12 @@ set_one_cmd_context( case CMD_cabbrev: case CMD_cnoreabbrev: case CMD_iabbrev: case CMD_inoreabbrev: return set_context_in_map_cmd(xp, cmd, arg, forceit, - TRUE, FALSE, ea.cmdidx); + TRUE, FALSE, cmdidx); case CMD_unabbreviate: case CMD_cunabbrev: case CMD_iunabbrev: return set_context_in_map_cmd(xp, cmd, arg, forceit, - TRUE, TRUE, ea.cmdidx); + TRUE, TRUE, cmdidx); #ifdef FEAT_MENU case CMD_menu: case CMD_noremenu: case CMD_unmenu: case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu: @@ -1916,6 +1835,196 @@ set_one_cmd_context( return NULL; } +/* + * This is all pretty much copied from do_one_cmd(), with all the extra stuff + * we don't need/want deleted. Maybe this could be done better if we didn't + * repeat all this stuff. The only problem is that they may not stay + * perfectly compatible with each other, but then the command line syntax + * probably won't change that much -- webb. + */ + static char_u * +set_one_cmd_context( + expand_T *xp, + char_u *buff) // buffer for command string +{ + char_u *p; + char_u *cmd, *arg; + int len = 0; + exarg_T ea; + int compl = EXPAND_NOTHING; + int forceit = FALSE; + int usefilter = FALSE; // filter instead of file name + + ExpandInit(xp); + xp->xp_pattern = buff; + xp->xp_line = buff; + xp->xp_context = EXPAND_COMMANDS; // Default until we get past command + ea.argt = 0; + + // 1. skip comment lines and leading space, colons or bars + for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++) + ; + xp->xp_pattern = cmd; + + if (*cmd == NUL) + return NULL; + if (*cmd == '"') // ignore comment lines + { + xp->xp_context = EXPAND_NOTHING; + return NULL; + } + + // 3. Skip over the range to find the command. + cmd = skip_range(cmd, TRUE, &xp->xp_context); + xp->xp_pattern = cmd; + if (*cmd == NUL) + return NULL; + if (*cmd == '"') + { + xp->xp_context = EXPAND_NOTHING; + return NULL; + } + + if (*cmd == '|' || *cmd == '\n') + return cmd + 1; // There's another command + + // Get the command index. + p = set_cmd_index(cmd, &ea, xp, &compl); + if (p == NULL) + return NULL; + + xp->xp_context = EXPAND_NOTHING; // Default now that we're past command + + if (*p == '!') // forced commands + { + forceit = TRUE; + ++p; + } + + // 6. parse arguments + if (!IS_USER_CMDIDX(ea.cmdidx)) + ea.argt = excmd_get_argt(ea.cmdidx); + + arg = skipwhite(p); + + // Skip over ++argopt argument + if ((ea.argt & EX_ARGOPT) && *arg != NUL && STRNCMP(arg, "++", 2) == 0) + { + p = arg; + while (*p && !vim_isspace(*p)) + MB_PTR_ADV(p); + arg = skipwhite(p); + } + + if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) + { + if (*arg == '>') // append + { + if (*++arg == '>') + ++arg; + arg = skipwhite(arg); + } + else if (*arg == '!' && ea.cmdidx == CMD_write) // :w !filter + { + ++arg; + usefilter = TRUE; + } + } + + if (ea.cmdidx == CMD_read) + { + usefilter = forceit; // :r! filter if forced + if (*arg == '!') // :r !filter + { + ++arg; + usefilter = TRUE; + } + } + + if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) + { + while (*arg == *cmd) // allow any number of '>' or '<' + ++arg; + arg = skipwhite(arg); + } + + // Does command allow "+command"? + if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') + { + // Check if we're in the +command + p = arg + 1; + arg = skip_cmd_arg(arg, FALSE); + + // Still touching the command after '+'? + if (*arg == NUL) + return p; + + // Skip space(s) after +command to get to the real argument + arg = skipwhite(arg); + } + + + // Check for '|' to separate commands and '"' to start comments. + // Don't do this for ":read !cmd" and ":write !cmd". + if ((ea.argt & EX_TRLBAR) && !usefilter) + { + p = arg; + // ":redir @" is not the start of a comment + if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"') + p += 2; + while (*p) + { + if (*p == Ctrl_V) + { + if (p[1] != NUL) + ++p; + } + else if ( (*p == '"' && !(ea.argt & EX_NOTRLCOM)) + || *p == '|' || *p == '\n') + { + if (*(p - 1) != '\\') + { + if (*p == '|' || *p == '\n') + return p + 1; + return NULL; // It's a comment + } + } + MB_PTR_ADV(p); + } + } + + if (!(ea.argt & EX_EXTRA) && *arg != NUL + && vim_strchr((char_u *)"|\"", *arg) == NULL) + // no arguments allowed but there is something + return NULL; + + // Find start of last argument (argument just before cursor): + p = buff; + xp->xp_pattern = p; + len = (int)STRLEN(buff); + while (*p && p < buff + len) + { + if (*p == ' ' || *p == TAB) + { + // argument starts after a space + xp->xp_pattern = ++p; + } + else + { + if (*p == '\\' && *(p + 1) != NUL) + ++p; // skip over escaped character + MB_PTR_ADV(p); + } + } + + if (ea.argt & EX_XFILE) + set_context_for_wildcard_arg(&ea, arg, usefilter, xp, &compl); + + // 6. Switch on command name. + return set_context_by_cmdname(cmd, ea.cmdidx, arg, ea.argt, compl, xp, + forceit); +} + void set_cmd_context( expand_T *xp, @@ -2015,6 +2124,78 @@ expand_cmdline( return EXPAND_OK; } +/* + * Expand file or directory names. + */ + static int +expand_files_and_dirs( + expand_T *xp, + char_u *pat, + char_u ***file, + int *num_file, + int flags, + int options) +{ + int free_pat = FALSE; + int i; + int ret; + + // for ":set path=" and ":set tags=" halve backslashes for escaped + // space + if (xp->xp_backslash != XP_BS_NONE) + { + free_pat = TRUE; + pat = vim_strsave(pat); + for (i = 0; pat[i]; ++i) + if (pat[i] == '\\') + { + if (xp->xp_backslash == XP_BS_THREE + && pat[i + 1] == '\\' + && pat[i + 2] == '\\' + && pat[i + 3] == ' ') + STRMOVE(pat + i, pat + i + 3); + if (xp->xp_backslash == XP_BS_ONE + && pat[i + 1] == ' ') + STRMOVE(pat + i, pat + i + 1); + } + } + + if (xp->xp_context == EXPAND_FILES) + flags |= EW_FILE; + else if (xp->xp_context == EXPAND_FILES_IN_PATH) + flags |= (EW_FILE | EW_PATH); + else + flags = (flags | EW_DIR) & ~EW_FILE; + if (options & WILD_ICASE) + flags |= EW_ICASE; + + // Expand wildcards, supporting %:h and the like. + ret = expand_wildcards_eval(&pat, num_file, file, flags); + if (free_pat) + vim_free(pat); +#ifdef BACKSLASH_IN_FILENAME + if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0) + { + int j; + + for (j = 0; j < *num_file; ++j) + { + char_u *ptr = (*file)[j]; + + while (*ptr != NUL) + { + if (p_csl[0] == 's' && *ptr == '\\') + *ptr = '/'; + else if (p_csl[0] == 'b' && *ptr == '/') + *ptr = '\\'; + ptr += (*mb_ptr2len)(ptr); + } + } + } +#endif + return ret; +} + /* * Function given to ExpandGeneric() to obtain the possible arguments of the * ":behave {mswin,xterm}" command. @@ -2049,6 +2230,94 @@ get_mapclear_arg(expand_T *xp UNUSED, int idx) return NULL; } +/* + * Do the expansion based on xp->xp_context and 'rmp'. + */ + static int +ExpandOther( + expand_T *xp, + regmatch_T *rmp, + int *num_file, + char_u ***file) +{ + static struct expgen + { + int context; + char_u *((*func)(expand_T *, int)); + int ic; + int escaped; + } tab[] = + { + {EXPAND_COMMANDS, get_command_name, FALSE, TRUE}, + {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE}, + {EXPAND_MAPCLEAR, get_mapclear_arg, TRUE, TRUE}, + {EXPAND_MESSAGES, get_messages_arg, TRUE, TRUE}, + {EXPAND_HISTORY, get_history_arg, TRUE, TRUE}, + {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE}, + {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE}, + {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE}, + {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE}, + {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE}, +# ifdef FEAT_EVAL + {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE}, + {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE}, + {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE}, + {EXPAND_DISASSEMBLE, get_disassemble_argument, FALSE, TRUE}, + {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE}, +# endif +# ifdef FEAT_MENU + {EXPAND_MENUS, get_menu_name, FALSE, TRUE}, + {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE}, +# endif +# ifdef FEAT_SYN_HL + {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE}, +# endif +# ifdef FEAT_PROFILE + {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE}, +# endif + {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE}, + {EXPAND_EVENTS, get_event_name, TRUE, FALSE}, + {EXPAND_AUGROUP, get_augroup_name, TRUE, FALSE}, +# ifdef FEAT_CSCOPE + {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE}, +# endif +# ifdef FEAT_SIGNS + {EXPAND_SIGN, get_sign_name, TRUE, TRUE}, +# endif +# ifdef FEAT_PROFILE + {EXPAND_PROFILE, get_profile_name, TRUE, TRUE}, +# endif +# if defined(HAVE_LOCALE_H) || defined(X_LOCALE) + {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE}, + {EXPAND_LOCALES, get_locales, TRUE, FALSE}, +# endif + {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, + {EXPAND_USER, get_users, TRUE, FALSE}, + {EXPAND_ARGLIST, get_arglist_name, TRUE, FALSE}, +#ifdef FEAT_GUI_MACVIM + {EXPAND_MACACTION, get_macaction_name, FALSE, FALSE}, +#endif + }; + int i; + int ret = FAIL; + + // Find a context in the table and call the ExpandGeneric() with the + // right function to do the expansion. + for (i = 0; i < (int)ARRAY_LENGTH(tab); ++i) + { + if (xp->xp_context == tab[i].context) + { + if (tab[i].ic) + rmp->rm_ic = TRUE; + ret = ExpandGeneric(xp, rmp, num_file, file, + tab[i].func, tab[i].escaped); + break; + } + } + + return ret; +} + /* * Do the expansion based on xp->xp_context and "pat". */ @@ -2082,66 +2351,7 @@ ExpandFromContext( if (xp->xp_context == EXPAND_FILES || xp->xp_context == EXPAND_DIRECTORIES || xp->xp_context == EXPAND_FILES_IN_PATH) - { - // Expand file or directory names. - int free_pat = FALSE; - int i; - - // for ":set path=" and ":set tags=" halve backslashes for escaped - // space - if (xp->xp_backslash != XP_BS_NONE) - { - free_pat = TRUE; - pat = vim_strsave(pat); - for (i = 0; pat[i]; ++i) - if (pat[i] == '\\') - { - if (xp->xp_backslash == XP_BS_THREE - && pat[i + 1] == '\\' - && pat[i + 2] == '\\' - && pat[i + 3] == ' ') - STRMOVE(pat + i, pat + i + 3); - if (xp->xp_backslash == XP_BS_ONE - && pat[i + 1] == ' ') - STRMOVE(pat + i, pat + i + 1); - } - } - - if (xp->xp_context == EXPAND_FILES) - flags |= EW_FILE; - else if (xp->xp_context == EXPAND_FILES_IN_PATH) - flags |= (EW_FILE | EW_PATH); - else - flags = (flags | EW_DIR) & ~EW_FILE; - if (options & WILD_ICASE) - flags |= EW_ICASE; - - // Expand wildcards, supporting %:h and the like. - ret = expand_wildcards_eval(&pat, num_file, file, flags); - if (free_pat) - vim_free(pat); -#ifdef BACKSLASH_IN_FILENAME - if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0) - { - int j; - - for (j = 0; j < *num_file; ++j) - { - char_u *ptr = (*file)[j]; - - while (*ptr != NUL) - { - if (p_csl[0] == 's' && *ptr == '\\') - *ptr = '/'; - else if (p_csl[0] == 'b' && *ptr == '/') - *ptr = '\\'; - ptr += (*mb_ptr2len)(ptr); - } - } - } -#endif - return ret; - } + return expand_files_and_dirs(xp, pat, file, num_file, flags, options); *file = (char_u **)""; *num_file = 0; @@ -2231,80 +2441,7 @@ ExpandFromContext( ret = ExpandUserDefined(xp, ®match, num_file, file); # endif else - { - static struct expgen - { - int context; - char_u *((*func)(expand_T *, int)); - int ic; - int escaped; - } tab[] = - { - {EXPAND_COMMANDS, get_command_name, FALSE, TRUE}, - {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE}, - {EXPAND_MAPCLEAR, get_mapclear_arg, TRUE, TRUE}, - {EXPAND_MESSAGES, get_messages_arg, TRUE, TRUE}, - {EXPAND_HISTORY, get_history_arg, TRUE, TRUE}, - {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE}, - {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE}, - {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE}, - {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE}, - {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE}, -# ifdef FEAT_EVAL - {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE}, - {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE}, - {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE}, - {EXPAND_DISASSEMBLE, get_disassemble_argument, FALSE, TRUE}, - {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE}, -# endif -# ifdef FEAT_MENU - {EXPAND_MENUS, get_menu_name, FALSE, TRUE}, - {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE}, -# endif -# ifdef FEAT_SYN_HL - {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE}, -# endif -# ifdef FEAT_PROFILE - {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE}, -# endif - {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE}, - {EXPAND_EVENTS, get_event_name, TRUE, FALSE}, - {EXPAND_AUGROUP, get_augroup_name, TRUE, FALSE}, -# ifdef FEAT_CSCOPE - {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE}, -# endif -# ifdef FEAT_SIGNS - {EXPAND_SIGN, get_sign_name, TRUE, TRUE}, -# endif -# ifdef FEAT_PROFILE - {EXPAND_PROFILE, get_profile_name, TRUE, TRUE}, -# endif -# if defined(HAVE_LOCALE_H) || defined(X_LOCALE) - {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE}, - {EXPAND_LOCALES, get_locales, TRUE, FALSE}, -# endif - {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, - {EXPAND_USER, get_users, TRUE, FALSE}, - {EXPAND_ARGLIST, get_arglist_name, TRUE, FALSE}, -#ifdef FEAT_GUI_MACVIM - {EXPAND_MACACTION, get_macaction_name, FALSE, FALSE}, -#endif - }; - int i; - - // Find a context in the table and call the ExpandGeneric() with the - // right function to do the expansion. - ret = FAIL; - for (i = 0; i < (int)ARRAY_LENGTH(tab); ++i) - if (xp->xp_context == tab[i].context) - { - if (tab[i].ic) - regmatch.rm_ic = TRUE; - ret = ExpandGeneric(xp, ®match, num_file, file, - tab[i].func, tab[i].escaped); - break; - } - } + ret = ExpandOther(xp, ®match, num_file, file); vim_regfree(regmatch.regprog); vim_free(tofree); diff --git a/src/crypt.c b/src/crypt.c index e5d0d9167b..d66e50cc48 100644 --- a/src/crypt.c +++ b/src/crypt.c @@ -162,6 +162,22 @@ typedef struct { # ifdef DYNAMIC_SODIUM +# ifdef MSWIN +# define SODIUM_PROC FARPROC +# define load_dll vimLoadLib +# define symbol_from_dll GetProcAddress +# define close_dll FreeLibrary +# define load_dll_error GetWin32Error +# else +# error Dynamic loading of libsodium is not supported for now. +//# define HINSTANCE void* +//# define SODIUM_PROC void* +//# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL) +//# define symbol_from_dll dlsym +//# define close_dll dlclose +//# define load_dll_error dlerror +# endif + # define sodium_init load_sodium # define sodium_free dll_sodium_free # define sodium_malloc dll_sodium_malloc @@ -214,53 +230,72 @@ static void (*dll_randombytes_buf)(void * const buf, const size_t size); static struct { const char *name; - FARPROC *ptr; + SODIUM_PROC *ptr; } sodium_funcname_table[] = { - {"sodium_init", (FARPROC*)&dll_sodium_init}, - {"sodium_free", (FARPROC*)&dll_sodium_free}, - {"sodium_malloc", (FARPROC*)&dll_sodium_malloc}, - {"sodium_memzero", (FARPROC*)&dll_sodium_memzero}, - {"sodium_mlock", (FARPROC*)&dll_sodium_mlock}, - {"sodium_munlock", (FARPROC*)&dll_sodium_munlock}, - {"crypto_secretstream_xchacha20poly1305_init_push", (FARPROC*)&dll_crypto_secretstream_xchacha20poly1305_init_push}, - {"crypto_secretstream_xchacha20poly1305_push", (FARPROC*)&dll_crypto_secretstream_xchacha20poly1305_push}, - {"crypto_secretstream_xchacha20poly1305_init_pull", (FARPROC*)&dll_crypto_secretstream_xchacha20poly1305_init_pull}, - {"crypto_secretstream_xchacha20poly1305_pull", (FARPROC*)&dll_crypto_secretstream_xchacha20poly1305_pull}, - {"crypto_pwhash", (FARPROC*)&dll_crypto_pwhash}, - {"randombytes_buf", (FARPROC*)&dll_randombytes_buf}, + {"sodium_init", (SODIUM_PROC*)&dll_sodium_init}, + {"sodium_free", (SODIUM_PROC*)&dll_sodium_free}, + {"sodium_malloc", (SODIUM_PROC*)&dll_sodium_malloc}, + {"sodium_memzero", (SODIUM_PROC*)&dll_sodium_memzero}, + {"sodium_mlock", (SODIUM_PROC*)&dll_sodium_mlock}, + {"sodium_munlock", (SODIUM_PROC*)&dll_sodium_munlock}, + {"crypto_secretstream_xchacha20poly1305_init_push", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_init_push}, + {"crypto_secretstream_xchacha20poly1305_push", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_push}, + {"crypto_secretstream_xchacha20poly1305_init_pull", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_init_pull}, + {"crypto_secretstream_xchacha20poly1305_pull", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_pull}, + {"crypto_pwhash", (SODIUM_PROC*)&dll_crypto_pwhash}, + {"randombytes_buf", (SODIUM_PROC*)&dll_randombytes_buf}, {NULL, NULL} }; static int -load_sodium(void) +sodium_runtime_link_init(int verbose) { - static HANDLE hsodium = NULL; + static HINSTANCE hsodium = NULL; + const char *libname = "libsodium.dll"; int i; if (hsodium != NULL) - return 0; + return OK; - hsodium = vimLoadLib("libsodium.dll"); + hsodium = load_dll(libname); if (hsodium == NULL) { - // TODO: Show error message. - return -1; + if (verbose) + semsg(_(e_could_not_load_library_str_str), libname, load_dll_error()); + return FAIL; } for (i = 0; sodium_funcname_table[i].ptr; ++i) { - if ((*sodium_funcname_table[i].ptr = GetProcAddress(hsodium, + if ((*sodium_funcname_table[i].ptr = symbol_from_dll(hsodium, sodium_funcname_table[i].name)) == NULL) { FreeLibrary(hsodium); hsodium = NULL; - // TODO: Show error message. - return -1; + if (verbose) + semsg(_(e_could_not_load_library_function_str), sodium_funcname_table[i].name); + return FAIL; } } + return OK; +} + + static int +load_sodium(void) +{ + if (sodium_runtime_link_init(TRUE) == FAIL) + return -1; return dll_sodium_init(); } # endif + +# if defined(DYNAMIC_SODIUM) || defined(PROTO) + int +sodium_enabled(int verbose) +{ + return sodium_runtime_link_init(verbose) == OK; +} +# endif #endif #define CRYPT_MAGIC_LEN 12 // cannot change diff --git a/src/errors.h b/src/errors.h index d71bd06b1c..a57f76db19 100644 --- a/src/errors.h +++ b/src/errors.h @@ -2833,7 +2833,7 @@ EXTERN char e_unknown_error_while_executing_str[] INIT(= N_("E1099: Unknown error while executing %s")); EXTERN char e_command_not_supported_in_vim9_script_missing_var_str[] INIT(= N_("E1100: Command not supported in Vim9 script (missing :var?): %s")); -EXTERN char e_cannot_declare_script_variable_in_function[] +EXTERN char e_cannot_declare_script_variable_in_function_str[] INIT(= N_("E1101: Cannot declare a script variable in a function: %s")); EXTERN char e_lambda_function_not_found_str[] INIT(= N_("E1102: Lambda function not found: %s")); @@ -3237,4 +3237,8 @@ EXTERN char e_critical_error_in_python3_initialization_check_your_installation[] #ifdef FEAT_EVAL EXTERN char e_function_name_must_start_with_capital_str[] INIT(= N_("E1267: Function name must start with a capital: %s")); +EXTERN char e_cannot_use_s_colon_in_vim9_script_str[] + INIT(= N_("E1268: Cannot use s: in Vim9 script: %s")); +EXTERN char e_cannot_create_vim9_script_variable_in_function_str[] + INIT(= N_("E1269: Cannot create a Vim9 script variable in a function: %s")); #endif diff --git a/src/eval.c b/src/eval.c index 81a1dd0a97..c4c403c19d 100644 --- a/src/eval.c +++ b/src/eval.c @@ -865,6 +865,7 @@ get_lval( hashtab_T *ht = NULL; int quiet = flags & GLV_QUIET; int writing; + int vim9script = in_vim9script(); // Clear everything in "lp". CLEAR_POINTER(lp); @@ -878,6 +879,14 @@ get_lval( return lp->ll_name_end; } + // Cannot use "s:var" at the Vim9 script level. "s: type" is OK. + if (vim9script && at_script_level() + && name[0] == 's' && name[1] == ':' && !VIM_ISWHITE(name[2])) + { + semsg(_(e_cannot_use_s_colon_in_vim9_script_str), name); + return NULL; + } + // Find the end of the name. p = find_name_end(name, &expr_start, &expr_end, fne_flags); lp->ll_name_end = p; @@ -910,7 +919,7 @@ get_lval( { lp->ll_name = name; - if (in_vim9script()) + if (vim9script) { // "a: type" is declaring variable "a" with a type, not "a:". if (p == name + 2 && p[-1] == ':') @@ -958,8 +967,7 @@ get_lval( if (*p == '.') { - imported_T *import = find_imported(lp->ll_name, p - lp->ll_name, - TRUE, NULL); + imported_T *import = find_imported(lp->ll_name, p - lp->ll_name, TRUE); if (import != NULL) { @@ -988,7 +996,7 @@ get_lval( if ((*p != '[' && *p != '.')) return p; - if (in_vim9script() && lval_root != NULL) + if (vim9script && lval_root != NULL) { // using local variable lp->ll_tv = lval_root; @@ -1010,7 +1018,7 @@ get_lval( lp->ll_tv = &v->di_tv; } - if (in_vim9script() && (flags & GLV_NO_DECL) == 0) + if (vim9script && (flags & GLV_NO_DECL) == 0) { if (!quiet) semsg(_(e_variable_already_declared), lp->ll_name); @@ -1053,7 +1061,7 @@ get_lval( return NULL; } - if (in_vim9script() && lp->ll_valtype == NULL + if (vim9script && lp->ll_valtype == NULL && v != NULL && lp->ll_tv == &v->di_tv && ht != NULL && ht == get_script_local_ht()) @@ -2604,7 +2612,7 @@ eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg) *arg = eval_next_line(evalarg_used); else { - if (evaluate && in_vim9script() && !VIM_ISWHITE(p[-1])) + if (evaluate && vim9script && !VIM_ISWHITE(p[-1])) { error_white_both(p, 2); clear_tv(rettv); @@ -2616,7 +2624,7 @@ eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg) /* * Get the second variable. */ - if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[2])) + if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[2])) { error_white_both(*arg, 2); clear_tv(rettv); @@ -2742,7 +2750,7 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg) /* * Get the second variable. */ - if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[2])) + if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[2])) { error_white_both(*arg, 2); clear_tv(rettv); @@ -3519,7 +3527,8 @@ eval7( char_u *start_leader, *end_leader; int ret = OK; char_u *alias; - static int recurse = 0; + static int recurse = 0; + int vim9script = in_vim9script(); /* * Initialise variable so that clear_tv() can't mistake this for a @@ -3531,7 +3540,7 @@ eval7( * Skip '!', '-' and '+' characters. They are handled later. */ start_leader = *arg; - if (eval_leader(arg, in_vim9script()) == FAIL) + if (eval_leader(arg, vim9script) == FAIL) return FAIL; end_leader = *arg; @@ -3606,7 +3615,7 @@ eval7( /* * Dictionary: #{key: val, key: val} */ - case '#': if (in_vim9script()) + case '#': if (vim9script) { ret = vim9_bad_comment(*arg) ? FAIL : NOTDONE; } @@ -3623,10 +3632,10 @@ eval7( * Lambda: {arg, arg -> expr} * Dictionary: {'key': val, 'key': val} */ - case '{': if (in_vim9script()) + case '{': if (vim9script) ret = NOTDONE; else - ret = get_lambda_tv(arg, rettv, in_vim9script(), evalarg); + ret = get_lambda_tv(arg, rettv, vim9script, evalarg); if (ret == NOTDONE) ret = eval_dict(arg, rettv, evalarg, FALSE); break; @@ -3649,9 +3658,9 @@ eval7( case '@': ++*arg; if (evaluate) { - if (in_vim9script() && IS_WHITE_OR_NUL(**arg)) + if (vim9script && IS_WHITE_OR_NUL(**arg)) semsg(_(e_syntax_error_at_str), *arg); - else if (in_vim9script() && !valid_yank_reg(**arg, FALSE)) + else if (vim9script && !valid_yank_reg(**arg, FALSE)) emsg_invreg(**arg); else { @@ -3669,7 +3678,7 @@ eval7( * or lambda: (arg) => expr */ case '(': ret = NOTDONE; - if (in_vim9script()) + if (vim9script) { ret = get_lambda_tv(arg, rettv, TRUE, evalarg); if (ret == OK && evaluate) @@ -3727,12 +3736,18 @@ eval7( { int flags = evalarg == NULL ? 0 : evalarg->eval_flags; - if (evaluate && in_vim9script() && len == 1 && *s == '_') + if (evaluate && vim9script && len == 1 && *s == '_') { emsg(_(e_cannot_use_underscore_here)); ret = FAIL; } - else if ((in_vim9script() ? **arg : *skipwhite(*arg)) == '(') + else if (evaluate && vim9script && len > 2 + && s[0] == 's' && s[1] == ':') + { + semsg(_(e_cannot_use_s_colon_in_vim9_script_str), s); + ret = FAIL; + } + else if ((vim9script ? **arg : *skipwhite(*arg)) == '(') { // "name(..." recursive! *arg = skipwhite(*arg); @@ -3743,21 +3758,19 @@ eval7( else if (evaluate) { // get the value of "true", "false" or a variable - if (len == 4 && in_vim9script() && STRNCMP(s, "true", 4) == 0) + if (len == 4 && vim9script && STRNCMP(s, "true", 4) == 0) { rettv->v_type = VAR_BOOL; rettv->vval.v_number = VVAL_TRUE; ret = OK; } - else if (len == 5 && in_vim9script() - && STRNCMP(s, "false", 5) == 0) + else if (len == 5 && vim9script && STRNCMP(s, "false", 5) == 0) { rettv->v_type = VAR_BOOL; rettv->vval.v_number = VVAL_FALSE; ret = OK; } - else if (len == 4 && in_vim9script() - && STRNCMP(s, "null", 4) == 0) + else if (len == 4 && vim9script && STRNCMP(s, "null", 4) == 0) { rettv->v_type = VAR_SPECIAL; rettv->vval.v_number = VVAL_NULL; @@ -3812,6 +3825,7 @@ eval7_leader( int error = FALSE; varnumber_T val = 0; vartype_T type = rettv->v_type; + int vim9script = in_vim9script(); #ifdef FEAT_FLOAT float_T f = 0.0; @@ -3822,7 +3836,7 @@ eval7_leader( { while (VIM_ISWHITE(end_leader[-1])) --end_leader; - if (in_vim9script() && end_leader[-1] == '!') + if (vim9script && end_leader[-1] == '!') val = tv2bool(rettv); else val = tv_get_number_chk(rettv, &error); @@ -3847,7 +3861,7 @@ eval7_leader( #ifdef FEAT_FLOAT if (rettv->v_type == VAR_FLOAT) { - if (in_vim9script()) + if (vim9script) { rettv->v_type = VAR_BOOL; val = f == 0.0 ? VVAL_TRUE : VVAL_FALSE; @@ -3885,7 +3899,7 @@ eval7_leader( #endif { clear_tv(rettv); - if (in_vim9script()) + if (vim9script) rettv->v_type = type; else rettv->v_type = VAR_NUMBER; @@ -4137,7 +4151,7 @@ eval_index( int range = FALSE; char_u *key = NULL; int keylen = -1; - int vim9 = in_vim9script(); + int vim9script = in_vim9script(); if (check_can_index(rettv, evaluate, verbose) == FAIL) return FAIL; @@ -4168,7 +4182,7 @@ eval_index( empty1 = TRUE; else if (eval1(arg, &var1, evalarg) == FAIL) // recursive! return FAIL; - else if (vim9 && **arg == ':') + else if (vim9script && **arg == ':') { semsg(_(e_white_space_required_before_and_after_str_at_str), ":", *arg); @@ -4181,14 +4195,14 @@ eval_index( #ifdef FEAT_FLOAT // allow for indexing with float - if (vim9 && rettv->v_type == VAR_DICT + if (vim9script && rettv->v_type == VAR_DICT && var1.v_type == VAR_FLOAT) { var1.vval.v_string = typval_tostring(&var1, TRUE); var1.v_type = VAR_STRING; } #endif - if (vim9 && rettv->v_type == VAR_LIST) + if (vim9script && rettv->v_type == VAR_LIST) tv_get_number_chk(&var1, &error); else error = tv_get_string_chk(&var1) == NULL; @@ -4208,7 +4222,7 @@ eval_index( { range = TRUE; ++*arg; - if (vim9 && !IS_WHITE_OR_NUL(**arg) && **arg != ']') + if (vim9script && !IS_WHITE_OR_NUL(**arg) && **arg != ']') { semsg(_(e_white_space_required_before_and_after_str_at_str), ":", *arg - 1); diff --git a/src/evalfunc.c b/src/evalfunc.c index 6de9364dc2..e70d66afc6 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3131,7 +3131,7 @@ f_call(typval_T *argvars, typval_T *rettv) dot = vim_strchr(func, '.'); if (dot != NULL) { - imported_T *import = find_imported(func, dot - func, TRUE, NULL); + imported_T *import = find_imported(func, dot - func, TRUE); if (import != NULL && SCRIPT_ID_VALID(import->imp_sid)) { @@ -6018,7 +6018,7 @@ f_has(typval_T *argvars, typval_T *rettv) #endif }, {"sodium", -#ifdef FEAT_SODIUM +#if defined(FEAT_SODIUM) && !defined(DYNAMIC_SODIUM) 1 #else 0 @@ -6353,6 +6353,10 @@ f_has(typval_T *argvars, typval_T *rettv) else if (STRICMP(name, "tcl") == 0) n = tcl_enabled(FALSE); #endif +#ifdef DYNAMIC_SODIUM + else if (STRICMP(name, "sodium") == 0) + n = sodium_enabled(FALSE); +#endif #if defined(FEAT_TERMINAL) && defined(MSWIN) else if (STRICMP(name, "terminal") == 0) n = terminal_enabled(); diff --git a/src/evalvars.c b/src/evalvars.c index cebe3041fd..216e1eb9cd 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -2737,7 +2737,7 @@ eval_variable( char_u *p = STRNCMP(name, "s:", 2) == 0 ? name + 2 : name; if (sid == 0) - import = find_imported(p, 0, TRUE, NULL); + import = find_imported(p, 0, TRUE); // imported variable from another script if (import != NULL || sid != 0) @@ -3098,7 +3098,7 @@ lookup_scriptitem( res = HASHITEM_EMPTY(hi) ? FAIL : OK; // if not script-local, then perhaps imported - if (res == FAIL && find_imported(p, 0, FALSE, NULL) != NULL) + if (res == FAIL && find_imported(p, 0, FALSE) != NULL) res = OK; if (p != buffer) vim_free(p); @@ -3493,7 +3493,7 @@ set_var_const( if (di == NULL && var_in_vim9script) { - imported_T *import = find_imported(varname, 0, FALSE, NULL); + imported_T *import = find_imported(varname, 0, FALSE); if (import != NULL) { @@ -3506,6 +3506,12 @@ set_var_const( semsg(_(e_cannot_use_str_itself_it_is_imported), name); goto failed; } + if (!in_vim9script()) + { + semsg(_(e_cannot_create_vim9_script_variable_in_function_str), + name); + goto failed; + } } if (dest_tv == NULL) @@ -4692,7 +4698,7 @@ expand_autload_callback(callback_T *cb) p = vim_strchr(name, '.'); if (p == NULL) return; - import = find_imported(name, p - name, FALSE, NULL); + import = find_imported(name, p - name, FALSE); if (import != NULL && SCRIPT_ID_VALID(import->imp_sid)) { scriptitem_T *si = SCRIPT_ITEM(import->imp_sid); diff --git a/src/feature.h b/src/feature.h index 36cd065c3e..18d5c75e8a 100644 --- a/src/feature.h +++ b/src/feature.h @@ -56,7 +56,7 @@ /* * For Unix, Mac and Win32 use +huge by default. These days CPUs are fast and * Memory is cheap. - * Use +big for older systems: Other MS-Windows and VMS. + * Use +big for older systems: VMS and Amiga. * Otherwise use +normal */ #if !defined(FEAT_TINY) && !defined(FEAT_SMALL) && !defined(FEAT_NORMAL) \ @@ -64,7 +64,7 @@ # if defined(UNIX) || defined(MSWIN) || defined(MACOS_X) # define FEAT_HUGE # else -# if defined(MSWIN) || defined(VMS) || defined(AMIGA) +# if defined(VMS) || defined(AMIGA) # define FEAT_BIG # else # define FEAT_NORMAL diff --git a/src/gui_dwrite.cpp b/src/gui_dwrite.cpp index 83acdab1ad..62d23e7277 100644 --- a/src/gui_dwrite.cpp +++ b/src/gui_dwrite.cpp @@ -59,7 +59,7 @@ #endif #ifdef DYNAMIC_DIRECTX -extern "C" HINSTANCE vimLoadLib(char *name); +extern "C" HINSTANCE vimLoadLib(const char *name); typedef int (WINAPI *PGETUSERDEFAULTLOCALENAME)(LPWSTR, int); typedef HRESULT (WINAPI *PD2D1CREATEFACTORY)(D2D1_FACTORY_TYPE, @@ -1212,8 +1212,8 @@ DWrite_Init(void) { #ifdef DYNAMIC_DIRECTX // Load libraries. - hD2D1DLL = vimLoadLib(const_cast("d2d1.dll")); - hDWriteDLL = vimLoadLib(const_cast("dwrite.dll")); + hD2D1DLL = vimLoadLib("d2d1.dll"); + hDWriteDLL = vimLoadLib("dwrite.dll"); if (hD2D1DLL == NULL || hDWriteDLL == NULL) { DWrite_Final(); diff --git a/src/if_cscope.c b/src/if_cscope.c index f8d4dc6df2..f373952dd8 100644 --- a/src/if_cscope.c +++ b/src/if_cscope.c @@ -1371,10 +1371,7 @@ cs_insert_filelist( char *winmsg = GetWin32Error(); if (winmsg != NULL) - { (void)semsg(cant_msg, winmsg); - LocalFree(winmsg); - } else // subst filename if can't get error text (void)semsg(cant_msg, fname); diff --git a/src/indent.c b/src/indent.c index 9b137b0b42..95fc74ee46 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1607,6 +1607,7 @@ ex_retab(exarg_T *eap) long start_col = 0; // For start of white-space string long start_vcol = 0; // For start of white-space string long old_len; + long new_len; char_u *ptr; char_u *new_line = (char_u *)1; // init to non-NULL int did_undo; // called u_save for current line @@ -1724,7 +1725,13 @@ ex_retab(exarg_T *eap) // len is actual number of white characters used len = num_spaces + num_tabs; old_len = (long)STRLEN(ptr); - new_line = alloc(old_len - col + start_col + len + 1); + new_len = old_len - col + start_col + len + 1; + if (new_len <= 0 || new_len >= MAXCOL) + { + emsg(_(e_resulting_text_too_long)); + break; + } + new_line = alloc(new_len); if (new_line == NULL) break; if (start_col > 0) @@ -1750,6 +1757,11 @@ ex_retab(exarg_T *eap) if (ptr[col] == NUL) break; vcol += chartabsize(ptr + col, (colnr_T)vcol); + if (vcol >= MAXCOL) + { + emsg(_(e_resulting_text_too_long)); + break; + } if (has_mbyte) col += (*mb_ptr2len)(ptr + col); else diff --git a/src/option.c b/src/option.c index 9390be64e8..29a014ec83 100644 --- a/src/option.c +++ b/src/option.c @@ -5715,7 +5715,7 @@ win_copy_options(win_T *wp_from, win_T *wp_to) * After copying window options: update variables depending on options. */ void -after_copy_winopt(win_T *wp UNUSED) +after_copy_winopt(win_T *wp) { #ifdef FEAT_LINEBREAK briopt_check(wp); diff --git a/src/os_amiga.c b/src/os_amiga.c index c6d9c253fe..6717f0b183 100644 --- a/src/os_amiga.c +++ b/src/os_amiga.c @@ -154,7 +154,7 @@ mch_inchar( char_u *buf, int maxlen, long time, // milliseconds - int tb_change_cnt) + int tb_change_cnt UNUSED) { int len; long utime; @@ -571,7 +571,7 @@ mch_input_isatty(void) void fname_case( char_u *name, - int len) // buffer size, ignored here + int len UNUSED) // buffer size, ignored here { struct FileInfoBlock *fib; size_t flen; @@ -837,7 +837,7 @@ mch_setperm(char_u *name, long perm) * Set hidden flag for "name". */ void -mch_hide(char_u *name) +mch_hide(char_u *name UNUSED) { // can't hide a file } @@ -889,7 +889,7 @@ mch_mkdir(char_u *name) * Return -1 if unknown. */ int -mch_can_exe(char_u *name, char_u **path, int use_path) +mch_can_exe(char_u *name, char_u **path UNUSED, int use_path) { int exe = -1; #ifdef __amigaos4__ @@ -942,7 +942,7 @@ mch_can_exe(char_u *name, char_u **path, int use_path) * NODE_OTHER: non-writable things */ int -mch_nodetype(char_u *name) +mch_nodetype(char_u *name UNUSED) { // TODO return NODE_NORMAL; @@ -1490,7 +1490,7 @@ mch_call_shell( * trouble with lattice-c programs. */ void -mch_breakcheck(int force) +mch_breakcheck(int force UNUSED) { if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C) got_int = TRUE; @@ -1755,7 +1755,7 @@ mch_getenv(char_u *var) */ // ARGSUSED int -mch_setenv(char *var, char *value, int x) +mch_setenv(char *var, char *value, int x UNUSED) { #ifdef FEAT_ARP if (!dos2) diff --git a/src/os_win32.c b/src/os_win32.c index 682fdf2bcf..fbf666598f 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -520,7 +520,7 @@ unescape_shellxquote(char_u *p, char_u *escaped) * Load library "name". */ HINSTANCE -vimLoadLib(char *name) +vimLoadLib(const char *name) { HINSTANCE dll = NULL; @@ -8279,15 +8279,20 @@ resize_console_buf(void) char * GetWin32Error(void) { + static char *oldmsg = NULL; char *msg = NULL; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, (LPSTR)&msg, 0, NULL); + if (oldmsg != NULL) + LocalFree(oldmsg); if (msg != NULL) { // remove trailing \r\n char *pcrlf = strstr(msg, "\r\n"); if (pcrlf != NULL) *pcrlf = '\0'; + oldmsg = msg; } return msg; } diff --git a/src/proto/crypt.pro b/src/proto/crypt.pro index 682fe4533b..d6c7b7ffde 100644 --- a/src/proto/crypt.pro +++ b/src/proto/crypt.pro @@ -1,4 +1,5 @@ /* crypt.c */ +int sodium_enabled(int verbose); int crypt_method_nr_from_name(char_u *name); int crypt_method_nr_from_magic(char *ptr, int len); int crypt_works_inplace(cryptstate_T *state); diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro index dac2b7142f..b3c85b7183 100644 --- a/src/proto/os_win32.pro +++ b/src/proto/os_win32.pro @@ -1,5 +1,5 @@ /* os_win32.c */ -HINSTANCE vimLoadLib(char *name); +HINSTANCE vimLoadLib(const char *name); int mch_is_gui_executable(void); HINSTANCE find_imported_module_by_funcname(HINSTANCE hInst, const char *funcname); void *get_dll_import_func(HINSTANCE hInst, const char *funcname); diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro index 4e30d83c4c..b8d14437de 100644 --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -24,6 +24,7 @@ int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T void save_funccal(funccal_entry_T *entry); void restore_funccal(void); funccall_T *get_current_funccal(void); +int at_script_level(void); void delete_script_functions(int sid); void free_all_functions(void); int builtin_function(char_u *name, int len); diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 9effb1744b..0e71b93fa0 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -8,7 +8,7 @@ int need_type_where(type_T *actual, type_T *expected, int offset, where_T where, int need_type(type_T *actual, type_T *expected, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const); lvar_T *reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type); int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx, cstack_T *cstack); -imported_T *find_imported(char_u *name, size_t len, int load, cctx_T *cctx); +imported_T *find_imported(char_u *name, size_t len, int load); char_u *may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp); char_u *peek_next_line_from_context(cctx_T *cctx); char_u *next_line_from_context(cctx_T *cctx, int skip_comment); diff --git a/src/scriptfile.c b/src/scriptfile.c index 3b9fec1cd5..2606737545 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1254,6 +1254,7 @@ do_source( #ifdef FEAT_PROFILE proftime_T wait_start; #endif + int save_sticky_cmdmod_flags = sticky_cmdmod_flags; int trigger_source_post = FALSE; ESTACK_CHECK_DECLARATION @@ -1394,6 +1395,9 @@ do_source( time_push(&tv_rel, &tv_start); #endif + // "legacy" does not apply to commands in the script + sticky_cmdmod_flags = 0; + save_current_sctx = current_sctx; current_sctx.sc_version = 1; // default script version @@ -1618,6 +1622,7 @@ almosttheend: theend: vim_free(fname_exp); + sticky_cmdmod_flags = save_sticky_cmdmod_flags; #ifdef FEAT_EVAL estack_compiling = save_estack_compiling; #endif diff --git a/src/term.c b/src/term.c index 686a4f0548..458adfefc9 100644 --- a/src/term.c +++ b/src/term.c @@ -37,7 +37,7 @@ * A few linux systems define outfuntype in termcap.h to be used as the third * argument for tputs(). */ -# ifdef VMS +# if defined(VMS) || defined(AMIGA) # define TPUTSFUNCAST (void (*)(unsigned int)) # else # ifdef HAVE_OUTFUNTYPE diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 6d0dc5bef7..a38499cca1 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -409,6 +409,12 @@ func Test_getcompletion() call assert_equal(cmds, l) let l = getcompletion('list ', 'sign') call assert_equal(['Testing'], l) + let l = getcompletion('de*', 'sign') + call assert_equal(['define'], l) + let l = getcompletion('p?', 'sign') + call assert_equal(['place'], l) + let l = getcompletion('j.', 'sign') + call assert_equal(['jump'], l) endif " Command line completion tests @@ -461,6 +467,18 @@ func Test_getcompletion() call delete('Xtags') set tags& + edit a~b + enew + call assert_equal(['a~b'], getcompletion('a~', 'buffer')) + bw a~b + + if has('unix') + edit Xtest\ + enew + call assert_equal(['Xtest\'], getcompletion('Xtest\', 'buffer')) + bw Xtest\ + endif + call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:') call assert_fails('call getcompletion("", "burp")', 'E475:') call assert_fails('call getcompletion("abc", [])', 'E475:') @@ -1006,6 +1024,25 @@ func Test_cmdline_complete_various() call feedkeys(":chist\\", 'xt') call assert_equal('"g/a\xb/clearjumps', @:) set wildchar& + + " should be able to complete a file name that starts with a '~'. + if has('unix') + call writefile([], '~Xtest') + call feedkeys(":e \\~X\\\"\", 'xt') + call assert_equal('"e \~Xtest', @:) + call delete('~Xtest') + endif +endfunc + +" Test for 'wildignorecase' +func Test_cmdline_wildignorecase() + CheckUnix + call writefile([], 'XTEST') + set wildignorecase + call feedkeys(":e xt\\\"\", 'xt') + call assert_equal('"e XTEST', @:) + set wildignorecase& + call delete('XTEST') endfunc func Test_cmdline_write_alternatefile() @@ -1627,6 +1664,14 @@ func Test_wildmode() call assert_equal('AAA AAAA AAAAA', g:Sline) call assert_equal('"b A', @:) + " when using longest completion match, matches shorter than the argument + " should be ignored (happens with :help) + set wildmode=longest,full + set wildmenu + call feedkeys(":help a*\t\\"\", 'xt') + call assert_equal('"help a', @:) + set wildmenu& + %argdelete delcommand MyCmd delfunc T diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim index 2189a0e8c6..7a998bc307 100644 --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -595,8 +595,8 @@ endfunc func Test_function_with_funcref() let lines =<< trim END - VAR s:F = function('type') - VAR s:Fref = function(s:F) + let s:F = function('type') + let s:Fref = function(s:F) call assert_equal(v:t_string, s:Fref('x')) call assert_fails("call function('s:F')", 'E700:') @@ -604,16 +604,34 @@ func Test_function_with_funcref() call assert_fails("call function('foo()')", 'foo()') call assert_fails("function('')", 'E129:') - legacy let s:Len = {s -> strlen(s)} + let s:Len = {s -> strlen(s)} call assert_equal(6, s:Len('foobar')) - VAR name = string(s:Len) - #" can evaluate "function('99')" - call execute('VAR Ref = ' .. name) + let name = string(s:Len) + " can evaluate "function('99')" + call execute('let Ref = ' .. name) call assert_equal(4, Ref('text')) END - call v9.CheckTransLegacySuccess(lines) - " cannot create s: variable in :def function - call v9.CheckTransVim9Success(lines) + call v9.CheckScriptSuccess(lines) + + let lines =<< trim END + vim9script + var F = function('type') + var Fref = function(F) + call assert_equal(v:t_string, Fref('x')) + call assert_fails("call function('F')", 'E700:') + + call assert_fails("call function('foo()')", 'E475:') + call assert_fails("call function('foo()')", 'foo()') + call assert_fails("function('')", 'E129:') + + var Len = (s) => strlen(s) + call assert_equal(6, Len('foobar')) + var name = string(Len) + # can evaluate "function('99')" + call execute('var Ref = ' .. name) + call assert_equal(4, Ref('text')) + END + call v9.CheckScriptSuccess(lines) endfunc func Test_funcref() diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 13a494b963..9d12070563 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -436,6 +436,7 @@ let s:filename_checks = { \ 'readline': ['.inputrc', 'inputrc'], \ 'remind': ['.reminders', 'file.remind', 'file.rem', '.reminders-file'], \ 'rego': ['file.rego'], + \ 'rescript': ['file.res', 'file.resi'], \ 'resolv': ['resolv.conf'], \ 'reva': ['file.frt'], \ 'rexx': ['file.rex', 'file.orx', 'file.rxo', 'file.rxj', 'file.jrexx', 'file.rexxj', 'file.rexx', 'file.testGroup', 'file.testUnit'], diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 6baba9707b..e2820db9c9 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -2798,7 +2798,7 @@ func Test_builtin_check() call assert_fails('let l:.trim = {x -> " " .. x}', 'E704:') let lines =<< trim END vim9script - var s:trim = (x) => " " .. x + var trim = (x) => " " .. x END call v9.CheckScriptFailure(lines, 'E704:') diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index 933f4434be..7e3fd296e2 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -1514,11 +1514,11 @@ func Test_completefunc_callback() bw! # Test for using a script-local function name - def s:LocalCompleteFunc(findstart: number, base: string): any + def LocalCompleteFunc(findstart: number, base: string): any add(g:LocalCompleteFuncArgs, [findstart, base]) return findstart ? 0 : [] enddef - &completefunc = s:LocalCompleteFunc + &completefunc = LocalCompleteFunc new | only setline(1, 'three') g:LocalCompleteFuncArgs = [] @@ -1771,11 +1771,11 @@ func Test_omnifunc_callback() bw! # Test for using a script-local function name - def s:LocalOmniFunc(findstart: number, base: string): any + def LocalOmniFunc(findstart: number, base: string): any add(g:LocalOmniFuncArgs, [findstart, base]) return findstart ? 0 : [] enddef - &omnifunc = s:LocalOmniFunc + &omnifunc = LocalOmniFunc new | only setline(1, 'three') g:LocalOmniFuncArgs = [] @@ -2064,11 +2064,11 @@ func Test_thesaurusfunc_callback() bw! # Test for using a script-local function name - def s:LocalTsrFunc(findstart: number, base: string): any + def LocalTsrFunc(findstart: number, base: string): any add(g:LocalTsrFuncArgs, [findstart, base]) return findstart ? 0 : [] enddef - &thesaurusfunc = s:LocalTsrFunc + &thesaurusfunc = LocalTsrFunc new | only setline(1, 'three') g:LocalTsrFuncArgs = [] diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index 2ed6a80dfa..cd987ab3d0 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -684,10 +684,10 @@ func Test_opfunc_callback() bw! # Test for using a script-local function name - def s:LocalOpFunc(type: string): void + def LocalOpFunc(type: string): void g:LocalOpFuncArgs = [type] enddef - &opfunc = s:LocalOpFunc + &opfunc = LocalOpFunc g:LocalOpFuncArgs = [] normal! g@l assert_equal(['char'], g:LocalOpFuncArgs) diff --git a/src/testdir/test_retab.vim b/src/testdir/test_retab.vim index c7190aaa66..6133e8fb4a 100644 --- a/src/testdir/test_retab.vim +++ b/src/testdir/test_retab.vim @@ -70,6 +70,8 @@ func Test_retab() call assert_equal(" a b c ", Retab('!', 3)) call assert_equal(" a b c ", Retab('', 5)) call assert_equal(" a b c ", Retab('!', 5)) + + set tabstop& expandtab& endfunc func Test_retab_error() @@ -80,4 +82,21 @@ func Test_retab_error() call assert_fails('ret 80000000000000000000', 'E475:') endfunc +func Test_retab_endless() + new + call setline(1, "\t0\t") + let caught = 'no' + try + while 1 + set ts=4000 + retab 4 + endwhile + catch /E1240/ + let caught = 'yes' + endtry + bwipe! + set tabstop& +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_tagfunc.vim b/src/testdir/test_tagfunc.vim index 66a58ec47b..05d8473cfb 100644 --- a/src/testdir/test_tagfunc.vim +++ b/src/testdir/test_tagfunc.vim @@ -369,11 +369,11 @@ func Test_tagfunc_callback() bw! # Test for using a script-local function name - def s:LocalTagFunc(pat: string, flags: string, info: dict ): any + def LocalTagFunc(pat: string, flags: string, info: dict ): any g:LocalTagFuncArgs = [pat, flags, info] return null enddef - &tagfunc = s:LocalTagFunc + &tagfunc = LocalTagFunc new g:LocalTagFuncArgs = [] assert_fails('tag a12', 'E433:') diff --git a/src/testdir/test_usercommands.vim b/src/testdir/test_usercommands.vim index 331e55f01a..d6ac9650a5 100644 --- a/src/testdir/test_usercommands.vim +++ b/src/testdir/test_usercommands.vim @@ -384,6 +384,17 @@ func Test_CmdCompletion() com! -nargs=? -complete=custom,min DoCmd call assert_fails("call feedkeys(':DoCmd \t', 'tx')", 'E118:') + " custom completion for a pattern with a backslash + let g:ArgLead = '' + func! CustCompl(A, L, P) + let g:ArgLead = a:A + return ['one', 'two', 'three'] + endfunc + com! -nargs=? -complete=customlist,CustCompl DoCmd + call feedkeys(":DoCmd a\\\t", 'xt') + call assert_equal('a\', g:ArgLead) + delfunc CustCompl + delcom DoCmd endfunc diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 7d3e2c1356..d9b8f3a24b 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -6,6 +6,7 @@ source term_util.vim let s:appendToMe = 'xxx' let s:addToMe = 111 +let s:newVar = '' let g:existing = 'yes' let g:inc_counter = 1 let $SOME_ENV_VAR = 'some' @@ -124,12 +125,12 @@ def Test_assignment() END v9.CheckScriptSuccess(lines) - s:appendToMe ..= 'yyy' - assert_equal('xxxyyy', s:appendToMe) - s:addToMe += 222 - assert_equal(333, s:addToMe) - s:newVar = 'new' - assert_equal('new', s:newVar) + appendToMe ..= 'yyy' + assert_equal('xxxyyy', appendToMe) + addToMe += 222 + assert_equal(333, addToMe) + newVar = 'new' + assert_equal('new', newVar) set ts=7 var ts: number = &ts @@ -1195,7 +1196,7 @@ def Test_assignment_default() assert_equal(5678, nr) enddef -let scriptvar = 'init' +let s:scriptvar = 'init' def Test_assignment_var_list() var lines =<< trim END @@ -1243,17 +1244,17 @@ def Test_assignment_var_list() END v9.CheckDefAndScriptSuccess(lines) - [g:globalvar, s:scriptvar, b:bufvar] = ['global', 'script', 'buf'] + [g:globalvar, scriptvar, b:bufvar] = ['global', 'script', 'buf'] assert_equal('global', g:globalvar) - assert_equal('script', s:scriptvar) + assert_equal('script', scriptvar) assert_equal('buf', b:bufvar) lines =<< trim END vim9script - var s:scriptvar = 'init' - [g:globalvar, s:scriptvar, w:winvar] = ['global', 'script', 'win'] + var scriptvar = 'init' + [g:globalvar, scriptvar, w:winvar] = ['global', 'script', 'win'] assert_equal('global', g:globalvar) - assert_equal('script', s:scriptvar) + assert_equal('script', scriptvar) assert_equal('win', w:winvar) END v9.CheckScriptSuccess(lines) @@ -1398,7 +1399,7 @@ def Test_assignment_failure() v9.CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1) v9.CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:') - v9.CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:') + v9.CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = notfound', 'enddef', 'defcompile'], 'E1001:') v9.CheckDefFailure(['var name: list = [123]'], 'expected list but got list') v9.CheckDefFailure(['var name: list = ["xx"]'], 'expected list but got list') @@ -1719,9 +1720,9 @@ def Test_var_declaration() g:var_uninit = name name = 'text' g:var_test = name - # prefixing s: is optional - s:name = 'prefixed' - g:var_prefixed = s:name + # prefixing s: is not allowed + name = 'prefixed' + g:var_prefixed = name const FOO: number = 123 assert_equal(123, FOO) @@ -1764,9 +1765,9 @@ def Test_var_declaration() var xyz: string # comment # type is inferred - var s:dict = {['a']: 222} + var dict = {['a']: 222} def GetDictVal(key: any) - g:dict_val = s:dict[key] + g:dict_val = dict[key] enddef GetDictVal('a') @@ -1879,13 +1880,13 @@ def Test_var_declaration_fails() enddef def Test_script_local_in_legacy() - # OK to define script-local later when prefixed with s: + # OK to define script-local later but before compiling var lines =<< trim END def SetLater() - s:legvar = 'two' + legvar = 'two' enddef - defcompile let s:legvar = 'one' + defcompile call SetLater() call assert_equal('two', s:legvar) END @@ -1902,7 +1903,7 @@ def Test_script_local_in_legacy() END v9.CheckScriptSuccess(lines) - # Not OK to leave out s: prefix when script-local defined later + # Not OK to leave out s: prefix when script-local defined after compiling lines =<< trim END def SetLaterNoPrefix() legvar = 'two' @@ -1944,15 +1945,15 @@ def Test_var_type_check() lines =<< trim END vim9script - var s:l: list - s:l = [] + var l: list + l = [] END v9.CheckScriptSuccess(lines) lines =<< trim END vim9script - var s:d: dict - s:d = {} + var d: dict + d = {} END v9.CheckScriptSuccess(lines) @@ -2124,7 +2125,7 @@ def Test_unlet() 'vim9script', 'var svar = 123', 'unlet s:svar', - ], 'E1081:') + ], 'E1268:') v9.CheckScriptFailure([ 'vim9script', 'var svar = 123', @@ -2267,14 +2268,14 @@ def Test_script_funcref_case() lines =<< trim END vim9script - var s:Len = (s: string): number => len(s) + 2 + var Len = (s: string): number => len(s) + 2 assert_equal(6, Len('asdf')) END v9.CheckScriptSuccess(lines) lines =<< trim END vim9script - var s:len = (s: string): number => len(s) + 1 + var len = (s: string): number => len(s) + 1 END v9.CheckScriptFailure(lines, 'E704:') enddef diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 3ad6e0e62d..23b9c4936b 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -2001,9 +2001,9 @@ def Test_insert() v9.CheckDefExecAndScriptFailure(lines, 'E1131:', 1) assert_equal([1, 2, 3], insert([2, 3], 1)) - assert_equal([1, 2, 3], insert([2, 3], s:number_one)) + assert_equal([1, 2, 3], insert([2, 3], number_one)) assert_equal([1, 2, 3], insert([1, 2], 3, 2)) - assert_equal([1, 2, 3], insert([1, 2], 3, s:number_two)) + assert_equal([1, 2, 3], insert([1, 2], 3, number_two)) assert_equal(['a', 'b', 'c'], insert(['b', 'c'], 'a')) assert_equal(0z1234, insert(0z34, 0x12)) diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index 4398cbf4f6..8325d7a808 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -106,6 +106,32 @@ def Test_cmdmod_execute() unlet b:undo unlet g:undone unlet g:undtwo + + # "legacy" does not apply to a loaded script + lines =<< trim END + vim9script + export var exported = 'x' + END + writefile(lines, 'Xvim9import.vim') + lines =<< trim END + legacy exe "import './Xvim9import.vim'" + END + v9.CheckScriptSuccess(lines) + delete('Xvim9import.vim') + + # "legacy" does not aply to a called function + lines =<< trim END + vim9script + + def g:TheFunc() + if exists('something') + echo 'yes' + endif + enddef + legacy exe 'call g:TheFunc()' + END + v9.CheckScriptSuccess(lines) + delfunc g:TheFunc enddef def Test_edit_wildcards() @@ -1706,7 +1732,12 @@ def Test_var_not_cmd() lines =<< trim END s:notexist:repl END - v9.CheckDefAndScriptFailure(lines, ['E488: Trailing characters: :repl', 'E121: Undefined variable: s:notexist'], 1) + v9.CheckDefAndScriptFailure(lines, ['E488: Trailing characters: :repl', 'E1268:'], 1) + + lines =<< trim END + notexist:repl + END + v9.CheckDefAndScriptFailure(lines, ['E476:', 'E492:'], 1) lines =<< trim END s-pat-repl diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 1e61853e08..ec71836606 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -300,11 +300,11 @@ def Test_disassemble_push() vim9script import autoload 'autoscript.vim' - def s:AutoloadFunc() + def AutoloadFunc() &operatorfunc = autoscript.Opfunc enddef - var res = execute('disass s:AutoloadFunc') + var res = execute('disass AutoloadFunc') assert_match('\d*_AutoloadFunc.*' .. '&operatorfunc = autoscript.Opfunc\_s*' .. '0 AUTOLOAD autoscript#Opfunc\_s*' .. diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 87b801446a..8399b69fa8 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -2329,7 +2329,7 @@ def Test_expr8_lambda_vim9script() v9.CheckDefAndScriptSuccess(lines) enddef -def Test_expr8_funcref() +def Test_expr8funcref() var lines =<< trim END def RetNumber(): number return 123 @@ -2344,7 +2344,7 @@ def Test_expr8_funcref() func g:GlobalFunc() return 'global' endfunc - func s:ScriptFunc() + func ScriptFunc() return 'script' endfunc def Test() @@ -2353,7 +2353,7 @@ def Test_expr8_funcref() Ref = g:GlobalFunc assert_equal('global', Ref()) - Ref = s:ScriptFunc + Ref = ScriptFunc assert_equal('script', Ref()) Ref = ScriptFunc assert_equal('script', Ref()) @@ -3347,7 +3347,7 @@ func Test_expr8_fails() call v9.CheckDefAndScriptFailure(["var x = ¬exist"], 'E113:', 1) call v9.CheckDefAndScriptFailure(["&grepprg = [343]"], ['E1012:', 'E730:'], 1) - call v9.CheckDefExecAndScriptFailure(["echo s:doesnt_exist"], 'E121:', 1) + call v9.CheckDefExecAndScriptFailure(["echo s:doesnt_exist"], ['E121:', 'E1268:'], 1) call v9.CheckDefExecAndScriptFailure(["echo g:doesnt_exist"], 'E121:', 1) call v9.CheckDefAndScriptFailure(["echo a:somevar"], ['E1075:', 'E121:'], 1) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 46e562d1ed..ecc9c64df5 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -713,7 +713,7 @@ def Test_nested_function() lines =<< trim END vim9script - def s:_Func() + def _Func() echo 'bad' enddef END @@ -930,7 +930,7 @@ def Test_global_local_function() def g:Funcy() echo 'funcy' enddef - s:Funcy() + Funcy() END v9.CheckScriptFailure(lines, 'E117:') enddef @@ -1441,10 +1441,10 @@ enddef def Test_use_script_func_name_with_prefix() var lines =<< trim END vim9script - func s:Getit() + func g:Getit() return 'it' endfunc - var Fn = s:Getit + var Fn = g:Getit assert_equal('it', Fn()) END v9.CheckScriptSuccess(lines) @@ -2849,7 +2849,7 @@ def Test_nested_inline_lambda() lines =<< trim END vim9script - def s:Func() + def Func() range(10) ->mapnew((_, _) => ({ key: range(10)->mapnew((_, _) => { @@ -3168,7 +3168,7 @@ def Test_invalid_function_name() vim9script def s: list END - v9.CheckScriptFailure(lines, 'E129:') + v9.CheckScriptFailure(lines, 'E1268:') lines =<< trim END vim9script diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim index 652e4d36b6..45f64b2c40 100644 --- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -1124,7 +1124,7 @@ def Test_vim9_reload_noclear() lines =<< trim END vim9script noclear g:loadCount += 1 - var s:reloaded = 'init' + var reloaded = 'init' import './XExportReload' as exp def Again(): string @@ -1133,13 +1133,13 @@ def Test_vim9_reload_noclear() exp.TheFunc() - if exists('s:loaded') | finish | endif - var s:loaded = true + if exists('loaded') | finish | endif + var loaded = true - var s:notReloaded = 'yes' - s:reloaded = 'first' + var notReloaded = 'yes' + reloaded = 'first' def g:Values(): list - return [s:reloaded, s:notReloaded, Again(), Once(), exp.exported] + return [reloaded, notReloaded, Again(), Once(), exp.exported] enddef def Once(): string diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 37459a76bc..9993c5edb3 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -69,7 +69,10 @@ def Test_delfunction() 'func CheckMe()', ' return 123', 'endfunc', - 'assert_equal(123, s:CheckMe())', + 'func DoTest()', + ' call assert_equal(123, s:CheckMe())', + 'endfunc', + 'DoTest()', ]) # Check function in script namespace cannot be deleted @@ -178,11 +181,55 @@ def Test_wrong_type() v9.CheckDefFailure(['var Ref: string', 'var res = Ref()'], 'E1085:') enddef +def Test_script_namespace() + # defining a function or variable with s: is not allowed + var lines =<< trim END + vim9script + def s:Function() + enddef + END + v9.CheckScriptFailure(lines, 'E1268:') + + for decl in ['var', 'const', 'final'] + lines =<< trim END + vim9script + var s:var = 'var' + END + v9.CheckScriptFailure([ + 'vim9script', + decl .. ' s:var = "var"', + ], 'E1268:') + endfor + + # Calling a function or using a variable with s: is not allowed at script + # level + lines =<< trim END + vim9script + def Function() + enddef + s:Function() + END + v9.CheckScriptFailure(lines, 'E1268:') + lines =<< trim END + vim9script + def Function() + enddef + call s:Function() + END + v9.CheckScriptFailure(lines, 'E1268:') + lines =<< trim END + vim9script + var var = 'var' + echo s:var + END + v9.CheckScriptFailure(lines, 'E1268:') +enddef + def Test_script_wrong_type() var lines =<< trim END vim9script - var s:dict: dict - s:dict['a'] = ['x'] + var dict: dict + dict['a'] = ['x'] END v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got list', 3) enddef @@ -1057,6 +1104,18 @@ def Test_try_catch_skipped() assert_match("NEWLIST size 0\n", instr) enddef +def Test_throw_line_number() + def Func() + eval 1 + 1 + eval 2 + 2 + throw 'exception' + enddef + try + Func() + catch /exception/ + assert_match('line 3', v:throwpoint) + endtry +enddef def Test_throw_vimscript() @@ -3012,13 +3071,21 @@ def Test_forward_declaration() delete('Xforward') enddef -def Test_declare_script_in_func() +def Test_declare_script_var_in_func() var lines =<< trim END vim9script func Declare() let s:local = 123 endfunc Declare() + END + v9.CheckScriptFailure(lines, 'E1269:') +enddef + +def Test_lock_script_var() + var lines =<< trim END + vim9script + var local = 123 assert_equal(123, local) var error: string diff --git a/src/testdir/vim9.vim b/src/testdir/vim9.vim index 92ea0bad73..bb50db08e9 100644 --- a/src/testdir/vim9.vim +++ b/src/testdir/vim9.vim @@ -73,8 +73,8 @@ endfunc export def CheckScriptFailure(lines: list, error: string, lnum = -3) var cwd = getcwd() - var fname = 'XScriptFailure' .. s:sequence - s:sequence += 1 + var fname = 'XScriptFailure' .. sequence + sequence += 1 writefile(lines, fname) try assert_fails('so ' .. fname, error, lines, lnum) @@ -86,8 +86,8 @@ enddef export def CheckScriptFailureList(lines: list, errors: list, lnum = -3) var cwd = getcwd() - var fname = 'XScriptFailure' .. s:sequence - s:sequence += 1 + var fname = 'XScriptFailure' .. sequence + sequence += 1 writefile(lines, fname) try assert_fails('so ' .. fname, errors, lines, lnum) @@ -99,8 +99,8 @@ enddef export def CheckScriptSuccess(lines: list) var cwd = getcwd() - var fname = 'XScriptSuccess' .. s:sequence - s:sequence += 1 + var fname = 'XScriptSuccess' .. sequence + sequence += 1 writefile(lines, fname) try exe 'so ' .. fname diff --git a/src/userfunc.c b/src/userfunc.c index 59415dbd73..10a529e03f 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -1328,8 +1328,9 @@ get_lambda_tv( int equal_arrow = **arg == '('; int white_error = FALSE; int called_emsg_start = called_emsg; + int vim9script = in_vim9script(); - if (equal_arrow && !in_vim9script()) + if (equal_arrow && !vim9script) return NOTDONE; ga_init(&newargs); @@ -1360,7 +1361,7 @@ get_lambda_tv( FALSE, NULL, NULL); if (ret == FAIL || (s = skip_arrow(*arg, equal_arrow, &ret_type, - equal_arrow || in_vim9script() ? &white_error : NULL)) == NULL) + equal_arrow || vim9script ? &white_error : NULL)) == NULL) { if (types_optional) ga_clear_strings(&argtypes); @@ -1485,7 +1486,7 @@ get_lambda_tv( if (types_optional) { if (parse_argument_types(fp, &argtypes, - in_vim9script() && varargs) == FAIL) + vim9script && varargs) == FAIL) goto errret; if (ret_type != NULL) { @@ -1514,7 +1515,7 @@ get_lambda_tv( flags |= FC_SANDBOX; // In legacy script a lambda can be called with more args than // uf_args.ga_len. In Vim9 script "...name" has to be used. - fp->uf_varargs = !in_vim9script() || varargs; + fp->uf_varargs = !vim9script || varargs; fp->uf_flags = flags; fp->uf_calls = 0; fp->uf_script_ctx = current_sctx; @@ -1613,7 +1614,7 @@ deref_func_name( p = name + 2; len -= 2; } - import = find_imported(p, len, FALSE, NULL); + import = find_imported(p, len, FALSE); // imported function from another script if (import != NULL) @@ -1779,7 +1780,7 @@ get_func_tv( } ret = call_func(name, len, rettv, argcount, argvars, funcexe); - if (in_vim9script() && did_emsg > did_emsg_before) + if (vim9script && did_emsg > did_emsg_before) { // An error in a builtin function does not return FAIL, but we do // want to abort further processing if an error was given. @@ -1800,7 +1801,7 @@ get_func_tv( while (--argcount >= 0) clear_tv(&argvars[argcount]); - if (in_vim9script()) + if (vim9script) *arg = argp; else *arg = skipwhite(argp); @@ -2513,6 +2514,7 @@ call_user_func( { sctx_T save_current_sctx; int using_sandbox = FALSE; + int save_sticky_cmdmod_flags = sticky_cmdmod_flags; funccall_T *fc; int save_did_emsg; int default_arg_err = FALSE; @@ -2569,6 +2571,7 @@ call_user_func( if (do_profiling == PROF_YES) profile_may_start_func(&profile_info, fp, caller); #endif + sticky_cmdmod_flags = 0; call_def_function(fp, argcount, argvars, funcexe->fe_partial, rettv); funcdepth_decrement(); #ifdef FEAT_PROFILE @@ -2578,6 +2581,7 @@ call_user_func( #endif current_funccal = fc->caller; free_funccal(fc); + sticky_cmdmod_flags = save_sticky_cmdmod_flags; return; } @@ -2797,6 +2801,9 @@ call_user_func( fc->caller == NULL ? NULL : fc->caller->func); #endif + // "legacy" does not apply to commands in the function + sticky_cmdmod_flags = 0; + save_current_sctx = current_sctx; current_sctx = fp->uf_script_ctx; save_did_emsg = did_emsg; @@ -2889,6 +2896,7 @@ call_user_func( #endif if (using_sandbox) --sandbox; + sticky_cmdmod_flags = save_sticky_cmdmod_flags; if (p_verbose >= 12 && SOURCING_NAME != NULL) { @@ -3009,6 +3017,18 @@ get_current_funccal(void) return current_funccal; } +/* + * Return TRUE when currently at the script level: + * - not in a function + * - not executing an autocommand + * Note that when an autocommand sources a script the result is FALSE; + */ + int +at_script_level(void) +{ + return current_funccal == NULL && autocmd_match == NULL; +} + /* * Mark all functions of script "sid" as deleted. */ @@ -3695,7 +3715,8 @@ trans_function_name( int extra = 0; int prefix_g = FALSE; lval_T lv; - int vim9script; + int vim9script = in_vim9script(); + int vim9_local; if (fdp != NULL) CLEAR_POINTER(fdp); @@ -3720,7 +3741,7 @@ trans_function_name( // Note that TFN_ flags use the same values as GLV_ flags. end = get_lval(start, NULL, &lv, FALSE, skip, flags | GLV_READ_ONLY, lead > 2 ? 0 : FNE_CHECK_START); - if (end == start || (in_vim9script() && end != NULL + if (end == start || (vim9script && end != NULL && end[-1] == AUTOLOAD_CHAR && *end == '(')) { if (!skip) @@ -3886,7 +3907,7 @@ trans_function_name( // In Vim9 script a user function is script-local by default, unless it // starts with a lower case character: dict.func(). - vim9script = ASCII_ISUPPER(*start) && in_vim9script(); + vim9_local = ASCII_ISUPPER(*start) && vim9script; /* * Copy the function name to allocated memory. @@ -3895,13 +3916,13 @@ trans_function_name( */ if (skip) lead = 0; // do nothing - else if (lead > 0 || vim9script) + else if (lead > 0 || vim9_local) { - if (!vim9script) + if (!vim9_local) { - if (in_vim9script() && lead == 2 && !ASCII_ISUPPER(*lv.ll_name)) + if (vim9script && lead == 2 && !ASCII_ISUPPER(*lv.ll_name)) { - semsg(_(in_vim9script() + semsg(_(vim9script ? e_function_name_must_start_with_capital_str : e_function_name_must_start_with_capital_or_s_str), start); @@ -3909,7 +3930,7 @@ trans_function_name( } lead = 3; } - if (vim9script || (lv.ll_exp_name != NULL + if (vim9_local || (lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name)) || eval_fname_sid(*pp)) { @@ -3920,17 +3941,16 @@ trans_function_name( goto theend; } sprintf((char *)sid_buf, "%ld_", (long)current_sctx.sc_sid); - if (vim9script) + if (vim9_local) extra = 3 + (int)STRLEN(sid_buf); else lead += (int)STRLEN(sid_buf); } } else if (!(flags & TFN_INT) && (builtin_function(lv.ll_name, len) - || (in_vim9script() && *lv.ll_name == '_'))) + || (vim9script && *lv.ll_name == '_'))) { - semsg(_(in_vim9script() - ? e_function_name_must_start_with_capital_str + semsg(_(vim9script ? e_function_name_must_start_with_capital_str : e_function_name_must_start_with_capital_or_s_str), start); goto theend; @@ -3949,12 +3969,12 @@ trans_function_name( name = alloc(len + lead + extra + 1); if (name != NULL) { - if (!skip && (lead > 0 || vim9script)) + if (!skip && (lead > 0 || vim9_local)) { name[0] = K_SPECIAL; name[1] = KS_EXTRA; name[2] = (int)KE_SNR; - if (vim9script || lead > 3) // If it's "" + if (vim9_local || lead > 3) // If it's "" STRCPY(name + 3, sid_buf); } else if (prefix_g) @@ -4205,6 +4225,12 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free) } else { + if (vim9script && p[0] == 's' && p[1] == ':') + { + semsg(_(e_cannot_use_s_colon_in_vim9_script_str), p); + return NULL; + } + name = save_function_name(&p, &is_global, eap->skip, TFN_NO_AUTOLOAD | TFN_NEW_FUNC, &fudi); paren = (vim_strchr(p, '(') != NULL); @@ -4521,7 +4547,7 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free) int ffed_flags = is_global ? FFED_IS_GLOBAL : 0; v = find_var(name, &ht, TRUE); - if (v != NULL && (in_vim9script() || v->di_tv.v_type == VAR_FUNC)) + if (v != NULL && (vim9script || v->di_tv.v_type == VAR_FUNC)) var_conflict = TRUE; if (SCRIPT_ID_VALID(current_sctx.sc_sid)) @@ -4565,8 +4591,7 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free) { char_u *uname = untrans_function_name(name); - import = find_imported(uname == NULL ? name : uname, 0, - FALSE, NULL); + import = find_imported(uname == NULL ? name : uname, 0, FALSE); } if (fp != NULL || import != NULL) @@ -5274,6 +5299,7 @@ ex_call(exarg_T *eap) evalarg_T evalarg; type_T *type = NULL; int found_var = FALSE; + int vim9script = in_vim9script(); fill_evalarg_from_eap(&evalarg, eap, eap->skip); if (eap->skip) @@ -5290,7 +5316,7 @@ ex_call(exarg_T *eap) } tofree = trans_function_name(&arg, NULL, eap->skip, TFN_INT, - &fudi, &partial, in_vim9script() ? &type : NULL); + &fudi, &partial, vim9script ? &type : NULL); if (fudi.fd_newkey != NULL) { // Still need to give an error message for missing key. @@ -5310,7 +5336,7 @@ ex_call(exarg_T *eap) // from trans_function_name(). len = (int)STRLEN(tofree); name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, - in_vim9script() && type == NULL ? &type : NULL, + vim9script && type == NULL ? &type : NULL, FALSE, FALSE, &found_var); // Skip white space to allow ":call func ()". Not good, but required for @@ -5321,7 +5347,7 @@ ex_call(exarg_T *eap) semsg(_(e_missing_parenthesis_str), eap->arg); goto end; } - if (in_vim9script() && startarg > arg) + if (vim9script && startarg > arg) { semsg(_(e_no_white_space_allowed_before_str_str), "(", eap->arg); goto end; diff --git a/src/version.c b/src/version.c index eab70e97b1..562ec05e65 100644 --- a/src/version.c +++ b/src/version.c @@ -558,7 +558,11 @@ static char *(features[]) = "-smartindent", #endif #ifdef FEAT_SODIUM +# ifdef DYNAMIC_SODIUM + "+sodium/dyn", +# else "+sodium", +# endif #else "-sodium", #endif @@ -761,6 +765,56 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 4375, +/**/ + 4374, +/**/ + 4373, +/**/ + 4372, +/**/ + 4371, +/**/ + 4370, +/**/ + 4369, +/**/ + 4368, +/**/ + 4367, +/**/ + 4366, +/**/ + 4365, +/**/ + 4364, +/**/ + 4363, +/**/ + 4362, +/**/ + 4361, +/**/ + 4360, +/**/ + 4359, +/**/ + 4358, +/**/ + 4357, +/**/ + 4356, +/**/ + 4355, +/**/ + 4354, +/**/ + 4353, +/**/ + 4352, +/**/ + 4351, /**/ 4350, /**/ diff --git a/src/vim.h b/src/vim.h index 468332b8bf..295f043619 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1748,7 +1748,9 @@ typedef unsigned short disptick_T; // display tick type # define MAXCOL (0x3fffffffL) // maximum column number, 30 bits # define MAXLNUM (0x3fffffffL) // maximum (invalid) line number #else -# define MAXCOL INT_MAX // maximum column number + // MAXCOL used to be INT_MAX, but with 64 bit ints that results in running + // out of memory when trying to allocate a very long line. +# define MAXCOL 0x7fffffffL // maximum column number # define MAXLNUM LONG_MAX // maximum (invalid) line number #endif diff --git a/src/vim9.h b/src/vim9.h index 45e97a2db9..87ee6b163f 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -691,7 +691,7 @@ typedef struct { } lhs_T; /* - * Context for compiling lines of Vim script. + * Context for compiling lines of a :def function. * Stores info about the local variables and condition stack. */ struct cctx_S { @@ -710,8 +710,6 @@ struct cctx_S { int ctx_has_closure; // set to one if a closure was created in // the function - garray_T ctx_imports; // imported items - skip_T ctx_skip; scope_T *ctx_scope; // current scope, NULL at toplevel int ctx_had_return; // last seen statement was "return" diff --git a/src/vim9compile.c b/src/vim9compile.c index 265ea665b8..edbd33e4b1 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -281,7 +281,7 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx) && (lookup_local(name, len, NULL, cctx) == OK || arg_exists(name, len, NULL, NULL, NULL, cctx) == OK)) || script_var_exists(name, len, cctx, NULL) == OK - || find_imported(name, len, FALSE, cctx) != NULL; + || find_imported(name, len, FALSE) != NULL; } /* @@ -291,27 +291,7 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx) static int item_exists(char_u *name, size_t len, int cmd UNUSED, cctx_T *cctx) { - int is_global; - char_u *p; - - if (variable_exists(name, len, cctx)) - return TRUE; - - // This is similar to what is in lookup_scriptitem(): - // Find a function, so that a following "->" works. - // Require "(" or "->" to follow, "Cmd" is a user command while "Cmd()" is - // a function call. - p = skipwhite(name + len); - - if (name[len] == '(' || (p[0] == '-' && p[1] == '>')) - { - // Do not check for an internal function, since it might also be a - // valid command, such as ":split" versus "split()". - // Skip "g:" before a function name. - is_global = (name[0] == 'g' && name[1] == ':'); - return find_func(is_global ? name + 2 : name, is_global) != NULL; - } - return FALSE; + return variable_exists(name, len, cctx); } /* @@ -349,7 +329,7 @@ check_defined( if ((cctx != NULL && (lookup_local(p, len, NULL, cctx) == OK || arg_exists(p, len, NULL, NULL, NULL, cctx) == OK)) - || find_imported(p, len, FALSE, cctx) != NULL + || find_imported(p, len, FALSE) != NULL || (ufunc = find_func_even_dead(p, 0)) != NULL) { // A local or script-local function can shadow a global function. @@ -614,36 +594,18 @@ find_imported_in_script(char_u *name, size_t len, int sid) } /* - * Find "name" in imported items of the current script or in "cctx" if not - * NULL. + * Find "name" in imported items of the current script. * If "load" is TRUE and the script was not loaded yet, load it now. */ imported_T * -find_imported(char_u *name, size_t len, int load, cctx_T *cctx) +find_imported(char_u *name, size_t len, int load) { - int idx; - imported_T *ret = NULL; + imported_T *ret; if (!SCRIPT_ID_VALID(current_sctx.sc_sid)) return NULL; - if (cctx != NULL) - for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx) - { - imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) - + idx; - - if (len == 0 ? STRCMP(name, import->imp_name) == 0 - : STRLEN(import->imp_name) == len - && STRNCMP(name, import->imp_name, len) == 0) - { - ret = import; - break; - } - } - - if (ret == NULL) - ret = find_imported_in_script(name, len, current_sctx.sc_sid); + ret = find_imported_in_script(name, len, current_sctx.sc_sid); if (ret != NULL && load && (ret->imp_flags & IMP_FLAGS_AUTOLOAD)) { scid_T dummy; @@ -656,23 +618,6 @@ find_imported(char_u *name, size_t len, int load, cctx_T *cctx) return ret; } -/* - * Free all imported variables. - */ - static void -free_imported(cctx_T *cctx) -{ - int idx; - - for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx) - { - imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx; - - vim_free(import->imp_name); - } - ga_clear(&cctx->ctx_imports); -} - /* * Called when checking for a following operator at "arg". When the rest of * the line is empty or only a comment, peek the next line. If there is a next @@ -1384,7 +1329,7 @@ compile_lhs( : script_var_exists(var_start, lhs->lhs_varlen, cctx, NULL)) == OK; imported_T *import = - find_imported(var_start, lhs->lhs_varlen, FALSE, cctx); + find_imported(var_start, lhs->lhs_varlen, FALSE); if (script_namespace || script_var || import != NULL) { @@ -1394,7 +1339,7 @@ compile_lhs( if (is_decl) { if (script_namespace) - semsg(_(e_cannot_declare_script_variable_in_function), + semsg(_(e_cannot_declare_script_variable_in_function_str), lhs->lhs_name); else semsg(_(e_variable_already_declared_in_script_str), @@ -2620,7 +2565,6 @@ compile_def_function( ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10); // Each entry on the type stack consists of two type pointers. ga_init2(&cctx.ctx_type_stack, sizeof(type2_T), 50); - ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10); cctx.ctx_type_list = &ufunc->uf_type_list; ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50); instr = &cctx.ctx_instr; @@ -3311,7 +3255,6 @@ erret: estack_pop(); ga_clear_strings(&lines_to_free); - free_imported(&cctx); free_locals(&cctx); ga_clear(&cctx.ctx_type_stack); return ret; diff --git a/src/vim9execute.c b/src/vim9execute.c index 1412d08365..f6456d64b2 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -3826,6 +3826,7 @@ exec_instructions(ectx_T *ectx) } } + SOURCING_LNUM = iptr->isn_lnum; if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL) { diff --git a/src/vim9expr.c b/src/vim9expr.c index 1e53478a50..46d14dc05e 100644 --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -266,7 +266,7 @@ compile_load_scriptvar( return OK; } - import = end == NULL ? NULL : find_imported(name, 0, FALSE, cctx); + import = end == NULL ? NULL : find_imported(name, 0, FALSE); if (import != NULL) { char_u *p = skipwhite(*end); @@ -502,7 +502,7 @@ compile_load( // "var" can be script-local even without using "s:" if it // already exists in a Vim9 script or when it's imported. if (script_var_exists(*arg, len, cctx, NULL) == OK - || find_imported(name, 0, FALSE, cctx) != NULL) + || find_imported(name, 0, FALSE) != NULL) res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE); // When evaluating an expression and the name starts with an @@ -681,7 +681,7 @@ compile_call( } vim_strncpy(namebuf, *arg, varlen); - import = find_imported(name, varlen, FALSE, cctx); + import = find_imported(name, varlen, FALSE); if (import != NULL) { semsg(_(e_cannot_use_str_itself_it_is_imported), namebuf); diff --git a/src/vim9script.c b/src/vim9script.c index fde51c91f9..74f9325891 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -593,7 +593,7 @@ handle_import( { imported_T *imported; - imported = find_imported(as_name, STRLEN(as_name), FALSE, cctx); + imported = find_imported(as_name, STRLEN(as_name), FALSE); if (imported != NULL && imported->imp_sid != sid) { semsg(_(e_name_already_defined_str), as_name); diff --git a/src/window.c b/src/window.c index e13b3993f4..81be780bf0 100644 --- a/src/window.c +++ b/src/window.c @@ -1419,10 +1419,6 @@ win_init(win_T *newp, win_T *oldp, int flags UNUSED) #endif win_init_some(newp, oldp); - -#ifdef FEAT_SYN_HL - check_colorcolumn(newp); -#endif #ifdef FEAT_TERMINAL term_update_wincolor(newp); #endif