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
|
local common = require "core.common"
local config = require "core.config"
-- functions for translating a Doc position to another position
-- these functions can be passed to Doc:move_to|select_to|delete()
local translate = {}
local function is_non_word(char)
return config.non_word_chars:find(char, nil, true)
end
function translate.previous_char(doc, line, col)
repeat
line, col = doc:position_offset(line, col, -1)
until not common.is_utf8_cont(doc:get_char(line, col))
return line, col
end
function translate.next_char(doc, line, col)
repeat
line, col = doc:position_offset(line, col, 1)
until not common.is_utf8_cont(doc:get_char(line, col))
return line, col
end
function translate.previous_word_boundary(doc, line, col)
local char = doc:get_char(doc:position_offset(line, col, -1))
local inword = not is_non_word(char)
repeat
local line2, col2 = line, col
line, col = doc:position_offset(line, col, -1)
if line == line2 and col == col2 then
break
end
local c = doc:get_char(doc:position_offset(line, col, -1))
until inword and is_non_word(c) or not inword and c ~= char
return line, col
end
function translate.next_word_boundary(doc, line, col)
local char = doc:get_char(line, col)
local inword = not is_non_word(char)
repeat
local line2, col2 = line, col
line, col = doc:position_offset(line, col, 1)
if line == line2 and col == col2 then
break
end
local c = doc:get_char(line, col)
until inword and is_non_word(c) or not inword and c ~= char
return line, col
end
function translate.start_of_word(doc, line, col)
while true do
local line2, col2 = doc:position_offset(line, col, -1)
local char = doc:get_char(line2, col2)
if is_non_word(char)
or line == line2 and col == col2 then
break
end
line, col = line2, col2
end
return line, col
end
function translate.end_of_word(doc, line, col)
while true do
local line2, col2 = doc:position_offset(line, col, 1)
local char = doc:get_char(line, col)
if is_non_word(char)
or line == line2 and col == col2 then
break
end
line, col = line2, col2
end
return line, col
end
function translate.previous_start_of_block(doc, line, col)
while true do
line = line - 1
if line <= 1 then
return 1, 1
end
if doc.lines[line-1]:match("^%s*$")
and not doc.lines[line]:match("^%s*$") then
return line, (doc.lines[line]:find("%S"))
end
end
end
function translate.next_start_of_block(doc, line, col)
while true do
line = line + 1
if line >= #doc.lines then
return #doc.lines, 1
end
if doc.lines[line-1]:match("^%s*$")
and not doc.lines[line]:match("^%s*$") then
return line, (doc.lines[line]:find("%S"))
end
end
end
function translate.start_of_line(doc, line, col)
return line, 1
end
function translate.end_of_line(doc, line, col)
return line, math.huge
end
function translate.start_of_doc(doc, line, col)
return 1, 1
end
function translate.end_of_doc(doc, line, col)
return #doc.lines, #doc.lines[#doc.lines]
end
return translate
|