diff --git a/ftplugin/matlab.lua b/ftplugin/matlab.lua index b12075f..091b3a6 100644 --- a/ftplugin/matlab.lua +++ b/ftplugin/matlab.lua @@ -39,6 +39,7 @@ map(prefix .. (mappings.clear_workspace or 'x'), 'MatlabClearWorkspace', 'MATLAB map(prefix .. (mappings.toggle_cell_fold or 'f'), 'MatlabToggleCellFold', 'MATLAB: Toggle cell fold') map(prefix .. (mappings.open_in_gui or 'g'), 'MatlabOpenInGUI', 'MATLAB: Open in GUI') map(prefix .. (mappings.run_tests or 'T'), 'MatlabRunTests', 'MATLAB: Run all tests') +map(prefix .. (mappings.run_current_test or 't'), 'MatlabRunCurrentTest', 'MATLAB: Run current test') -- ============================================================================ -- Debug Commands (md + key) @@ -78,6 +79,7 @@ vim.api.nvim_buf_create_user_command(0, 'MatlabKeymaps', function() ' ' .. p .. 'f - Toggle cell fold', ' ' .. p .. 'g - Open in GUI', ' ' .. p .. 'T - Run all tests', + ' ' .. p .. 't - Run current test', '', 'Debug (' .. dp .. ' + key):', ' ' .. dp .. 's - Start debug', diff --git a/lua/matlab/commands.lua b/lua/matlab/commands.lua index a919bcf..524a1f4 100644 --- a/lua/matlab/commands.lua +++ b/lua/matlab/commands.lua @@ -98,6 +98,101 @@ function M.run_tests() tmux.run('runtests(pwd)') end +-- Run the test at cursor +function M.run_current_test() + if not tmux.exists() then + return + end + + -- Ensure we are in a MATLAB buffer + if not M.is_matlab_script() then + return + end + + -- Try to get the parser for the current buffer + local has_parser, parser = pcall(vim.treesitter.get_parser, 0, "matlab") + if not has_parser or not parser then + vim.notify('MATLAB Tree-sitter parser not found. Please run :TSInstall matlab', vim.log.levels.ERROR) + return + end + + -- Get the root of the tree + local tree = parser:parse()[1] + local root = tree:root() + + -- Get the node at the cursor + local cursor = vim.api.nvim_win_get_cursor(0) + local row, col = cursor[1] - 1, cursor[2] + local node = root:named_descendant_for_range(row, col, row, col) + + if not node then + vim.notify('No syntax node found at cursor position.', vim.log.levels.WARN) + return + end + + local function_name = nil + local class_name = nil + + -- Traverse up to find Function or Class definition + local curr = node + while curr do + local type = curr:type() + if type == "function_definition" then + -- In many parsers, name is a field. We can use field() to check. + -- However, iterating children and checking their field name is safer + -- for different parser versions. + for child, field in curr:iter_children() do + if field == "name" then + function_name = vim.treesitter.get_node_text(child, 0) + break + end + end + -- Fallback if field "name" wasn't found (though it should be) + if not function_name then + for child in curr:iter_children() do + if child:type() == "identifier" then + function_name = vim.treesitter.get_node_text(child, 0) + break + end + end + end + elseif type == "classdef" then + for child, field in curr:iter_children() do + if field == "name" then + class_name = vim.treesitter.get_node_text(child, 0) + break + end + end + end + curr = curr:parent() + end + + local test_cmd = nil + local filename = M.get_filename() + + if function_name then + -- It's a method or a function + if class_name then + -- Class-based test + test_cmd = string.format("runtests('%s/%s')", class_name, function_name) + else + -- Function-based test (or just a local function in a test file) + test_cmd = string.format("runtests('%s/%s')", filename, function_name) + end + elseif class_name then + -- Just the class + test_cmd = string.format("runtests('%s')", class_name) + else + -- Fallback to running the whole file as a test + test_cmd = string.format("runtests('%s')", filename) + end + + if test_cmd then + vim.notify('Running test: ' .. test_cmd, vim.log.levels.INFO) + tmux.run(test_cmd) + end +end + -- Show documentation for the word under cursor function M.doc() if not tmux.exists() then diff --git a/lua/matlab/config.lua b/lua/matlab/config.lua index 797e809..c72b975 100644 --- a/lua/matlab/config.lua +++ b/lua/matlab/config.lua @@ -40,6 +40,7 @@ M.defaults = { toggle_cell_fold = 'f', -- mf - Toggle cell fold open_in_gui = 'g', -- mg - Open in MATLAB GUI run_tests = 'T', -- mT - Run all tests + run_current_test = 't', -- mt - Run current test -- Debug commands (md + key) debug_prefix = 'd', -- Makes md the debug prefix diff --git a/lua/matlab/init.lua b/lua/matlab/init.lua index 995da24..a68f6ac 100644 --- a/lua/matlab/init.lua +++ b/lua/matlab/init.lua @@ -60,6 +60,10 @@ function M.setup(opts) commands.run_tests() end, {}) + vim.api.nvim_create_user_command('MatlabRunCurrentTest', function() + commands.run_current_test() + end, {}) + -- Cell execution commands vim.api.nvim_create_user_command('MatlabRunCell', function() cells.execute_current_cell()