From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Mike Mattie Newsgroups: gmane.emacs.help Subject: Re: finding tags files based on location Date: Thu, 28 Feb 2008 00:43:15 -0800 Message-ID: <20080228004315.3dae0ed3@reforged> References: <8433d21a-3b4e-48b1-a88a-f5639d8e2f2d@i7g2000prf.googlegroups.com> <38795075-7c18-4e8e-b9a4-ba42fc3f5119@e6g2000prf.googlegroups.com> <20080227021914.1c54cfd6@reforged> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/H.Irp4yc5wxhQ+bzXdp3zHF"; protocol="application/pgp-signature"; micalg=PGP-SHA1 X-Trace: ger.gmane.org 1204189694 4777 80.91.229.12 (28 Feb 2008 09:08:14 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 28 Feb 2008 09:08:14 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Thu Feb 28 10:08:40 2008 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1JUeko-00071o-Ms for geh-help-gnu-emacs@m.gmane.org; Thu, 28 Feb 2008 10:08:39 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JUekI-00073R-9G for geh-help-gnu-emacs@m.gmane.org; Thu, 28 Feb 2008 04:08:06 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JUek0-00073J-R9 for help-gnu-emacs@gnu.org; Thu, 28 Feb 2008 04:07:48 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JUejz-000737-Tg for help-gnu-emacs@gnu.org; Thu, 28 Feb 2008 04:07:48 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JUejz-000734-Qi for help-gnu-emacs@gnu.org; Thu, 28 Feb 2008 04:07:47 -0500 Original-Received: from mx20.gnu.org ([199.232.41.8]) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1JUejz-0003vZ-DY for help-gnu-emacs@gnu.org; Thu, 28 Feb 2008 04:07:47 -0500 Original-Received: from el-out-1112.google.com ([209.85.162.179]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JUeRI-0007h3-PW for help-gnu-emacs@gnu.org; Thu, 28 Feb 2008 03:48:29 -0500 Original-Received: by el-out-1112.google.com with SMTP id m34so3433416ele.10 for ; Thu, 28 Feb 2008 00:48:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:date:from:to:subject:message-id:in-reply-to:references:x-mailer:mime-version:content-type; bh=OIaJP/rytYxYfardATIduXCYs8HlG6hkahpIl9DZaB8=; b=OmBegqSvzEguc53xkAWfa9qquX6yZlvI6MfElGSN2hn/tz4JzDubhJd8OfBx5NqQH5xBh0IdeaozTttjwBomFtR/ViegMQ77UBj3r5kMe967SMFdOH+6Xu0OGSPFD6bEpyMOk6Gt1BnrhsI7z94tQ4tig0pTmJx7lhFGvcj1GkQ= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:subject:message-id:in-reply-to:references:x-mailer:mime-version:content-type; b=Q+eMOLv/2tZwSpPGhvz/cZksfxXBSy2vmN4kUb90A0R6pRl1EnyLTCqTiWkzPJ/EJsX+P0Dgb4/MKCazE5/cZ5FRpnB3WPzzssOY0i5DV0KS/YRomdspR68CzyzRpwxlQGCdHAbLvrSG/Gk0HReYmR53nI+a9eQxNG+Nb7vav2Q= Original-Received: by 10.115.74.1 with SMTP id b1mr8865294wal.93.1204188497640; Thu, 28 Feb 2008 00:48:17 -0800 (PST) Original-Received: from reforged ( [71.217.206.83]) by mx.google.com with ESMTPS id m29sm14920955poh.3.2008.02.28.00.48.16 (version=SSLv3 cipher=OTHER); Thu, 28 Feb 2008 00:48:17 -0800 (PST) In-Reply-To: X-Mailer: Claws Mail 3.0.2 (GTK+ 2.12.5; i686-pc-linux-gnu) X-detected-kernel: by mx20.gnu.org: Linux 2.4-2.6 (Google crawlbot) X-detected-kernel: by monty-python.gnu.org: Linux 2.6, seldom 2.4 (older, 4) X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:51932 Archived-At: --Sig_/H.Irp4yc5wxhQ+bzXdp3zHF Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable On Wed, 27 Feb 2008 21:49:05 -0700 Kevin Rodgers wrote: > Mike Mattie wrote: > > On Tue, 26 Feb 2008 21:31:28 -0700 > > Kevin Rodgers wrote: > >=20 > >> gamename wrote: > >>> On Feb 25, 8:08 pm, Kevin Rodgers > >>> wrote: > >>>> gamename wrote: > >>>>> I often have to checkout multiple copies of the same source tree > >>>>> from cvs. For example, if I have a source tree 'foo' in cvs, I > >>>>> may have 2 copies like ~/foo0/bar and ~/foo1/bar in my home > >>>>> directory at the same time. Each copy of the foo tree will have > >>>>> a tags file in 'foo/tags'. Does anyone have code that will > >>>>> enable emacs to determine which tags file to use based on the > >>>>> tree i'm currently using? For example, if I'm in foo1/bar, I > >>>>> would be using the tags file in foo1/tags, not foo0/ tags. Is > >>>>> there code to dynamically determine that? > >> >> > >>>> Is it enough to make tags-file-name a buffer local variable, set > >>>> appropriately for each file? If so: > >>>> > >>>> (defun set-local-tags-file-name () > >>>> (when (file-exists-p "tags") > >>>> (set (make-local-variable 'tags-file-name) > >>>> (expand-file-name "tags")))) > >>>> > >>>> (add-hook 'find-file-hook 'set-local-tags-file-name) > >>> Thanks Kevin, but I don't think that scales very well. If I have > >>> thousands of files, that wouldn't be workable. > >> Actually, it scales perfectly well: No matter how many files you > >> have, the hook is only run once for each file that you actually > >> visit. > >> > >> The question is: Does it actually work? I see now that > >> vist-tags-table explicitly provides a way to do the same thing, so > >> perhaps this is better: > >> > >> (defun set-local-tags-file-name () > >> (when (file-exists-p "tags") > >> (visit-tags-table (expand-file-name "tags") t))) > >> > >=20 > > Actually that won't be all that useful as it will scope the tags > > table to the directory of the file, instead of the entire source > > tree. If you use version control alot you can find a good location > > for the tags table by ascending the FS tree looking for the highest > > directory that is writable and under version control. >=20 > Yes, OP mentioned source trees but since the examples given simply had > the tags file in the same directory as the source file, that's what I > presented. My statement was a poor articulation without vital qualification, and sounds harsh besides wrong.=20 My technique of using vc to find a source tree root is opportunistic.=20 Both techniques would be best since placing the tags table in the=20 immediate directory is a sane decision when there is no version control meta-information or other hints that mark the source tree root. Ah, much better. > > The code below will give you a sketch of the algorithm. It's all > > recursive so it will hit the stack limit with valid inputs. But it > > might help you. > >=20 > > If your hook used a global structure that paired the loaded tags > > tables with their directory you could cheaply determine a best > > table from the list to associate with a buffer. >=20 > Why bother generating a global structure, instead of just searching up > the directory tree from the source file towards the root until you > find a tags file? Maybe it's a premature optimization. If a tags table is already loaded i figured it should find the buffer before it started walking the FS with system calls. By creating a index of the tags tables keyed by the path the design treads lightly on the FS. nice for laptop batteries ? Not a big deal overall though. > (defun set-local-tags-file-name (&optional directory) > "Set the buffer's local `tags-file-name' value to the directory's=20 > TAGS file. > If there is no TAGS file in the current directory, search up the > directory tree to the root until a TAGS file is found." > (interactive) > (let ((file (expand-file-name "TAGS" directory))) > (cond ((file-exists-p file) (visit-tags-table file t)) > ((equal directory "/") nil) > (t (set-local-tags-file-name (expand-file-name ".." > directory)))))) >=20 > > If you know the root of the tree it's pretty easy to make up the > > commands to generate the table when it is missing as well. >=20 > Now that's an interesting idea! It would be even slicker if it tried the standard makefile tags targets fir= st. I=20 might resurrect my old tag configuration and rebuild it along these lines. Another good question is the usefulness of pre-loading tags tables. An alwa= ys-load=20 list of TAG table paths might be neat for making libraries searchable by ta= gs tables as well=20 as projects. When run from the initialization hook of a programming mode it= would be quite handy. > > (defun prefix-strings (prefix list) > > "prefix all the strings of the list concatenating the result." > > (mapcar > > (lambda ( string ) > > (concat prefix string)) > > list)) > >=20 > > (defun strip-list-last ( list ) > > "strip the last element from a list" > > (if (consp (cdr list)) > > (cons > > (car list) > > (strip-list-last (cdr list))) > > nil)) > >=20 > > (defun ascend-to-checkout-root ( dir ) > > "The recursive core of find-checkout-root. use that entry point > > instead." (if (and > > (file-accessible-directory-p dir) > > (file-writable-p (concat dir "/_"))) > >=20 > > ;; vc-backend is not robust with inputs. If a directory is > > given without a trailing ;; slash a nil value will be returned > > incorrectly for directories under version ;; control. > >=20 > > (if (vc-backend dir) > > (lexical-let > > ((traverse (strip-list-last (split-string dir "/" t)))) > >=20 > > (if traverse > > (lexical-let > > ((found (ascend-to-checkout-root (prefix-strings "/" > > traverse)))) (if (eq 't found) > > dir > > found)) > > t)) ;; halt when list is exhausted > > t) ;; halt when the directory is no longer under > > version control. t)) ;; halt when we don't have read and > > write permission for the directory. > >=20 > > (defun find-checkout-root ( dir ) > > "Find the ancestor directory that is the root of the checkout > > containing DIR. > >=20 > > Recursion halts on these conditions: > > * exhausted path. > > * directory is not: accesible,readable, and writable. > > * directory is not under version control according to vc-backend. > > " > > (lexical-let > > ((found (ascend-to-checkout-root dir))) > > (if (eq 't found) > > dir > > found))) >=20 >=20 >=20 >=20 --Sig_/H.Irp4yc5wxhQ+bzXdp3zHF Content-Type: application/pgp-signature; name=signature.asc Content-Disposition: attachment; filename=signature.asc -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHxnQjdfRchrkBInkRAu+RAKCLHenqW6Mx/3dmN4TyhjWsLyT0UACg7q6b H7nCruMaNlZETR9Q67irWVk= =hLpK -----END PGP SIGNATURE----- --Sig_/H.Irp4yc5wxhQ+bzXdp3zHF--