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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
require("vis")
local M = {}
M.par_prg = "par"
M.par_tw = 72
M.ex_args = function () return "RET4bhgqw" .. M.par_tw end
M.debug = false
-- ex_args = "RET4bhgqB=.,?_A_aQ=_s>|w" .. par_tw
-- export PARINIT='Tbp2hgqR B=.,?_A_a Q=_s>|'
function print(...)
if M.debug then
_print_ = _print_ or io.open("/tmp/visprint", "w")
_print_:write(..., "\n")
end
end
--- Dump value of a variable in a formatted string
--
--- @param o table Dumpable object
--- @param tbs string|nil Tabulation string, ' ' by default
--- @param tb number|nil Initial tabulation level, 0 by default
--- @return string
local function dump(o, tbs, tb)
tb = tb or 0
tbs = tbs or " "
if type(o) == "table" then
local s = "{"
if (next(o)) then
s = s .. "\n"
else
return s .. "}"
end
tb = tb + 1
for k, v in pairs(o) do
if type(k) ~= "number" then
k = '"' .. k .. '"'
end
s = s .. tbs:rep(tb) .. "[" .. k .. "] = " .. dump(v, tbs, tb)
s = s .. ",\n"
end
tb = tb - 1
return s .. tbs:rep(tb) .. "}"
else
return tostring(o)
end
end
local supress_stdout = " >/dev/null"
local supress_stderr = " 2>/dev/null"
local supress_output = supress_stdout .. supress_stderr
-- Return nil or a string of formatted text from a specific file range or text
-- by calling the formatter command.
-- If given a range we will use vis:pipe to get the output from the formatter.
-- If a string was passed we call the formatter ourself and redirect its stdout
-- to a temporary file. See http://lua-users.org/lists/lua-l/2007-10/msg00189.html.
local function run_shell_cmd(cmd, params, inp)
local out
print("cmd = " .. cmd .. ", params = " .. params .. ", inp = " .. inp .. ", (" .. type(inp) .. ")")
if type(inp) == "string" then
local full_cmd = cmd .. " '" .. params .. "'"
local tmp_name = os.tmpname()
print("tmp_name = " .. tmp_name)
full_cmd = full_cmd .. " > " .. tmp_name
print("full_cmd = " .. full_cmd)
local proc = assert(io.popen(full_cmd, "w"))
print("proc = " .. type(proc))
proc:write(inp)
-- this error detection may need lua5.2
proc:flush()
local exit_code = proc:close()
print("exit_code = " .. tostring(exit_code))
local tmp_file = assert(io.open(tmp_name, "r"))
out = tmp_file:read("*a")
tmp_file:close()
-- print("out = " .. out)
os.remove(tmp_name)
if not exit_code then
print("calling " .. full_cmd .. " failed (" .. out .. ")")
return nil
end
else
local range = inp
local ret, so, _ = vis:pipe(vis.win.file, range, cmd)
if ret ~= 0 then
print("calling " .. cmd .. " failed (" .. ret .. ")")
return nil
end
out = so
end
return out
end
function lines(str)
local t = {}
local function helper(line)
table.insert(t, line)
return ""
end
helper((str:gsub("(.-)\r?\n", helper)))
return t
end
getmetatable(_VERSION).__index.lines = lines
function hanging_symbol(line, nspc)
local beg, fin = 0, 0
-- itemized list
beg, fin = line:find("^[-+*] ", nspc)
if beg then
print("item beg = " .. beg .. ", fin = " .. fin)
return fin
end
local beg, fin = line:find("^%d+%. ", nspc)
if beg then
print("enum beg = " .. beg .. ", fin = " .. fin)
return fin
end
return nspc -- no hanging idennt
end
function new_segment(segment, p_arg)
if next(segment) then
print("M.par_prg = " .. M.par_prg .. ", M.ex_args = " .. M.ex_args() .. ", p_arg = " .. p_arg)
local new_text = run_shell_cmd(M.par_prg, M.ex_args() .. "p" .. p_arg,
table.concat(segment, "\n"))
print("new_text = " .. new_text)
return new_text, {}, 0 -- add-to-out, segment, p_arg
else
return "", {}, 0 -- add-to-out, segment, p_arg
end
end
vis:operator_new(
"gq",
function(file, range, pos)
local out = ""
local hang_sym = ""
local segment = {}
local p_arg = 0
local range_lines = file:content(range):lines()
for _, line in ipairs(range_lines) do
local beg, beg_spc_len = line:find("^%s*")
assert(beg == 1, "There is no way this would not be 1.")
local non_spc_idx = line:len() >= beg_spc_len + 1 and beg_spc_len + 1 or 0
print("non_spc_idx = " .. non_spc_idx)
hang_sym = hanging_symbol(line, non_spc_idx)
print("hang_sym = " .. hang_sym .. ", non_spc_idx = " .. non_spc_idx)
if non_spc_idx ~= 0 then -- non-empty line
-- item: start new segment
if hang_sym ~= non_spc_idx then
seg_pared, segment, p_arg = new_segment(segment, p_arg)
if seg_pared then
out = out .. seg_pared
p_arg = hang_sym
end
table.insert(segment, line)
else
-- continuous line in a segment, just collect it
table.insert(segment, line)
end
else -- this is an empty line
seg_pared, segment, p_arg = new_segment(segment, p_arg)
if seg_pared then
out = out .. seg_pared
end
end
end
if out:len() == 0 then
print("Cannot process paragraph.")
else
file:delete(range)
file:insert(range.start, out)
end
return range.start -- new cursor location
end,
"Formating operator, filter range through formatting filter"
)
vis:option_register(
"autoformat",
"bool",
function(value, toogle)
if not vis.win then
return false
end
vis.win.autoformat = toogle and not vis.win.autoformat or value
print("Option autoformat = " .. tostring(vis.win.autoformat))
return true
end,
"Automatically format current paragraph."
)
return M
|