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
next prev parent 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).