@@ -10,6 +10,7 @@ added get-regions
10
10
(require racket/class
11
11
racket/unit
12
12
racket/gui/base
13
+ racket/match
13
14
syntax-color/token-tree
14
15
syntax-color/paren-tree
15
16
syntax-color/default-lexer
@@ -60,6 +61,17 @@ added get-regions
60
61
attribs
61
62
(or (hash-ref attribs 'color #f )
62
63
(hash-ref attribs 'type 'unknown ))))
64
+ (define (attribs->invisible attribs)
65
+ (cond
66
+ [(symbol? attribs)
67
+ (values 0 #f )]
68
+ [else
69
+ (define open-count (hash-ref attribs 'invisible-open-count #f ))
70
+ (define close-count (hash-ref attribs 'invisible-close-count #f ))
71
+ (cond
72
+ [open-count (values open-count invisible-open)]
73
+ [close-count (values close-count invisible-close)]
74
+ [else (values 0 #f )])]))
63
75
(define (attribs->table attribs)
64
76
(if (symbol? attribs)
65
77
(hasheq 'type attribs)
@@ -420,7 +432,10 @@ added get-regions
420
432
len
421
433
(make-data attribs new-lexer-mode backup-delta))
422
434
#; (show-tree (lexer-state-tokens ls))
423
- (send (lexer-state-parens ls) add-token paren len)
435
+ (define-values (invisible-count invisible-paren)
436
+ (attribs->invisible attribs))
437
+ (send (lexer-state-parens ls) add-token (or paren invisible-paren) len
438
+ #:invisible invisible-count)
424
439
(cond
425
440
[(and (not (send (lexer-state-invalid-tokens ls) is-empty?))
426
441
(= (lexer-state-invalid-tokens-start ls)
@@ -852,52 +867,115 @@ added get-regions
852
867
;; This leads to the nice behavior that we don't have to block to
853
868
;; highlight parens, and the parens will be highlighted as soon as
854
869
;; possible.
855
- (define/private match-parens
856
- (lambda ([just-clear? #f ])
857
- ;;(printf "(match-parens ~a)\n" just-clear?)
858
- (when (and (not in-match-parens?)
859
- ;; Trying to match open parens while the
860
- ;; background thread is going slows it down.
861
- ;; The random number slows down how often it
862
- ;; tries.
863
- (or just-clear?
864
- (andmap lexer-state-up-to-date? lexer-states)
865
- (= 0 (random 5 ))))
866
- (set! in-match-parens? #t )
867
- (begin-edit-sequence #f #f )
868
- (clear-old-locations)
869
- (set! clear-old-locations void)
870
- (when (and (preferences:get 'framework:highlight-parens )
871
- (not just-clear?)
872
- (not stopped?))
873
- (let* ((here (get-start-position)))
874
- (when (= here (get-end-position))
875
- (let ([ls (find-ls here)])
876
- (when ls
877
- (let-values (((start-f end-f error-f)
878
- (send (lexer-state-parens ls) match-forward
879
- (- here (lexer-state-start-pos ls)))))
880
- (when (and (not (f-match-false-error ls start-f end-f error-f))
881
- start-f end-f)
882
- (if error-f
883
- (highlight ls start-f end-f here (and error-f #t ))
884
- (highlight-nested-region ls start-f end-f here))))
885
- (let-values (((start-b end-b error-b)
886
- (send (lexer-state-parens ls) match-backward
887
- (- here (lexer-state-start-pos ls)))))
888
- (when (and start-b end-b)
889
- (if error-b
890
- (highlight ls start-b end-b here (and error-b #t ))
891
- (highlight-nested-region ls start-b end-b here)))))))))
892
- (end-edit-sequence)
893
- (set! in-match-parens? #f ))))
870
+ (define/private (match-parens [just-clear? #f ])
871
+ ;; (printf "(match-parens ~a)\n" just-clear?)
872
+ (when (and (not in-match-parens?)
873
+ ;; Trying to match open parens while the
874
+ ;; background thread is going slows it down.
875
+ ;; The random number slows down how often it
876
+ ;; tries.
877
+ (or just-clear?
878
+ (andmap lexer-state-up-to-date? lexer-states)
879
+ (= 0 (random 5 ))))
880
+ (set! in-match-parens? #t )
881
+ (begin-edit-sequence #f #f )
882
+ (clear-old-locations)
883
+ (set! clear-old-locations void)
884
+ (when (and (preferences:get 'framework:highlight-parens )
885
+ (not just-clear?)
886
+ (not stopped?))
887
+ (define caret-pos (get-start-position))
888
+ (when (= caret-pos (get-end-position))
889
+ (define ls (find-ls caret-pos))
890
+ (when ls
891
+ (define-values (start-f end-f error-f)
892
+ (send (lexer-state-parens ls) match-forward
893
+ (- caret-pos (lexer-state-start-pos ls))))
894
+ (when (and (not (f-match-false-error ls start-f end-f error-f))
895
+ start-f end-f)
896
+ (if error-f
897
+ (highlight ls start-f end-f caret-pos (and error-f #t ))
898
+ (highlight-nested-region ls start-f end-f caret-pos)))
899
+ (define-values (start-b end-b error-b)
900
+ (send (lexer-state-parens ls) match-backward
901
+ (- caret-pos (lexer-state-start-pos ls))))
902
+ (when (and start-b end-b)
903
+ (if error-b
904
+ (highlight ls start-b end-b caret-pos (and error-b #t ))
905
+ (highlight-nested-region ls start-b end-b caret-pos))))))
906
+ (end-edit-sequence)
907
+ (set! in-match-parens? #f )))
894
908
895
909
;; highlight-nested-region : lexer-state number number number -> void
896
910
;; colors nested regions of parentheses.
897
- (define/private (highlight-nested-region ls orig-start orig-end here )
911
+ (define/private (highlight-nested-region ls orig-start orig-end caret-pos )
898
912
(define priority (get-parenthesis-priority))
899
913
(define paren-colors (get-parenthesis-colors))
900
- (let paren-loop ([start orig-start]
914
+
915
+ ;; this goes over a range at a specific depth, highlighting
916
+ ;; of the the parens it finds at that depth and calling `single-spot-loop` to go deeper inside
917
+ (define (seq-loop start end depth)
918
+ (when (< depth (vector-length paren-colors))
919
+ (define color (vector-ref paren-colors depth))
920
+ (let loop ([start start])
921
+ (when (< start end)
922
+ (define afterwards (or (single-spot-loop start depth) (+ start 1 )))
923
+ (loop afterwards)))))
924
+
925
+ ;; single-spot-loop : natural natural -> void
926
+ ;; loops over the parens that open at `start` and inside
927
+ ;; the region from `start` to its outermost close paren
928
+ ;;
929
+ ;; instead of a more conventional traversal that would go over the
930
+ ;; parens at the current level and then goes across the positions
931
+ ;; inside the parens, looking for parens inside, we instead view the
932
+ ;; parens all starting at `start` as a series of nested parens that
933
+ ;; might look something like this, where the first three parens are
934
+ ;; all starting at the same spot.
935
+ ;; ((( ) ) )
936
+ ;; 12344433333222221
937
+ ;; This function loops over those first three parens (via the result
938
+ ;; of get-spot-parens) and, at each iteration, also considers the region
939
+ ;; following the close paren out to the enclosing close paren. That is,
940
+ ;; when we're looking at the paren labelled with a 2 in the diagram
941
+ ;; above, we'll recur with depth+1 to handle depth 3 (and eventually
942
+ ;; depth 4) and then use `seq-loop` to go over the region with the 2s
943
+ ;; underneath it, between the last two parens.
944
+ (define (single-spot-loop start depth)
945
+ ;; the -1 and +1s in the calls to seq-loop should probably be based on the tokenization,
946
+ ;; as more positions can be skipped in general
947
+ (cond
948
+ [(send (lexer-state-parens ls) is-open-pos? start #:invisible-ok? #t )
949
+ (define invisible-paren-count (send (lexer-state-parens ls) get-invisible-count start))
950
+ (define-values (outermost-start outermost-end error-outermost)
951
+ (send (lexer-state-parens ls) match-forward start #:invisible invisible-paren-count))
952
+ (let loop ([invisible-paren-count invisible-paren-count]
953
+ [end-position outermost-end]
954
+ [depth depth])
955
+ (when (< depth (vector-length paren-colors))
956
+ (define color (vector-ref paren-colors depth))
957
+ (cond
958
+ [(zero? invisible-paren-count)
959
+ (when (send (lexer-state-parens ls) is-open-pos? start #:invisible-ok? #f )
960
+ (define-values (start-inner end-inner error-inner)
961
+ (send (lexer-state-parens ls) match-forward start))
962
+ (unless error-inner
963
+ (seq-loop (+ start-inner 1 ) (- end-inner 1 ) (+ depth 1 ))
964
+ (seq-loop (+ end-inner 1 ) (- end-position 1 ) depth)
965
+ (highlight ls start-inner end-inner caret-pos color priority)))]
966
+ [else
967
+ (define-values (start-inner end-inner error-inner)
968
+ (send (lexer-state-parens ls) match-forward start #:invisible invisible-paren-count))
969
+ (unless error-inner
970
+ (seq-loop (+ end-inner 1 ) (- end-position 1 ) depth)
971
+ (loop (- invisible-paren-count 1 ) end-inner (+ depth 1 ))
972
+ (highlight ls start-inner end-inner caret-pos color priority))])))
973
+ outermost-end]
974
+ [else #f ]))
975
+
976
+ (single-spot-loop orig-start 0 )
977
+
978
+ #; (let paren-loop ([start orig-start]
901
979
[end orig-end]
902
980
[depth 0 ])
903
981
(when (< depth (vector-length paren-colors))
0 commit comments