diff options
author | Blendoit <blendoit@gmail.com> | 2020-08-01 15:24:03 -0700 |
---|---|---|
committer | Blendoit <blendoit@gmail.com> | 2020-08-01 15:24:03 -0700 |
commit | e47650852b8aa4da6d0b0cea3b5421955795cc64 (patch) | |
tree | 2535f7cc4fa4b5c25bbd46f9523da5944b76e201 /elpa/pdf-tools-20200512.1524/pdf-sync.el | |
parent | 374ae3de24187512adddf01a56e5eb52c79db65f (diff) |
Definitely /not/ including elpa/, that would be chaos.
Diffstat (limited to 'elpa/pdf-tools-20200512.1524/pdf-sync.el')
-rw-r--r-- | elpa/pdf-tools-20200512.1524/pdf-sync.el | 781 |
1 files changed, 0 insertions, 781 deletions
diff --git a/elpa/pdf-tools-20200512.1524/pdf-sync.el b/elpa/pdf-tools-20200512.1524/pdf-sync.el deleted file mode 100644 index 54eb4fa..0000000 --- a/elpa/pdf-tools-20200512.1524/pdf-sync.el +++ /dev/null @@ -1,781 +0,0 @@ -;;; pdf-sync.el --- Use synctex to correlate LaTeX-Sources with PDF positions. -*- lexical-binding:t -*- -;; Copyright (C) 2013, 2014 Andreas Politz - -;; Author: Andreas Politz <politza@fh-trier.de> -;; Keywords: files, doc-view, pdf - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; -;; The backward search uses a heuristic, which is pretty simple, but -;; effective: It extracts the text around the click-position in the -;; PDF, normalizes it's whitespace, deletes certain notorious -;; character and translates certain other character into their latex -;; equivalents. This transformed text is split into a series of -;; token. A similar operation is performed on the source code around -;; the position synctex points at. These two sequences of token are -;; aligned with a standard sequence alignment algorithm, resulting in -;; an alist of matched and unmatched tokens. This is then used to -;; find the corresponding word from the PDF file in the LaTeX buffer. - - -(require 'pdf-view) -(require 'pdf-info) -(require 'pdf-util) -(require 'let-alist) - -;;; Code: - -(defgroup pdf-sync nil - "Jump from TeX sources to PDF pages and back." - :group 'pdf-tools) - -(defcustom pdf-sync-forward-display-pdf-key "C-c C-g" - "Key to jump from a TeX buffer to it's PDF file. - -This key is added to `TeX-source-correlate-method', when -command `pdf-sync-minor-mode' is activated and this map is defined." - :group 'pdf-sync - :type 'key-sequence) - -(make-obsolete-variable - 'pdf-sync-forward-display-pdf-key - "Bound in Auctex's to C-c C-v, if TeX-source-correlate-mode is activate." "1.0") - -(defcustom pdf-sync-backward-hook nil - "Hook ran after going to a source location. - -The hook is run in the TeX buffer." - :group 'pdf-sync - :type 'hook - :options '(pdf-sync-backward-beginning-of-word)) - -(defcustom pdf-sync-forward-hook nil - "Hook ran after displaying the PDF buffer. - -The hook is run in the PDF's buffer." - :group 'pdf-sync - :type 'hook) - -(defcustom pdf-sync-forward-display-action nil - "Display action used when displaying PDF buffers." - :group 'pdf-sync - :type 'display-buffer--action-custom-type) - -(defcustom pdf-sync-backward-display-action nil - "Display action used when displaying TeX buffers." - :group 'pdf-sync - :type 'display-buffer--action-custom-type) - -(defcustom pdf-sync-locate-synctex-file-functions nil - "A list of functions for locating the synctex database. - -Each function on this hook should accept a single argument: The -absolute path of a PDF file. It should return the absolute path -of the corresponding synctex database or nil, if it was unable to -locate it." - :group 'pdf-sync - :type 'hook) - -(defvar pdf-sync-minor-mode-map - (let ((kmap (make-sparse-keymap))) - (define-key kmap [double-mouse-1] 'pdf-sync-backward-search-mouse) - (define-key kmap [C-mouse-1] 'pdf-sync-backward-search-mouse) - kmap)) - -(defcustom pdf-sync-backward-redirect-functions nil - "List of functions which may redirect a backward search. - -Functions on this hook should accept three arguments, namely -SOURCE, LINE and COLUMN, where SOURCE is the absolute filename of -the source file and LINE and COLUMN denote the position in the -file. COLUMN may be negative, meaning unspecified. - -These functions should either return nil, if no redirection is -necessary. Or a list of the same structure, with some or all (or -none) values modified. - -AUCTeX installs a function here which changes the backward search -location for synthetic `TeX-region' files back to the equivalent -position in the original tex file." - :group 'pdf-sync - :type '(repeat function)) - - -;;;###autoload -(define-minor-mode pdf-sync-minor-mode - "Correlate a PDF position with the TeX file. -\\<pdf-sync-minor-mode-map> -This works via SyncTeX, which means the TeX sources need to have -been compiled with `--synctex=1'. In AUCTeX this can be done by -setting `TeX-source-correlate-method' to 'synctex \(before AUCTeX -is loaded\) and enabling `TeX-source-correlate-mode'. - -Then \\[pdf-sync-backward-search-mouse] in the PDF buffer will open the -corresponding TeX location. - -If AUCTeX is your preferred tex-mode, this library arranges to -bind `pdf-sync-forward-display-pdf-key' \(the default is `C-c C-g'\) -to `pdf-sync-forward-search' in `TeX-source-correlate-map'. This -function displays the PDF page corresponding to the current -position in the TeX buffer. This function only works together -with AUCTeX." - - nil nil nil - (pdf-util-assert-pdf-buffer)) - - -;; * ================================================================== * -;; * Backward search (PDF -> TeX) -;; * ================================================================== * - -(defcustom pdf-sync-backward-use-heuristic t - "Whether to apply a heuristic when backward searching. - -If nil, just go where Synctex tells us. Otherwise try to find -the exact location of the clicked-upon text in the PDF." - :group 'pdf-sync - :type 'boolean) - -(defcustom pdf-sync-backward-text-translations - '((88 "X" "sum") - (94 "textasciicircum") - (126 "textasciitilde") - (169 "copyright" "textcopyright") - (172 "neg" "textlnot") - (174 "textregistered" "textregistered") - (176 "textdegree") - (177 "pm" "textpm") - (181 "upmu" "mu") - (182 "mathparagraph" "textparagraph" "P" "textparagraph") - (215 "times") - (240 "eth" "dh") - (915 "Upgamma" "Gamma") - (920 "Uptheta" "Theta") - (923 "Uplambda" "Lambda") - (926 "Upxi" "Xi") - (928 "Uppi" "Pi") - (931 "Upsigma" "Sigma") - (933 "Upupsilon" "Upsilon") - (934 "Upphi" "Phi") - (936 "Uppsi" "Psi") - (945 "upalpha" "alpha") - (946 "upbeta" "beta") - (947 "upgamma" "gamma") - (948 "updelta" "delta") - (949 "upvarepsilon" "varepsilon") - (950 "upzeta" "zeta") - (951 "upeta" "eta") - (952 "uptheta" "theta") - (953 "upiota" "iota") - (954 "upkappa" "varkappa" "kappa") - (955 "uplambda" "lambda") - (957 "upnu" "nu") - (958 "upxi" "xi") - (960 "uppi" "pi") - (961 "upvarrho" "uprho" "rho") - (962 "varsigma") - (963 "upvarsigma" "upsigma" "sigma") - (964 "uptau" "tau") - (965 "upupsilon" "upsilon") - (966 "upphi" "phi") - (967 "upchi" "chi") - (968 "uppsi" "psi") - (969 "upomega" "omega") - (977 "upvartheta" "vartheta") - (981 "upvarphi" "varphi") - (8224 "dagger") - (8225 "ddagger") - (8226 "bullet") - (8486 "Upomega" "Omega") - (8501 "aleph") - (8592 "mapsfrom" "leftarrow") - (8593 "uparrow") - (8594 "to" "mapsto" "rightarrow") - (8595 "downarrow") - (8596 "leftrightarrow") - (8656 "shortleftarrow" "Leftarrow") - (8657 "Uparrow") - (8658 "Mapsto" "rightrightarrows" "Rightarrow") - (8659 "Downarrow") - (8660 "Leftrightarrow") - (8704 "forall") - (8706 "partial") - (8707 "exists") - (8709 "varnothing" "emptyset") - (8710 "Updelta" "Delta") - (8711 "nabla") - (8712 "in") - (8722 "-") - (8725 "setminus") - (8727 "*") - (8734 "infty") - (8743 "wedge") - (8744 "vee") - (8745 "cap") - (8746 "cup") - (8756 "therefore") - (8757 "because") - (8764 "thicksim" "sim") - (8776 "thickapprox" "approx") - (8801 "equiv") - (8804 "leq") - (8805 "geq") - (8810 "lll") - (8811 "ggg") - (8814 "nless") - (8815 "ngtr") - (8822 "lessgtr") - (8823 "gtrless") - (8826 "prec") - (8832 "nprec") - (8834 "subset") - (8835 "supset") - (8838 "subseteq") - (8839 "supseteq") - (8853 "oplus") - (8855 "otimes") - (8869 "bot" "perp") - (9702 "circ") - (9792 "female" "venus") - (9793 "earth") - (9794 "male" "mars") - (9824 "spadesuit") - (9827 "clubsuit") - (9829 "heartsuit") - (9830 "diamondsuit")) - "Alist mapping PDF character to a list of LaTeX macro names. - -Adding a character here with it's LaTeX equivalent names allows -the heuristic backward search to find it's location in the source -file. These strings should not match -`pdf-sync-backward-source-flush-regexp'. - -Has no effect if `pdf-sync-backward-use-heuristic' is nil." - :group 'pdf-sync - :type '(alist :key-type character - :value-type (repeat string))) - -(defconst pdf-sync-backward-text-flush-regexp - "[][.ยท{}|\\]\\|\\C.\\|-\n+" - "Regexp of ignored text when backward searching.") - -(defconst pdf-sync-backward-source-flush-regexp - "\\(?:\\\\\\(?:begin\\|end\\|\\(?:eq\\)?ref\\|label\\|cite\\){[^}]*}\\)\\|[][\\&{}$_]" - "Regexp of ignored source when backward searching.") - -(defconst pdf-sync-backward-context-limit 64 - "Number of character to include in the backward search.") - -(defun pdf-sync-backward-search-mouse (ev) - "Go to the source corresponding to position at event EV." - (interactive "@e") - (let* ((posn (event-start ev)) - (image (posn-image posn)) - (xy (posn-object-x-y posn))) - (unless image - (error "Outside of image area")) - (pdf-sync-backward-search (car xy) (cdr xy)))) - -(defun pdf-sync-backward-search (x y) - "Go to the source corresponding to image coordinates X, Y. - -Try to find the exact position, if -`pdf-sync-backward-use-heuristic' is non-nil." - (cl-destructuring-bind (source finder) - (pdf-sync-backward-correlate x y) - (pop-to-buffer (or (find-buffer-visiting source) - (find-file-noselect source)) - pdf-sync-backward-display-action) - (push-mark) - (funcall finder) - (run-hooks 'pdf-sync-backward-hook))) - -(defun pdf-sync-backward-correlate (x y) - "Find the source corresponding to image coordinates X, Y. - -Returns a list \(SOURCE FINDER\), where SOURCE is the name of the -TeX file and FINDER a function of zero arguments which, when -called in the buffer of the aforementioned file, will try to move -point to the correct position." - - (pdf-util-assert-pdf-window) - (let ((size (pdf-view-image-size)) - (page (pdf-view-current-page))) - (setq x (/ x (float (car size))) - y (/ y (float (cdr size)))) - (let-alist (pdf-info-synctex-backward-search page x y) - (let ((data (list (expand-file-name .filename) - .line .column))) - (cl-destructuring-bind (source line column) - (or (save-selected-window - (apply 'run-hook-with-args-until-success - 'pdf-sync-backward-redirect-functions data)) - data) - (list source - (if (not pdf-sync-backward-use-heuristic) - (lambda nil - (pdf-util-goto-position line column)) - (let ((context (pdf-sync-backward--get-text-context page x y))) - (lambda nil - (pdf-sync-backward--find-position line column context)))))))))) - -(defun pdf-sync-backward--find-position (line column context) - (pdf-util-goto-position line column) - (cl-destructuring-bind (windex chindex words) - context - (let* ((swords (pdf-sync-backward--get-source-context - nil (* 6 pdf-sync-backward-context-limit))) - (similarity-fn (lambda (text source) - (if (if (consp text) - (member source text) - (equal text source)) - 1024 -1024))) - (alignment - (pdf-util-seq-alignment - words swords similarity-fn 'infix))) - (setq alignment (cl-remove-if-not 'car (cdr alignment))) - (cl-assert (< windex (length alignment))) - - (let ((word (cdr (nth windex alignment)))) - (unless word - (setq chindex 0 - word (cdr (nth (1+ windex) alignment)))) - (unless word - (setq word (cdr (nth (1- windex) alignment)) - chindex (length word))) - (when word - (cl-assert (get-text-property 0 'position word) t) - (goto-char (get-text-property 0 'position word)) - (forward-char chindex)))))) - -(defun pdf-sync-backward--get-source-context (&optional position limit) - (save-excursion - (when position (goto-char position)) - (goto-char (line-beginning-position)) - (let* ((region - (cond - ((eq limit 'line) - (cons (line-beginning-position) - (line-end-position))) - - ;; Synctex usually jumps to the end macro, in case it - ;; does not understand the environment. - ((and (fboundp 'LaTeX-find-matching-begin) - (looking-at " *\\\\\\(end\\){")) - (cons (or (ignore-errors - (save-excursion - (LaTeX-find-matching-begin) - (forward-line 1) - (point))) - (point)) - (point))) - ((and (fboundp 'LaTeX-find-matching-end) - (looking-at " *\\\\\\(begin\\){")) - (goto-char (line-end-position)) - (cons (point) - (or (ignore-errors - (save-excursion - (LaTeX-find-matching-end) - (forward-line 0) - (point))) - (point)))) - (t (cons (point) (point))))) - (begin (car region)) - (end (cdr region))) - (when (numberp limit) - (let ((delta (- limit (- end begin)))) - (when (> delta 0) - (setq begin (max (point-min) - (- begin (/ delta 2))) - end (min (point-max) - (+ end (/ delta 2))))))) - (let ((string (buffer-substring-no-properties begin end))) - (dotimes (i (length string)) - (put-text-property i (1+ i) 'position (+ begin i) string)) - (nth 2 (pdf-sync-backward--tokenize - (pdf-sync-backward--source-strip-comments string) - nil - pdf-sync-backward-source-flush-regexp)))))) - -(defun pdf-sync-backward--source-strip-comments (string) - "Strip all standard LaTeX comments from string." - (with-temp-buffer - (save-excursion (insert string)) - (while (re-search-forward - "^\\(?:[^\\\n]\\|\\(?:\\\\\\\\\\)\\)*\\(%.*\\)" nil t) - (delete-region (match-beginning 1) (match-end 1))) - (buffer-string))) - -(defun pdf-sync-backward--get-text-context (page x y) - (cl-destructuring-bind (&optional char edges) - (car (pdf-info-charlayout page (cons x y))) - (when edges - (setq x (nth 0 edges) - y (nth 1 edges))) - (let* ((prefix (pdf-info-gettext page (list 0 0 x y))) - (suffix (pdf-info-gettext page (list x y 1 1))) - (need-suffix-space-p (memq char '(?\s ?\n))) - ;; Figure out whether we missed a space by matching the - ;; prefix's suffix with the line's prefix. Due to the text - ;; extraction in poppler, spaces are only inserted in - ;; between words. This test may fail, if prefix and line - ;; do not overlap, which may happen in various cases, but - ;; we don't care. - (need-prefix-space-p - (and (not need-suffix-space-p) - (memq - (ignore-errors - (aref (pdf-info-gettext page (list x y x y) 'line) - (- (length prefix) - (or (cl-position ?\n prefix :from-end t) - -1) - 1))) - '(?\s ?\n))))) - (setq prefix - (concat - (substring - prefix (max 0 (min (1- (length prefix)) - (- (length prefix) - pdf-sync-backward-context-limit)))) - (if need-prefix-space-p " ")) - suffix - (concat - (if need-suffix-space-p " ") - (substring - suffix 0 (max 0 (min (1- (length suffix)) - pdf-sync-backward-context-limit))))) - (pdf-sync-backward--tokenize - prefix suffix - pdf-sync-backward-text-flush-regexp - pdf-sync-backward-text-translations)))) - -(defun pdf-sync-backward--tokenize (prefix &optional suffix flush-re translation) - (with-temp-buffer - (when prefix (insert prefix)) - (let* ((center (copy-marker (point))) - (case-fold-search nil)) - (when suffix (insert suffix)) - (goto-char 1) - ;; Delete ignored text. - (when flush-re - (save-excursion - (while (re-search-forward flush-re nil t) - (replace-match " " t t)))) - ;; Normalize whitespace. - (save-excursion - (while (re-search-forward "[ \t\f\n]+" nil t) - (replace-match " " t t))) - ;; Split words and non-words - (save-excursion - (while (re-search-forward "[^ ]\\b\\|[^ [:alnum:]]" nil t) - (insert-before-markers " "))) - ;; Replace character - (let ((translate - (lambda (string) - (or (and (= (length string) 1) - (cdr (assq (aref string 0) - translation))) - string))) - words - (windex -1) - (chindex 0)) - (skip-chars-forward " ") - (while (and (not (eobp)) - (<= (point) center)) - (cl-incf windex) - (skip-chars-forward "^ ") - (skip-chars-forward " ")) - (goto-char center) - (when (eq ?\s (char-after)) - (skip-chars-backward " ")) - (setq chindex (- (skip-chars-backward "^ "))) - (setq words (split-string (buffer-string))) - (when translation - (setq words (mapcar translate words))) - (list windex chindex words))))) - -(defun pdf-sync-backward-beginning-of-word () - "Maybe move to the beginning of the word. - -Don't move if already at the beginning, or if not at a word -character. - -This function is meant to be put on `pdf-sync-backward-hook', when -word-level searching is desired." - (interactive) - (unless (or (looking-at "\\b\\w") - (not (looking-back "\\w" (1- (point))))) - (backward-word))) - -;; * ------------------------------------------------------------------ * -;; * Debugging backward search -;; * ------------------------------------------------------------------ * - -(defvar pdf-sync-backward-debug-trace nil) - -(defun pdf-sync-backward-debug-wrapper (fn-symbol fn &rest args) - (cond - ((eq fn-symbol 'pdf-sync-backward-search) - (setq pdf-sync-backward-debug-trace nil) - (apply fn args)) - (t - (let ((retval (apply fn args))) - (push `(,args . ,retval) - pdf-sync-backward-debug-trace) - retval)))) - -(define-minor-mode pdf-sync-backward-debug-minor-mode - "Aid in debugging the backward search." - nil nil nil - (if (and (fboundp 'advice-add) - (fboundp 'advice-remove)) - (let ((functions - '(pdf-sync-backward-search - pdf-sync-backward--tokenize - pdf-util-seq-alignment))) - (cond - (pdf-sync-backward-debug-minor-mode - (dolist (fn functions) - (advice-add fn :around (apply-partially 'pdf-sync-backward-debug-wrapper - fn) - `((name . ,(format "%s-debug" fn)))))) - (t - (dolist (fn functions) - (advice-remove fn (format "%s-debug" fn)))))) - (error "Need Emacs version >= 24.4"))) - -(defun pdf-sync-backward-debug-explain () - "Explain the last backward search. - -Needs to have `pdf-sync-backward-debug-minor-mode' enabled." - - (interactive) - (unless pdf-sync-backward-debug-trace - (error "No last search or `pdf-sync-backward-debug-minor-mode' not enabled.")) - - (with-current-buffer (get-buffer-create "*pdf-sync-backward trace*") - (cl-destructuring-bind (text source alignment &rest ignored) - (reverse pdf-sync-backward-debug-trace) - (let* ((fill-column 68) - (sep (format "\n%s\n" (make-string fill-column ?-))) - (highlight '(:background "chartreuse" :foreground "black")) - (or-sep "|") - (inhibit-read-only t) - (windex (nth 0 (cdr text))) - (chindex (nth 1 (cdr text)))) - (erase-buffer) - (font-lock-mode -1) - (view-mode 1) - (insert (propertize "Text Raw:" 'face 'font-lock-keyword-face)) - (insert sep) - (insert (nth 0 (car text))) - (insert (propertize "<|>" 'face highlight)) - (insert (nth 1 (car text))) - (insert sep) - (insert (propertize "Text Token:" 'face 'font-lock-keyword-face)) - (insert sep) - (fill-region (point) - (progn - (insert - (mapconcat (lambda (elt) - (if (consp elt) - (mapconcat 'identity elt or-sep) - elt)) - (nth 2 (cdr text)) " ")) - (point))) - (insert sep) - - (insert (propertize "Source Raw:" 'face 'font-lock-keyword-face)) - (insert sep) - (insert (nth 0 (car source))) - (insert sep) - (insert (propertize "Source Token:" 'face 'font-lock-keyword-face)) - (insert sep) - (fill-region (point) - (progn (insert (mapconcat 'identity (nth 2 (cdr source)) " ")) - (point))) - (insert sep) - - (insert (propertize "Alignment:" 'face 'font-lock-keyword-face)) - (insert (format " (windex=%d, chindex=%d" windex chindex)) - (insert sep) - (save-excursion (newline 2)) - (let ((column 0) - (index 0)) - (dolist (a (cdr (cdr alignment))) - (let* ((source (cdr a)) - (text (if (consp (car a)) - (mapconcat 'identity (car a) or-sep) - (car a))) - (extend (max (length text) - (length source)))) - (when (and (not (bolp)) - (> (+ column extend) - fill-column)) - (forward-line 2) - (newline 3) - (forward-line -2) - (setq column 0)) - (when text - (insert (propertize text 'face - (if (= index windex) - highlight - (if source 'match - 'lazy-highlight))))) - (move-to-column (+ column extend) t) - (insert " ") - (save-excursion - (forward-line) - (move-to-column column t) - (when source - (insert (propertize source 'face (if text - 'match - 'lazy-highlight)))) - (move-to-column (+ column extend) t) - (insert " ")) - (cl-incf column (+ 1 extend)) - (when text (cl-incf index))))) - (goto-char (point-max)) - (insert sep) - (goto-char 1) - (pop-to-buffer (current-buffer)))))) - - -;; * ================================================================== * -;; * Forward search (TeX -> PDF) -;; * ================================================================== * - -(defun pdf-sync-forward-search (&optional line column) - "Display the PDF location corresponding to LINE, COLUMN." - (interactive) - (cl-destructuring-bind (pdf page _x1 y1 _x2 _y2) - (pdf-sync-forward-correlate line column) - (let ((buffer (or (find-buffer-visiting pdf) - (find-file-noselect pdf)))) - (with-selected-window (display-buffer - buffer pdf-sync-forward-display-action) - (pdf-util-assert-pdf-window) - (when page - (pdf-view-goto-page page) - (when y1 - (let ((top (* y1 (cdr (pdf-view-image-size))))) - (pdf-util-tooltip-arrow (round top)))))) - (with-current-buffer buffer - (run-hooks 'pdf-sync-forward-hook))))) - -(defun pdf-sync-forward-correlate (&optional line column) - "Find the PDF location corresponding to LINE, COLUMN. - -Returns a list \(PDF PAGE X1 Y1 X2 Y2\), where PAGE, X1, Y1, X2 -and Y2 may be nil, if the destination could not be found." - (unless (fboundp 'TeX-master-file) - (error "This function works only with AUCTeX")) - (unless line (setq line (line-number-at-pos))) - (unless column (setq column (current-column))) - - (let* ((pdf (expand-file-name - (with-no-warnings (TeX-master-file "pdf")))) - (sfilename (pdf-sync-synctex-file-name - (buffer-file-name) pdf))) - (cons pdf - (condition-case error - (let-alist (pdf-info-synctex-forward-search - (or sfilename - (buffer-file-name)) - line column pdf) - (cons .page .edges)) - (error - (message "%s" (error-message-string error)) - (list nil nil nil nil nil)))))) - - - -;; * ================================================================== * -;; * Dealing with synctex files. -;; * ================================================================== * - -(defun pdf-sync-locate-synctex-file (pdffile) - "Locate the synctex database corresponding to PDFFILE. - -Returns either the absolute path of the database or nil. - -See also `pdf-sync-locate-synctex-file-functions'." - (cl-check-type pdffile string) - (setq pdffile (expand-file-name pdffile)) - (or (run-hook-with-args-until-success - 'pdf-sync-locate-synctex-file-functions pdffile) - (pdf-sync-locate-synctex-file-default pdffile))) - -(defun pdf-sync-locate-synctex-file-default (pdffile) - "The default function for locating a synctex database for PDFFILE. - -See also `pdf-sync-locate-synctex-file'." - (let ((default-directory - (file-name-directory pdffile)) - (basename (file-name-sans-extension - (file-name-nondirectory pdffile)))) - (cl-labels ((file-if-exists-p (file) - (and (file-exists-p file) - file))) - (or (file-if-exists-p - (expand-file-name (concat basename ".synctex.gz"))) - (file-if-exists-p - (expand-file-name (concat basename ".synctex"))) - ;; Some pdftex quote the basename. - (file-if-exists-p - (expand-file-name (concat "\"" basename "\"" ".synctex.gz"))) - (file-if-exists-p - (expand-file-name (concat "\"" basename "\"" ".synctex"))))))) - -(defun pdf-sync-synctex-file-name (filename pdffile) - "Find SyncTeX filename corresponding to FILENAME in the context of PDFFILE. - -This function consults the synctex.gz database of PDFFILE and -searches for a filename, which is `file-equal-p' to FILENAME. -The first such filename is returned, or nil if none was found." - - (when (file-exists-p filename) - (setq filename (expand-file-name filename)) - (let* ((synctex (pdf-sync-locate-synctex-file pdffile)) - (basename (file-name-nondirectory filename)) - (regexp (format "^ *Input *: *[^:\n]+ *:\\(.*%s\\)$" - (regexp-quote basename))) - (jka-compr-verbose nil)) - (when (and synctex - (file-readable-p synctex)) - (with-current-buffer (find-file-noselect synctex :nowarn) - (unless (or (verify-visited-file-modtime) - (buffer-modified-p)) - (revert-buffer :ignore-auto :noconfirm) - (goto-char (point-min))) - ;; Keep point in front of the found filename. It will - ;; probably be queried for again next time. - (let ((beg (point)) - (end (point-max))) - (catch 'found - (dotimes (_x 2) - (while (re-search-forward regexp end t) - (let ((syncname (match-string-no-properties 1))) - (when (and (file-exists-p syncname) - (file-equal-p filename syncname)) - (goto-char (point-at-bol)) - (throw 'found syncname)))) - (setq end beg - beg (point-min)) - (goto-char beg))))))))) - -(provide 'pdf-sync) -;;; pdf-sync.el ends here |