Skip to content

Commit 3d38576

Browse files
committed
fix(bable) tangle-mode support ls-style, chmod-style and octal style file mode
1 parent a146841 commit 3d38576

File tree

1 file changed

+58
-40
lines changed

1 file changed

+58
-40
lines changed

Diff for: lua/orgmode/babel/tangle.lua

+58-40
Original file line numberDiff line numberDiff line change
@@ -14,44 +14,51 @@ function Tangle:new(opts)
1414
}, self)
1515
end
1616

17-
function mode_to_string(mode)
18-
local permissions = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}
19-
local result = ""
20-
21-
-- File type
22-
local file_type = bit.band(bit.rshift(mode, 12), 15)
23-
local type_char = {
24-
[0] = "-", -- regular file
25-
[1] = "p", -- named pipe (fifo)
26-
[2] = "c", -- character special
27-
[4] = "d", -- directory
28-
[6] = "b", -- block special
29-
[8] = "f", -- regular file (rarely used)
30-
[10] = "l", -- symbolic link
31-
[12] = "s" -- socket
32-
}
33-
result = result .. (type_char[file_type] or "-")
34-
35-
-- Owner, group, others permissions
36-
for i = 2, 0, -1 do
37-
local perm = bit.band(bit.rshift(mode, i * 3), 7)
38-
result = result .. permissions[perm + 1]
39-
end
40-
41-
-- Special bits
42-
if bit.band(mode, 0x800) ~= 0 then -- sticky bit
43-
result = result:sub(1, 9) .. (result:sub(10, 10) == "-" and "T" or "t")
44-
end
45-
if bit.band(mode, 0x400) ~= 0 then -- setgid
46-
result = result:sub(1, 6) .. (result:sub(7, 7) == "-" and "S" or "s")
47-
end
48-
if bit.band(mode, 0x200) ~= 0 then -- setuid
49-
result = result:sub(1, 3) .. (result:sub(4, 4) == "-" and "S" or "s")
17+
function ls_style_to_octal(rwx_string)
18+
local result = 0
19+
local value = 0
20+
21+
for i = 1, #rwx_string, 3 do
22+
local chunk = rwx_string:sub(i, i+2)
23+
value = 0
24+
25+
if chunk:sub(1, 1) == 'r' then value = value + 4 end
26+
if chunk:sub(2, 2) == 'w' then value = value + 2 end
27+
if chunk:sub(3, 3) == 'x' then value = value + 1 end
28+
29+
result = result * 8 + value
30+
utils.echo_info(("ls style mode: %o"):format(result))
5031
end
51-
32+
5233
return result
5334
end
5435

36+
37+
function chmod_style_to_octal(chmod_string)
38+
local owner, group, other = 0, 0, 0
39+
40+
for part in chmod_string:gmatch('[^,]+') do
41+
utils.echo_info(('part: %s'):format(part))
42+
local who, what = part:match('(%a+)[=+](.+)')
43+
utils.echo_info(('who: %s what: %s'):format(who, what))
44+
if not who or not what then
45+
return nil
46+
end
47+
48+
49+
local perm = 0
50+
if what:find('r') then perm = perm + 4 end
51+
if what:find('w') then perm = perm + 2 end
52+
if what:find('x') then perm = perm + 1 end
53+
54+
if who:find('u') or who:find('a') then owner = bit.bor(owner, perm) end
55+
if who:find('g') or who:find('a') then group = bit.bor(group, perm) end
56+
if who:find('o') or who:find('a') then other = bit.bor(other, perm) end
57+
end
58+
59+
return owner * 64 + group * 8 + other
60+
end
61+
5562
function Tangle:tangle()
5663
local block_content_by_name = {}
5764
---@type OrgBlockTangleInfo[]
@@ -127,17 +134,28 @@ function Tangle:tangle()
127134

128135
local promises = {}
129136
for filename, block in pairs(tangle_info) do
130-
local mode_str = block['mode']
131-
if mode_str and mode_str:sub(1, 1) == 'o' then
132-
mode_str[1] = 0
133-
mode_str = mode_to_string(mode_str)
134-
end
135137

136138
table.insert(
137139
promises,
138-
utils.writefile(filename, table.concat(self:_remove_obsolete_indent(block['content']), '\n'), mode_str)
140+
utils.writefile(filename, table.concat(self:_remove_obsolete_indent(block['content']), '\n'))
139141
)
140142

143+
local mode_str = block['mode']
144+
local mode = nil
145+
146+
if mode_str and mode_str:sub(1, 1) == 'o' then
147+
mode = tonumber(mode_str:sub(2), 8)
148+
else
149+
mode = chmod_style_to_octal(mode_str)
150+
if mode == nil then
151+
mode = ls_style_to_octal(mode_str)
152+
end
153+
end
154+
155+
if mode then
156+
utils.echo_info(('change mode %s mode %o'):format(filename, mode))
157+
vim.loop.fs_chmod(filename, mode)
158+
end
141159
end
142160
Promise.all(promises):wait()
143161
utils.echo_info(('Tangled %d blocks from %s'):format(#valid_blocks, vim.fn.fnamemodify(self.file.filename, ':t')))

0 commit comments

Comments
 (0)