[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Etags completion problem for local tags table
From: |
Radey Shouman |
Subject: |
Re: Etags completion problem for local tags table |
Date: |
24 Apr 2008 15:03:19 -0400 |
Radey Shouman <shouman@comcast.net> writes:
> In (at least) emacs 22.1, completing reads for find-tag and list-tags
> will use the global tags table list even if a local tags file has
> been specified using a prefix argument for visit-tags-table.
>
> To reproduce, visit two files, in the first buffer visit a tags file
> globally, in the second a different tags file locally. From the
> second buffer, try M.[TAB] . The tag list displayed will correspond
> to the first, globally visited, tags file.
The patch presented earlier had problems - the root issue is that
variables tags-file-name and tags-table-list are used for returning
information from functions which may change the current buffer.
One manifestation of the problem can be seen by setting a local tags
file using C-uM-x visit-tags-table twice in the same buffer. The
second attempt will fail to set a local tags table, but will set the
global tags table.
This patch also modifies visit-tags-table so that it will remove a
local tags table if present in the buffer in which it is called to set
a global tags table. This is arguably not a bug fix, but seems much
less suprising than the current behavior.
*** etags.el.dist 2007-01-21 03:20:46.000000000 -0500
--- etags.el 2008-04-24 09:57:37.660821100 -0400
***************
*** 257,262 ****
--- 257,264 ----
"Function to do the work of `tags-included-tables' (which see).")
(defvar verify-tags-table-function nil
"Function to return t iff current buffer contains valid tags file.")
+ (defvar etags-calling-buffer nil
+ "Buffer from which a completing read was made, so we can determine the
appropriate tags file to visit.")
;; Initialize the tags table in the current buffer.
;; Returns non-nil iff it is a valid tags table. On
***************
*** 305,323 ****
;; Calling visit-tags-table-buffer with tags-file-name set to FILE will
;; initialize a buffer for FILE and set tags-file-name to the
;; fully-expanded name.
! (let ((tags-file-name file))
(save-excursion
(or (visit-tags-table-buffer file)
(signal 'file-error (list "Visiting tags table"
"file does not exist"
! file)))
! ;; Set FILE to the expanded name.
! (setq file tags-file-name)))
(if local
;; Set the local value of tags-file-name.
(set (make-local-variable 'tags-file-name) file)
;; Set the global value of tags-file-name.
! (setq-default tags-file-name file)))
(defun tags-table-check-computed-list ()
"Compute `tags-table-computed-list' from `tags-table-list' if necessary."
--- 307,335 ----
;; Calling visit-tags-table-buffer with tags-file-name set to FILE will
;; initialize a buffer for FILE and set tags-file-name to the
;; fully-expanded name.
! (let (table-list)
! (let ((tags-file-name file)
! (tags-table-list tags-table-list))
(save-excursion
(or (visit-tags-table-buffer file)
(signal 'file-error (list "Visiting tags table"
"file does not exist"
! file))))
! ;; Set FILE to the expanded name. Note that we have to do this from
the original
! ;; buffer, in case tags-file-name or tags-table-list are buffer-local.
! (setq file tags-file-name
! table-list tags-table-list))
!
(if local
;; Set the local value of tags-file-name.
+ (progn
(set (make-local-variable 'tags-file-name) file)
+ (set (make-local-variable 'tags-table-list) table-list))
;; Set the global value of tags-file-name.
! (kill-local-variable 'tags-file-name)
! (kill-local-variable 'tags-table-list)
! (setq tags-file-name file
! tags-table-list table-list))))
(defun tags-table-check-computed-list ()
"Compute `tags-table-computed-list' from `tags-table-list' if necessary."
***************
*** 444,459 ****
(revert-buffer t t)
(tags-table-mode)))
(and (file-exists-p file)
! (progn
(set-buffer (find-file-noselect file))
(or (string= file buffer-file-name)
;; find-file-noselect has changed the file name.
;; Propagate the change to tags-file-name and tags-table-list.
(let ((tail (member file tags-table-list)))
(if tail
(setcar tail buffer-file-name))
(if (eq file tags-file-name)
! (setq tags-file-name buffer-file-name))))
(tags-table-mode)))))
;; Subroutine of visit-tags-table-buffer. Search the current tags tables
--- 456,475 ----
(revert-buffer t t)
(tags-table-mode)))
(and (file-exists-p file)
! (let ((obuf (current-buffer)))
(set-buffer (find-file-noselect file))
(or (string= file buffer-file-name)
;; find-file-noselect has changed the file name.
;; Propagate the change to tags-file-name and tags-table-list.
+ ;; We have to do this in the buffer current when we were called
+ ;; because tags-table-list and tags-file-name may be buffer
local.
+ (save-excursion
+ (set-buffer obuf)
(let ((tail (member file tags-table-list)))
(if tail
(setcar tail buffer-file-name))
(if (eq file tags-file-name)
! (setq tags-file-name buffer-file-name)))))
(tags-table-mode)))))
;; Subroutine of visit-tags-table-buffer. Search the current tags tables
***************
*** 538,543 ****
--- 554,564 ----
`tags-file-name', `tags-table-list', `tags-table-list-pointer'.
Returns t if it visits a tags table, or nil if there are no more in the list."
+ ;; We may be called from a minibuffer if invoked during completion.
+ ;; this can be a problem when the tags tables are buffer-local.
+ (if etags-calling-buffer
+ (set-buffer etags-calling-buffer))
+
;; Set tags-file-name to the tags table file we want to visit.
(cond ((eq cont 'same)
;; Use the ambient value of tags-file-name.
***************
*** 781,787 ****
;; Read a tag name from the minibuffer with defaulting and completion.
(defun find-tag-tag (string)
! (let* ((completion-ignore-case (if (memq tags-case-fold-search '(t nil))
tags-case-fold-search
case-fold-search))
(default (funcall (or find-tag-default-function
--- 802,809 ----
;; Read a tag name from the minibuffer with defaulting and completion.
(defun find-tag-tag (string)
! (let* ((etags-calling-buffer (current-buffer))
! (completion-ignore-case (if (memq tags-case-fold-search '(t nil))
tags-case-fold-search
case-fold-search))
(default (funcall (or find-tag-default-function