emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Integrating ctags & org mode (patch)
@ 2009-12-15  3:02 Paul Sexton
  2009-12-15  3:41 ` Bill Powell
  2009-12-15  7:20 ` Carsten Dominik
  0 siblings, 2 replies; 11+ messages in thread
From: Paul Sexton @ 2009-12-15  3:02 UTC (permalink / raw)
  To: emacs-orgmode

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)----

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Integrating ctags & org mode (patch)
  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
  1 sibling, 0 replies; 11+ messages in thread
From: Bill Powell @ 2009-12-15  3:41 UTC (permalink / raw)
  To: Paul Sexton; +Cc: emacs-orgmode

At Tue, 15 Dec 2009 03:02:12 +0000 (UTC),
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. 

Wow! This looks really great. Thanks!

Bill Powell

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Integrating ctags & org mode (patch)
  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
  2009-12-15 19:58   ` Paul Sexton
  1 sibling, 2 replies; 11+ messages in thread
From: Carsten Dominik @ 2009-12-15  7:20 UTC (permalink / raw)
  To: Paul Sexton; +Cc: emacs-orgmode

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

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Integrating ctags & org mode (patch)
  2009-12-15  7:20 ` Carsten Dominik
@ 2009-12-15 14:29   ` Carsten Dominik
  2009-12-15 19:58   ` Paul Sexton
  1 sibling, 0 replies; 11+ messages in thread
From: Carsten Dominik @ 2009-12-15 14:29 UTC (permalink / raw)
  To: Carsten Dominik; +Cc: emacs-orgmode, Paul Sexton


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

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Integrating ctags & org mode (patch)
  2009-12-15  7:20 ` Carsten Dominik
  2009-12-15 14:29   ` Carsten Dominik
@ 2009-12-15 19:58   ` Paul Sexton
  2009-12-15 20:36     ` Paul Sexton
  1 sibling, 1 reply; 11+ messages in thread
From: Paul Sexton @ 2009-12-15 19:58 UTC (permalink / raw)
  To: emacs-orgmode

Carsten Dominik <carsten.dominik <at> gmail.com> writes:

> 
> 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.
> 


I'm glad you like it. I would be happy for it to be included in the core.

Re your followup to this post: I have written a function which takes a tag name
and returns the file where it is found:


(defun get-filename-for-tag (tag)
  "TAG is a string. Search the active TAGS file for a matching tag,
and if found, return a list containing the filename, line number, and
buffer position where the tag is found."
  (unless tags-file-name
    (visit-tags-file-buffer))
  (with-current-buffer (get-file-buffer tags-file-name)
    (beginning-of-buffer)
    (cond
     ;; In the following line, the special characters on either side of
     ;; the %s should be ASCII 127 (^?) and ASCII 1 (^A)
     ((re-search-forward (format "^.*\x7f%s\x01\\([0-9]+\\),\\([0-9]+\\)$"
                                 (regexp-quote tag)) nil t)
      (let ((line (string-to-number (match-string 1)))
            (pos (string-to-number (match-string 2))))
        (cond
         ((re-search-backward "\f\n\\(.*\\),[0-9]+\n")
          (list (match-string 1) line pos))
         (t  ; can't find a file name preceding the matched tag??
          (error "Malformed TAGS file: %s" (buffer-name))))))
      (t  ; tag not found
       nil))))

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Integrating ctags & org mode (patch)
  2009-12-15 19:58   ` Paul Sexton
@ 2009-12-15 20:36     ` Paul Sexton
  2009-12-15 21:08       ` Paul Sexton
  0 siblings, 1 reply; 11+ messages in thread
From: Paul Sexton @ 2009-12-15 20:36 UTC (permalink / raw)
  To: emacs-orgmode

Also I realised there was a misplaced parenthesis in the "(if (y-or-n-p..."
clause. Corrected patch follows.

----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)----

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Integrating ctags & org mode (patch)
  2009-12-15 20:36     ` Paul Sexton
@ 2009-12-15 21:08       ` Paul Sexton
  2009-12-15 21:33         ` Nick Dokos
  2009-12-18 16:00         ` Carsten Dominik
  0 siblings, 2 replies; 11+ messages in thread
From: Paul Sexton @ 2009-12-15 21:08 UTC (permalink / raw)
  To: emacs-orgmode

Sorry guys, I seem to be spamming this topic, but I just fixed another problem
-- properties on the link string were causing problems with find-tag, which
expected a propertyless string.

Fixed patch follows.

----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
{                    (let ((linktext path))
{                      (set-text-properties 0 (length linktext)
{                                           nil linktext)
{                      (condition-case nil (find-tag linktext)
{                        (error
{                         (cond
{                          (org-make-new-topics-for-missing-links-p
{                           (if (y-or-n-p
{                                (format "Topic `%S' not found; append to
current buffer?"
{                                        linktext))
{                               (org-append-new-topic linktext 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)----

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Re: Integrating ctags & org mode (patch)
  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
  1 sibling, 1 reply; 11+ messages in thread
From: Nick Dokos @ 2009-12-15 21:33 UTC (permalink / raw)
  To: Paul Sexton; +Cc: emacs-orgmode

Paul,

Can these patches be applied using the standard patch(1) command?
I tried and I get 

$ patch < ~/Mail/inbox/1265
patch: **** Only garbage was found in the patch input.

If they cannot be applied that way, can you please provide them in a
more standard format?  Unified diff format is probably the best:

     diff -u file.orig file.modified

Thanks,
Nick

PS. Not sure what to do if you are on Windows, however.


Paul Sexton <psexton@xnet.co.nz> wrote:

> Sorry guys, I seem to be spamming this topic, but I just fixed another problem
> -- properties on the link string were causing problems with find-tag, which
> expected a propertyless string.
> 
> Fixed patch follows.
> 
> ----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
> {                    (let ((linktext path))
> {                      (set-text-properties 0 (length linktext)
> {                                           nil linktext)
> {                      (condition-case nil (find-tag linktext)
> {                        (error
> {                         (cond
> {                          (org-make-new-topics-for-missing-links-p
> {                           (if (y-or-n-p
> {                                (format "Topic `%S' not found; append to
> current buffer?"
> {                                        linktext))
> {                               (org-append-new-topic linktext 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)----
> 
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Integrating ctags & org mode (patch)
  2009-12-15 21:33         ` Nick Dokos
@ 2009-12-15 22:06           ` Óscar Fuentes
  0 siblings, 0 replies; 11+ messages in thread
From: Óscar Fuentes @ 2009-12-15 22:06 UTC (permalink / raw)
  To: emacs-orgmode

Nick Dokos <nicholas.dokos@hp.com> writes:

> Can these patches be applied using the standard patch(1) command?
> I tried and I get 
>
> $ patch < ~/Mail/inbox/1265
> patch: **** Only garbage was found in the patch input.

You have to replace `{' with `>' and `}' with `<' in the patch before
applying it.

> If they cannot be applied that way, can you please provide them in a
> more standard format?  Unified diff format is probably the best:
>
>      diff -u file.orig file.modified

The problem the OP has is with the web form he uses for sending the
messages.

-- 
Óscar

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Re: Integrating ctags & org mode (patch)
  2009-12-15 21:08       ` Paul Sexton
  2009-12-15 21:33         ` Nick Dokos
@ 2009-12-18 16:00         ` Carsten Dominik
  2010-02-06  0:10           ` Samuel Wales
  1 sibling, 1 reply; 11+ messages in thread
From: Carsten Dominik @ 2009-12-18 16:00 UTC (permalink / raw)
  To: Paul Sexton; +Cc: emacs-orgmode

Hi Paul,

I have now made a new hook `org-open-link-functions'.
Each function in this hook will be called with the link text as the  
single
argument.  If the function feels responsible for this link, it should
follow the link and return a non-nil value.  If it does not feel
responsible for the link, it should return nil.

Can I persuade you to change your implementation to use this hook
instead of a patch modifying org.el?  The we could wrap this
functionality into org-etags.el and include it with Emacs.

Could you please at the same time start the paperwork with Emacs?
To see how, follow the link near the end of http://orgmode.org

Thanks

- Carsten

P.S.  Actually, before getting to work on this, maybe you should wait
for the discussion just started in another thread.


On Dec 15, 2009, at 10:08 PM, Paul Sexton wrote:

> Sorry guys, I seem to be spamming this topic, but I just fixed  
> another problem
> -- properties on the link string were causing problems with find- 
> tag, which
> expected a propertyless string.
>
> Fixed patch follows.
>
> ----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
> {                    (let ((linktext path))
> {                      (set-text-properties 0 (length linktext)
> {                                           nil linktext)
> {                      (condition-case nil (find-tag linktext)
> {                        (error
> {                         (cond
> {                          (org-make-new-topics-for-missing-links-p
> {                           (if (y-or-n-p
> {                                (format "Topic `%S' not found;  
> append to
> current buffer?"
> {                                        linktext))
> {                               (org-append-new-topic linktext 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

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Re: Integrating ctags & org mode (patch)
  2009-12-18 16:00         ` Carsten Dominik
@ 2010-02-06  0:10           ` Samuel Wales
  0 siblings, 0 replies; 11+ messages in thread
From: Samuel Wales @ 2010-02-06  0:10 UTC (permalink / raw)
  To: Carsten Dominik; +Cc: emacs-orgmode, Paul Sexton

Hi Paul,

I think I haven't been following this closely enough, because I don't
understand why an external program is necessary for <<targets>>.  Can
you just have a variable to hold the files that need searching?

Then use the existing org ID mechanism.  The targets would hold org IDs.

I realize it would have been better to suggest this earlier (actually
I did, but many months earlier :)).

Samuel

-- 
Q: How many CDC "scientists" does it take to change a lightbulb?
A: You only think it's dark. [CDC has denied ME/CFS for 25 years]
=================================================================
Retrovirus: http://www.wpinstitute.org/xmrv/xmrv_qa.html

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2010-02-06  0:10 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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).