diff --git a/lua/nvim-sync-ftp.lua b/lua/nvim-sync-ftp.lua index b014659..a162442 100644 --- a/lua/nvim-sync-ftp.lua +++ b/lua/nvim-sync-ftp.lua @@ -3,42 +3,46 @@ local cli = require("nvim-sync-ftp.cli") local M = {} function M.setup(opts) + local config = cli.getConfig() - local config = cli.getConfig() + vim.api.nvim_create_user_command("SyncFtpMapToRemote", function(params) + cli.MapToRemote(params) + end, { + force = true, + nargs = '*', + range = true, + }) - vim.api.nvim_create_user_command("SyncFtpMapToRemote", function (params) - cli.MapToRemote(params) - end,{ - force = true, - nargs = '*', - range = true, - }) + vim.api.nvim_create_user_command("SyncFtpUpload", function(params) + cli.UploadFile() + end, { + force = true, + nargs = '*', + range = true, + }) - vim.api.nvim_create_user_command("SyncFtpUpload", function(params) - cli.Upload() - end,{ - force = true, - nargs = '*', - range = true, - }) + vim.api.nvim_create_user_command("SyncFtpUploadDir", function(params) + cli.UploadDir() + end, { + force = true, + nargs = '*', + range = true, + }) - if next(config) ~= nil then - -- Config for on save - if config.upload_to_save == 'true' then - vim.api.nvim_create_augroup("SyncFtpUploadGroup", { clear = true }) - - vim.api.nvim_create_autocmd("BufWritePost", { - group = "SyncFtpUploadGroup", - pattern = "*.*", - callback = function(args) - cli.Upload() - end - }) - end - - - end + if next(config) ~= nil then + -- Config for on save + if config.upload_to_save == 'true' then + vim.api.nvim_create_augroup("SyncFtpUploadGroup", { clear = true }) + vim.api.nvim_create_autocmd("BufWritePost", { + group = "SyncFtpUploadGroup", + pattern = "*.*", + callback = function(args) + cli.Upload() + end + }) + end + end end return M diff --git a/lua/nvim-sync-ftp/cli.lua b/lua/nvim-sync-ftp/cli.lua index 47b45e6..8cfc7cc 100644 --- a/lua/nvim-sync-ftp/cli.lua +++ b/lua/nvim-sync-ftp/cli.lua @@ -5,120 +5,199 @@ local config = {} local M = {} +local function path_components(path) + -- Remove trailing slashes + path = path:gsub("/+$", "") + + -- Extract the directory (dirname) + local dir = path:match("^(.*)/[^/]*$") or "." + if dir == "" then dir = "/" end -- Handle edge case for root-level paths like "/file.txt" + + -- Extract the basename + local base = path:match("[^/]+$") or path + if base == "" then base = "/" end -- Handle edge case for "/" or empty path + + -- Extract the parent directory (one level up from dir) + local parent + if dir == "." then + parent = ".." -- Parent of current directory + elseif dir == "/" then + parent = "/" -- Root's parent is itself + else + parent = dir:match("^(.*)/[^/]*$") or "/" + if parent == "" then parent = "/" end -- Handle edge case for "/dir" + end + + return { + dir = dir, -- Directory containing the file (dirname) + base = base, -- Filename without directory (basename) + parent = parent -- Parent directory one level up from dir + } +end + +local function dirname(str) + if str:match(".-/.-") then + local name = string.gsub(str, "(.*/)(.*)", "%1") + return name + else + return '' + end +end + local function file_exists() - return vim.loop.fs_stat(filePath) ~= nil + return vim.loop.fs_stat(filePath) ~= nil end local function create_file() + local buf = vim.api.nvim_create_buf(true, true) - local buf = vim.api.nvim_create_buf(true, true) + vim.api.nvim_buf_set_name(buf, filePath) - vim.api.nvim_buf_set_name(buf, filePath) + vim.api.nvim_buf_set_lines(buf, 0, -1, false, { + "host hostName", + "user userName", + "password password", + "port 21", + "remote_path /remote/", + "upload_to_save false", + }) - vim.api.nvim_buf_set_lines(buf, 0, -1, false, { - "host hostName" , - "user userName", - "password password", - "port 21", - "remote_path /remote/", - "upload_to_save false", - }) + vim.api.nvim_set_option_value("buftype", "", { buf = buf }) - vim.api.nvim_buf_set_option(buf, "buftype", "") + vim.api.nvim_buf_call(buf, function() + vim.cmd("write") + end) - vim.api.nvim_buf_call(buf, function() - vim.cmd("write") - end) - - vim.api.nvim_win_set_buf(0, buf) - - message.success("File created successfully!!!") + vim.api.nvim_win_set_buf(0, buf) + message.success("File created successfully!!!") end -function M.MapToRemote () - - if file_exists() then - message.warn("File already exists!!!"); - else - create_file() - end - +function M.MapToRemote() + if file_exists() then + message.warn("File already exists!!!"); + else + create_file() + end end local function read_file(path) - local file = io.open(path, "r") + local file = io.open(path, "r") - if not file then - return nil, "Config file not found!" - end + if not file then + return nil, "Config file not found!" + end - local lines = {} - for line in file:lines() do - table.insert(lines, line) - end - file:close() - return lines + local lines = {} + for line in file:lines() do + table.insert(lines, line) + end + file:close() + return lines end function M.getConfig() + local configTemp = {}; - local configTemp = {}; + if file_exists() then + local content, err = read_file(filePath) - if file_exists() then - local content, err = read_file(filePath) + if content then + for _, line in ipairs(content) do + local first_word, second_word = line:match("^(%S+)%s+(%S+)$") + configTemp[first_word] = second_word + end + else + message(err); + end + end - if content then - for i, line in ipairs(content) do - local first_word, second_word = line:match("^(%S+)%s+(%S+)$") - configTemp[first_word] = second_word - end - else - message(err); - end - end - - return configTemp + return configTemp end -function M.Upload() +function M.UploadFile() + config = M.getConfig() + local current_buffer_path = vim.api.nvim_buf_get_name(0) + local directoryTemp = directory - config = M.getConfig() - local current_buffer_path = vim.api.nvim_buf_get_name(0) - local directoryTemp = directory + message.warn("Send file ... Wait") - message.warn("Send file ... Wait") + if not directoryTemp:match("/$") then + directoryTemp = directoryTemp .. "/" + end - if not directoryTemp:match("/$") then - directoryTemp = directoryTemp .. "/" - end + local relative_path = current_buffer_path:sub(#directoryTemp + 1) - local relative_path = current_buffer_path:sub(#directoryTemp + 1) + if not config.remote_path:match("/$") then + config.remote_path = config.remote_path .. "/" + end - if not config.remote_path:match("/$") then - config.remote_path = config.remote_path .. "/" - end + local remotePath = config.remote_path .. relative_path - local remotePath = config.remote_path .. relative_path + print("remotePath:", remotePath) + print("current_buffer_path:", current_buffer_path) + local dir = dirname(remotePath) + local command = string.format( + "lftp -u '%s,%s' ftp://%s -e 'set ssl:verify-certificate no;mkdir -p %s; cd %s;put %s; quit' > /dev/null 2>&1", + config.user, config.password, config.host, dir, dir, current_buffer_path + ) + print("Generated command:", command) - local command = string.format( - 'curl -T "%s" ftp://%s/%s --user "%s:%s" > /dev/null 2>&1', - current_buffer_path, config.host, remotePath, config.user, config.password) + vim.uv.spawn("sh", { + args = { "-c", command }, + }, function(code, signal) + if code == 0 then + vim.schedule(function() + message.info("File uploaded successfully!") + end) + else + vim.schedule(function() + message.error("File upload failed with exit code: " .. code) + end) + end + end) +end - vim.loop.spawn("sh", { - args = { "-c", command }, - }, function(code, signal) - if code == 0 then - vim.schedule(function() - message.info("File uploaded successfully!") - end) - else - vim.schedule(function() - message.error("File upload failed with exit code: " .. code) - end) - end - end) +function M.UploadDir() + config = M.getConfig() + local current_buffer_path = vim.api.nvim_buf_get_name(0) + local directoryTemp = directory + message.warn("Send directory... Wait") + + if not directoryTemp:match("/$") then + directoryTemp = directoryTemp .. "/" + end + + local relative_path = current_buffer_path:sub(#directoryTemp + 1) + + if not config.remote_path:match("/$") then + config.remote_path = config.remote_path .. "/" + end + + local remotePath = config.remote_path .. relative_path + + local remote = path_components(remotePath) + local localDir = dirname(current_buffer_path) + local command = string.format( + "lftp -u '%s,%s' ftp://%s -e 'set ssl:verify-certificate no;mkdir -p %q;cd %q;mirror -R %q; quit'", + config.user, config.password, config.host, remote.parent, remote.parent, localDir + ) + print("Generated command:", command) + + vim.uv.spawn("sh", { + args = { "-c", command }, + }, function(code, signal) + if code == 0 then + vim.schedule(function() + message.info("Directory uploaded successfully!") + end) + else + vim.schedule(function() + message.error("Directory upload failed with exit code: " .. code) + end) + end + end) end return M diff --git a/lua/nvim-sync-ftp/message.lua b/lua/nvim-sync-ftp/message.lua index d00a515..8253558 100644 --- a/lua/nvim-sync-ftp/message.lua +++ b/lua/nvim-sync-ftp/message.lua @@ -4,26 +4,26 @@ local M = {} --- @type fun(fmt: string, ...: string) M.warn = vim.schedule_wrap(function(fmt, ...) - vim.notify(fmt:format(...), levels.WARN, { title = 'Sync FTP' }) + vim.notify(fmt:format(...), levels.WARN, { title = 'Sync FTP' }) end) --- @type fun(fmt: string, ...: string) M.info = vim.schedule_wrap(function(fmt, ...) - vim.notify(fmt:format(...), vim.log.INFO, { title = 'Sync FTP' }) + vim.notify(fmt:format(...), vim.log.INFO, { title = 'Sync FTP' }) end) --- @type fun(fmt: string, ...: string) M.error = vim.schedule_wrap(function(fmt, ...) - vim.notify(fmt:format(...), vim.log.levels.ERROR, { title = 'Sync FTP' }) + vim.notify(fmt:format(...), vim.log.levels.ERROR, { title = 'Sync FTP' }) end) --- @type fun(fmt: string, ...: string) M.error_once = vim.schedule_wrap(function(fmt, ...) - vim.notify_once(fmt:format(...), vim.log.levels.ERROR, { title = 'Sync FTP' }) + vim.notify_once(fmt:format(...), vim.log.levels.ERROR, { title = 'Sync FTP' }) end) M.success = vim.schedule_wrap(function(fmt, ...) - vim.notify(fmt:format(...), vim.log.INFO, { title = 'Sync FTP'}) + vim.notify(fmt:format(...), vim.log.INFO, { title = 'Sync FTP' }) end) return M