aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Nelson2025-04-02 21:38:48 +0200
committerStefan Monnier2025-04-04 14:37:33 -0400
commit03fc0e0fd51990570759601fa7e64f1cc5b76932 (patch)
treefe7c04557e02ce5ea056ee10bceb6d543d43e0e1
parent8c411381c69bf889243dc8a40cda22557e4b32be (diff)
downloademacs-03fc0e0fd51990570759601fa7e64f1cc5b76932.tar.gz
emacs-03fc0e0fd51990570759601fa7e64f1cc5b76932.zip
Add RefTeX support for non-file buffers
* lisp/textmodes/reftex.el (reftex--get-buffer-identifier) (reftex--get-directory, reftex--abbreviate-name) (reftex--get-basename, reftex--get-truename): New helper functions that handle both files and buffer objects. (reftex--remove-buffer-from-master-index): New helper function. (reftex-tie-multifile-symbols): Support non-file buffers, using the above. (reftex-TeX-master-file): Return current buffer when no file. (reftex-access-scan-info): Remove check requiring file buffers. (reftex-access-parse-file, reftex-check-parse-consistency): Skip for non-file buffers. (reftex-select-external-document): Use new helper function. (reftex-locate-file): Return buffer objects directly. (reftex-get-file-buffer-force): Handle buffer objects and special 'buffer:' strings. * lisp/textmodes/reftex-global.el (reftex-create-tags-file): Add error handling for non-file buffers. Leave TAGS unsupported in non-file buffers. (reftex-find-duplicate-labels) (reftex-isearch-switch-to-next-file): Use new helper functions that handle both files and buffer objects. (reftex-isearch-switch-to-next-file): Use equal rather than string= to compare strings/buffers. * lisp/textmodes/reftex-index.el (reftex-display-index) (reftex-index-change-entry): Use new helper functions. (reftex-index-visit-phrases-buffer): Add error handling for non-file buffers. Leave phrases unsupported in non-file buffers. * lisp/textmodes/reftex-parse.el (reftex-do-parse) (reftex-parse-from-file): Add support for non-file buffers. (reftex-all-document-files, reftex-where-am-I) (reftex-notice-new): Use new helper functions. * lisp/textmodes/reftex-ref.el (reftex-label-info-update): Support non-file buffers. (reftex-label-info, reftex-replace-prefix-escapes, reftex-label) (reftex-replace-prefix-escapes, reftex-offer-label-menu): Use new helper functions. * lisp/textmodes/reftex-sel.el (reftex-insert-docstruct): Use new helper function. * lisp/textmodes/reftex-toc.el (reftex-toc) (reftex-recenter-toc-when-idle): Support non-file buffers. * lisp/textmodes/reftex-cite.el (reftex-bib-or-thebib) (reftex-get-bibfile-list): Use new helper functions. * lisp/textmodes/reftex-global.el (reftex-save-all-document-buffers, reftex-ensure-write-access): Ignore non-file buffers. * lisp/textmodes/reftex-parse.el (reftex-all-document-files): For non-file objects, do not apply relative path transformation. * test/lisp/textmodes/reftex-tests.el (reftex-all-used-citation-keys-buffer) (reftex-renumber-simple-labels-buffer): New tests for operations on non-file buffers. RefTeX historically assumed that the buffers it operates on visit files. To handle non-file buffers: Modify reftex-TeX-master-file so that it returns the buffer object itself (as suggested by Stefan Monnier). Modify each caller to handle buffer objects, aided by some helper functions added to reftex.el. Replace 'string=' by 'equal' in places. Use buffer-base-buffer, where appropriate, to handle indirect buffers (file and non-file). TAGS files and phrases buffers remain unsupported for non-file buffers.
-rw-r--r--lisp/textmodes/reftex-cite.el9
-rw-r--r--lisp/textmodes/reftex-global.el70
-rw-r--r--lisp/textmodes/reftex-index.el25
-rw-r--r--lisp/textmodes/reftex-parse.el49
-rw-r--r--lisp/textmodes/reftex-ref.el25
-rw-r--r--lisp/textmodes/reftex-sel.el2
-rw-r--r--lisp/textmodes/reftex-toc.el11
-rw-r--r--lisp/textmodes/reftex.el246
-rw-r--r--test/lisp/textmodes/reftex-tests.el323
9 files changed, 585 insertions, 175 deletions
diff --git a/lisp/textmodes/reftex-cite.el b/lisp/textmodes/reftex-cite.el
index fe6751a13f6..8830f188c93 100644
--- a/lisp/textmodes/reftex-cite.el
+++ b/lisp/textmodes/reftex-cite.el
@@ -76,7 +76,8 @@ The expanded value is cached."
76 "Test if BibTeX or \\begin{thebibliography} should be used for the citation. 76 "Test if BibTeX or \\begin{thebibliography} should be used for the citation.
77Find the bof of the current file." 77Find the bof of the current file."
78 (let* ((docstruct (symbol-value reftex-docstruct-symbol)) 78 (let* ((docstruct (symbol-value reftex-docstruct-symbol))
79 (rest (or (member (list 'bof (buffer-file-name)) docstruct) 79 (rest (or (member (list 'bof (reftex--get-buffer-identifier))
80 docstruct)
80 docstruct)) 81 docstruct))
81 (bib (assq 'bib rest)) 82 (bib (assq 'bib rest))
82 (thebib (assq 'thebib rest)) 83 (thebib (assq 'thebib rest))
@@ -104,11 +105,11 @@ Then this function will return the applicable database files."
104 (or 105 (or
105 ;; Try inside this file (and its includes) 106 ;; Try inside this file (and its includes)
106 (cdr (reftex-last-assoc-before-elt 107 (cdr (reftex-last-assoc-before-elt
107 'bib (list 'eof (buffer-file-name)) 108 'bib (list 'eof (reftex--get-buffer-identifier))
108 (member (list 'bof (buffer-file-name)) 109 (member (list 'bof (reftex--get-buffer-identifier))
109 (symbol-value reftex-docstruct-symbol)))) 110 (symbol-value reftex-docstruct-symbol))))
110 ;; Try after the beginning of this file 111 ;; Try after the beginning of this file
111 (cdr (assq 'bib (member (list 'bof (buffer-file-name)) 112 (cdr (assq 'bib (member (list 'bof (reftex--get-buffer-identifier))
112 (symbol-value reftex-docstruct-symbol)))) 113 (symbol-value reftex-docstruct-symbol))))
113 ;; Anywhere in the entire document 114 ;; Anywhere in the entire document
114 (cdr (assq 'bib (symbol-value reftex-docstruct-symbol))) 115 (cdr (assq 'bib (symbol-value reftex-docstruct-symbol)))
diff --git a/lisp/textmodes/reftex-global.el b/lisp/textmodes/reftex-global.el
index 20abd36192d..bd330d3a418 100644
--- a/lisp/textmodes/reftex-global.el
+++ b/lisp/textmodes/reftex-global.el
@@ -37,16 +37,18 @@
37The TAGS file is also immediately visited with `visit-tags-table'." 37The TAGS file is also immediately visited with `visit-tags-table'."
38 (interactive) 38 (interactive)
39 (reftex-access-scan-info current-prefix-arg) 39 (reftex-access-scan-info current-prefix-arg)
40 (let* ((master (reftex-TeX-master-file)) 40 (let ((master (reftex-TeX-master-file)))
41 (files (reftex-all-document-files)) 41 (if (bufferp master)
42 (cmd (format "%s %s" 42 (user-error "Cannot create TAGS file for non-file buffers")
43 etags-program-name 43 (let* ((files (reftex-all-document-files))
44 (mapconcat #'shell-quote-argument 44 (cmd (format "%s %s"
45 files " ")))) 45 etags-program-name
46 (with-current-buffer (reftex-get-file-buffer-force master) 46 (mapconcat #'shell-quote-argument
47 (message "Running etags to create TAGS file...") 47 files " "))))
48 (shell-command cmd) 48 (with-current-buffer (reftex-get-file-buffer-force master)
49 (visit-tags-table "TAGS")))) 49 (message "Running etags to create TAGS file...")
50 (shell-command cmd)
51 (visit-tags-table "TAGS"))))))
50 52
51;; History of grep commands. 53;; History of grep commands.
52(defvar reftex-grep-history nil) 54(defvar reftex-grep-history nil)
@@ -144,7 +146,7 @@ No active TAGS table is required."
144 (if (< 1 (length x1)) 146 (if (< 1 (length x1))
145 (append (list (car x)) 147 (append (list (car x))
146 (mapcar (lambda(x) 148 (mapcar (lambda(x)
147 (abbreviate-file-name (nth 3 x))) 149 (reftex--abbreviate-name (nth 3 x)))
148 x1)) 150 x1))
149 (list nil)))))) 151 (list nil))))))
150 (reftex-uniquify-by-car (symbol-value reftex-docstruct-symbol))))) 152 (reftex-uniquify-by-car (symbol-value reftex-docstruct-symbol)))))
@@ -369,31 +371,33 @@ labels."
369 file buffer) 371 file buffer)
370 (save-current-buffer 372 (save-current-buffer
371 (while (setq file (pop files)) 373 (while (setq file (pop files))
372 (setq buffer (find-buffer-visiting file)) 374 (when (stringp file) ; Ignore non-file buffers.
373 (when buffer 375 (setq buffer (find-buffer-visiting file))
374 (set-buffer buffer) 376 (when buffer
375 (save-buffer)))))) 377 (set-buffer buffer)
378 (save-buffer)))))))
376 379
377(defun reftex-ensure-write-access (files) 380(defun reftex-ensure-write-access (files)
378 "Make sure we have write access to all files in FILES. 381 "Make sure we have write access to all files in FILES.
379Also checks if buffers visiting the files are in read-only mode." 382Also checks if buffers visiting the files are in read-only mode."
380 (let (file buf) 383 (let (file buf)
381 (while (setq file (pop files)) 384 (while (setq file (pop files)) ; Ignore non-file buffers.
382 (unless (file-exists-p file) 385 (when (stringp file)
383 (ding) 386 (unless (file-exists-p file)
384 (or (y-or-n-p (format "No such file %s. Continue?" file)) 387 (ding)
385 (error "Abort"))) 388 (or (y-or-n-p (format "No such file %s. Continue?" file))
386 (unless (file-writable-p file) 389 (error "Abort")))
387 (ding) 390 (unless (file-writable-p file)
388 (or (y-or-n-p (format "No write access to %s. Continue?" file)) 391 (ding)
389 (error "Abort"))) 392 (or (y-or-n-p (format "No write access to %s. Continue?" file))
390 (when (and (setq buf (find-buffer-visiting file)) 393 (error "Abort")))
391 (with-current-buffer buf 394 (when (and (setq buf (find-buffer-visiting file))
392 buffer-read-only)) 395 (with-current-buffer buf
393 (ding) 396 buffer-read-only))
394 (or (y-or-n-p (format "Buffer %s is read-only. Continue?" 397 (ding)
395 (buffer-name buf))) 398 (or (y-or-n-p (format "Buffer %s is read-only. Continue?"
396 (error "Abort")))))) 399 (buffer-name buf)))
400 (error "Abort")))))))
397 401
398;;; Multi-file RefTeX Isearch 402;;; Multi-file RefTeX Isearch
399 403
@@ -456,7 +460,7 @@ Also checks if buffers visiting the files are in read-only mode."
456;; beginning/end of the file list, depending of the search direction. 460;; beginning/end of the file list, depending of the search direction.
457(defun reftex-isearch-switch-to-next-file (crt-buf &optional wrapp) 461(defun reftex-isearch-switch-to-next-file (crt-buf &optional wrapp)
458 (reftex-access-scan-info) 462 (reftex-access-scan-info)
459 (let ((cb (buffer-file-name crt-buf)) 463 (let ((cb (reftex--get-buffer-identifier crt-buf))
460 (flist (reftex-all-document-files))) 464 (flist (reftex-all-document-files)))
461 (when flist 465 (when flist
462 (if wrapp 466 (if wrapp
@@ -464,7 +468,7 @@ Also checks if buffers visiting the files are in read-only mode."
464 (setq flist (last flist))) 468 (setq flist (last flist)))
465 (unless isearch-forward 469 (unless isearch-forward
466 (setq flist (reverse flist))) 470 (setq flist (reverse flist)))
467 (while (not (string= (car flist) cb)) 471 (while (not (equal (car flist) cb))
468 (setq flist (cdr flist))) 472 (setq flist (cdr flist)))
469 (setq flist (cdr flist))) 473 (setq flist (cdr flist)))
470 (when flist 474 (when flist
diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el
index db6ebb4caf8..1d18d6047b5 100644
--- a/lisp/textmodes/reftex-index.el
+++ b/lisp/textmodes/reftex-index.el
@@ -475,7 +475,7 @@ With prefix 3, restrict index to region."
475 (docstruct-symbol reftex-docstruct-symbol) 475 (docstruct-symbol reftex-docstruct-symbol)
476 (index-tag (or tag (reftex-index-select-tag))) 476 (index-tag (or tag (reftex-index-select-tag)))
477 (master (reftex-TeX-master-file)) 477 (master (reftex-TeX-master-file))
478 (calling-file (buffer-file-name)) 478 (calling-file (reftex--get-buffer-identifier))
479 (restriction 479 (restriction
480 (or overriding-restriction 480 (or overriding-restriction
481 (and (not redo) 481 (and (not redo)
@@ -531,7 +531,7 @@ Restriction: <%s>
531SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan [f]ollow [?]Help 531SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan [f]ollow [?]Help
532------------------------------------------------------------------------------ 532------------------------------------------------------------------------------
533" 533"
534 index-tag (abbreviate-file-name master) 534 index-tag (reftex--abbreviate-name master)
535 (if (eq (car (car reftex-index-restriction-data)) 'toc) 535 (if (eq (car (car reftex-index-restriction-data)) 'toc)
536 (nth 2 (car reftex-index-restriction-data)) 536 (nth 2 (car reftex-index-restriction-data))
537 reftex-index-restriction-indicator))) 537 reftex-index-restriction-indicator)))
@@ -1107,7 +1107,8 @@ values are accessible individually."
1107 (when (and (re-search-forward (reftex-everything-regexp) nil t) 1107 (when (and (re-search-forward (reftex-everything-regexp) nil t)
1108 (match-end 10) 1108 (match-end 10)
1109 (< (abs (- (match-beginning 10) beg)) (length new)) 1109 (< (abs (- (match-beginning 10) beg)) (length new))
1110 (setq info (reftex-index-info-safe buffer-file-name))) 1110 (setq info (reftex-index-info-safe
1111 (reftex--get-buffer-identifier))))
1111 (setcdr data (cdr info)))) 1112 (setcdr data (cdr info))))
1112 (let ((buffer-read-only nil)) 1113 (let ((buffer-read-only nil))
1113 (save-excursion 1114 (save-excursion
@@ -1281,14 +1282,16 @@ You get a chance to edit the entry in the phrases buffer - finish with
1281 (interactive) 1282 (interactive)
1282 (reftex-access-scan-info) 1283 (reftex-access-scan-info)
1283 (set-marker reftex-index-return-marker (point)) 1284 (set-marker reftex-index-return-marker (point))
1284 (let* ((master (reftex-TeX-master-file)) 1285 (let ((master (reftex-TeX-master-file)))
1285 (name (concat (file-name-sans-extension master) 1286 (when (bufferp master)
1286 reftex-index-phrase-file-extension))) 1287 (user-error "RefTeX phrases buffer requires a file buffer"))
1287 (find-file name) 1288 (let ((name (concat (file-name-sans-extension master)
1288 (unless (eq major-mode 'reftex-index-phrases-mode) 1289 reftex-index-phrase-file-extension)))
1289 (reftex-index-phrases-mode)) 1290 (find-file name)
1290 (if (= (buffer-size) 0) 1291 (unless (eq major-mode 'reftex-index-phrases-mode)
1291 (reftex-index-initialize-phrases-buffer master)))) 1292 (reftex-index-phrases-mode))
1293 (if (= (buffer-size) 0)
1294 (reftex-index-initialize-phrases-buffer master)))))
1292 1295
1293(defun reftex-index-initialize-phrases-buffer (&optional master) 1296(defun reftex-index-initialize-phrases-buffer (&optional master)
1294 "Initialize the phrases buffer by creating the header. 1297 "Initialize the phrases buffer by creating the header.
diff --git a/lisp/textmodes/reftex-parse.el b/lisp/textmodes/reftex-parse.el
index 7795c583076..cd8b3378558 100644
--- a/lisp/textmodes/reftex-parse.el
+++ b/lisp/textmodes/reftex-parse.el
@@ -74,10 +74,10 @@ When allowed, do only a partial scan from FILE."
74 74
75 (let* ((old-list (symbol-value reftex-docstruct-symbol)) 75 (let* ((old-list (symbol-value reftex-docstruct-symbol))
76 (master (reftex-TeX-master-file)) 76 (master (reftex-TeX-master-file))
77 (true-master (file-truename master)) 77 (true-master (reftex--get-truename master))
78 (master-dir (file-name-as-directory (file-name-directory master))) 78 (master-dir (file-name-as-directory (reftex--get-directory master)))
79 (file (or file (buffer-file-name))) 79 (file (or file (reftex--get-buffer-identifier)))
80 (true-file (file-truename file)) 80 (true-file (reftex--get-truename file))
81 (bibview-cache (assq 'bibview-cache old-list)) 81 (bibview-cache (assq 'bibview-cache old-list))
82 (reftex--index-tags (cdr (assq 'index-tags old-list))) 82 (reftex--index-tags (cdr (assq 'index-tags old-list)))
83 from-file appendix docstruct tmp) 83 from-file appendix docstruct tmp)
@@ -88,7 +88,7 @@ When allowed, do only a partial scan from FILE."
88 (member (list 'eof file) old-list)))) 88 (member (list 'eof file) old-list))))
89 ;; Scan whole document because no such file section exists 89 ;; Scan whole document because no such file section exists
90 (setq rescan 1)) 90 (setq rescan 1))
91 (when (string= true-file true-master) 91 (when (equal true-file true-master)
92 ;; Scan whole document because this file is the master 92 ;; Scan whole document because this file is the master
93 (setq rescan 1)) 93 (setq rescan 1))
94 94
@@ -186,13 +186,14 @@ When allowed, do only a partial scan from FILE."
186When RELATIVE is non-nil, give file names relative to directory 186When RELATIVE is non-nil, give file names relative to directory
187of master file." 187of master file."
188 (let* ((all (symbol-value reftex-docstruct-symbol)) 188 (let* ((all (symbol-value reftex-docstruct-symbol))
189 (master-dir (file-name-directory (reftex-TeX-master-file))) 189 (master-dir (reftex--get-directory (reftex-TeX-master-file)))
190 (re (concat "\\`" (regexp-quote master-dir))) 190 (re (concat "\\`" (regexp-quote master-dir)))
191 file-list tmp file) 191 file-list tmp file)
192 (while (setq tmp (assoc 'bof all)) 192 (while (setq tmp (assoc 'bof all))
193 (setq file (nth 1 tmp) 193 (setq file (nth 1 tmp)
194 all (cdr (memq tmp all))) 194 all (cdr (memq tmp all)))
195 (and relative 195 (and relative
196 (stringp file) ; Ignore non-file buffers.
196 (string-match re file) 197 (string-match re file)
197 (setq file (substring file (match-end 0)))) 198 (setq file (substring file (match-end 0))))
198 (push file file-list)) 199 (push file file-list))
@@ -228,7 +229,7 @@ of master file."
228 (not (eq t reftex-keep-temporary-buffers))))) 229 (not (eq t reftex-keep-temporary-buffers)))))
229 230
230 ;; Begin of file mark 231 ;; Begin of file mark
231 (setq file (buffer-file-name)) 232 (setq file (reftex--get-buffer-identifier))
232 (push (list 'bof file) docstruct) 233 (push (list 'bof file) docstruct)
233 234
234 (reftex-with-special-syntax 235 (reftex-with-special-syntax
@@ -275,7 +276,8 @@ of master file."
275 (when (and toc-entry 276 (when (and toc-entry
276 (eq ;; Either both are t or both are nil. 277 (eq ;; Either both are t or both are nil.
277 (= (char-after bound) ?%) 278 (= (char-after bound) ?%)
278 (string-suffix-p ".dtx" file))) 279 (and (stringp file)
280 (string-suffix-p ".dtx" file))))
279 ;; It can happen that section info returns nil 281 ;; It can happen that section info returns nil
280 (setq level (nth 5 toc-entry)) 282 (setq level (nth 5 toc-entry))
281 (setq highest-level (min highest-level level)) 283 (setq highest-level (min highest-level level))
@@ -638,7 +640,8 @@ if the information is exact (t) or approximate (nil)."
638 ((not found) 640 ((not found)
639 ;; no match 641 ;; no match
640 (or 642 (or
641 (car (member (list 'bof (buffer-file-name)) docstruct)) 643 (car (member (list 'bof (reftex--get-buffer-identifier))
644 docstruct))
642 (not (setq cnt 2)) 645 (not (setq cnt 2))
643 (assq 'bof docstruct) ;; for safety reasons 646 (assq 'bof docstruct) ;; for safety reasons
644 'corrupted)) 647 'corrupted))
@@ -649,15 +652,16 @@ if the information is exact (t) or approximate (nil)."
649 ((match-end 3) 652 ((match-end 3)
650 ;; Section 653 ;; Section
651 (goto-char (1- (match-beginning 3))) 654 (goto-char (1- (match-beginning 3)))
652 (let* ((list (member (list 'bof (buffer-file-name)) 655 (let* ((buffile (reftex--get-buffer-identifier))
656 (list (member (list 'bof buffile)
653 docstruct)) 657 docstruct))
654 (endelt (car (member (list 'eof (buffer-file-name)) 658 (endelt (car (member (list 'eof buffile)
655 list))) 659 list)))
656 rtn1) 660 rtn1)
657 (while (and list (not (eq endelt (car list)))) 661 (while (and list (not (eq endelt (car list))))
658 (if (and (eq (car (car list)) 'toc) 662 (if (and (eq (car (car list)) 'toc)
659 (string= (buffer-file-name) 663 (equal buffile
660 (nth 3 (car list)))) 664 (nth 3 (car list))))
661 (cond 665 (cond
662 ((equal (point) 666 ((equal (point)
663 (or (and (markerp (nth 4 (car list))) 667 (or (and (markerp (nth 4 (car list)))
@@ -685,10 +689,13 @@ if the information is exact (t) or approximate (nil)."
685 (when reftex-support-index 689 (when reftex-support-index
686 (let* ((index-info (save-excursion 690 (let* ((index-info (save-excursion
687 (reftex-index-info-safe nil))) 691 (reftex-index-info-safe nil)))
688 (list (member (list 'bof (buffer-file-name)) 692 (list (member
689 docstruct)) 693 (list 'bof (reftex--get-buffer-identifier))
690 (endelt (car (member (list 'eof (buffer-file-name)) 694 docstruct))
691 list))) 695 (endelt
696 (car (member
697 (list 'eof (reftex--get-buffer-identifier))
698 list)))
692 dist last-dist last (n 0)) 699 dist last-dist last (n 0))
693 ;; Check all index entries with equal text 700 ;; Check all index entries with equal text
694 (while (and list (not (eq endelt (car list)))) 701 (while (and list (not (eq endelt (car list))))
@@ -758,12 +765,13 @@ if the information is exact (t) or approximate (nil)."
758 (when (re-search-forward (reftex-everything-regexp) nil t) 765 (when (re-search-forward (reftex-everything-regexp) nil t)
759 (cond 766 (cond
760 ((match-end 1) 767 ((match-end 1)
761 (push (reftex-label-info (reftex-match-string 1) buffer-file-name) 768 (push (reftex-label-info (reftex-match-string 1)
769 (reftex--get-buffer-identifier))
762 (cdr tail))) 770 (cdr tail)))
763 771
764 ((match-end 3) 772 ((match-end 3)
765 (setq star (= ?* (char-after (match-end 3))) 773 (setq star (= ?* (char-after (match-end 3)))
766 entry (reftex-section-info (buffer-file-name)) 774 entry (reftex-section-info (reftex--get-buffer-identifier))
767 level (nth 5 entry)) 775 level (nth 5 entry))
768 ;; Insert the section info 776 ;; Insert the section info
769 (push entry (cdr tail)) 777 (push entry (cdr tail))
@@ -795,7 +803,8 @@ if the information is exact (t) or approximate (nil)."
795 ((match-end 10) 803 ((match-end 10)
796 ;; Index entry 804 ;; Index entry
797 (and reftex-support-index 805 (and reftex-support-index
798 (setq entry (reftex-index-info-safe buffer-file-name)) 806 (setq entry (reftex-index-info-safe
807 (reftex--get-buffer-identifier)))
799 ;; FIXME: (add-to-list 'reftex--index-tags (nth 1 index-entry)) 808 ;; FIXME: (add-to-list 'reftex--index-tags (nth 1 index-entry))
800 (push entry (cdr tail)))))))))) 809 (push entry (cdr tail))))))))))
801 810
diff --git a/lisp/textmodes/reftex-ref.el b/lisp/textmodes/reftex-ref.el
index 30e9968a8e5..8aa34ec942a 100644
--- a/lisp/textmodes/reftex-ref.el
+++ b/lisp/textmodes/reftex-ref.el
@@ -73,8 +73,10 @@ If optional BOUND is an integer, limit backward searches to that point."
73 (file (nth 3 cell)) 73 (file (nth 3 cell))
74 (comment (nth 4 cell)) 74 (comment (nth 4 cell))
75 (note (nth 5 cell)) 75 (note (nth 5 cell))
76 (buf (reftex-get-file-buffer-force 76 (buf (if (bufferp file)
77 file (not (eq t reftex-keep-temporary-buffers))))) 77 file
78 (reftex-get-file-buffer-force
79 file (not (eq t reftex-keep-temporary-buffers))))))
78 (if (not buf) 80 (if (not buf)
79 (list label typekey "" file comment "LOST LABEL. RESCAN TO FIX.") 81 (list label typekey "" file comment "LOST LABEL. RESCAN TO FIX.")
80 (with-current-buffer buf 82 (with-current-buffer buf
@@ -102,7 +104,7 @@ If optional BOUND is an integer, limit backward searches to that point."
102 (let* ((prefix (if (string-match "^[a-zA-Z0-9]+:" label) 104 (let* ((prefix (if (string-match "^[a-zA-Z0-9]+:" label)
103 (match-string 0 label))) 105 (match-string 0 label)))
104 (typekey (cdr (assoc prefix reftex-prefix-to-typekey-alist))) 106 (typekey (cdr (assoc prefix reftex-prefix-to-typekey-alist)))
105 (file (or file (buffer-file-name))) 107 (file (or file (reftex--get-buffer-identifier)))
106 (trust reftex-trust-label-prefix) 108 (trust reftex-trust-label-prefix)
107 (in-comment (reftex-in-comment))) 109 (in-comment (reftex-in-comment)))
108 (if (and typekey 110 (if (and typekey
@@ -249,7 +251,7 @@ This function is controlled by the settings of reftex-insert-label-flags."
249 (note (if (cdr here-I-am-info) 251 (note (if (cdr here-I-am-info)
250 "" 252 ""
251 "POSITION UNCERTAIN. RESCAN TO FIX.")) 253 "POSITION UNCERTAIN. RESCAN TO FIX."))
252 (file (buffer-file-name)) 254 (file (reftex--get-buffer-identifier))
253 ;; (text nil) 255 ;; (text nil)
254 (tail (memq here-I-am (symbol-value reftex-docstruct-symbol)))) 256 (tail (memq here-I-am (symbol-value reftex-docstruct-symbol))))
255 257
@@ -314,19 +316,21 @@ also applies `reftex-translate-to-ascii-function' to the string."
314 (save-match-data 316 (save-match-data
315 (cond 317 (cond
316 ((equal letter "f") 318 ((equal letter "f")
317 (file-name-base (buffer-file-name))) 319 (file-name-base (reftex--get-buffer-identifier)))
318 ((equal letter "F") 320 ((equal letter "F")
319 (let ((masterdir (file-name-directory (reftex-TeX-master-file))) 321 (let ((masterdir (reftex--get-directory
320 (file (file-name-sans-extension (buffer-file-name)))) 322 (reftex-TeX-master-file)))
323 (file (file-name-sans-extension
324 (reftex--get-buffer-identifier))))
321 (if (string-match (concat "\\`" (regexp-quote masterdir)) 325 (if (string-match (concat "\\`" (regexp-quote masterdir))
322 file) 326 file)
323 (substring file (length masterdir)) 327 (substring file (length masterdir))
324 file))) 328 file)))
325 ((equal letter "m") 329 ((equal letter "m")
326 (file-name-base (reftex-TeX-master-file))) 330 (reftex--get-basename (reftex-TeX-master-file)))
327 ((equal letter "M") 331 ((equal letter "M")
328 (file-name-nondirectory 332 (file-name-nondirectory
329 (substring (file-name-directory (reftex-TeX-master-file)) 333 (substring (reftex--get-directory (reftex-TeX-master-file))
330 0 -1))) 334 0 -1)))
331 ((equal letter "u") 335 ((equal letter "u")
332 (or (user-login-name) "")) 336 (or (user-login-name) ""))
@@ -536,7 +540,8 @@ When called with 2 \\[universal-argument] prefix args, disable magic word recogn
536 ;; Offer a menu with the appropriate labels. 540 ;; Offer a menu with the appropriate labels.
537 (let* ((buf (current-buffer)) 541 (let* ((buf (current-buffer))
538 (xr-data (assq 'xr (symbol-value reftex-docstruct-symbol))) 542 (xr-data (assq 'xr (symbol-value reftex-docstruct-symbol)))
539 (xr-alist (cons (cons "" (buffer-file-name)) (nth 1 xr-data))) 543 (xr-alist (cons (cons "" (reftex--get-buffer-identifier))
544 (nth 1 xr-data)))
540 (xr-index 0) 545 (xr-index 0)
541 (here-I-am (car (reftex-where-am-I))) 546 (here-I-am (car (reftex-where-am-I)))
542 (here-I-am1 here-I-am) 547 (here-I-am1 here-I-am)
diff --git a/lisp/textmodes/reftex-sel.el b/lisp/textmodes/reftex-sel.el
index 1f1c74550a5..6e65ad4786c 100644
--- a/lisp/textmodes/reftex-sel.el
+++ b/lisp/textmodes/reftex-sel.el
@@ -234,7 +234,7 @@ During a selection process, these are the local bindings.
234 reftex-active-toc nil 234 reftex-active-toc nil
235 master-dir-re 235 master-dir-re
236 (concat "\\`" (regexp-quote 236 (concat "\\`" (regexp-quote
237 (file-name-directory (reftex-TeX-master-file)))))) 237 (reftex--get-directory (reftex-TeX-master-file))))))
238 238
239 (setq-local reftex-docstruct-symbol docstruct-symbol) 239 (setq-local reftex-docstruct-symbol docstruct-symbol)
240 (setq-local reftex-prefix 240 (setq-local reftex-prefix
diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el
index d8d09da5ed0..2e3be51c87c 100644
--- a/lisp/textmodes/reftex-toc.el
+++ b/lisp/textmodes/reftex-toc.el
@@ -184,14 +184,14 @@ When called with a raw \\[universal-argument] prefix, rescan the document first.
184 184
185 (interactive) 185 (interactive)
186 186
187 (if (or (not (string= reftex-last-toc-master (reftex-TeX-master-file))) 187 (if (or (not (equal reftex-last-toc-master (reftex-TeX-master-file)))
188 ;; FIXME: use (interactive "P") to receive current-prefix-arg as 188 ;; FIXME: use (interactive "P") to receive current-prefix-arg as
189 ;; an argument instead of using the var here, which forces us to set 189 ;; an argument instead of using the var here, which forces us to set
190 ;; current-prefix-arg in the callers. 190 ;; current-prefix-arg in the callers.
191 current-prefix-arg) 191 current-prefix-arg)
192 (reftex-erase-buffer "*toc*")) 192 (reftex-erase-buffer "*toc*"))
193 193
194 (setq reftex-last-toc-file (buffer-file-name)) 194 (setq reftex-last-toc-file (reftex--get-buffer-identifier))
195 (setq reftex-last-toc-master (reftex-TeX-master-file)) 195 (setq reftex-last-toc-master (reftex-TeX-master-file))
196 196
197 (set-marker reftex-toc-return-marker (point)) 197 (set-marker reftex-toc-return-marker (point))
@@ -211,7 +211,8 @@ When called with a raw \\[universal-argument] prefix, rescan the document first.
211 (let* ((this-buf (current-buffer)) 211 (let* ((this-buf (current-buffer))
212 (docstruct-symbol reftex-docstruct-symbol) 212 (docstruct-symbol reftex-docstruct-symbol)
213 (xr-data (assq 'xr (symbol-value reftex-docstruct-symbol))) 213 (xr-data (assq 'xr (symbol-value reftex-docstruct-symbol)))
214 (xr-alist (cons (cons "" (buffer-file-name)) (nth 1 xr-data))) 214 (xr-alist (cons (cons "" (reftex--get-buffer-identifier))
215 (nth 1 xr-data)))
215 (here-I-am (if reftex--rebuilding-toc 216 (here-I-am (if reftex--rebuilding-toc
216 (get 'reftex-toc :reftex-data) 217 (get 'reftex-toc :reftex-data)
217 (car (reftex-where-am-I)))) 218 (car (reftex-where-am-I))))
@@ -261,7 +262,7 @@ When called with a raw \\[universal-argument] prefix, rescan the document first.
261"TABLE-OF-CONTENTS on %s 262"TABLE-OF-CONTENTS on %s
262SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help 263SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help
263------------------------------------------------------------------------------ 264------------------------------------------------------------------------------
264" (abbreviate-file-name reftex-last-toc-master))) 265" (reftex--abbreviate-name reftex-last-toc-master)))
265 266
266 (if reftex-use-fonts 267 (if reftex-use-fonts
267 (put-text-property (point-min) (point) 'font-lock-face reftex-toc-header-face)) 268 (put-text-property (point-min) (point) 'font-lock-face reftex-toc-header-face))
@@ -997,7 +998,7 @@ label prefix determines the wording of a reference."
997 (not (active-minibuffer-window)) 998 (not (active-minibuffer-window))
998 (fboundp 'reftex-toc-mode) 999 (fboundp 'reftex-toc-mode)
999 (get-buffer-window "*toc*" 'visible) 1000 (get-buffer-window "*toc*" 'visible)
1000 (string= reftex-last-toc-master (reftex-TeX-master-file)) 1001 (equal reftex-last-toc-master (reftex-TeX-master-file))
1001 (let (current-prefix-arg) 1002 (let (current-prefix-arg)
1002 (reftex-toc-recenter)))) 1003 (reftex-toc-recenter))))
1003 1004
diff --git a/lisp/textmodes/reftex.el b/lisp/textmodes/reftex.el
index 2dde5232077..0bc20ed46e9 100644
--- a/lisp/textmodes/reftex.el
+++ b/lisp/textmodes/reftex.el
@@ -62,12 +62,6 @@
62 (setq reftex-tables-dirty t) 62 (setq reftex-tables-dirty t)
63 (set symbol value))) 63 (set symbol value)))
64 64
65(defvar reftex--suppress-nonfile-error nil
66 "When non-nil, don't signal error in non-file buffer.
67
68Note that this is just a quick and dirty hack and is _not_ reliable at
69all. It only circumvents disastrous error in `reftex-TeX-master-file',
70in case that the user turns on RefTeX in latex mode hook.")
71 65
72;; Configuration variables 66;; Configuration variables
73(require 'reftex-vars) 67(require 'reftex-vars)
@@ -259,6 +253,52 @@ on the menu bar.
259 253
260;;; ========================================================================= 254;;; =========================================================================
261;;; 255;;;
256;;; Helper functions for handling both file names and buffer objects.
257;;;
258
259(defun reftex--get-buffer-identifier (&optional buffer)
260 "Return the base buffer's file name or buffer identifier.
261For file buffers, returns the file name of the base buffer.
262For non-file buffers, return the base buffer object itself.
263When BUFFER is nil, use the current buffer."
264 (let* ((buffer (or (buffer-base-buffer buffer) buffer (current-buffer))))
265 (or (buffer-local-value 'buffer-file-name buffer)
266 buffer)))
267
268(defun reftex--get-directory (file-or-buffer)
269 "Get the directory associated with FILE-OR-BUFFER.
270FILE-OR-BUFFER can be a file name or a buffer object."
271 (if (bufferp file-or-buffer)
272 (buffer-local-value 'default-directory file-or-buffer)
273 (file-name-directory file-or-buffer)))
274
275(defun reftex--abbreviate-name (file-or-buffer)
276 "Get a nice display name for FILE-OR-BUFFER.
277For files, returns the abbreviated file name.
278For buffers, returns the buffer name."
279 (if (bufferp file-or-buffer)
280 (prin1-to-string file-or-buffer)
281 (abbreviate-file-name file-or-buffer)))
282
283(defun reftex--get-basename (file-or-buffer)
284 "Get the base name (without extension) for FILE-OR-BUFFER.
285For file names, returns the file name without directory and extension.
286For buffer objects, returns a sanitized version of the buffer name
287suitable for use in LaTeX labels."
288 (if (bufferp file-or-buffer)
289 (file-name-base (buffer-name file-or-buffer))
290 (file-name-base file-or-buffer)))
291
292(defun reftex--get-truename (file-or-buffer)
293 "Get the canonical form of FILE-OR-BUFFER's identity.
294For files, returns the result of file-truename.
295For buffer objects, returns the buffer object itself."
296 (if (bufferp file-or-buffer)
297 file-or-buffer
298 (file-truename file-or-buffer)))
299
300;;; =========================================================================
301;;;
262;;; Multibuffer Variables 302;;; Multibuffer Variables
263;;; 303;;;
264;; Technical notes: These work as follows: We keep just one list 304;; Technical notes: These work as follows: We keep just one list
@@ -285,10 +325,16 @@ on the menu bar.
285 ;; Return the next free index for multifile symbols. 325 ;; Return the next free index for multifile symbols.
286 (incf reftex-multifile-index)) 326 (incf reftex-multifile-index))
287 327
328(defun reftex--remove-buffer-from-master-index ()
329 "Remove current buffer from `reftex-master-index-list'."
330 (setq reftex-master-index-list
331 (assq-delete-all (current-buffer) reftex-master-index-list)))
332
288(defun reftex-tie-multifile-symbols () 333(defun reftex-tie-multifile-symbols ()
289 "Tie the buffer-local symbols to globals connected with the master file. 334 "Tie the buffer-local symbols to globals connected with the master file.
290If the symbols for the current master file do not exist, they are created." 335If the symbols for the current master file do not exist, they are created."
291 (let* ((master (file-truename (reftex-TeX-master-file))) 336 (let* ((master (reftex-TeX-master-file))
337 (master (reftex--get-truename master))
292 (index (assoc master reftex-master-index-list)) 338 (index (assoc master reftex-master-index-list))
293 (symlist reftex-multifile-symbols) 339 (symlist reftex-multifile-symbols)
294 symbol symname newflag) 340 symbol symname newflag)
@@ -299,7 +345,11 @@ If the symbols for the current master file do not exist, they are created."
299 ;; Get a new index and add info to the alist. 345 ;; Get a new index and add info to the alist.
300 (setq index (reftex-next-multifile-index) 346 (setq index (reftex-next-multifile-index)
301 newflag t) 347 newflag t)
302 (push (cons master index) reftex-master-index-list)) 348 (push (cons master index) reftex-master-index-list)
349 (when (bufferp master)
350 (with-current-buffer master
351 (add-hook 'kill-buffer-hook
352 #'reftex--remove-buffer-from-master-index nil t))))
303 353
304 ;; Get/create symbols and tie them. 354 ;; Get/create symbols and tie them.
305 (while symlist 355 (while symlist
@@ -332,74 +382,76 @@ If the symbols for the current master file do not exist, they are created."
332 ;; When AUCTeX is loaded, we will use it's more sophisticated method. 382 ;; When AUCTeX is loaded, we will use it's more sophisticated method.
333 ;; We also support the default TeX and LaTeX modes by checking for a 383 ;; We also support the default TeX and LaTeX modes by checking for a
334 ;; variable tex-main-file. 384 ;; variable tex-main-file.
335 (let 385 (with-current-buffer (or (buffer-base-buffer) (current-buffer))
336 ((master 386 (let
337 (cond 387 ;; Set master to a file name (possibly non-existent), or nil:
338 ;; Test if we're in a subfile using the subfiles document 388 ((master
339 ;; class, e.g., \documentclass[main.tex]{subfiles}. It's
340 ;; argument is the main file, however it's not really the
341 ;; master file in `TeX-master-file' or `tex-main-file's
342 ;; sense. It should be used for references but not for
343 ;; compilation, thus subfiles use a setting of
344 ;; `TeX-master'/`tex-main-file' being themselves.
345 ((save-excursion
346 (goto-char (point-min))
347 (re-search-forward
348 "^[[:space:]]*\\\\documentclass\\[\\([^]]+\\)\\]{subfiles}"
349 nil t))
350 (match-string-no-properties 1))
351 ;; AUCTeX is loaded. Use its mechanism.
352 ((fboundp 'TeX-master-file)
353 (condition-case nil
354 (TeX-master-file t)
355 (error (buffer-file-name))))
356 ;; Emacs LaTeX mode
357 ((fboundp 'tex-main-file) (tex-main-file))
358 ;; Check the `TeX-master' variable.
359 ((boundp 'TeX-master)
360 (cond 389 (cond
361 ((eq TeX-master t) 390 ;; Test if we're in a subfile using the subfiles document
362 (buffer-file-name)) 391 ;; class, e.g., \documentclass[main.tex]{subfiles}. It's
363 ((eq TeX-master 'shared) 392 ;; argument is the main file, however it's not really the
364 (setq TeX-master (read-file-name "Master file: " 393 ;; master file in `TeX-master-file' or `tex-main-file's
365 nil nil t nil))) 394 ;; sense. It should be used for references but not for
366 (TeX-master) 395 ;; compilation, thus subfiles use a setting of
396 ;; `TeX-master'/`tex-main-file' being themselves.
397 ((save-excursion
398 (goto-char (point-min))
399 (re-search-forward
400 "^[[:space:]]*\\\\documentclass\\[\\([^]]+\\)\\]{subfiles}"
401 nil t))
402 (match-string-no-properties 1))
403 ;; AUCTeX is loaded. Use its mechanism.
404 ((fboundp 'TeX-master-file)
405 (condition-case nil
406 (TeX-master-file t)
407 (error (buffer-file-name))))
408 ;; Emacs LaTeX mode
409 ((fboundp 'tex-main-file)
410 (condition-case nil
411 (tex-main-file)
412 (error (buffer-file-name))))
413 ;; Check the `TeX-master' variable.
414 ((boundp 'TeX-master)
415 (cond
416 ((eq TeX-master t)
417 (buffer-file-name))
418 ((eq TeX-master 'shared)
419 (setq TeX-master (read-file-name "Master file: "
420 nil nil t nil)))
421 (TeX-master)
422 (t
423 (setq TeX-master (read-file-name "Master file: "
424 nil nil t nil)))))
425 ;; Check the `tex-main-file' variable.
426 ((boundp 'tex-main-file)
427 ;; This is the variable from the default TeX modes.
428 (cond
429 ((stringp tex-main-file)
430 ;; ok, this must be it
431 tex-main-file)
432 (t
433 ;; In this case, the buffer is its own master.
434 (buffer-file-name))))
435 ;; We know nothing about master file. Assume this is a
436 ;; master file.
367 (t 437 (t
368 (setq TeX-master (read-file-name "Master file: " 438 (buffer-file-name)))))
369 nil nil t nil))))) 439 (cond
370 ;; Check the `tex-main-file' variable. 440 ((null master))
371 ((boundp 'tex-main-file) 441 ((or (file-exists-p (concat master ".tex"))
372 ;; This is the variable from the default TeX modes. 442 (find-buffer-visiting (concat master ".tex")))
373 (cond 443 ;; Ahh, an extra .tex was missing...
374 ((stringp tex-main-file) 444 (setq master (concat master ".tex")))
375 ;; ok, this must be it 445 ((or (file-exists-p master)
376 tex-main-file) 446 (find-buffer-visiting master))
377 (t 447 ;; We either see the file, or have a buffer on it. OK.
378 ;; In this case, the buffer is its own master. 448 )
379 (buffer-file-name)))) 449 (t
380 ;; We know nothing about master file. Assume this is a 450 ;; Use buffer file name.
381 ;; master file. 451 (setq master (buffer-file-name))))
382 (t 452 (if master
383 (buffer-file-name))))) 453 (expand-file-name master)
384 (cond 454 (current-buffer)))))
385 ((null master)
386 (or reftex--suppress-nonfile-error
387 (error "Need a filename for this buffer, please save it first")))
388 ((or (file-exists-p (concat master ".tex"))
389 (find-buffer-visiting (concat master ".tex")))
390 ;; Ahh, an extra .tex was missing...
391 (setq master (concat master ".tex")))
392 ((or (file-exists-p master)
393 (find-buffer-visiting master))
394 ;; We either see the file, or have a buffer on it. OK.
395 )
396 (t
397 ;; Use buffer file name.
398 (setq master (buffer-file-name))))
399 (if (and (not master)
400 reftex--suppress-nonfile-error)
401 "<none>.tex"
402 (expand-file-name master))))
403 455
404(defun reftex-is-multi () 456(defun reftex-is-multi ()
405 ;; Tell if this is a multifile document. When not sure, say yes. 457 ;; Tell if this is a multifile document. When not sure, say yes.
@@ -722,7 +774,7 @@ on next use."
722(defun reftex-reset-scanning-information () 774(defun reftex-reset-scanning-information ()
723 "Reset the symbols containing information from buffer scanning. 775 "Reset the symbols containing information from buffer scanning.
724This enforces rescanning the buffer on next use." 776This enforces rescanning the buffer on next use."
725 (if (string= reftex-last-toc-master (reftex-TeX-master-file)) 777 (if (equal reftex-last-toc-master (reftex-TeX-master-file))
726 (reftex-erase-buffer "*toc*")) 778 (reftex-erase-buffer "*toc*"))
727 (let ((symlist reftex-multifile-symbols) 779 (let ((symlist reftex-multifile-symbols)
728 symbol) 780 symbol)
@@ -1115,11 +1167,6 @@ This enforces rescanning the buffer on next use."
1115 ;; But, when RESCAN is -1, don't rescan even if docstruct is empty. 1167 ;; But, when RESCAN is -1, don't rescan even if docstruct is empty.
1116 ;; When FILE is non-nil, parse only from that file. 1168 ;; When FILE is non-nil, parse only from that file.
1117 1169
1118 ;; Error out in a buffer without a file.
1119 (if (and reftex-mode
1120 (not (buffer-file-name)))
1121 (error "RefTeX works only in buffers visiting a file"))
1122
1123 ;; Make sure we have the symbols tied 1170 ;; Make sure we have the symbols tied
1124 (if (eq reftex-docstruct-symbol nil) 1171 (if (eq reftex-docstruct-symbol nil)
1125 ;; Symbols are not yet tied: Tie them. 1172 ;; Symbols are not yet tied: Tie them.
@@ -1167,16 +1214,26 @@ This enforces rescanning the buffer on next use."
1167 1214
1168(defun reftex-access-parse-file (action) 1215(defun reftex-access-parse-file (action)
1169 "Perform ACTION on the parse file (the .rel file). 1216 "Perform ACTION on the parse file (the .rel file).
1170Valid actions are: readable, restore, read, kill, write." 1217Valid actions are: readable, restore, read, kill, write.
1218For non-file buffers, persistence operations are skipped."
1171 (let* ((list (symbol-value reftex-docstruct-symbol)) 1219 (let* ((list (symbol-value reftex-docstruct-symbol))
1172 (docstruct-symbol reftex-docstruct-symbol) 1220 (docstruct-symbol reftex-docstruct-symbol)
1173 (master (reftex-TeX-master-file)) 1221 (master (reftex-TeX-master-file))
1174 (enable-local-variables nil) 1222 (enable-local-variables nil)
1175 (file (if (string-match "\\.[a-zA-Z]+\\'" master) 1223 (non-file (bufferp master))
1176 (concat (substring master 0 (match-beginning 0)) 1224 (file (if non-file
1177 reftex-parse-file-extension) 1225 nil
1178 (concat master reftex-parse-file-extension)))) 1226 (if (string-match "\\.[a-zA-Z]+\\'" master)
1227 (concat (substring master 0 (match-beginning 0))
1228 reftex-parse-file-extension)
1229 (concat master reftex-parse-file-extension)))))
1179 (cond 1230 (cond
1231 ;; For non-file buffers, skip file operations but allow initialization.
1232 (non-file (cond ((eq action 'readable) nil)
1233 ((eq action 'read) nil)
1234 ((eq action 'kill) t)
1235 ((eq action 'restore)
1236 (error "Cannot restore for non-file buffer"))))
1180 ((eq action 'readable) 1237 ((eq action 'readable)
1181 (file-readable-p file)) 1238 (file-readable-p file))
1182 ((eq action 'restore) 1239 ((eq action 'restore)
@@ -1250,7 +1307,9 @@ Valid actions are: readable, restore, read, kill, write."
1250 (let* ((real-master (reftex-TeX-master-file)) 1307 (let* ((real-master (reftex-TeX-master-file))
1251 (parsed-master 1308 (parsed-master
1252 (nth 1 (assq 'bof (symbol-value reftex-docstruct-symbol))))) 1309 (nth 1 (assq 'bof (symbol-value reftex-docstruct-symbol)))))
1253 (unless (string= (file-truename real-master) (file-truename parsed-master)) 1310 ;; Skip this check for buffer objects.
1311 (unless (equal (reftex--get-truename real-master)
1312 (reftex--get-truename parsed-master))
1254 (message "Master file name in load file is different: %s versus %s" 1313 (message "Master file name in load file is different: %s versus %s"
1255 parsed-master real-master) 1314 parsed-master real-master)
1256 (error "Master file name error"))) 1315 (error "Master file name error")))
@@ -1291,7 +1350,7 @@ Valid actions are: readable, restore, read, kill, write."
1291 (mapconcat 1350 (mapconcat
1292 (lambda (x) 1351 (lambda (x)
1293 (format fmt (incf n) (or (car x) "") 1352 (format fmt (incf n) (or (car x) "")
1294 (abbreviate-file-name (cdr x)))) 1353 (reftex--abbreviate-name (cdr x))))
1295 xr-alist "")) 1354 xr-alist ""))
1296 nil t)) 1355 nil t))
1297 (cond 1356 (cond
@@ -1309,8 +1368,11 @@ Valid actions are: readable, restore, read, kill, write."
1309 "Find FILE of type TYPE in MASTER-DIR or on the path associated with TYPE. 1368 "Find FILE of type TYPE in MASTER-DIR or on the path associated with TYPE.
1310If the file does not have any of the valid extensions for TYPE, 1369If the file does not have any of the valid extensions for TYPE,
1311try first the default extension and only then the naked file name. 1370try first the default extension and only then the naked file name.
1312When DIE is non-nil, throw an error if file not found." 1371When DIE is non-nil, throw an error if file not found.
1313 (let* ((rec-values (if reftex-search-unrecursed-path-first '(nil t) '(t))) 1372When FILE is a buffer object, return that buffer."
1373 (if (bufferp file)
1374 file
1375 (let* ((rec-values (if reftex-search-unrecursed-path-first '(nil t) '(t)))
1314 (extensions (cdr (assoc type reftex-file-extensions))) 1376 (extensions (cdr (assoc type reftex-file-extensions)))
1315 (def-ext (car extensions)) 1377 (def-ext (car extensions))
1316 (ext-re (concat "\\(" 1378 (ext-re (concat "\\("
@@ -1345,7 +1407,7 @@ When DIE is non-nil, throw an error if file not found."
1345 (setq file1 (reftex-find-file-on-path f path master-dir))))))) 1407 (setq file1 (reftex-find-file-on-path f path master-dir)))))))
1346 (cond (file1 file1) 1408 (cond (file1 file1)
1347 (die (error "No such file: %s" file) nil) 1409 (die (error "No such file: %s" file) nil)
1348 (t (message "No such file: %s (ignored)" file) nil)))) 1410 (t (message "No such file: %s (ignored)" file) nil)))))
1349 1411
1350(defun reftex-find-file-externally (file type &optional master-dir) 1412(defun reftex-find-file-externally (file type &optional master-dir)
1351 ;; Use external program to find FILE. 1413 ;; Use external program to find FILE.
@@ -1752,7 +1814,9 @@ When DIE is non-nil, throw an error if file not found."
1752 ;; initializations according to `reftex-initialize-temporary-buffers', 1814 ;; initializations according to `reftex-initialize-temporary-buffers',
1753 ;; and mark the buffer to be killed after use. 1815 ;; and mark the buffer to be killed after use.
1754 1816
1755 (let ((buf (find-buffer-visiting file))) 1817 (let ((buf (if (bufferp file)
1818 file
1819 (find-buffer-visiting file))))
1756 1820
1757 (cond (buf 1821 (cond (buf
1758 ;; We have it already as a buffer - just return it 1822 ;; We have it already as a buffer - just return it
diff --git a/test/lisp/textmodes/reftex-tests.el b/test/lisp/textmodes/reftex-tests.el
index 4e5053065cd..3a4d9b1f2e5 100644
--- a/test/lisp/textmodes/reftex-tests.el
+++ b/test/lisp/textmodes/reftex-tests.el
@@ -548,6 +548,329 @@ This is with listings package:
548\\end{document}")) 548\\end{document}"))
549 (kill-buffer (file-name-nondirectory tex-file))))) 549 (kill-buffer (file-name-nondirectory tex-file)))))
550 550
551;;; non-file buffers
552
553(ert-deftest reftex-all-used-citation-keys-buffer ()
554 "Test `reftex-all-used-citation-keys' on a buffer without a file."
555 (with-temp-buffer
556 (insert "\
557\\documentclass{article}
558\\usepackage{biblatex}
559\\begin{document}
560
561Standard commands:
562\\cite[pre][pos]{cite:2022}
563\\Cite[pos]{Cite:2022}
564\\parencite{parencite:2022}
565\\Parencite[pre][]{Parencite:2022}
566\\footcite[][]{footcite:2022}
567\\footcitetext[pre][pos]{footcitetext:2022}
568
569Style specific commands:
570\\textcite{textcite:2022}
571\\Textcite[pos]{Textcite:2022}
572\\smartcite[pre][pos]{smartcite:2022}
573\\Smartcite[pre][]{Smartcite:2022}
574\\cite*[pre][pos]{cite*:2022}
575\\parencite*[][]{parencite*:2022}
576
577Style independent commands:
578\\autocite[pre][pos]{autocite:2022}
579\\autocite*[pos]{autocite*:2022}
580\\Autocite[pre][]{Autocite:2022}
581\\Autocite*{Autocite*:2022}
582
583Text commands:
584\\citeauthor[pre][pos]{citeauthor:2022}
585\\citeauthor*[pre][]{citeauthor*:2022}
586\\Citeauthor[pos]{Citeauthor:2022}
587\\Citeauthor*{Citeauthor*:2022}
588\\citetitle[][]{citetitle:2022}
589\\citetitle*[pre][pos]{citetitle*:2022}
590\\citeyear[pre][pos]{citeyear:2022}
591\\citeyear*[pre][pos]{citeyear*:2022}
592\\citedate[pre][pos]{citedate:2022}
593\\citedate*[pre][pos]{citedate*:2022}
594\\citeurl[pre][pos]{citeurl:2022}
595
596Special commands:
597\\nocite{nocite:2022}
598\\fullcite[pos]{fullcite:2022}
599\\footfullcite[][]{fullfootcite:2022}
600``volcite'' macros have different number of args.
601\\volcite{2}{volcite:2022}
602\\Volcite[pre]{1}{Volcite:2022}
603\\pvolcite{1}[pg]{pvolcite:2022}
604\\Pvolcite[pre]{2}[pg]{Pvolcite:2022}
605\\fvolcite[pre]{3}[pg]{fvolcite:2022}
606\\ftvolcite[pre]{3}[pg]{ftvolcite:2022}
607\\svolcite[pre]{2}[pg]{svolcite:2022}
608\\Svolcite[pre]{4}[pg]{Svolcite:2022}
609\\tvolcite[pre]{5}[pg]{tvolcite:2022}
610\\Tvolcite[pre]{2}[pg]{Tvolcite:2022}
611\\avolcite[pre]{3}[pg]{avolcite:2022}
612\\Avolcite[pre]{1}[pg]{Avolcite:2022}
613\\Notecite[pre]{Notecite:2022}
614\\pnotecite[pre]{pnotecite:2022}
615\\Pnotecite[pre]{Pnotecite:2022}
616\\fnotecite[pre]{fnotecite:2022}
617
618Natbib compatibility commands:
619\\citet{citet:2022}
620\\citet*[pre][pos]{citet*:2022}
621\\citep[pre][pos]{citep:2022}
622\\citep*[pos]{citep*:2022}
623\\citealt[pre][]{citealt:2022}
624\\citealt*[][]{citealt*:2022}
625\\citealp[pre][pos]{citealp:2022}
626\\citealp*{citealp*:2022}
627\\Citet[pre][pos]{Citet:2022}
628\\Citet*[pre][pos]{Citet*:2022}
629\\Citep[pre][pos]{Citep:2022}
630\\Citep*[pre][pos]{Citep*:2022}
631
632Qualified Citation Lists:
633\\cites(Global Prenote)(Global Postnote)[pre][post]{cites:1}[pre][post]{cites:2}
634\\Cites(Global Prenote)(Global Postnote)[pre][post]{Cites:1}[pre][post]{Cites:2}
635\\parencites(Global Prenote)(Global Postnote)[pre][post]{parencites:1}
636 [pre][post]{parencites:2}
637\\Parencites(Global Prenote)(Global Postnote)[pre][post]{Parencites:1}{Parencites:2}
638\\footcites[pre][post]{footcites:1}[pre][post]{footcites:2}
639\\footcitetexts{footcitetexts:1}{footcitetexts:2}
640\\smartcites{smartcites:1}
641% This is comment about \\smartcites{smartcites:2}
642[pre][post]{smartcites:2}
643% And this should be ignored \\smartcites{smartcites:3}{smartcites:4}
644
645
646Test for bug#56655:
647There was a few \\% of increase in budget \\Citep*{bug:56655}.
648
649And this should be % \\cite{ignored}.
650\\end{document}")
651 (tex-mode)
652 (let ((keys (reftex-all-used-citation-keys)))
653 (should (equal (sort keys #'string<)
654 (sort (list
655 ;; Standard commands:
656 "cite:2022" "Cite:2022"
657 "parencite:2022" "Parencite:2022"
658 "footcite:2022" "footcitetext:2022"
659 ;; Style specific commands:
660 "textcite:2022" "Textcite:2022"
661 "smartcite:2022" "Smartcite:2022"
662 "cite*:2022" "parencite*:2022"
663 ;; Style independent commands:
664 "autocite:2022" "autocite*:2022"
665 "Autocite:2022" "Autocite*:2022"
666 ;; Text commands
667 "citeauthor:2022" "citeauthor*:2022"
668 "Citeauthor:2022" "Citeauthor*:2022"
669 "citetitle:2022" "citetitle*:2022"
670 "citeyear:2022" "citeyear*:2022"
671 "citedate:2022" "citedate*:2022"
672 "citeurl:2022"
673 ;; Special commands:
674 "nocite:2022" "fullcite:2022"
675 "fullfootcite:2022"
676 "volcite:2022" "Volcite:2022"
677 "pvolcite:2022" "Pvolcite:2022"
678 "fvolcite:2022" "ftvolcite:2022"
679 "svolcite:2022" "Svolcite:2022"
680 "tvolcite:2022" "Tvolcite:2022"
681 "avolcite:2022" "Avolcite:2022"
682 "Notecite:2022" "pnotecite:2022"
683 "Pnotecite:2022" "fnotecite:2022"
684 ;; Natbib compatibility commands:
685 "citet:2022" "citet*:2022"
686 "citep:2022" "citep*:2022"
687 "citealt:2022" "citealt*:2022"
688 "citealp:2022" "citealp*:2022"
689 "Citet:2022" "Citet*:2022"
690 "Citep:2022" "Citep*:2022"
691 ;; Qualified Citation Lists
692 "cites:1" "cites:2"
693 "Cites:1" "Cites:2"
694 "parencites:1" "parencites:2"
695 "Parencites:1" "Parencites:2"
696 "footcites:1" "footcites:2"
697 "footcitetexts:1" "footcitetexts:2"
698 "smartcites:1" "smartcites:2"
699 "bug:56655")
700 #'string<))))))
701
702(ert-deftest reftex-renumber-simple-labels-buffer ()
703 "Test `reftex-renumber-simple-labels' on a buffer without a file."
704 (let ((temp-buffer (generate-new-buffer " *temp*")))
705 (unwind-protect
706 (with-current-buffer temp-buffer
707 (insert "\
708\\documentclass{article}
709\\usepackage{tcolorbox}
710\\tcbuselibrary{theorems}
711\\usepackage{fancyvrb}
712\\usepackage{listings}
713
714\\begin{document}
715
716This is with tcolorbox package:
717\\begin{problem}[%
718 colback = white ,
719 colframe = red!50!black ,
720 fonttitle = \\bfseries ,
721 description delimiters = {\\flqq}{\\frqq} ,
722 label = {problem:2}]{Prove RH2}{}
723 Problem
724\\end{problem}
725
726This is with vanilla \\LaTeX:
727\\begin{equation}
728 \\label{eq:2}
729 2
730\\end{equation}
731By \\eqref{eq:2} and \\ref{problem:2}
732
733This is with tcolorbox package:
734\\begin{problem}[%
735 colback=white,
736 colframe=red!50!black,
737 fonttitle=\\bfseries,
738 theorem label supplement={hypertarget={XYZ-##1}},
739 theorem full label supplement={code={\\marginnote{##1}}},
740 label={problem:1}]{Prove RH1}{}
741 Problem
742\\end{problem}
743
744This is with vanilla \\LaTeX:
745\\begin{equation}
746 \\label{eq:1}
747 1
748\\end{equation}
749
750\\Cref{problem:1} and \\pageref{eq:1}.
751
752\\begin{problem}[label={problem:6}]{Some Problem}{}
753 Problem
754\\end{problem}
755
756\\Ref{problem:6}.
757
758This is with fancyvrb package:
759\\begin{Verbatim}[reflabel={lst:6}]
760Some Verb Content
761\\end{Verbatim}
762
763\\pageref{lst:6}
764
765This is with listings package:
766\\begin{lstlisting}[language=elisp,caption=Some Caption,label={lst:3}]
767(car (cons 1 '(2)))
768\\end{lstlisting}
769
770\\ref{lst:3}
771
772\\end{document}")
773
774 ;; The label prefix must be known to RefTeX:
775 (add-to-list 'reftex-label-alist
776 '("problem" ?p "problem:" "~\\ref{%s}"
777 nil nil nil)
778 t)
779 (add-to-list 'reftex-label-alist
780 '("Verbatim" ?l "lst:" "~\\ref{%s}"
781 nil nil nil)
782 t)
783 ;; The environments must be known to RefTeX otherwise the labels
784 ;; aren't parsed correctly:
785 (add-to-list 'reftex-label-regexps
786 (concat "\\\\begin{\\(?:problem\\|Verbatim\\)}"
787 "\\[[^][]*"
788 "\\(?:{[^}{]*"
789 "\\(?:{[^}{]*"
790 "\\(?:{[^}{]*}[^}{]*\\)*"
791 "}[^}{]*\\)*"
792 "}[^][]*\\)*"
793 "\\<\\(?:ref\\)?label[[:space:]]*=[[:space:]]*"
794 "{?\\(?1:[^] ,}\r\n\t%]+\\)"
795 "[^]]*\\]")
796 t)
797 ;; Always run this after changing `reftex-label-regexps':
798 (reftex-compile-variables)
799
800 ;; Silence the user query:
801 (cl-letf (((symbol-function 'yes-or-no-p) #'always))
802 (reftex-renumber-simple-labels))
803
804 (should (string= (buffer-string)
805 "\
806\\documentclass{article}
807\\usepackage{tcolorbox}
808\\tcbuselibrary{theorems}
809\\usepackage{fancyvrb}
810\\usepackage{listings}
811
812\\begin{document}
813
814This is with tcolorbox package:
815\\begin{problem}[%
816 colback = white ,
817 colframe = red!50!black ,
818 fonttitle = \\bfseries ,
819 description delimiters = {\\flqq}{\\frqq} ,
820 label = {problem:1}]{Prove RH2}{}
821 Problem
822\\end{problem}
823
824This is with vanilla \\LaTeX:
825\\begin{equation}
826 \\label{eq:1}
827 2
828\\end{equation}
829By \\eqref{eq:1} and \\ref{problem:1}
830
831This is with tcolorbox package:
832\\begin{problem}[%
833 colback=white,
834 colframe=red!50!black,
835 fonttitle=\\bfseries,
836 theorem label supplement={hypertarget={XYZ-##1}},
837 theorem full label supplement={code={\\marginnote{##1}}},
838 label={problem:2}]{Prove RH1}{}
839 Problem
840\\end{problem}
841
842This is with vanilla \\LaTeX:
843\\begin{equation}
844 \\label{eq:2}
845 1
846\\end{equation}
847
848\\Cref{problem:2} and \\pageref{eq:2}.
849
850\\begin{problem}[label={problem:3}]{Some Problem}{}
851 Problem
852\\end{problem}
853
854\\Ref{problem:3}.
855
856This is with fancyvrb package:
857\\begin{Verbatim}[reflabel={lst:1}]
858Some Verb Content
859\\end{Verbatim}
860
861\\pageref{lst:1}
862
863This is with listings package:
864\\begin{lstlisting}[language=elisp,caption=Some Caption,label={lst:2}]
865(car (cons 1 '(2)))
866\\end{lstlisting}
867
868\\ref{lst:2}
869
870\\end{document}")))
871 (kill-buffer temp-buffer))))
872
873
551;;; Autoload tests 874;;; Autoload tests
552 875
553;; Test to check whether reftex autoloading mechanisms are working 876;; Test to check whether reftex autoloading mechanisms are working