summaryrefslogtreecommitdiff
path: root/script-beta/parser/calcline.lua
blob: 26f475d93a458519e67131bb23e98afc14eefe38 (plain)
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,
}