diff --git a/runtime/plugin/shada.lua b/runtime/plugin/shada.lua new file mode 100644 index 0000000000..e1517de626 --- /dev/null +++ b/runtime/plugin/shada.lua @@ -0,0 +1,76 @@ +if vim.g.loaded_shada_plugin then + return +end +vim.g.loaded_shada_plugin = 1 + +local augroup = vim.api.nvim_create_augroup('nvim.shada', {}) + +---@type fun(binstrings: string[]): string[] +local shada_get_strings = vim.fn['shada#get_strings'] + +---@type fun(strings: string[]): string[] +local shada_get_binstrings = vim.fn['shada#get_binstrings'] + +---Ensures that pattern and augroup are set correctly. +---@param event string|string[] +---@param opts vim.api.keyset.create_autocmd +---@param fn fun(args: vim.api.keyset.create_autocmd.callback_args): boolean? +local function def_autocmd(event, opts, fn) + opts = opts or {} + opts.group = augroup + opts.pattern = { '*.shada', '*.shada.tmp.[a-z]' } + opts.callback = function(ev) + if vim.v.cmdarg ~= '' then + error('++opt not supported') + end + fn(ev) + end + vim.api.nvim_create_autocmd(event, opts) +end + +---Read shada strings from file. +---@param file string Filename +---@return string[] # lines from shada file +local function read_strings(file) + local f = assert(io.open(file, 'rb')) + local strings = f:read('*a') + f:close() + return shada_get_strings(strings) +end + +def_autocmd('BufReadCmd', {}, function(ev) + local lines = read_strings(ev.file) + vim.api.nvim_buf_set_lines(ev.buf, 0, -1, false, lines) + vim.bo[ev.buf].filetype = 'shada' +end) + +def_autocmd('FileReadCmd', {}, function(ev) + local lines = read_strings(ev.file) + local lnum = vim.fn.line("'[") + vim.api.nvim_buf_set_lines(ev.buf, lnum, lnum, true, lines) +end) + +def_autocmd('BufWriteCmd', {}, function(ev) + local buflines = vim.api.nvim_buf_get_lines(0, 0, -1, false) + local err = vim.fn.writefile(shada_get_binstrings(buflines), ev.file, 'b') + if not err then + vim.bo[ev.buf].modified = false + end +end) + +def_autocmd({ 'FileWriteCmd', 'FileAppendCmd' }, {}, function(ev) + vim.fn.writefile( + shada_get_binstrings( + vim.fn.getline( + math.min(vim.fn.line("'["), vim.fn.line("']")), + math.max(vim.fn.line("'["), vim.fn.line("']")) + ) --[=[@as string[]]=] + ), + ev.file, + ev.event == 'FileAppendCmd' and 'ab' or 'b' + ) +end) + +def_autocmd('SourceCmd', {}, function(ev) + vim.cmd.rshada(vim.fn.fnameescape(ev.file)) +end) diff --git a/runtime/plugin/shada.vim b/runtime/plugin/shada.vim deleted file mode 100644 index 5c7d93aaa0..0000000000 --- a/runtime/plugin/shada.vim +++ /dev/null @@ -1,39 +0,0 @@ -if exists('g:loaded_shada_plugin') - finish -endif -let g:loaded_shada_plugin = 1 - -augroup nvim.shada - autocmd! - autocmd BufReadCmd *.shada,*.shada.tmp.[a-z] - \ :if !empty(v:cmdarg)|throw '++opt not supported'|endif - \ |call setline('.', shada#get_strings(readfile(expand(''),'b'))) - \ |setlocal filetype=shada - autocmd FileReadCmd *.shada,*.shada.tmp.[a-z] - \ :if !empty(v:cmdarg)|throw '++opt not supported'|endif - \ |call append("'[", shada#get_strings(readfile(expand(''), 'b'))) - autocmd BufWriteCmd *.shada,*.shada.tmp.[a-z] - \ :if !empty(v:cmdarg)|throw '++opt not supported'|endif - \ |if writefile(shada#get_binstrings(getline(1, '$')), - \expand(''), 'b') == 0 - \ | let &l:modified = (expand('') is# bufname(+expand('')) - \? 0 - \: stridx(&cpoptions, '+') != -1) - \ |endif - autocmd FileWriteCmd *.shada,*.shada.tmp.[a-z] - \ :if !empty(v:cmdarg)|throw '++opt not supported'|endif - \ |call writefile( - \shada#get_binstrings(getline(min([line("'["), line("']")]), - \max([line("'["), line("']")]))), - \expand(''), - \'b') - autocmd FileAppendCmd *.shada,*.shada.tmp.[a-z] - \ :if !empty(v:cmdarg)|throw '++opt not supported'|endif - \ |call writefile( - \shada#get_binstrings(getline(min([line("'["), line("']")]), - \max([line("'["), line("']")]))), - \expand(''), - \'ab') - autocmd SourceCmd *.shada,*.shada.tmp.[a-z] - \ :execute 'rshada' fnameescape(expand('')) -augroup END diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua index 26af1a127a..58b33a21ec 100644 --- a/test/functional/plugin/shada_spec.lua +++ b/test/functional/plugin/shada_spec.lua @@ -2664,7 +2664,12 @@ describe('plugin/shada.vim', function() }, nvim_eval('getline(1, "$")')) eq(false, api.nvim_get_option_value('modified', {})) eq('shada', api.nvim_get_option_value('filetype', {})) - eq('++opt not supported', exc_exec('edit ++enc=latin1 ' .. fname)) + t.matches( + '++opt not supported', + t.pcall_err(function() + nvim_command('edit ++enc=latin1 ' .. fname) + end) + ) neq({ 'History entry with timestamp ' .. epoch .. ':', ' @ Description_ Value', @@ -2707,7 +2712,12 @@ describe('plugin/shada.vim', function() eq(true, api.nvim_get_option_value('modified', {})) neq('shada', api.nvim_get_option_value('filetype', {})) api.nvim_set_option_value('modified', false, {}) - eq('++opt not supported', exc_exec('$read ++enc=latin1 ' .. fname)) + t.matches( + '++opt not supported', + t.pcall_err(function() + nvim_command('$read ++enc=latin1 ' .. fname) + end) + ) eq({ '', 'History entry with timestamp ' .. epoch .. ':', @@ -2744,7 +2754,12 @@ describe('plugin/shada.vim', function() nvim_command('w ' .. fname .. '.tst') nvim_command('w ' .. fname) nvim_command('w ' .. fname_tmp) - eq('++opt not supported', exc_exec('w! ++enc=latin1 ' .. fname)) + t.matches( + '++opt not supported', + t.pcall_err(function() + nvim_command('w! ++enc=latin1 ' .. fname) + end) + ) eq(table.concat({ 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', @@ -2805,7 +2820,12 @@ describe('plugin/shada.vim', function() nvim_command('1,3w ' .. fname .. '.tst') nvim_command('1,3w ' .. fname) nvim_command('1,3w ' .. fname_tmp) - eq('++opt not supported', exc_exec('1,3w! ++enc=latin1 ' .. fname)) + t.matches( + '++opt not supported', + t.pcall_err(function() + nvim_command('1,3w! ++enc=latin1 ' .. fname) + end) + ) eq(table.concat({ 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', @@ -2855,7 +2875,12 @@ describe('plugin/shada.vim', function() nvim_command('w >> ' .. fname .. '.tst') nvim_command('w >> ' .. fname) nvim_command('w >> ' .. fname_tmp) - eq('++opt not supported', exc_exec('1,3w! ++enc=latin1 >> ' .. fname)) + t.matches( + '++opt not supported', + t.pcall_err(function() + nvim_command('1,3w! ++enc=latin1 >> ' .. fname) + end) + ) eq(table.concat({ 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value',