@@ -388,48 +388,66 @@ extractLine rope l = do
388
388
(prefix, _) = Rope. splitAtLine 1 suffix
389
389
pure $ prefix
390
390
391
+ -- | Translate a code-point offset into a code-unit offset.
392
+ -- Linear in the length of the rope.
393
+ codePointOffsetToCodeUnitOffset :: URope. Rope -> Word -> Maybe Word
394
+ codePointOffsetToCodeUnitOffset rope offset = do
395
+ -- Check for the position being out of bounds
396
+ guard $ offset <= URope. length rope
397
+ -- Split at the given position in *code points*
398
+ let (prefix, _) = URope. splitAt offset rope
399
+ -- Convert the prefix to a rope using *code units*
400
+ utf16Prefix = Rope. fromText $ URope. toText prefix
401
+ -- Get the length of the prefix in *code units*
402
+ pure $ Rope. length utf16Prefix
403
+
404
+ -- | Translate a code-unit offset into a code-point offset.
405
+ -- Linear in the length of the rope.
406
+ codeUnitOffsetToCodePointOffset :: Rope. Rope -> Word -> Maybe Word
407
+ codeUnitOffsetToCodePointOffset rope offset = do
408
+ -- Check for the position being out of bounds
409
+ guard $ offset <= Rope. length rope
410
+ -- Split at the given position in *code units*
411
+ (prefix, _) <- Rope. splitAt offset rope
412
+ -- Convert the prefixto a rope using *code points*
413
+ let utfPrefix = URope. fromText $ Rope. toText prefix
414
+ -- Get the length of the prefix in *code points*
415
+ pure $ URope. length utfPrefix
416
+
391
417
-- | Given a virtual file, translate a 'CodePointPosition' in that file into a 'J.Position' in that file.
392
418
--
393
419
-- Will return 'Nothing' if the requested position is out of bounds of the document.
394
420
--
395
421
-- We need the file itself because this requires translating between code points and code units.
422
+ --
423
+ -- Logarithmic in the number of lines in the document, and linear in the length of the line containing
424
+ -- the position.
396
425
codePointPositionToPosition :: VirtualFile -> CodePointPosition -> Maybe J. Position
397
426
codePointPositionToPosition vFile (CodePointPosition l cpc) = do
398
427
-- See Note [Converting between code points and code units]
399
428
let text = _file_text vFile
400
429
utf16Line <- extractLine text (fromIntegral l)
401
-
402
430
-- Convert the line a rope using *code points*
403
431
let utfLine = URope. fromText $ Rope. toText utf16Line
404
- -- Check for the position being out of bounds
405
- guard $ (fromIntegral cpc) <= URope. length utfLine
406
- -- Split at the given position in *code points*
407
- let (utfLinePrefix, _) = URope. splitAt (fromIntegral cpc) utfLine
408
- -- Convert the prefix to a rope using *code units*
409
- utf16LinePrefix = Rope. fromText $ URope. toText utfLinePrefix
410
- -- Get the length of the prefix in *code units*
411
- cuc = Rope. length utf16LinePrefix
432
+
433
+ cuc <- codePointOffsetToCodeUnitOffset utfLine (fromIntegral cpc)
412
434
pure $ J. Position l (fromIntegral cuc)
413
435
414
436
-- | Given a virtual file, translate a 'J.Position' in that file into a 'CodePointPosition' in that file.
415
437
--
416
438
-- Will return 'Nothing' if the requested position lies inside a code point, or if it is out of bounds of the document.
417
439
--
418
440
-- We need the file itself because this requires translating between code unit and code points.
441
+ --
442
+ -- Logarithmic in the number of lines in the document, and linear in the length of the line containing
443
+ -- the position.
419
444
positionToCodePointPosition :: VirtualFile -> J. Position -> Maybe CodePointPosition
420
445
positionToCodePointPosition vFile (J. Position l cuc) = do
421
446
-- See Note [Converting between code points and code units]
422
447
let text = _file_text vFile
423
448
utf16Line <- extractLine text (fromIntegral l)
424
449
425
- -- Check for the position being out of bounds
426
- guard $ (fromIntegral cuc) <= Rope. length utf16Line
427
- -- Split at the given position in *code units*
428
- (utf16LinePrefix, _) <- Rope. splitAt (fromIntegral cuc) utf16Line
429
- -- Convert the prefixto a rope using *code points*
430
- let utfLinePrefix = URope. fromText $ Rope. toText utf16LinePrefix
431
- -- Get the length of the prefix in *code points*
432
- cpc = URope. length utfLinePrefix
450
+ cpc <- codeUnitOffsetToCodePointOffset utf16Line (fromIntegral cuc)
433
451
pure $ CodePointPosition l (fromIntegral cpc)
434
452
435
453
-- ---------------------------------------------------------------------
0 commit comments