@@ -6,6 +6,9 @@ import strings
6
6
import os
7
7
import math
8
8
import term.ui as tui
9
+ import encoding.utf8
10
+
11
+ const rune_digits = [`0` , `1` , `2` , `3` , `4` , `5` , `6` , `7` , `8` , `9` ]
9
12
10
13
enum Movement {
11
14
up
@@ -131,7 +134,7 @@ fn (b Buffer) raw() string {
131
134
}
132
135
133
136
fn (b Buffer) view (from int , to int ) View {
134
- l := b.cur_line ()
137
+ l := b.cur_line (). runes ()
135
138
mut x := 0
136
139
for i := 0 ; i < b.cursor.pos_x && i < l.len; i++ {
137
140
if l[i] == `\t ` {
@@ -174,7 +177,7 @@ fn (b Buffer) cursor_index() int {
174
177
i + = b.cursor.pos_x
175
178
break
176
179
}
177
- i + = line.len + 1
180
+ i + = line.runes (). len + 1
178
181
}
179
182
return i
180
183
}
@@ -185,22 +188,22 @@ fn (mut b Buffer) put(s string) {
185
188
if b.lines.len == 0 {
186
189
b.lines.prepend ('' )
187
190
}
188
- line := b.lines[y]
189
- l , r := line[..x], line[x..]
191
+ line := b.lines[y]. runes ()
192
+ l , r := line[..x]. string () , line[x..]. string ()
190
193
if has_line_ending {
191
194
mut lines := s.split ('\n ' )
192
195
lines[0 ] = l + lines[0 ]
193
196
lines[lines.len - 1 ] + = r
194
197
b.lines.delete (y)
195
198
b.lines.insert (y, lines)
196
- last := lines[lines.len - 1 ]
199
+ last := lines[lines.len - 1 ]. runes ()
197
200
b.cursor.set (last.len, y + lines.len - 1 )
198
201
if s == '\n ' {
199
202
b.cursor.set (0 , b.cursor.pos_y)
200
203
}
201
204
} else {
202
205
b.lines[y] = l + s + r
203
- b.cursor.set (x + s.len, y)
206
+ b.cursor.set (x + s.runes (). len, y)
204
207
}
205
208
$if debug {
206
209
flat := s.replace ('\n ' , r '\n' )
@@ -217,24 +220,35 @@ fn (mut b Buffer) del(amount int) string {
217
220
if x == 0 && y == 0 {
218
221
return ''
219
222
}
220
- } else if x > = b.cur_line ().len && y > = b.lines.len - 1 {
223
+ } else if x > = b.cur_line ().runes (). len && y > = b.lines.len - 1 {
221
224
return ''
222
225
}
223
226
mut removed := ''
224
227
if amount < 0 { // backspace (backward)
225
228
i := b.cursor_index ()
226
- removed = b.raw ()[i + amount..i]
229
+ raw_runes := b.raw ().runes ()
230
+ removed = raw_runes[i + amount..i].string ()
227
231
mut left := amount * - 1
228
232
for li := y; li > = 0 && left > 0 ; li-- {
229
- ln := b.lines[li]
230
- if left > ln.len {
233
+ ln := b.lines[li].runes ()
234
+ if left == ln.len + 1 { // All of the line + 1 - since we're going backwards the "+1" is the line break delimiter.
235
+ b.lines.delete (li)
236
+ left = 0
237
+ if y == 0 {
238
+ return ''
239
+ }
240
+ line_above := b.lines[li - 1 ].runes ()
241
+ b.cursor.pos_x = line_above.len
242
+ b.cursor.pos_y--
243
+ break
244
+ } else if left > ln.len {
231
245
b.lines.delete (li)
232
246
if ln.len == 0 { // line break delimiter
233
247
left--
234
248
if y == 0 {
235
249
return ''
236
250
}
237
- line_above := b.lines[li - 1 ]
251
+ line_above := b.lines[li - 1 ]. runes ()
238
252
b.cursor.pos_x = line_above.len
239
253
} else {
240
254
left - = ln.len
@@ -245,22 +259,23 @@ fn (mut b Buffer) del(amount int) string {
245
259
if y == 0 {
246
260
return ''
247
261
}
248
- line_above := b.lines[li - 1 ]
262
+ line_above := b.lines[li - 1 ]. runes ()
249
263
if ln.len == 0 { // at line break
250
264
b.lines.delete (li)
251
265
b.cursor.pos_y--
252
266
b.cursor.pos_x = line_above.len
253
267
} else {
254
- b.lines[li - 1 ] = line_above + ln
268
+ b.lines[li - 1 ] = line_above. string () + ln. string ()
255
269
b.lines.delete (li)
256
270
b.cursor.pos_y--
257
271
b.cursor.pos_x = line_above.len
258
272
}
259
273
} else if x == 1 {
260
- b.lines[li] = b.lines[li][left..]
274
+ runes := b.lines[li].runes ()
275
+ b.lines[li] = runes[left..].string ()
261
276
b.cursor.pos_x = 0
262
277
} else {
263
- b.lines[li] = ln[..x - left] + ln[x..]
278
+ b.lines[li] = ln[..x - left]. string () + ln[x..]. string ()
264
279
b.cursor.pos_x - = left
265
280
}
266
281
left = 0
@@ -269,13 +284,20 @@ fn (mut b Buffer) del(amount int) string {
269
284
}
270
285
} else { // delete (forward)
271
286
i := b.cursor_index () + 1
272
- removed = b.raw ()[i - amount..i]
287
+ raw_buffer := b.raw ().runes ()
288
+ from_i := i
289
+ mut to_i := i + amount
290
+
291
+ if to_i > raw_buffer.len {
292
+ to_i = raw_buffer.len
293
+ }
294
+ removed = raw_buffer[from_i..to_i].string ()
273
295
mut left := amount
274
296
for li := y; li > = 0 && left > 0 ; li++ {
275
- ln := b.lines[li]
297
+ ln := b.lines[li]. runes ()
276
298
if x == ln.len { // at line end
277
299
if y + 1 < = b.lines.len {
278
- b.lines[li] = ln + b.lines[y + 1 ]
300
+ b.lines[li] = ln. string () + b.lines[y + 1 ]
279
301
b.lines.delete (y + 1 )
280
302
left--
281
303
b.del (left)
@@ -284,7 +306,7 @@ fn (mut b Buffer) del(amount int) string {
284
306
b.lines.delete (li)
285
307
left - = ln.len
286
308
} else {
287
- b.lines[li] = ln[..x] + ln[x + left..]
309
+ b.lines[li] = ln[..x]. string () + ln[x + left..]. string ()
288
310
left = 0
289
311
}
290
312
}
@@ -309,15 +331,15 @@ fn (mut b Buffer) free() {
309
331
fn (mut b Buffer) move_updown (amount int ) {
310
332
b.cursor.move (0 , amount)
311
333
// Check the move
312
- line := b.cur_line ()
334
+ line := b.cur_line (). runes ()
313
335
if b.cursor.pos_x > line.len {
314
336
b.cursor.set (line.len, b.cursor.pos_y)
315
337
}
316
338
}
317
339
318
340
// move_cursor will navigate the cursor within the buffer bounds
319
341
fn (mut b Buffer) move_cursor (amount int , movement Movement) {
320
- cur_line := b.cur_line ()
342
+ cur_line := b.cur_line (). runes ()
321
343
match movement {
322
344
.up {
323
345
if b.cursor.pos_y - amount > = 0 {
@@ -341,7 +363,7 @@ fn (mut b Buffer) move_cursor(amount int, movement Movement) {
341
363
if b.cursor.pos_x - amount > = 0 {
342
364
b.cursor.move (- amount, 0 )
343
365
} else if b.cursor.pos_y > 0 {
344
- b.cursor.set (b.line (b.cursor.pos_y - 1 ).len, b.cursor.pos_y - 1 )
366
+ b.cursor.set (b.line (b.cursor.pos_y - 1 ).runes (). len, b.cursor.pos_y - 1 )
345
367
}
346
368
}
347
369
.right {
@@ -362,25 +384,26 @@ fn (mut b Buffer) move_cursor(amount int, movement Movement) {
362
384
363
385
fn (mut b Buffer) move_to_word (movement Movement) {
364
386
a := if movement == .left { - 1 } else { 1 }
365
- mut line := b.cur_line ()
387
+
388
+ mut line := b.cur_line ().runes ()
366
389
mut x, mut y := b.cursor.pos_x, b.cursor.pos_y
367
390
if x + a < 0 && y > 0 {
368
391
y--
369
- line = b.line (b.cursor.pos_y - 1 )
392
+ line = b.line (b.cursor.pos_y - 1 ). runes ()
370
393
x = line.len
371
394
} else if x + a > = line.len && y + 1 < b.lines.len {
372
395
y++
373
- line = b.line (b.cursor.pos_y + 1 )
396
+ line = b.line (b.cursor.pos_y + 1 ). runes ()
374
397
x = 0
375
398
}
376
399
// first, move past all non-`a-zA-Z0-9_` characters
377
- for x + a > = 0 && x + a < line.len && ! (line[x + a]. is_letter ( )
378
- || line[x + a]. is_digit () || line[x + a] == `_` ) {
400
+ for x + a > = 0 && x + a < line.len && ! (utf 8 . is_letter ( line[x + a])
401
+ || line[x + a] in rune_digits || line[x + a] == `_` ) {
379
402
x + = a
380
403
}
381
404
// then, move past all the letters and numbers
382
- for x + a > = 0 && x + a < line.len && (line[x + a]. is_letter ( )
383
- || line[x + a]. is_digit () || line[x + a] == `_` ) {
405
+ for x + a > = 0 && x + a < line.len && (utf 8 . is_letter ( line[x + a])
406
+ || line[x + a] in rune_digits || line[x + a] == `_` ) {
384
407
x + = a
385
408
}
386
409
// if the cursor is out of bounds, move it to the next/previous line
@@ -457,7 +480,7 @@ fn (a &App) view_height() int {
457
480
fn (mut a App) magnet_cursor_x () {
458
481
mut buffer := a.ed
459
482
if buffer.cursor.pos_x < a.magnet_x {
460
- if a.magnet_x < buffer.cur_line ().len {
483
+ if a.magnet_x < buffer.cur_line ().runes (). len {
461
484
move_x := a.magnet_x - buffer.cursor.pos_x
462
485
buffer.move_cursor (move_x, .right)
463
486
}
@@ -555,7 +578,8 @@ fn event(e &tui.Event, x voidptr) {
555
578
return
556
579
}
557
580
}
558
- buffer.put (e.utf8 .bytes ().bytestr ())
581
+
582
+ buffer.put (e.utf8 )
559
583
}
560
584
}
561
585
} else if e.typ == .mouse_scroll {
0 commit comments