aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
3 files changed, 98 insertions, 28 deletions
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