1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
-- 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 <https://www.gnu.org/licenses/>.
local source_str = debug.getinfo(1, 'S').source:sub(2)
local script_path = source_str:match('(.*/)')
local lockfiles = dofile(script_path .. 'lockfiles.lua')
-- function used for all actions resulting from a FILE_OPEN event that can not
-- be done during the handler
local pending_action = nil
--[[
local function count_windows()
-- Count the currently open vis windows
local n = 0
for _ in vis:windows() do
n = n + 1
end
return n
end
]] --
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 prompt(path, lfile_path, pid)
local choices = 'a\ne\nq'
local msg = 'Lock file found!\n\t lock file: "' .. lfile_path .. '"\n\tfile name: ' .. path ..
'\n\tprocess ID: ' .. pid
local menu_prompt = '(E)dit anyway, (Q)uit, [A]bort'
local cmd1 = 'printf >/dev/tty %s \'' .. msg .. '\n\''
local cmd2 = 'printf %s \'' .. choices .. '\''
local cmd3 = 'vis-menu -b -p \'' .. menu_prompt .. '\''
local cmd = cmd1 .. ';' .. cmd2 .. '|' .. cmd3
local status, output = vis:pipe(cmd, true)
vis:redraw()
if status == 0 then
if output:sub(1, 1) == 'e' then
return true
elseif output:sub(1, 1) == 'q' then
vis:exit(1)
end
end
-- else 'abort' or dialog canceled
local hnd1
hnd1 = function()
if vis.win.file and vis.win.file.path == path then
vis.events.unsubscribe(vis.events.UI_DRAW, hnd1)
vis:command('q')
vis:command('new')
end
end
vis.events.subscribe(vis.events.UI_DRAW, hnd1)
vis:redraw()
end
local created_locks = {}
vis.events.subscribe(vis.events.WIN_OPEN, function(win)
local file = win.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
else
prompt(file.path, lfile_path, lock_pid)
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)
vis.events.subscribe(vis.events.UI_DRAW, function()
if not pending_action or not vis.win then
return
end
if pending_action() then
pending_action = nil
end
end)
return M
|