From c7f90b5bbacc174a1900e9912770515e1d3e372e Mon Sep 17 00:00:00 2001 From: MarcHamamji Date: Fri, 3 Feb 2023 20:39:38 +0200 Subject: [PATCH] MVP --- lua/runner/handlers/helpers.lua | 93 ++++++++++++++++ lua/runner/handlers/init.lua | 11 ++ .../handlers/languages/nodejs/get-scripts.sh | 2 + lua/runner/handlers/languages/nodejs/init.lua | 24 +++++ lua/runner/handlers/languages/python.lua | 5 + .../handlers/languages/rust/get-bins.sh | 2 + lua/runner/handlers/languages/rust/init.lua | 27 +++++ lua/runner/handlers/utils.lua | 102 ++++++++++++++++++ lua/runner/init.lua | 30 ++++++ 9 files changed, 296 insertions(+) create mode 100644 lua/runner/handlers/helpers.lua create mode 100644 lua/runner/handlers/init.lua create mode 100755 lua/runner/handlers/languages/nodejs/get-scripts.sh create mode 100644 lua/runner/handlers/languages/nodejs/init.lua create mode 100644 lua/runner/handlers/languages/python.lua create mode 100755 lua/runner/handlers/languages/rust/get-bins.sh create mode 100644 lua/runner/handlers/languages/rust/init.lua create mode 100644 lua/runner/handlers/utils.lua create mode 100644 lua/runner/init.lua diff --git a/lua/runner/handlers/helpers.lua b/lua/runner/handlers/helpers.lua new file mode 100644 index 0000000..a7d0f6e --- /dev/null +++ b/lua/runner/handlers/helpers.lua @@ -0,0 +1,93 @@ +local pickers = require('telescope.pickers') +local finders = require('telescope.finders') +local actions = require('telescope.actions') +local action_state = require('telescope.actions.state') +local sorters = require('telescope.sorters') + +local utils = require('runner.handlers.utils') + +local M = {} + +M._job_id = nil + +M.shell_handler = function(command, editable) + if editable == nil then + editable = false + end + return function(code_buffer) + if editable then + command = vim.fn.input('Command: ', command) + end + + local current_buffer_name = vim.api.nvim_buf_get_name(code_buffer) + + local output_buffer = utils.create_buffer('OUTPUT - ' .. current_buffer_name) + vim.api.nvim_create_autocmd('BufHidden', { + buffer = output_buffer, + callback = function() + vim.schedule(function() + vim.api.nvim_buf_delete(output_buffer, {}) + vim.fn.jobstop(M._job_id) + M._job_id = nil + print('Terminated running process') + end) + end + }) + + local output_window = utils.create_window() + + vim.api.nvim_win_set_buf(output_window, output_buffer) + + local add_line = utils.create_add_line(output_buffer) + + if M._job_id then + vim.fn.jobstop(M._job_id) + M._job_id = nil + end + + M._job_id = vim.fn.jobstart(command, { + pty = true, + cwd = vim.fn.getcwd(), + on_stdout = add_line, + on_stderr = add_line + }) + end +end + +M.command_handler = function(command) + return function() + vim.cmd(command) + end +end + +-- handlers = { 'Run Tests' = test_handler, 'Run Code' = code_handler } +M.choice = function(handlers) + local handlers_count = vim.tbl_count(handlers) + if handlers_count == 0 then + print('No handler available right now') + return function() end + elseif handlers_count == 1 then + return vim.tbl_values(handlers)[1] + end + + return function(buffer) + local picker = pickers.new({}, { + prompt_title = "Runner", + finder = finders.new_table { + results = vim.tbl_keys(handlers) + }, + sorter = sorters.get_generic_fuzzy_sorter(), + attach_mappings = function(prompt_bufnr) + actions.select_default:replace(function() + actions.close(prompt_bufnr) + local handler_name = action_state.get_selected_entry()[1] + handlers[handler_name](buffer) + end) + return true + end, + }) + picker:find() + end +end + +return M diff --git a/lua/runner/handlers/init.lua b/lua/runner/handlers/init.lua new file mode 100644 index 0000000..abd4e4b --- /dev/null +++ b/lua/runner/handlers/init.lua @@ -0,0 +1,11 @@ +local helpers = require('runner.handlers.helpers') + +local handlers = { + rust = require('runner.handlers.languages.rust'), + python = require('runner.handlers.languages.python'), + lua = helpers.command_handler('luafile %'), + javascript = require('runner.handlers.languages.nodejs'), + typescript = require('runner.handlers.languages.nodejs') +} + +return handlers diff --git a/lua/runner/handlers/languages/nodejs/get-scripts.sh b/lua/runner/handlers/languages/nodejs/get-scripts.sh new file mode 100755 index 0000000..becc993 --- /dev/null +++ b/lua/runner/handlers/languages/nodejs/get-scripts.sh @@ -0,0 +1,2 @@ +npm run 2>&1 | grep " " | awk '{$1=$1};1' | sed -n 'p;n' + diff --git a/lua/runner/handlers/languages/nodejs/init.lua b/lua/runner/handlers/languages/nodejs/init.lua new file mode 100644 index 0000000..8733254 --- /dev/null +++ b/lua/runner/handlers/languages/nodejs/init.lua @@ -0,0 +1,24 @@ +local helpers = require('runner.handlers.helpers') +local utils = require('runner.handlers.utils') + +return function(buffer) + utils.run_command(utils.script_path() .. 'get-scripts.sh', function(output) + local bins = {} + + for _, line in pairs(output) do + for _, data in pairs(line) do + if vim.trim(data) ~= '' then + bins[#bins + 1] = data + end + end + end + + local handlers = {} + + for _, bin in pairs(bins) do + handlers['Run "' .. bin .. '"'] = helpers.shell_handler('npm run ' .. bin) + end + + helpers.choice(handlers)(buffer) + end) +end diff --git a/lua/runner/handlers/languages/python.lua b/lua/runner/handlers/languages/python.lua new file mode 100644 index 0000000..993231e --- /dev/null +++ b/lua/runner/handlers/languages/python.lua @@ -0,0 +1,5 @@ +local helpers = require('runner.handlers.helpers') + +return function(buffer) + helpers.shell_handler('python ' .. vim.fn.expand('%'))(buffer) +end diff --git a/lua/runner/handlers/languages/rust/get-bins.sh b/lua/runner/handlers/languages/rust/get-bins.sh new file mode 100755 index 0000000..63b2647 --- /dev/null +++ b/lua/runner/handlers/languages/rust/get-bins.sh @@ -0,0 +1,2 @@ +cargo run --bin 2>&1 | grep " " | awk '{$1=$1};1' + diff --git a/lua/runner/handlers/languages/rust/init.lua b/lua/runner/handlers/languages/rust/init.lua new file mode 100644 index 0000000..9357eca --- /dev/null +++ b/lua/runner/handlers/languages/rust/init.lua @@ -0,0 +1,27 @@ +local helpers = require('runner.handlers.helpers') +local utils = require('runner.handlers.utils') + +return function(buffer) + utils.run_command(utils.script_path() .. 'get-bins.sh', function(output) + local bins = {} + + for _, line in pairs(output) do + for _, data in pairs(line) do + if vim.trim(data) ~= '' then + bins[#bins + 1] = data + end + end + end + + local handlers = { + ['Run main'] = helpers.shell_handler('cargo run'), + ['Test'] = helpers.shell_handler('cargo test'), + } + + for _, bin in pairs(bins) do + handlers['Run "' .. bin .. '"'] = helpers.shell_handler('cargo run --bin ' .. bin) + end + + helpers.choice(handlers)(buffer) + end) +end diff --git a/lua/runner/handlers/utils.lua b/lua/runner/handlers/utils.lua new file mode 100644 index 0000000..bffc211 --- /dev/null +++ b/lua/runner/handlers/utils.lua @@ -0,0 +1,102 @@ +local baleia = require('baleia').setup {} + +local M = {} + +M._buffer = nil +M._window = nil + +M.create_buffer = function(name) + if M._buffer and vim.api.nvim_buf_is_valid(M._buffer) then + vim.api.nvim_buf_set_option(M._buffer, 'modifiable', true) + vim.api.nvim_buf_set_lines(M._buffer, 0, -1, false, {}) + vim.api.nvim_buf_set_option(M._buffer, 'modifiable', false) + return M._buffer + end + + local buffer = vim.api.nvim_create_buf(true, true) + vim.api.nvim_buf_set_name(buffer, name) + vim.api.nvim_buf_set_option(buffer, 'modifiable', false) + + M._buffer = buffer + return buffer +end + +M.create_window = function() + if M._window and vim.api.nvim_win_is_valid(M._window) and vim.api.nvim_win_get_buf(M._window) == M._buffer then + return M._window + end + vim.cmd [[ vsplit ]] + local window = vim.api.nvim_get_current_win() + + local window_opts = { + number = false, + relativenumber = false, + wrap = true, + spell = false, + foldenable = false, + signcolumn = "no", + colorcolumn = "", + cursorline = true, + } + + for key, value in pairs(window_opts) do + vim.api.nvim_win_set_option(window, key, value) + end + + M._window = window + return window +end + +M.create_add_line = function(buffer) + return function(_, data) + vim.api.nvim_buf_set_option(buffer, 'modifiable', true) + local row = vim.api.nvim_buf_line_count(buffer) - 1 + local col = vim.fn.len(vim.api.nvim_buf_get_lines(buffer, -2, -1, false)[1]) + baleia.buf_set_text(buffer, row, col, row, col, vim.tbl_map( + function(d) + return vim.fn.trim(d, ('\x0D')) + end, + data + )) + vim.api.nvim_buf_set_option(buffer, 'modifiable', false) + end +end + +M.run_command = function(command, callback) + local output = {} + + local add_line = function(_, data) + output[#output + 1] = data + end + + vim.fn.jobstart(command, { + cwd = vim.fn.getcwd(), + on_stdout = add_line, + on_exit = function() + callback(output) + end + }) + +end + + +local is_win = function() + return package.config:sub(1, 1) == '\\' +end + +local get_path_separator = function() + if package.config:sub(1, 1) == '\\' then + return '\\' + end + return '/' +end + +M.script_path = function() + local str = debug.getinfo(2, 'S').source:sub(2) + if is_win() then + str = str:gsub('/', '\\') + end + return str:match('(.*' .. get_path_separator() .. ')') +end + +return M diff --git a/lua/runner/init.lua b/lua/runner/init.lua new file mode 100644 index 0000000..f2cbf3f --- /dev/null +++ b/lua/runner/init.lua @@ -0,0 +1,30 @@ +local handlers = require('runner.handlers') + +local M = {} + +M._handlers = handlers + +M.set_handler = function(filetype, handler) + M._handlers[filetype] = handler +end + +M.run = function(bufnr) + local buffer + if bufnr == nil or bufnr == 0 then + buffer = vim.api.nvim_get_current_buf() + else + buffer = bufnr + end + local filetype = vim.filetype.match({ buf = buffer }) + + local handler = M._handlers[filetype] + + if not handler then + print(string.format('No handler defined for filetype \'%s\'', filetype)) + return + end + + handler(buffer) +end + +return M