From mboxrd@z Thu Jan 1 00:00:00 1970 From: Carsten Dominik Subject: Re: Integrating ctags & org mode (patch) Date: Tue, 15 Dec 2009 08:20:54 +0100 Message-ID: <2AC5C31A-0ABA-4163-9F4F-9F0D26A6F538@gmail.com> References: Mime-Version: 1.0 (Apple Message framework v936) Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NKSFX-0003gc-W5 for emacs-orgmode@gnu.org; Tue, 15 Dec 2009 02:55:16 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NKSFT-0003co-1Z for emacs-orgmode@gnu.org; Tue, 15 Dec 2009 02:55:15 -0500 Received: from [199.232.76.173] (port=48662 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NKSFS-0003cl-UB for emacs-orgmode@gnu.org; Tue, 15 Dec 2009 02:55:10 -0500 Received: from mx20.gnu.org ([199.232.41.8]:52531) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NKSFR-0008JC-HZ for emacs-orgmode@gnu.org; Tue, 15 Dec 2009 02:55:10 -0500 Received: from mail-ew0-f224.google.com ([209.85.219.224]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NKSFP-0005aF-SP for emacs-orgmode@gnu.org; Tue, 15 Dec 2009 02:55:08 -0500 Received: by ewy24 with SMTP id 24so4423752ewy.26 for ; Mon, 14 Dec 2009 23:55:06 -0800 (PST) In-Reply-To: List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Paul Sexton Cc: emacs-orgmode@gnu.org Hi Paul, I like this very much. But I would like to change the implementation so that there will be a hook. Then people can do different things, including matching tags in source code files etc. Would you be interested to turn your way of doing things into a little add-on that people could load? I realize that it would be a very small file because the heavy lifting is done by the tags creating file and Emacs ctags searches. But it would keep the way open for other ideas. If you agree I will make a new hook and interface for this. I would be very interested to include the new module (if you write it) at least as a contributed package, or, if you are willing to sign the papers with the FSF, in the core. - Carsten On Dec 15, 2009, at 4:02 AM, Paul Sexton wrote: > Hi, > > I have managed to get exuberant ctags working with org mode. This > means that > plain links [[like this]], instead of defaulting to plain text > search when no > match is found in the current file, now look for a matching tag > <> in > all your *.org files, and jumps there. > > This means your org files all now "seamlessly" talk to each other > and interlink. > You can split that monolithic file up into smaller files and the > plain links > still work. You can throw a plain link to a topic you know exists in > another > file, without having to worry about the format of special inter-file > links, > whether you got the directory right, and so on. > > Steps: > > 1. First you need a small patch to org.el. This is necessary because > AFAIK there > is no easy way to customise or advise org's behaviour when opening a > plain link. > The patch is at the end of this post. > > 2. Next you need to get exuberant ctags from http://ctags.sourceforge.net/ > There is a windows executable there (a zip file). Many linux > distributions have > 'ctags-exuberant' as an installable package in their repositories. > > If you are using windows, extract the ctags.zip file into a > directory somewhere, > eg C:\emacs23\ctags > > 3. Now make a new file called .ctags in your HOME directory. If you > are not sure > where this is, evaluate (getenv "HOME") in the emacs scratch buffer. > > Put the following 3 lines into this file, then save it: > > --langdef=orgmode > --langmap=orgmode:.org > --regex-orgmode=/<<([^>]+)>>/\1/d,definition/ > > The last line is a regular expression that defines what a tag is in > orgmode. If > you don't like my definition based on angle brackets, or you want to > add other > destinations as tags, just alter the bit between the first > two /...slashes.../ > > 4. Paste the following into your .emacs file: > > (defvar home-dir "/home/paul/") ; replace with your home dir > > (defun operating-system () > (case system-type > ((windows-nt cygwin) 'windows) > (darwin 'macos) > (otherwise 'unix))) > > (defvar path-to-ctags > (case (operating-system) > (windows "c:/emacs/ctags/ctags.exe") ; or whereever you > extracted it > (unix "/usr/bin/ctags-exuberant")) ; wherever it went > "Path to the CTAGS executable.") > > (defun create-tags (dir-name) > "Create tags file." > (interactive "DBase directory: ") > (shell-command > (format "%s --options=%s/.ctags -f %s/TAGS -e -R %s/*" > path-to-ctags home-dir dir-name dir-name))) > > (global-set-key (kbd "") 'pop-tag-mark) > > (defadvice find-tag (before set-org-mark-before-finding-tag > activate compile) > "Before trying to find a tag, save our current position on org mark > ring." > (save-excursion > (if (org-mode-p) > (org-mark-ring-push)))) > > 5. Now run create-tags: > > M-x create-tags ENTER "/path/to/org/files/" ENTER > > create-tags searches all subdirectories as well, and will also > create tags for > all source code files that if finds (*.c, *.lisp, *.el, etc). All > these tags > will go in one big TAGS file, located in the "base" directory that > you specify > as an argument to create-tags. Thus, if you have any large source > trees in > subdirectories, create-tags may pause for a few seconds. > > 6. Check that the file 'TAGS' is in the right place and is not an > empty file. > > Tags is now ready to use. See below for usage. The first time you > try and find > a tag, you will be asked which tags file to use. The right answer is > the file > named TAGS which you created with create-tags. > To avoid being asked this every time you restart emacs, try putting > this in your > .emacs: > > (add-hook 'org-mode-hook > (lambda () (visit-tags-table "/path/to/TAGSfile") > > Tags are defined in the .ctags file as any text in < brackets>>. > (triple angle brackets work too) > > When you click on a link "[[foo]]" and org cannot find a matching > "<>" in > the current buffer, the tags facility will take over. The file TAGS > is examined > to see if the tags facility knows about "<>" in any other > files. If it > does, the matching file will be opened and the cursor will jump to > the position > of "<>" in that file. > > Important commands: > * M-. > Press to enter a tag name (default is a string extracted from the > current cursor position) and then try & jump there. No > autocompletion yet. > * C-M-. > as above, but search term is a regular expression > * M-x tags-search > Also searches for a regexp, but searches through the *entire text* of > all the files that the tags facility knows about. Jumps to the > first match. > Then, press M-, to jump to each successive match. > * M-* "go back" from a tag jump. (note: if you jumped from an org- > mode buffer, > your previous position will also have been saved on the org mark > ring). > > Tags mode has no way of knowing when you create new tags. So, any > new < targets>> you make after running create-tags will not be in the > 'TAGS' file & so > will be unknown to the tags facility. For new tags to make it into > the TAGS > file, you need to re-run (create-tags "path") to refresh the file. > > You also might want to put (create-tags "/path/to/org/files") in > your .emacs or > even "ctags-exuberant -e -R /path/to/org/ &" in your .bashrc or > equivalent. > > There is probably a clever way to re-run create-tags at sensible > times eg when > saving an org file, but I haven't looked into it. > > Also if someone clever wants to enable tabbed completion when > prompted for a tag > name with find-tag: please feel free. > > There are other tags programs that interface with emacs, for example > GNU Global. > However I believe that to write parsers for new languages like > orgmode, you have > to write them in C for most of the other tags programs. With > exuberant ctags > it's just a matter of writing a regular expression. > > Hope some people find this helpful. > > Here is the patch. Sadly the dumb gmane web interface thingy forced > me to change > all '<' to '{' and '>' to '}' before I could post this, as it > accused me of top > posting. You will therefore need to change them all back. > > ----BEGIN PATCH for org.el (delete this line)---- > 8349,8369c8349,8350 > { (condition-case nil (eval cmd) > { ;; ORG-TAGS > { (error > { (progn > { (widen) > { (condition-case nil (eval cmd) > { (error > { ;; No matching link found anywhere in this file > { ;; See if we can find a tag > { ;; If so, jump to it > { (condition-case nil (find-tag path) > { (error > { (cond > { (org-make-new-topics-for-missing-links-p > { (if (y-or-n-p > { (format "Topic `%S' not found; > append to current > buffer?" > { path))) > { (org-append-new-topic path nil)) > { (t > { (error "No match found")))))))))))) > { > --- > } (condition-case nil (eval cmd) > } (error (progn (widen) (eval cmd)))))) > 8592,8595d8572 > { ;; ORG-TAGS > { ((not org-open-link-defaults-to-normal-string-search-p) > { ;; We don't want to search for a plain text match. > { (error "No match.")) > 8651,8682d8627 > { > { > { ;; ORG-TAGS > { > { (defvar org-open-link-defaults-to-normal-string-search-p nil > { "Behaviour when attempting to open a 'thisfile' hyperlink for > which no > { EXACT match can be found (i.e. no match in angled brackets, etc). > { If true (default), exhibit normal org behaviour of doing a search > for a string > { matching the link name. > { If nil, abort the attempt to open the link.") > { > { > { (defvar org-make-new-topics-for-missing-links-p nil > { "If true, when attempting to follow a 'plain' hyperlink for > which no precise > { match is found, offer to append a top-level heading with the same > name as the > { hyperlink, to the end of the buffer.") > { > { > { (defun org-append-new-topic (word) > { (interactive "s") > { (widen) > { (end-of-buffer) > { (newline 2) > { (insert (format "* <<%s>>" word)) ; <<<>>> to make radio word > { (backward-char 4) > { ;;(org-update-radio-target-regexp) > { (end-of-line) > { (newline 2) > { (next-line 2)) > { > { > { > ----END PATCH (delete this line)---- > > > > > _______________________________________________ > Emacs-orgmode mailing list > Please use `Reply All' to send replies to the list. > Emacs-orgmode@gnu.org > http://lists.gnu.org/mailman/listinfo/emacs-orgmode - Carsten