@@ -2,7 +2,7 @@ import std/[options, strformat, tables, algorithm]
22import nimsumtree/ [rope, sumtree, buffer, clock]
33import scripting_api except DocumentEditor , TextDocumentEditor , AstDocumentEditor
44from scripting_api as api import nil
5- import misc/ [custom_async, custom_unicode, util, regex, timer, rope_utils, arena, array_view]
5+ import misc/ [custom_async, custom_unicode, util, regex, timer, rope_utils, arena, array_view, array_table ]
66import text/ diff, text/ [custom_treesitter, treesitter_type_conv]
77from language/ lsp_types import nil
88import theme
8888 parenColors: seq [Color ]
8989 depthOffset: int
9090 currentNode: TSNode
91+ regexCache: ArrayTable [cstring , Regex ]
9192
9293func high * (_: typedesc [Point ]): Point = Point (row: uint32 .high, column: uint32 .high)
9394
@@ -448,7 +449,9 @@ func contentString(self: var StyledChunkIterator, selection: Range[Point], byteR
448449 if selection.a >= currentChunk.point and selection.b <= currentChunk.endPoint:
449450 let startIndex = selection.a.column - currentChunk.point.column
450451 let endIndex = selection.b.column - currentChunk.point.column
451- return $ currentChunk[startIndex.int ... endIndex.int ]
452+ result = newStringOfCap (endIndex.int - startIndex.int )
453+ for c in currentChunk.data.toOpenArray (startIndex.int , endIndex.int - 1 ):
454+ result .add c
452455 else :
453456 result = newStringOfCap (min (selection.b.column.int - selection.a.column.int , maxLen))
454457 for slice in self.chunks.rope.iterateChunks (byteRange):
@@ -475,17 +478,13 @@ proc addHighlight(highlights: var seq[Highlight], nextHighlight: sink Highlight)
475478 elif highlights.len == 0 or nextHighlight != highlights[^ 1 ]:
476479 highlights.add nextHighlight
477480
478- var regexes = initTable [string , Regex ]()
479-
480481proc depth (n: TSNode ): int =
481482 var n = n
482483 while not n.parent.isNull:
483484 inc result
484485 n = n.parent
485486
486487proc next * (self: var StyledChunkIterator ): Option [StyledChunk ] =
487- var regexes = ({.gcsafe .}: regexes.addr )
488-
489488 if self.atEnd:
490489 return
491490
@@ -537,73 +536,80 @@ proc next*(self: var StyledChunkIterator): Option[StyledChunk] =
537536 let predicates = self.highlighter.get.query.predicatesForPattern (match.pattern, self.arena)
538537 for capture in match.captures:
539538 let node = capture.node
540- # let byteRange = node.startByte...node.endByte
539+ let byteRange = node.startByte... node.endByte
541540 let nodeRange = node.startPoint.toCursor.toPoint... node.endPoint.toCursor.toPoint
542541 if nodeRange.b <= currentChunk.point or nodeRange.a >= currentChunk.endPoint:
543542 continue
544543
545544 var matches = true
546- if nodeRange.a.row != nodeRange.b.row:
547- matches = false
548-
549- for predicate in predicates:
550- if not matches:
551- break
552-
553- for operand in predicate.operands:
554- if operand.name != capture.name:
555- matches = false
545+ if nodeRange.a.row == nodeRange.b.row:
546+ for predicate in predicates:
547+ if not matches:
556548 break
557549
558- case predicate.operator
559- # of "match?":
560- # if not regexes[].contains(operand.`type`):
561- # try:
562- # regexes[][operand.`type`] = re(operand.`type`)
563- # except RegexError:
564- # matches = false
565- # break
566- # let regex {.cursor.} = regexes[][operand.`type`]
567-
568- # let nodeText = self.contentString(nodeRange, byteRange, maxPredicateCheckLen)
569- # if nodeText.matchLen(regex, 0) != nodeText.len:
570- # matches = false
571- # break
572-
573- # of "not-match?":
574- # if not regexes[].contains(operand.`type`):
575- # try:
576- # regexes[][operand.`type`] = re(operand.`type`)
577- # except RegexError:
578- # matches = false
579- # break
580- # let regex {.cursor.} = regexes[][operand.`type`]
581-
582- # let nodeText = self.contentString(nodeRange, byteRange, maxPredicateCheckLen)
583- # if nodeText.matchLen(regex, 0) == nodeText.len:
584- # matches = false
585- # break
586-
587- # of "eq?":
588- # # @todo: second arg can be capture aswell
589- # let nodeText = self.contentString(nodeRange, byteRange, maxPredicateCheckLen)
590- # if nodeText != operand.`type`:
591- # matches = false
592- # break
593-
594- # of "not-eq?":
595- # # @todo: second arg can be capture aswell
596- # let nodeText = self.contentString(nodeRange, byteRange, maxPredicateCheckLen)
597- # if nodeText == operand.`type`:
598- # matches = false
599- # break
600-
601- # of "any-of?":
602- # # todo
603- # log(lvlError, fmt"Unknown predicate '{predicate.name}'")
604-
605- else :
606- discard
550+ for operand in predicate.operands:
551+ if operand.name != capture.name:
552+ matches = false
553+ break
554+
555+ case predicate.operator
556+ of " match?" :
557+ let cachedRegex = self.regexCache.tryGet (operand.`type`)
558+ var regex: Regex
559+ if cachedRegex.isSome:
560+ regex = cachedRegex.get
561+ else :
562+ try :
563+ regex = re ($ operand.`type`)
564+ self.regexCache[operand.`type`] = regex
565+ except RegexError :
566+ matches = false
567+ break
568+
569+ let nodeText = self.contentString (nodeRange, byteRange, maxPredicateCheckLen)
570+ if nodeText.matchLen (regex, 0 ) != nodeText.len:
571+ matches = false
572+ break
573+
574+ of " not-match?" :
575+ let cachedRegex = self.regexCache.tryGet (operand.`type`)
576+ var regex: Regex
577+ if cachedRegex.isSome:
578+ regex = cachedRegex.get
579+ else :
580+ try :
581+ regex = re ($ operand.`type`)
582+ self.regexCache[operand.`type`] = regex
583+ except RegexError :
584+ matches = false
585+ break
586+
587+ let nodeText = self.contentString (nodeRange, byteRange, maxPredicateCheckLen)
588+ if nodeText.matchLen (regex, 0 ) == nodeText.len:
589+ matches = false
590+ break
591+
592+ of " eq?" :
593+ # @todo: second arg can be capture aswell
594+ let nodeText = self.contentString (nodeRange, byteRange, maxPredicateCheckLen)
595+ if nodeText != operand.`type`:
596+ matches = false
597+ break
598+
599+ of " not-eq?" :
600+ # @todo: second arg can be capture aswell
601+ let nodeText = self.contentString (nodeRange, byteRange, maxPredicateCheckLen)
602+ if nodeText == operand.`type`:
603+ matches = false
604+ break
605+
606+ # of "any-of?":
607+ # # todo
608+ # # echo &"Unknown predicate '{predicate.name}'"
609+ # discard
610+
611+ else :
612+ discard
607613
608614 if not matches:
609615 continue
0 commit comments