etc/committer: Speed up surrounding-sexp.
The old surrounding-sexp procedure would read all S-expressions from the beginning of the file up to the given line number and then return the last encountered S-expression. This is quite wasteful. Instead we can record all lines that begin with an S-expression and jump straight to the offset closest to the desired line number to read the S-expression there. * etc/committer.scm.in (lines+offsets-with-opening-parens): New procedure. (surrounding-sexp): Use it.master
parent
5027bc19d8
commit
670fc6ee50
|
@ -85,21 +85,39 @@ the expression."
|
||||||
(seek port start SEEK_SET)
|
(seek port start SEEK_SET)
|
||||||
result))
|
result))
|
||||||
|
|
||||||
(define (surrounding-sexp port line-no)
|
(define (lines+offsets-with-opening-parens port)
|
||||||
|
"Record all line numbers (and their offsets) where an opening parenthesis is
|
||||||
|
found in column 0. The resulting list is in reverse order."
|
||||||
|
(let loop ((acc '())
|
||||||
|
(number 0))
|
||||||
|
(let ((line (read-line port)))
|
||||||
|
(cond
|
||||||
|
((eof-object? line) acc)
|
||||||
|
((string-prefix? "(" line)
|
||||||
|
(loop (cons (cons number ;line number
|
||||||
|
(- (ftell port)
|
||||||
|
(string-length line) 1)) ;offset
|
||||||
|
acc)
|
||||||
|
(1+ number)))
|
||||||
|
(else (loop acc (1+ number)))))))
|
||||||
|
|
||||||
|
(define (surrounding-sexp port target-line-no)
|
||||||
"Return the top-level S-expression surrounding the change at line number
|
"Return the top-level S-expression surrounding the change at line number
|
||||||
LINE-NO in PORT."
|
TARGET-LINE-NO in PORT."
|
||||||
(let loop ((i (1- line-no))
|
(let* ((line-numbers+offsets
|
||||||
(last-top-level-sexp #f))
|
(lines+offsets-with-opening-parens port))
|
||||||
(if (zero? i)
|
(closest-offset
|
||||||
last-top-level-sexp
|
(or (and=> (list-index (match-lambda
|
||||||
(match (peek-char port)
|
((line-number . offset)
|
||||||
(#\(
|
(< line-number target-line-no)))
|
||||||
(let ((sexp (read-excursion port)))
|
line-numbers+offsets)
|
||||||
(read-line port)
|
(lambda (index)
|
||||||
(loop (1- i) sexp)))
|
(match (list-ref line-numbers+offsets index)
|
||||||
(_
|
((line-number . offset) offset))))
|
||||||
(read-line port)
|
(error "Could not find surrounding S-expression for line"
|
||||||
(loop (1- i) last-top-level-sexp))))))
|
target-line-no))))
|
||||||
|
(seek port closest-offset SEEK_SET)
|
||||||
|
(read port)))
|
||||||
|
|
||||||
;;; Whether the hunk contains a newly added package (definition), a removed
|
;;; Whether the hunk contains a newly added package (definition), a removed
|
||||||
;;; package (removal) or something else (#false).
|
;;; package (removal) or something else (#false).
|
||||||
|
|
Reference in New Issue