aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/vim.c2
-rw-r--r--src/nvim/ex_docmd.c22
-rw-r--r--src/nvim/lua/vim.lua246
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/testdir/test_writefile.vim21
5 files changed, 106 insertions, 187 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index e9a0b0df2e..a76cefe294 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -984,7 +984,7 @@ Dictionary nvim_get_all_options_info(Error *err)
/// Resulting dictionary has keys:
/// - name: Name of the option (like 'filetype')
/// - shortname: Shortened name of the option (like 'ft')
-/// - type: type of option ("string", "integer" or "boolean")
+/// - type: type of option ("string", "number" or "boolean")
/// - default: The default value for the option
/// - was_set: Whether the option was set.
///
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index c93f9fe6f2..29347def4c 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -5017,7 +5017,7 @@ char_u *check_nextcmd(char_u *p)
static int
check_more(
int message, // when FALSE check only, no messages
- int forceit
+ bool forceit
)
{
int n = ARGCOUNT - curwin->w_arg_idx - 1;
@@ -6340,7 +6340,7 @@ void not_exiting(void)
exiting = false;
}
-static bool before_quit_autocmds(win_T *wp, bool quit_all, int forceit)
+bool before_quit_autocmds(win_T *wp, bool quit_all, bool forceit)
{
apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, wp->w_buffer);
@@ -6406,7 +6406,7 @@ static void ex_quit(exarg_T *eap)
return;
}
- // If there are more files or windows we won't exit.
+ // If there is only one relevant window we will exit.
if (check_more(false, eap->forceit) == OK && only_one_window()) {
exiting = true;
}
@@ -6749,7 +6749,7 @@ static void ex_stop(exarg_T *eap)
apply_autocmds(EVENT_VIMRESUME, NULL, NULL, false, NULL);
}
-// ":exit", ":xit" and ":wq": Write file and quite the current window.
+// ":exit", ":xit" and ":wq": Write file and quit the current window.
static void ex_exit(exarg_T *eap)
{
if (cmdwin_type != 0) {
@@ -6762,17 +6762,15 @@ static void ex_exit(exarg_T *eap)
return;
}
- if (before_quit_autocmds(curwin, false, eap->forceit)) {
- return;
- }
-
- // if more files or windows we won't exit
+ // we plan to exit if there is only one relevant window
if (check_more(false, eap->forceit) == OK && only_one_window()) {
exiting = true;
}
- if (((eap->cmdidx == CMD_wq
- || curbufIsChanged())
- && do_write(eap) == FAIL)
+ // Write the buffer for ":wq" or when it was changed.
+ // Trigger QuitPre and ExitPre.
+ // Check if we can exit now, after autocommands have changed things.
+ if (((eap->cmdidx == CMD_wq || curbufIsChanged()) && do_write(eap) == FAIL)
+ || before_quit_autocmds(curwin, false, eap->forceit)
|| check_more(true, eap->forceit) == FAIL
|| (only_one_window() && check_changed_any(eap->forceit, false))) {
not_exiting();
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index bc0770da31..5c9c5103a7 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -39,6 +39,75 @@ assert(vim)
vim.inspect = package.loaded['vim.inspect']
assert(vim.inspect)
+local pathtrails = {}
+vim._so_trails = {}
+for s in (package.cpath..';'):gmatch('[^;]*;') do
+ s = s:sub(1, -2) -- Strip trailing semicolon
+ -- Find out path patterns. pathtrail should contain something like
+ -- /?.so, \?.dll. This allows not to bother determining what correct
+ -- suffixes are.
+ local pathtrail = s:match('[/\\][^/\\]*%?.*$')
+ if pathtrail and not pathtrails[pathtrail] then
+ pathtrails[pathtrail] = true
+ table.insert(vim._so_trails, pathtrail)
+ end
+end
+
+function vim._load_package(name)
+ local basename = name:gsub('%.', '/')
+ local paths = {"lua/"..basename..".lua", "lua/"..basename.."/init.lua"}
+ for _,path in ipairs(paths) do
+ local found = vim.api.nvim_get_runtime_file(path, false)
+ if #found > 0 then
+ local f, err = loadfile(found[1])
+ return f or error(err)
+ end
+ end
+
+ for _,trail in ipairs(vim._so_trails) do
+ local path = "lua"..trail:gsub('?', basename) -- so_trails contains a leading slash
+ local found = vim.api.nvim_get_runtime_file(path, false)
+ if #found > 0 then
+ -- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
+ -- a) strip prefix up to and including the first dash, if any
+ -- b) replace all dots by underscores
+ -- c) prepend "luaopen_"
+ -- So "foo-bar.baz" should result in "luaopen_bar_baz"
+ local dash = name:find("-", 1, true)
+ local modname = dash and name:sub(dash + 1) or name
+ local f, err = package.loadlib(found[1], "luaopen_"..modname:gsub("%.", "_"))
+ return f or error(err)
+ end
+ end
+ return nil
+end
+
+table.insert(package.loaders, 1, vim._load_package)
+
+-- These are for loading runtime modules lazily since they aren't available in
+-- the nvim binary as specified in executor.c
+setmetatable(vim, {
+ __index = function(t, key)
+ if key == 'treesitter' then
+ t.treesitter = require('vim.treesitter')
+ return t.treesitter
+ elseif key == 'F' then
+ t.F = require('vim.F')
+ return t.F
+ elseif require('vim.uri')[key] ~= nil then
+ -- Expose all `vim.uri` functions on the `vim` module.
+ t[key] = require('vim.uri')[key]
+ return t[key]
+ elseif key == 'lsp' then
+ t.lsp = require('vim.lsp')
+ return t.lsp
+ elseif key == 'highlight' then
+ t.highlight = require('vim.highlight')
+ return t.highlight
+ end
+ end
+})
+
vim.log = {
levels = {
TRACE = 0;
@@ -105,51 +174,6 @@ function vim._os_proc_children(ppid)
return children
end
-local pathtrails = {}
-vim._so_trails = {}
-for s in (package.cpath..';'):gmatch('[^;]*;') do
- s = s:sub(1, -2) -- Strip trailing semicolon
- -- Find out path patterns. pathtrail should contain something like
- -- /?.so, \?.dll. This allows not to bother determining what correct
- -- suffixes are.
- local pathtrail = s:match('[/\\][^/\\]*%?.*$')
- if pathtrail and not pathtrails[pathtrail] then
- pathtrails[pathtrail] = true
- table.insert(vim._so_trails, pathtrail)
- end
-end
-
-function vim._load_package(name)
- local basename = name:gsub('%.', '/')
- local paths = {"lua/"..basename..".lua", "lua/"..basename.."/init.lua"}
- for _,path in ipairs(paths) do
- local found = vim.api.nvim_get_runtime_file(path, false)
- if #found > 0 then
- local f, err = loadfile(found[1])
- return f or error(err)
- end
- end
-
- for _,trail in ipairs(vim._so_trails) do
- local path = "lua"..trail:gsub('?', basename) -- so_trails contains a leading slash
- local found = vim.api.nvim_get_runtime_file(path, false)
- if #found > 0 then
- -- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
- -- a) strip prefix up to and including the first dash, if any
- -- b) replace all dots by underscores
- -- c) prepend "luaopen_"
- -- So "foo-bar.baz" should result in "luaopen_bar_baz"
- local dash = name:find("-", 1, true)
- local modname = dash and name:sub(dash + 1) or name
- local f, err = package.loadlib(found[1], "luaopen_"..modname:gsub("%.", "_"))
- return f or error(err)
- end
- end
- return nil
-end
-
-table.insert(package.loaders, 1, vim._load_package)
-
-- TODO(ZyX-I): Create compatibility layer.
--- Return a human-readable representation of the given object.
@@ -282,32 +306,6 @@ vim.funcref = function(viml_func_name)
return vim.fn[viml_func_name]
end
--- These are for loading runtime modules lazily since they aren't available in
--- the nvim binary as specified in executor.c
-local function __index(t, key)
- if key == 'treesitter' then
- t.treesitter = require('vim.treesitter')
- return t.treesitter
- elseif require('vim.uri')[key] ~= nil then
- -- Expose all `vim.uri` functions on the `vim` module.
- t[key] = require('vim.uri')[key]
- return t[key]
- elseif key == 'lsp' then
- t.lsp = require('vim.lsp')
- return t.lsp
- elseif key == 'highlight' then
- t.highlight = require('vim.highlight')
- return t.highlight
- elseif key == 'F' then
- t.F = require('vim.F')
- return t.F
- end
-end
-
-setmetatable(vim, {
- __index = __index
-})
-
-- An easier alias for commands.
vim.cmd = function(command)
return vim.api.nvim_exec(command, false)
@@ -315,32 +313,8 @@ end
-- These are the vim.env/v/g/o/bo/wo variable magic accessors.
do
- local a = vim.api
local validate = vim.validate
- local function make_meta_accessor(get, set, del)
- validate {
- get = {get, 'f'};
- set = {set, 'f'};
- del = {del, 'f', true};
- }
- local mt = {}
- if del then
- function mt:__newindex(k, v)
- if v == nil then
- return del(k)
- end
- return set(k, v)
- end
- else
- function mt:__newindex(k, v)
- return set(k, v)
- end
- end
- function mt:__index(k)
- return get(k)
- end
- return setmetatable({}, mt)
- end
+
local function make_dict_accessor(scope)
validate {
scope = {scope, 's'};
@@ -354,88 +328,12 @@ do
end
return setmetatable({}, mt)
end
+
vim.g = make_dict_accessor('g')
vim.v = make_dict_accessor('v')
vim.b = make_dict_accessor('b')
vim.w = make_dict_accessor('w')
vim.t = make_dict_accessor('t')
- vim.o = make_meta_accessor(a.nvim_get_option, a.nvim_set_option)
-
- local function getenv(k)
- local v = vim.fn.getenv(k)
- if v == vim.NIL then
- return nil
- end
- return v
- end
- vim.env = make_meta_accessor(getenv, vim.fn.setenv)
- -- TODO(ashkan) if/when these are available from an API, generate them
- -- instead of hardcoding.
- local window_options = {
- arab = true; arabic = true; breakindent = true; breakindentopt = true;
- bri = true; briopt = true; cc = true; cocu = true;
- cole = true; colorcolumn = true; concealcursor = true; conceallevel = true;
- crb = true; cuc = true; cul = true; cursorbind = true;
- cursorcolumn = true; cursorline = true; diff = true; fcs = true;
- fdc = true; fde = true; fdi = true; fdl = true;
- fdm = true; fdn = true; fdt = true; fen = true;
- fillchars = true; fml = true; fmr = true; foldcolumn = true;
- foldenable = true; foldexpr = true; foldignore = true; foldlevel = true;
- foldmarker = true; foldmethod = true; foldminlines = true; foldnestmax = true;
- foldtext = true; lbr = true; lcs = true; linebreak = true;
- list = true; listchars = true; nu = true; number = true;
- numberwidth = true; nuw = true; previewwindow = true; pvw = true;
- relativenumber = true; rightleft = true; rightleftcmd = true; rl = true;
- rlc = true; rnu = true; scb = true; scl = true;
- scr = true; scroll = true; scrollbind = true; signcolumn = true;
- spell = true; statusline = true; stl = true; wfh = true;
- wfw = true; winbl = true; winblend = true; winfixheight = true;
- winfixwidth = true; winhighlight = true; winhl = true; wrap = true;
- }
-
- --@private
- local function new_buf_opt_accessor(bufnr)
- --@private
- local function get(k)
- if window_options[k] then
- return a.nvim_err_writeln(k.." is a window option, not a buffer option")
- end
- if bufnr == nil and type(k) == "number" then
- return new_buf_opt_accessor(k)
- end
- return a.nvim_buf_get_option(bufnr or 0, k)
- end
-
- --@private
- local function set(k, v)
- if window_options[k] then
- return a.nvim_err_writeln(k.." is a window option, not a buffer option")
- end
- return a.nvim_buf_set_option(bufnr or 0, k, v)
- end
-
- return make_meta_accessor(get, set)
- end
- vim.bo = new_buf_opt_accessor(nil)
-
- --@private
- local function new_win_opt_accessor(winnr)
-
- --@private
- local function get(k)
- if winnr == nil and type(k) == "number" then
- return new_win_opt_accessor(k)
- end
- return a.nvim_win_get_option(winnr or 0, k)
- end
-
- --@private
- local function set(k, v)
- return a.nvim_win_set_option(winnr or 0, k, v)
- end
- return make_meta_accessor(get, set)
- end
- vim.wo = new_win_opt_accessor(nil)
end
--- Get a table of lines with start, end columns for a region marked by two points
@@ -738,4 +636,6 @@ vim._expand_pat_get_parts = function(lua_string)
return parts, search_index
end
+pcall(require, 'vim._meta')
+
return module
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 335fa1cb62..67fb78bcc8 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -4883,7 +4883,7 @@ int get_option_value_strict(char *name,
if (p->flags & P_STRING) {
*stringval = xstrdup(*(char **)(varp));
} else if (p->flags & P_NUM) {
- *numval = *(long *) varp;
+ *numval = *(long *)varp;
} else {
*numval = *(int *)varp;
}
diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim
index c7710ff198..6922e2185d 100644
--- a/src/nvim/testdir/test_writefile.vim
+++ b/src/nvim/testdir/test_writefile.vim
@@ -361,4 +361,25 @@ func Test_write_file_encoding()
%bw!
endfunc
+" Check that buffer is written before triggering QuitPre
+func Test_wq_quitpre_autocommand()
+ edit Xsomefile
+ call setline(1, 'hello')
+ split
+ let g:seq = []
+ augroup Testing
+ au QuitPre * call add(g:seq, 'QuitPre - ' .. (&modified ? 'modified' : 'not modified'))
+ au BufWritePost * call add(g:seq, 'written')
+ augroup END
+ wq
+ call assert_equal(['written', 'QuitPre - not modified'], g:seq)
+
+ augroup Testing
+ au!
+ augroup END
+ bwipe!
+ unlet g:seq
+ call delete('Xsomefile')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab