@@ -14,44 +14,51 @@ function Tangle:new(opts)
1414 }, self )
1515end
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
5334end
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+
5562function 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