aboutsummaryrefslogtreecommitdiff
path: root/data/core/doc/translate.lua
blob: a52c2cacdd6a0832706d4e244b119c9a6f9e34a3 (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
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