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
|
local m = require 'lpeglabel'
local row
local fl
local NL = (m.P'\r\n' + m.S'\r\n') * m.Cp() / function (pos)
row = row + 1
fl = pos
end
local ROWCOL = (NL + m.P(1))^0
local function rowcol(str, n)
row = 1
fl = 1
ROWCOL:match(str:sub(1, n))
local col = n - fl + 1
return row, col
end
local function rowcol_utf8(str, n)
row = 1
fl = 1
ROWCOL:match(str:sub(1, n))
return row, utf8.len(str, fl, n)
end
local function position(str, _row, _col)
local cur = 1
local row = 1
while true do
if row == _row then
return cur + _col - 1
elseif row > _row then
return cur - 1
end
local pos = str:find('[\r\n]', cur)
if not pos then
return #str
end
row = row + 1
if str:sub(pos, pos+1) == '\r\n' then
cur = pos + 2
else
cur = pos + 1
end
end
end
local function position_utf8(str, _row, _col)
local cur = 1
local row = 1
while true do
if row == _row then
return utf8.offset(str, _col, cur)
elseif row > _row then
return cur - 1
end
local pos = str:find('[\r\n]', cur)
if not pos then
return #str
end
row = row + 1
if str:sub(pos, pos+1) == '\r\n' then
cur = pos + 2
else
cur = pos + 1
end
end
end
local NL = m.P'\r\n' + m.S'\r\n'
local function line(str, row)
local count = 0
local res
local LINE = m.Cmt((1 - NL)^0, function (_, _, c)
count = count + 1
if count == row then
res = c
return false
end
return true
end)
local MATCH = (LINE * NL)^0 * LINE
MATCH:match(str)
return res
end
return {
rowcol = rowcol,
rowcol_utf8 = rowcol_utf8,
position = position,
position_utf8 = position_utf8,
line = line,
}
|