From 5ac378c355f7539d44fc6b5e55cd6ea5513c3f04 Mon Sep 17 00:00:00 2001 From: Aotrix <9aotrix@protonmail.com> Date: Sun, 30 Aug 2026 16:12:13 +0200 Subject: Added command for competitive programming --- init.lua | 2 +- lua/aotrix/build.lua | 78 ------------ lua/aotrix/competitive_programming.lua | 79 ++++++++++++ lua/aotrix/plugins/build.lua | 224 +++++++++++++++++++++++++++++++++ 4 files changed, 304 insertions(+), 79 deletions(-) delete mode 100644 lua/aotrix/build.lua create mode 100644 lua/aotrix/competitive_programming.lua create mode 100644 lua/aotrix/plugins/build.lua diff --git a/init.lua b/init.lua index 9eaa2e2..0ed647f 100644 --- a/init.lua +++ b/init.lua @@ -11,5 +11,5 @@ vim.opt.rtp:prepend(lazypath) require('aotrix.set') require('aotrix.remap') -require('aotrix.build') +require('aotrix.competitive_programming') require('lazy').setup('aotrix.plugins') diff --git a/lua/aotrix/build.lua b/lua/aotrix/build.lua deleted file mode 100644 index 5b70627..0000000 --- a/lua/aotrix/build.lua +++ /dev/null @@ -1,78 +0,0 @@ -function Compile_and_run_cpp() - local filename = vim.fn.expand("%:p") - local basename = vim.fn.expand("%:r") - local output_file = "output.txt" -- Change this to the desired output file name - local input_file = "input.txt" -- Change this to the desired input file name - - -- Check if current file is a valid C++ or C file - local valid_extensions = {"cpp", "c"} - local valid_file = false - for _, ext in ipairs(valid_extensions) do - if filename:match("%." .. ext .. "$") then - valid_file = true - break - end - end - - -- Exit function if file is not valid - if not valid_file then - vim.api.nvim_err_writeln("Not a valid C++ or C file.") - return - end - - -- Check if input file exists, create if it doesn't - local input_fd = io.open(input_file, "a+") -- Open in append mode to create if it doesn't exist - if input_fd == nil then - vim.api.nvim_err_writeln("Failed to open or create input file: " .. - input_file) - return - end - input_fd:close() - - -- Check if output file exists, create if it doesn't - local output_fd = io.open(output_file, "a+") -- Open in append mode to create if it doesn't exist - if output_fd == nil then - vim.api.nvim_err_writeln("Failed to open or create output file: " .. - output_file) - return - end - output_fd:close() - - -- Check if input file buffer is already open - local input_bufnr = vim.fn.bufnr(input_file) - if input_bufnr == -1 then - -- Open input file in a new split at top right side - vim.cmd("vsp " .. input_file) - else - -- Switch to existing buffer for input file - vim.cmd(input_bufnr .. "wincmd w") - end - -- Check if input file buffer is already open - local output_butnr = vim.fn.bufnr(output_file) - if output_butnr == -1 then - -- Open input file in a new split at top right side - vim.cmd("split " .. output_file) - else - -- Switch to existing buffer for input file - vim.cmd(input_bufnr .. "wincmd w") - end - - vim.cmd("vertical resize 40%") - - local file = vim.fn.bufnr(filename) - vim.cmd(file .. "wincmd w") - - -- Compile and run C++ file - local compile_cmd = string.format("g++ %s -o %s && ./%s < %s > %s", - filename, basename, basename, input_file, - output_file) - vim.cmd("silent w") -- Save the current file - vim.cmd("silent !clear") -- Clear the terminal - vim.cmd("silent !" .. compile_cmd) -- Execute the compile and run command - - -- Open the output file in a new buffer - -- vim.cmd("edit " .. output_file) -end - -vim.api.nvim_set_keymap("n", "mt", ":lua Compile_and_run_cpp()", - {noremap = true, silent = true}) diff --git a/lua/aotrix/competitive_programming.lua b/lua/aotrix/competitive_programming.lua new file mode 100644 index 0000000..bcb5888 --- /dev/null +++ b/lua/aotrix/competitive_programming.lua @@ -0,0 +1,79 @@ +function Compile_and_run_cpp() + local filename = vim.fn.expand("%:p") + local basename = vim.fn.expand("%:r") + local output_file = "output.txt" -- Change this to the desired output file name + local input_file = "input.txt" -- Change this to the desired input file name + + -- Check if current file is a valid C++ or C file + local valid_extensions = {"cpp", "c"} + local valid_file = false + for _, ext in ipairs(valid_extensions) do + if filename:match("%." .. ext .. "$") then + valid_file = true + break + end + end + + -- Exit function if file is not valid + if not valid_file then + vim.api.nvim_err_writeln("Not a valid C++ or C file.") + return + end + + -- Check if input file exists, create if it doesn't + local input_fd = io.open(input_file, "a+") -- Open in append mode to create if it doesn't exist + if input_fd == nil then + vim.api.nvim_err_writeln("Failed to open or create input file: " .. + input_file) + return + end + input_fd:close() + + -- Check if output file exists, create if it doesn't + local output_fd = io.open(output_file, "a+") -- Open in append mode to create if it doesn't exist + if output_fd == nil then + vim.api.nvim_err_writeln("Failed to open or create output file: " .. + output_file) + return + end + output_fd:close() + + -- Check if input file buffer is already open + local input_bufnr = vim.fn.bufnr(input_file) + if input_bufnr == -1 then + -- Open input file in a new split at top right side + vim.cmd("vsp " .. input_file) + else + -- Switch to existing buffer for input file + vim.cmd(input_bufnr .. "wincmd w") + end + -- Check if input file buffer is already open + local output_butnr = vim.fn.bufnr(output_file) + if output_butnr == -1 then + -- Open input file in a new split at top right side + vim.cmd("split " .. output_file) + else + -- Switch to existing buffer for input file + vim.cmd(input_bufnr .. "wincmd w") + end + + vim.cmd("vertical resize 40%") + + local file = vim.fn.bufnr(filename) + vim.cmd(file .. "wincmd w") + + -- Compile and run C++ file + local compile_cmd = string.format("g++ %s -o %s && ./%s < %s > %s", + filename, basename, basename, input_file, + output_file) + vim.cmd("silent w") -- Save the current file + vim.cmd("silent !clear") -- Clear the terminal + vim.cmd("silent !" .. compile_cmd) -- Execute the compile and run command + + -- Open the output file in a new buffer + -- vim.cmd("edit " .. output_file) +end + +vim.api.nvim_create_user_command("CompetitiveProgrammingRun", + function() Compile_and_run_cpp() end, + { desc = 'Run current cpp file with input/output windows' }) diff --git a/lua/aotrix/plugins/build.lua b/lua/aotrix/plugins/build.lua new file mode 100644 index 0000000..c940993 --- /dev/null +++ b/lua/aotrix/plugins/build.lua @@ -0,0 +1,224 @@ +return { + "MunifTanjim/nui.nvim", + config = function() + local COMMANDS = {} + local CURRENT_COMMAND = nil + local data_path = vim.fn.stdpath("data") + local PERSONAL_COMMAND_JSON_PATH = data_path .. + "/personal_commands.json" + + ---@param command string|nil + ---@return nil + local executeCommandInTerminal = function(command) + if (command ~= nil) then + vim.cmd.term() + vim.cmd.startinsert() + local channel = vim.bo.channel + -- 'clear' is used to hide the command + local exitMessage = "\nPress enter to exit..." + local commandString = command() + vim.api.nvim_chan_send(channel, + "clear && " .. commandString .. + "; echo '" .. exitMessage .. + "' && read -s && exit" .. "\n") + end + end + + local readJsonFromFile = function(filePath) + local file, error = io.open(filePath, 'r') + if file ~= nil then + local content = file:read("*a") + local decoded_json = vim.json.decode(content) + return decoded_json + else + print("Error in readJsonFromFile: " .. error) + end + return nil + end + + local addCommandToJsonFile = function(commandBlock, commandsFilePath, + directory) + local current_json = readJsonFromFile(commandsFilePath) + if current_json ~= nil then + if current_json[directory] == nil then + current_json[directory] = {} + end + -- FIXME: duplicates + table.insert(current_json[directory], { + command = tostring(commandBlock.command()), + description = tostring(commandBlock.description()) + }) + end + local file, error = io.open(commandsFilePath, 'w') + if file then + local indent = + vim.bo.expandtab and (' '):rep(vim.o.shiftwidth) or '\t' + file:write(vim.json.encode(current_json, {indent = indent})) + file:close() + else + print("Error in writeTableToJsonFile: " .. error) + end + end + + local updateJsonFile = function(listOfCommands, commandsFilePath, + directory) + local current_json = readJsonFromFile(commandsFilePath) + current_json[directory] = {} + for _, value in pairs(listOfCommands) do + table.insert(current_json[directory], { + command = tostring(value.command()), + description = tostring(value.description()) + }) + end + + local file, error = io.open(commandsFilePath, 'w') + if file then + local indent = + vim.bo.expandtab and (' '):rep(vim.o.shiftwidth) or '\t' + file:write(vim.json.encode(current_json, {indent = indent})) + file:close() + else + print("Error in updateJsonFile: " .. error) + end + end + + local appendCommandsFromFile = function(commands, commandsFilePath, + directory) + local current_list_of_commands_json = readJsonFromFile( + commandsFilePath) + if current_list_of_commands_json ~= nil and + current_list_of_commands_json[directory] ~= nil then + for _, block in pairs(current_list_of_commands_json[directory]) do + local new_command_name = block["description"] + commands[new_command_name] = { + command = function() + return block["command"] + end, + description = function() + return new_command_name + end + } + end + end + end + + local selectCommand = function(listOfCommands, callback) + vim.ui.select(vim.tbl_keys(listOfCommands), { + prompt = "Select your command.", + format_item = function(item) + return listOfCommands[item].description() + end + }, function(choice) + if (choice ~= nil) then + CURRENT_COMMAND = listOfCommands[choice].command + callback(choice) + end + end) + end + + local addCommand = function(current_command, commands, + personal_command_json_path) + + local selectedCommand = nil + local event = require("nui.utils.autocmd").event + local Input = require("nui.input") + local input = Input({ + position = "50%", + size = {width = 120}, + border = { + style = "single", + text = {top = "[Howdy?]", top_align = "center"} + }, + win_options = { + winhighlight = "Normal:Normal,FloatBorder:Normal" + } + }, { + prompt = "> ", + default_value = "", + on_submit = function(value) + selectedCommand = value + local selectedDescription = vim.fn.input( + 'Name the command: ') + commands[selectedDescription] = { + command = function() + return selectedCommand + end, + description = function() + return selectedDescription + end + } + local created_command = commands[selectedDescription] + addCommandToJsonFile(created_command, + personal_command_json_path, + vim.fn.getcwd()) + current_command = created_command.command + executeCommandInTerminal(current_command) + end + }) + -- mount/open the component + input:mount() + + input:map("n", "", function() input:unmount() end, + {noremap = true}) + + end + + local deleteCommand = function() + local previous_command = CURRENT_COMMAND + selectCommand(COMMANDS, function(choice) + local index = 0 + for key, _ in pairs(COMMANDS) do + index = index + 1 + if key == choice then + COMMANDS[key] = nil + updateJsonFile(COMMANDS, PERSONAL_COMMAND_JSON_PATH, + vim.fn.getcwd()) + break + end + end + CURRENT_COMMAND = previous_command + end) + end + + vim.api.nvim_create_user_command("AddCommand", function() + addCommand(CURRENT_COMMAND, COMMANDS, PERSONAL_COMMAND_JSON_PATH) + end, {}) + + vim.api.nvim_create_user_command("DeleteCommand", deleteCommand, {}) + + vim.api.nvim_create_autocmd({'BufEnter', 'BufWinEnter', 'DirChanged'}, { + callback = function() + COMMANDS = {} + local current_json = + readJsonFromFile(PERSONAL_COMMAND_JSON_PATH) + local current_path = vim.fn.getcwd() + if current_json ~= nil then + for existing_directory, _ in pairs(current_json) do + if (string.find(current_path, existing_directory) == 1) then + appendCommandsFromFile(COMMANDS, + PERSONAL_COMMAND_JSON_PATH, + existing_directory) + end + end + end + end + }) + + vim.keymap.set("n", "mc", function() + if (CURRENT_COMMAND == nil) then + selectCommand(COMMANDS, function() + executeCommandInTerminal(CURRENT_COMMAND) + end) + else + executeCommandInTerminal(CURRENT_COMMAND) + end + end) + + vim.keymap.set("n", "mC", function() + selectCommand(COMMANDS, function() + executeCommandInTerminal(CURRENT_COMMAND) + end) + end) + + end +} -- cgit v1.2.3