Revisit VLF setup
This commit is contained in:
parent
c10537ac54
commit
12982abd0e
109
config.org
109
config.org
|
@ -1746,17 +1746,118 @@ have the following.
|
||||||
|
|
||||||
The /very large files/ mode loads large files in chunks, allowing one to open
|
The /very large files/ mode loads large files in chunks, allowing one to open
|
||||||
ridiculously large files.
|
ridiculously large files.
|
||||||
|
|
||||||
#+begin_src emacs-lisp :tangle packages.el
|
#+begin_src emacs-lisp :tangle packages.el
|
||||||
(package! vlf :recipe (:host github :repo "m00natic/vlfi" :files ("*.el"))
|
(package! vlf :recipe (:host github :repo "emacs-straight/vlf" :files ("*.el"))
|
||||||
:pin "cc02f2533782d6b9b628cec7e2dcf25b2d05a27c" :disable t)
|
:pin "cacdb359f8c37c6e7e4c7937462b632d22462130")
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
To make VLF available without delaying startup, we'll just load it in quiet moments.
|
To make VLF available without delaying startup, we'll just load it in quiet moments.
|
||||||
#+begin_src emacs-lisp
|
|
||||||
|
#+begin_src emacs-lisp :noweb no-export
|
||||||
(use-package! vlf-setup
|
(use-package! vlf-setup
|
||||||
:defer-incrementally vlf-tune vlf-base vlf-write vlf-search vlf-occur vlf-follow vlf-ediff vlf)
|
:defer-incrementally vlf-tune vlf-base vlf-write
|
||||||
|
vlf-search vlf-occur vlf-follow vlf-ediff vlf
|
||||||
|
:commands vlf vlf-mode
|
||||||
|
:init
|
||||||
|
<<vlf-largefile-prompt>>
|
||||||
|
:config
|
||||||
|
(advice-remove 'abort-if-file-too-large #'ad-Advice-abort-if-file-too-large)
|
||||||
|
<<vlf-linenum-offset>>
|
||||||
|
)
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
Now, there are one or two tweaks worth applying to VLF. For starters, it goes to
|
||||||
|
the liberty of advising ~abort-if-file-too-large~, and in doing so removes the
|
||||||
|
option of opening files literally. I think that's a bit much, so we can remove
|
||||||
|
the advice and instead override ~files--ask-user-about-large-file~ (the more
|
||||||
|
appropriate function, I think) as a simpler approach, just sacrificing the
|
||||||
|
original behaviour with src_elisp{(setq vlf-application 'always)} (which I can't
|
||||||
|
imagine using anyway).
|
||||||
|
|
||||||
|
#+name: vlf-largefile-prompt
|
||||||
|
#+begin_src emacs-lisp :tangle no
|
||||||
|
(defadvice! +files--ask-about-large-file-vlf (size op-type filename offer-raw)
|
||||||
|
"Like `files--ask-user-about-large-file', but with support for `vlf'."
|
||||||
|
:override #'files--ask-user-about-large-file
|
||||||
|
(if (eq vlf-application 'dont-ask)
|
||||||
|
(progn (vlf filename) (error ""))
|
||||||
|
(let ((prompt (format "File %s is large (%s), really %s?"
|
||||||
|
(file-name-nondirectory filename)
|
||||||
|
(funcall byte-count-to-string-function size) op-type)))
|
||||||
|
(if (not offer-raw)
|
||||||
|
(if (y-or-n-p prompt) nil 'abort)
|
||||||
|
(let ((choice
|
||||||
|
(car
|
||||||
|
(read-multiple-choice
|
||||||
|
prompt '((?y "yes")
|
||||||
|
(?n "no")
|
||||||
|
(?l "literally")
|
||||||
|
(?v "vlf"))
|
||||||
|
(files--ask-user-about-large-file-help-text
|
||||||
|
op-type (funcall byte-count-to-string-function size))))))
|
||||||
|
(cond ((eq choice ?y) nil)
|
||||||
|
((eq choice ?l) 'raw)
|
||||||
|
((eq choice ?v)
|
||||||
|
(vlf filename)
|
||||||
|
(error ""))
|
||||||
|
(t 'abort)))))))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
As you go from one chunk fetched by VLF to the next, the displayed line number
|
||||||
|
of the first line /in each chunk/ is unchanged. I think it's reasonable to hope
|
||||||
|
for an /overall/ line number, and by tracking chunk's cumulative line numbers we
|
||||||
|
can implement this behaviour fairly easily.
|
||||||
|
|
||||||
|
#+name: vlf-linenum-offset
|
||||||
|
#+begin_src emacs-lisp :tangle no
|
||||||
|
(defvar-local +vlf-cumulative-linenum '((0 . 0))
|
||||||
|
"An alist keeping track of the cumulative line number.")
|
||||||
|
|
||||||
|
(defun +vlf-update-linum ()
|
||||||
|
"Update the line number offset."
|
||||||
|
(let ((linenum-offset (alist-get vlf-start-pos +vlf-cumulative-linenum)))
|
||||||
|
(setq display-line-numbers-offset (or linenum-offset 0))
|
||||||
|
(when (and linenum-offset (not (assq vlf-end-pos +vlf-cumulative-linenum)))
|
||||||
|
(push (cons vlf-end-pos (+ linenum-offset
|
||||||
|
(count-lines (point-min) (point-max))))
|
||||||
|
+vlf-cumulative-linenum))))
|
||||||
|
|
||||||
|
(add-hook 'vlf-after-chunk-update-hook #'+vlf-log-poses-a)
|
||||||
|
|
||||||
|
;; Since this only works with absolute line numbers, let's make sure we use them.
|
||||||
|
(add-hook! 'vlf-mode-hook (setq-local display-line-numbers t))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
The other thing that doesn't work too well with VLF is searching with anything
|
||||||
|
other than =M-x occur=. This is because trying to go to the next match at the end
|
||||||
|
of a chunk usually wraps the point to the beginning of the chunk, instead of
|
||||||
|
moving to the next chunk.
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp :tangle no
|
||||||
|
(defun +vlf-next-chunk-or-start ()
|
||||||
|
(if (= vlf-file-size vlf-end-pos)
|
||||||
|
(vlf-jump-to-chunk 1)
|
||||||
|
(vlf-next-batch 1))
|
||||||
|
(goto-char (point-min)))
|
||||||
|
|
||||||
|
(defun +vlf-last-chunk-or-end ()
|
||||||
|
(if (= 0 vlf-start-pos)
|
||||||
|
(vlf-end-of-file)
|
||||||
|
(vlf-prev-batch 1))
|
||||||
|
(goto-char (point-max)))
|
||||||
|
|
||||||
|
(defun +vlf-isearch-wrap ()
|
||||||
|
(if isearch-forward
|
||||||
|
(+vlf-next-chunk-or-start)
|
||||||
|
(+vlf-last-chunk-or-end)))
|
||||||
|
|
||||||
|
(add-hook! 'vlf-mode-hook (setq-local isearch-wrap-function #'+vlf-isearch-wrap))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Unfortunately, since evil-search doesn't have an analogue to
|
||||||
|
~isearch-wrap-function~, we can't easily add support to it.
|
||||||
|
|
||||||
*** Eros
|
*** Eros
|
||||||
|
|
||||||
#+begin_quote
|
#+begin_quote
|
||||||
|
|
Loading…
Reference in a new issue