aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/autoload/dist/ft.vim22
-rw-r--r--runtime/doc/lua.txt43
-rw-r--r--runtime/filetype.vim18
-rw-r--r--runtime/lua/vim/filetype.lua5
-rw-r--r--runtime/syntax/query.lua6
-rw-r--r--src/nvim/ex_docmd.c52
-rw-r--r--src/nvim/lua/executor.c22
-rw-r--r--src/nvim/testdir/test_filetype.vim52
-rw-r--r--test/functional/api/command_spec.lua48
9 files changed, 214 insertions, 54 deletions
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim
index 0063e9da0b..866196a7df 100644
--- a/runtime/autoload/dist/ft.vim
+++ b/runtime/autoload/dist/ft.vim
@@ -773,6 +773,28 @@ func dist#ft#SQL()
endif
endfunc
+" This function checks the first 25 lines of file extension "sc" to resolve
+" detection between scala and SuperCollider
+func dist#ft#FTsc()
+ for lnum in range(1, min([line("$"), 25]))
+ if getline(lnum) =~# '[A-Za-z0-9]*\s:\s[A-Za-z0-9]\|var\s<\|classvar\s<\|\^this.*\||\w*|\|+\s\w*\s{\|\*ar\s'
+ setf supercollider
+ return
+ endif
+ endfor
+ setf scala
+endfunc
+
+" This function checks the first line of file extension "scd" to resolve
+" detection between scdoc and SuperCollider
+func dist#ft#FTscd()
+ if getline(1) =~# '\%^\S\+(\d[0-9A-Za-z]*)\%(\s\+\"[^"]*\"\%(\s\+\"[^"]*\"\)\=\)\=$'
+ setf scdoc
+ else
+ setf supercollider
+ endif
+endfunc
+
" If the file has an extension of 't' and is in a directory 't' or 'xt' then
" it is almost certainly a Perl test file.
" If the first line starts with '#' and contains 'perl' it's probably a Perl
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 25c5dd326e..46b9f0576f 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -21,19 +21,44 @@ Nvim includes a "standard library" |lua-stdlib| for Lua. It complements the
which can be used from Lua code. A good overview of using Lua in neovim is
given by https://github.com/nanotee/nvim-lua-guide.
-Module conflicts are resolved by "last wins". For example if both of these
-are on 'runtimepath':
- runtime/lua/foo.lua
- ~/.config/nvim/lua/foo.lua
-then `require('foo')` loads "~/.config/nvim/lua/foo.lua", and
-"runtime/lua/foo.lua" is not used. See |lua-require| to understand how Nvim
-finds and loads Lua modules. The conventions are similar to those of
-Vimscript |plugin|s, with some extra features. See |lua-require-example| for
-a walkthrough.
+The |:source| and |:runtime| commands can run Lua scripts as well as Vim
+scripts. Lua modules can be loaded with `require('name')`, which
+conventionally returns a table but can return any value.
+
+See |lua-require| for details on how Nvim finds and loads Lua modules.
+See |lua-require-example| for an example of how to write and use a module.
==============================================================================
IMPORTING LUA MODULES *lua-require*
+Modules are searched for under the directories specified in 'runtimepath', in
+the order they appear. Any `.` in the module name is treated as a directory
+separator when searching. For a module `foo.bar`, each directory is searched
+for `lua/foo/bar.lua`, then `lua/foo/bar/init.lua`. If no files are found,
+the directories are searched again for a shared library with a name matching
+`lua/foo/bar.?`, where `?` is a list of suffixes (such as `so` or `dll`)
+derived from the initial value of `package.cpath`. If still no files are
+found, Nvim falls back to Lua's default search mechanism. The first script
+found is run and `require()` returns the value returned by the script if any,
+else `true`.
+
+The return value is cached after the first call to `require()` for each
+module, with subsequent calls returning the cached value without searching for
+or executing any script. For further details on `require()`, see the Lua
+documentation at https://www.lua.org/manual/5.1/manual.html#pdf-require.
+
+For example, if 'runtimepath' is `foo,bar` and `package.cpath` was
+`./?.so;./?.dll` at startup, `require('mod')` searches these paths in order
+and loads the first module found:
+ foo/lua/mod.lua
+ foo/lua/mod/init.lua
+ bar/lua/mod.lua
+ bar/lua/mod/init.lua
+ foo/lua/mod.so
+ foo/lua/mod.dll
+ bar/lua/mod.so
+ bar/lua/mod.dll
+
*lua-package-path*
Nvim automatically adjusts `package.path` and `package.cpath` according to
effective 'runtimepath' value. Adjustment happens whenever 'runtimepath' is
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index c5690ba716..f7c0317eff 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -202,12 +202,12 @@ au BufNewFile,BufRead *.iba,*.ibi setf ibasic
au BufNewFile,BufRead *.fb setf freebasic
" Batch file for MSDOS. See dist#ft#FTsys for *.sys
-au BufNewFile,BufRead *.bat setf dosbatch
+au BufNewFile,BufRead *.bat setf dosbatch
" *.cmd is close to a Batch file, but on OS/2 Rexx files also use *.cmd.
au BufNewFile,BufRead *.cmd
\ if getline(1) =~ '^/\*' | setf rexx | else | setf dosbatch | endif
" ABB RAPID or Batch file for MSDOS.
-au BufNewFile,BufRead *.sys\c call dist#ft#FTsys()
+au BufNewFile,BufRead *.sys\c call dist#ft#FTsys()
" Batch file for 4DOS
au BufNewFile,BufRead *.btm call dist#ft#FTbtm()
@@ -1140,7 +1140,7 @@ au BufNewFile,BufRead *.mms call dist#ft#FTmms()
au BufNewFile,BufRead *.mmp setf mmp
" ABB Rapid, Modula-2, Modsim III or LambdaProlog
-au BufNewFile,BufRead *.mod\c call dist#ft#FTmod()
+au BufNewFile,BufRead *.mod\c call dist#ft#FTmod()
" Modula-2 (.md removed in favor of Markdown, see dist#ft#FTmod for *.MOD)
au BufNewFile,BufRead *.m2,*.DEF,*.mi setf modula2
@@ -1630,16 +1630,22 @@ au BufNewFile,BufRead *.sass setf sass
au BufNewFile,BufRead *.sa setf sather
" Scala
-au BufNewFile,BufRead *.scala,*.sc setf scala
+au BufNewFile,BufRead *.scala setf scala
" SBT - Scala Build Tool
au BufNewFile,BufRead *.sbt setf sbt
+" SuperCollider
+au BufNewFile,BufRead *.sc call dist#ft#FTsc()
+
+au BufNewFile,BufRead *.quark setf supercollider
+
+" scdoc
+au BufNewFile,BufRead *.scd call dist#ft#FTscd()
+
" Scilab
au BufNewFile,BufRead *.sci,*.sce setf scilab
-" scdoc
-au BufNewFile,BufRead *.scd setf scdoc
" SCSS
au BufNewFile,BufRead *.scss setf scss
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 880b99a2fa..603f9f854a 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -569,8 +569,6 @@ local extension = {
sa = "sather",
sbt = "sbt",
scala = "scala",
- sc = "scala",
- scd = "scdoc",
ss = "scheme",
scm = "scheme",
sld = "scheme",
@@ -644,6 +642,7 @@ local extension = {
mata = "stata",
ado = "stata",
stp = "stp",
+ quark = "supercollider",
sface = "surface",
svelte = "svelte",
svg = "svg",
@@ -830,6 +829,8 @@ local extension = {
r = function() vim.fn["dist#ft#FTr"]() end,
rdf = function() vim.fn["dist#ft#Redif"]() end,
rules = function() vim.fn["dist#ft#FTRules"]() end,
+ sc = function() vim.fn["dist#ft#FTsc"]() end,
+ scd = function() vim.fn["dist#ft#FTscd"]() end,
sh = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
shtml = function() vim.fn["dist#ft#FThtml"]() end,
sql = function() vim.fn["dist#ft#SQL"]() end,
diff --git a/runtime/syntax/query.lua b/runtime/syntax/query.lua
new file mode 100644
index 0000000000..e24ff65360
--- /dev/null
+++ b/runtime/syntax/query.lua
@@ -0,0 +1,6 @@
+-- Neovim syntax file
+-- Language: Tree-sitter query
+-- Last Change: 2022 Apr 13
+
+-- it's a lisp!
+vim.cmd [[ runtime! syntax/lisp.vim ]]
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 482bf69f67..cbfe6e3789 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -5774,26 +5774,44 @@ static void ex_delcommand(exarg_T *eap)
/// Split a string by unescaped whitespace (space & tab), used for f-args on Lua commands callback.
/// Similar to uc_split_args(), but does not allocate, add quotes, add commas and is an iterator.
///
-/// @note If no separator is found start = 0 and end = length - 1
-/// @param[in] arg String to split
-/// @param[in] iter Iteration counter
-/// @param[out] start Start of the split
-/// @param[out] end End of the split
-/// @param[in] length Length of the string
+/// @param[in] arg String to split
+/// @param[in] arglen Length of {arg}
+/// @param[inout] end Index of last character of previous iteration
+/// @param[out] buf Buffer to copy string into
+/// @param[out] len Length of string in {buf}
///
-/// @return false if it's the last split (don't call again), true otherwise (call again).
-bool uc_split_args_iter(const char_u *arg, int iter, int *start, int *end, int length)
-{
- int pos;
- *start = *end + (iter > 1 ? 2 : 0); // Skip whitespace after the first split
- for (pos = *start; pos < length - 2; pos++) {
- if (arg[pos] != '\\' && ascii_iswhite(arg[pos + 1])) {
- *end = pos;
- return true;
+/// @return true if iteration is complete, else false
+bool uc_split_args_iter(const char_u *arg, size_t arglen, size_t *end, char *buf, size_t *len)
+{
+ if (!arglen) {
+ return true;
+ }
+
+ size_t pos = *end;
+ while (pos < arglen && ascii_iswhite(arg[pos])) {
+ pos++;
+ }
+
+ size_t l = 0;
+ for (; pos < arglen - 1; pos++) {
+ if (arg[pos] == '\\' && (arg[pos + 1] == '\\' || ascii_iswhite(arg[pos + 1]))) {
+ buf[l++] = arg[++pos];
+ } else {
+ buf[l++] = arg[pos];
+ if (ascii_iswhite(arg[pos + 1])) {
+ *end = pos + 1;
+ *len = l;
+ return false;
+ }
}
}
- *end = length - 1;
- return false;
+
+ if (pos < arglen && !ascii_iswhite(arg[pos])) {
+ buf[l++] = arg[pos];
+ }
+
+ *len = l;
+ return true;
}
/// split and quote args for <f-args>
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 21625854fb..81396f1715 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1869,17 +1869,21 @@ void nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap)
} else {
// Commands with more than one possible argument we split
lua_pop(lstate, 1); // Pop the reference of opts.args
- int length = (int)STRLEN(eap->arg);
- int start = 0;
- int end = 0;
+ size_t length = STRLEN(eap->arg);
+ size_t end = 0;
+ size_t len = 0;
int i = 1;
- bool res = true;
- while (res) {
- res = uc_split_args_iter(eap->arg, i, &start, &end, length);
- lua_pushlstring(lstate, (const char *)eap->arg + start, (size_t)(end - start + 1));
- lua_rawseti(lstate, -2, i);
- i++;
+ char *buf = xcalloc(length, sizeof(char));
+ bool done = false;
+ while (!done) {
+ done = uc_split_args_iter(eap->arg, length, &end, buf, &len);
+ if (len > 0) {
+ lua_pushlstring(lstate, buf, len);
+ lua_rawseti(lstate, -2, i);
+ i++;
+ }
}
+ xfree(buf);
}
lua_setfield(lstate, -2, "fargs");
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index aeb6e12ead..197a9edb76 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -463,12 +463,11 @@ let s:filename_checks = {
\ 'sass': ['file.sass'],
\ 'sather': ['file.sa'],
\ 'sbt': ['file.sbt'],
- \ 'scala': ['file.scala', 'file.sc'],
+ \ 'scala': ['file.scala'],
\ 'scheme': ['file.scm', 'file.ss', 'file.sld', 'file.rkt', 'file.rktd', 'file.rktl'],
\ 'scilab': ['file.sci', 'file.sce'],
\ 'screen': ['.screenrc', 'screenrc'],
\ 'sexplib': ['file.sexp'],
- \ 'scdoc': ['file.scd'],
\ 'scss': ['file.scss'],
\ 'sd': ['file.sd'],
\ 'sdc': ['file.sdc'],
@@ -516,6 +515,7 @@ let s:filename_checks = {
\ 'stata': ['file.ado', 'file.do', 'file.imata', 'file.mata'],
\ 'stp': ['file.stp'],
\ 'sudoers': ['any/etc/sudoers', 'sudoers.tmp', '/etc/sudoers', 'any/etc/sudoers.d/file'],
+ \ 'supercollider': ['file.quark'],
\ 'surface': ['file.sface'],
\ 'svg': ['file.svg'],
\ 'svn': ['svn-commitfile.tmp', 'svn-commit-file.tmp', 'svn-commit.tmp'],
@@ -1470,6 +1470,54 @@ func Test_prg_file()
filetype off
endfunc
+" Test dist#ft#FTsc()
+func Test_sc_file()
+ filetype on
+
+ " SC file mehtods are defined 'Class : Method'
+ call writefile(['SCNvimDocRenderer : SCDocHTMLRenderer {'], 'srcfile.sc')
+ split srcfile.sc
+ call assert_equal('supercollider', &filetype)
+ bwipe!
+ call delete('srcfile.sc')
+
+ " SC classes are defined with '+ Class {}'
+ call writefile(['+ SCNvim {', '*methodArgs {|method|'], 'srcfile.sc')
+ split srcfile.sc
+ call assert_equal('supercollider', &filetype)
+ bwipe!
+ call delete('srcfile.sc')
+
+ " Some SC class files start with comment and define methods many lines later
+ call writefile(['// Query', '//Method','^this {'], 'srcfile.sc')
+ split srcfile.sc
+ call assert_equal('supercollider', &filetype)
+ bwipe!
+ call delete('srcfile.sc')
+
+ " Some SC class files put comments between method declaration after class
+ call writefile(['PingPong {', '//comment','*ar { arg'], 'srcfile.sc')
+ split srcfile.sc
+ call assert_equal('supercollider', &filetype)
+ bwipe!
+ call delete('srcfile.sc')
+
+ filetype off
+endfunc
+
+" Test dist#ft#FTscd()
+func Test_scd_file()
+ filetype on
+
+ call writefile(['ijq(1)'], 'srcfile.scd')
+ split srcfile.scd
+ call assert_equal('scdoc', &filetype)
+ bwipe!
+ call delete('srcfile.scd')
+
+ filetype off
+endfunc
+
func Test_src_file()
filetype on
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index ad162473ec..e4963e8a65 100644
--- a/test/functional/api/command_spec.lua
+++ b/test/functional/api/command_spec.lua
@@ -114,8 +114,8 @@ describe('nvim_create_user_command', function()
]]
eq({
- args = [[hello my\ friend how\ are\ you?]],
- fargs = {[[hello]], [[my\ friend]], [[how\ are\ you?]]},
+ args = [[this is a\ test]],
+ fargs = {"this", "is", "a test"},
bang = false,
line1 = 1,
line2 = 1,
@@ -124,12 +124,42 @@ describe('nvim_create_user_command', function()
count = 2,
reg = "",
}, exec_lua [=[
- vim.api.nvim_command([[CommandWithLuaCallback hello my\ friend how\ are\ you?]])
+ vim.api.nvim_command([[CommandWithLuaCallback this is a\ test]])
return result
]=])
eq({
- args = 'h\tey',
+ args = [[this includes\ a backslash: \\]],
+ fargs = {"this", "includes a", "backslash:", "\\"},
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = "",
+ range = 0,
+ count = 2,
+ reg = "",
+ }, exec_lua [=[
+ vim.api.nvim_command([[CommandWithLuaCallback this includes\ a backslash: \\]])
+ return result
+ ]=])
+
+ eq({
+ args = "a\\b",
+ fargs = {"a\\b"},
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = "",
+ range = 0,
+ count = 2,
+ reg = "",
+ }, exec_lua [=[
+ vim.api.nvim_command('CommandWithLuaCallback a\\b')
+ return result
+ ]=])
+
+ eq({
+ args = 'h\tey ',
fargs = {[[h]], [[ey]]},
bang = true,
line1 = 10,
@@ -139,7 +169,7 @@ describe('nvim_create_user_command', function()
count = 10,
reg = "",
}, exec_lua [=[
- vim.api.nvim_command('botright 10CommandWithLuaCallback! h\tey')
+ vim.api.nvim_command('botright 10CommandWithLuaCallback! h\tey ')
return result
]=])
@@ -160,7 +190,7 @@ describe('nvim_create_user_command', function()
eq({
args = "",
- fargs = {""}, -- fargs works without args
+ fargs = {}, -- fargs works without args
bang = false,
line1 = 1,
line2 = 1,
@@ -186,8 +216,8 @@ describe('nvim_create_user_command', function()
]]
eq({
- args = "hello I'm one argmuent",
- fargs = {"hello I'm one argmuent"}, -- Doesn't split args
+ args = "hello I'm one argument",
+ fargs = {"hello I'm one argument"}, -- Doesn't split args
bang = false,
line1 = 1,
line2 = 1,
@@ -196,7 +226,7 @@ describe('nvim_create_user_command', function()
count = 2,
reg = "",
}, exec_lua [[
- vim.api.nvim_command('CommandWithOneArg hello I\'m one argmuent')
+ vim.api.nvim_command('CommandWithOneArg hello I\'m one argument')
return result
]])