-- Copyright (c) 2024 Florian Fischer. All rights reserved. -- -- vis-lockfiles is free software: you can redistribute it and/or modify it under -- the terms of the GNU General Public License as published by the Free Software -- Foundation, either version 3 of the License, or (at your option) any later -- version. -- -- vis-lockfiles is distributed in the hope that it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- vis-lockfiles found in the LICENSE file. -- If not, see . local source_str = debug.getinfo(1, 'S').source:sub(2) local script_path = source_str:match('(.*/)') local lockfiles = dofile(script_path .. 'lockfiles.lua') local M = {} M.directory = '${XDG_STATE_HOME:-${HOME}/.local/state}/vis/locks' M.directory_expanded = nil local function get_lock_dir() if M.directory_expanded ~= M.directory then M.directory = lockfiles.capture_cmd('printf %s "' .. M.directory .. '"') M.directory_expanded = M.directory end return M.directory end -- get a user confirmation -- return true if user selected yes, false otherwise local function confirm(path, pid) local choices = 'no\nyes' local prompt = path .. ' for PID '..pid .. ' exists. Edit anyway:' local cmd = 'printf %s \'' .. choices .. '\' | vis-menu -b -p \'' .. prompt .. '\'' -- local status, output = vis:pipe(nil, {start = 0, finish = 0}, cmd) local menu = assert(io.popen(cmd)) local output = menu:read('*a') local _, _, status = menu:close() vis:redraw() if status == 0 then return 'yes' == output:sub(1, 3) end return false end local created_locks = {} vis.events.subscribe(vis.events.FILE_OPEN, function(file) if created_locks[file.path] or not file.path then -- either a noname buffer, or already locked by us return end local lfile_path = lockfiles.lock_file_path(get_lock_dir(), file.path) local lock_pid = lockfiles.create_lock_file(get_lock_dir(), lfile_path) if lockfiles.vis_pid == lock_pid then created_locks[file.path] = lfile_path elseif not confirm(lfile_path, lock_pid) then vis:exit(1) end end) vis.events.subscribe(vis.events.FILE_CLOSE, function(file) if not file.path then return end local lfile_path = created_locks[file.path] if lfile_path then lockfiles.delete_lock_file(lfile_path) created_locks[file.path] = nil end end) vis.events.subscribe(vis.events.QUIT, function() for _, lfile_path in pairs(created_locks) do if lfile_path then lockfiles.delete_lock_file(lfile_path) end end created_locks = {} end) return M