emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Carsten Dominik <dominik@uva.nl>
To: Carsten Dominik <carsten.dominik@gmail.com>
Cc: emacs-orgmode@gnu.org, Paul Sexton <psexton@xnet.co.nz>
Subject: Re: Integrating ctags & org mode (patch)
Date: Tue, 15 Dec 2009 15:29:07 +0100	[thread overview]
Message-ID: <CA82A55B-3BB3-4B8F-AD8C-4B43EE1D58D7@uva.nl> (raw)
In-Reply-To: <2AC5C31A-0ABA-4163-9F4F-9F0D26A6F538@gmail.com>


Another issue is the following:  How should we handle
export of such links?  Maybe we need another function that does
not *jump* to the link location, but just returns the file in
which the target is, so that the exporters can make use of this?

- Carsten


On Dec 15, 2009, at 8:20 AM, Carsten Dominik wrote:

> 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  
>> <<like this>> 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 "<M-kp-multiply>") '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 <<double angle  
>> brackets>>.
>> (triple angle brackets work too)
>>
>> When you click on a link "[[foo]]" and org cannot find a matching  
>> "<<foo>>" in
>> the current buffer, the tags facility will take over. The file TAGS  
>> is examined
>> to see if the tags facility knows about "<<foo>>" in any other  
>> files. If it
>> does, the matching file will be opened and the cursor will jump to  
>> the position
>> of "<<foo>>" 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 <<link
>> 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
>
>
>

- Carsten

  reply	other threads:[~2009-12-15 14:29 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-15  3:02 Integrating ctags & org mode (patch) Paul Sexton
2009-12-15  3:41 ` Bill Powell
2009-12-15  7:20 ` Carsten Dominik
2009-12-15 14:29   ` Carsten Dominik [this message]
2009-12-15 19:58   ` Paul Sexton
2009-12-15 20:36     ` Paul Sexton
2009-12-15 21:08       ` Paul Sexton
2009-12-15 21:33         ` Nick Dokos
2009-12-15 22:06           ` Óscar Fuentes
2009-12-18 16:00         ` Carsten Dominik
2010-02-06  0:10           ` Samuel Wales

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CA82A55B-3BB3-4B8F-AD8C-4B43EE1D58D7@uva.nl \
    --to=dominik@uva.nl \
    --cc=carsten.dominik@gmail.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=psexton@xnet.co.nz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).