X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/6e104790e756226cbb5b7feaf01854103ded9f36..0e963201d03d9229bb8ac4323291d2b0119526ed:/lisp/org/org-ctags.el diff --git a/lisp/org/org-ctags.el b/lisp/org/org-ctags.el index 3a2a57ad30..ea4f52b586 100644 --- a/lisp/org/org-ctags.el +++ b/lisp/org/org-ctags.el @@ -1,12 +1,11 @@ ;;; org-ctags.el - Integrate Emacs "tags" facility with org mode. -;;; -;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +;; +;; Copyright (C) 2007-2016 Free Software Foundation, Inc. + +;; Author: Paul Sexton -;;; Author: Paul Sexton -;;; Version: 1.0 ;; Keywords: org, wp -;; Version: 6.35i ;; ;; This file is part of GNU Emacs. ;; @@ -23,120 +22,125 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . -;;; -;;; Synopsis -;;; ======== -;;; -;;; Allows org-mode to make use of the Emacs `etags' system. Defines tag -;;; destinations in org-mode files as any text between <>. This allows the tags-generation program `exuberant ctags' to -;;; parse these files and create tag tables that record where these -;;; destinations are found. Plain [[links]] in org mode files which do not have -;;; <> within the same file will then be interpreted as -;;; links to these 'tagged' destinations, allowing seamless navigation between -;;; multiple org-mode files. Topics can be created in any org mode file and -;;; will always be found by plain links from other files. Other file types -;;; recognised by ctags (source code files, latex files, etc) will also be -;;; available as destinations for plain links, and similarly, org-mode links -;;; will be available as tags from source files. Finally, the function -;;; `org-ctags-find-tag-interactive' lets you choose any known tag, using -;;; autocompletion, and quickly jump to it. -;;; -;;; Installation -;;; ============ -;;; -;;; Install org mode -;;; Ensure org-ctags.el is somewhere in your emacs load path. -;;; Download and install Exuberant ctags -- "http://ctags.sourceforge.net/" -;;; Edit your .emacs file (see next section) and load emacs. - -;;; To put in your init file (.emacs): -;;; ================================== -;;; -;;; Assuming you already have org mode installed and set up: -;;; -;;; (setq org-ctags-path-to-ctags "/path/to/ctags/executable") -;;; (add-hook 'org-mode-hook -;;; (lambda () -;;; (define-key org-mode-map "\C-co" 'org-ctags-find-tag-interactive))) -;;; -;;; By default, with org-ctags loaded, org will first try and visit the tag -;;; with the same name as the link; then, if unsuccessful, ask the user if -;;; he/she wants to rebuild the 'TAGS' database and try again; then ask if -;;; the user wishes to append 'tag' as a new toplevel heading at the end of -;;; the buffer; and finally, defer to org's default behaviour which is to -;;; search the entire text of the current buffer for 'tag'. -;;; -;;; This behaviour can be modified by changing the value of -;;; ORG-CTAGS-OPEN-LINK-FUNCTIONS. For example I have the following in my -;;; .emacs, which describes the same behaviour as the above paragraph with -;;; one difference: -;;; -;;; (setq org-ctags-open-link-functions -;;; '(org-ctags-find-tag -;;; org-ctags-ask-rebuild-tags-file-then-find-tag -;;; org-ctags-ask-append-topic -;;; org-ctags-fail-silently)) ; <-- prevents org default behaviour -;;; -;;; -;;; Usage -;;; ===== -;;; -;;; 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 in -;;; the active directory 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. -;;; -;;; User-visible functions: -;;; - `org-ctags-find-tag-interactive': type a tag (plain link) name and visit -;;; it. With autocompletion. Bound to ctrl-O in the above setup. -;;; - All the etags functions should work. These include: -;;; -;;; M-. `find-tag' -- finds the tag at point -;;; -;;; C-M-. find-tag based on regular expression -;;; -;;; M-x tags-search RET -- like C-M-. but searches through ENTIRE TEXT -;;; of ALL the files referenced in the TAGS file. A quick way to -;;; search through an entire 'project'. -;;; -;;; M-* "go back" from a tag jump. Like `org-mark-ring-goto'. -;;; You may need to bind this key yourself with (eg) -;;; (global-set-key (kbd "") 'pop-tag-mark) -;;; -;;; (see etags chapter in Emacs manual for more) -;;; -;;; -;;; Keeping the TAGS file up to date -;;; ================================ -;;; -;;; Tags mode has no way of knowing that you have created new tags by typing in -;;; your org-mode buffer. New tags make it into the TAGS file in 3 ways: -;;; -;;; 1. You re-run (org-ctags-create-tags "directory") to rebuild the file. -;;; 2. You put the function `org-ctags-ask-rebuild-tags-file-then-find-tag' in -;;; your `org-open-link-functions' list, as is done in the setup -;;; above. This will cause the TAGS file to be rebuilt whenever a link -;;; cannot be found. This may be slow with large file collections however. -;;; 3. You run the following from the command line (all 1 line): -;;; -;;; ctags --langdef=orgmode --langmap=orgmode:.org -;;; --regex-orgmode="/<<([^>]+)>>/\1/d,definition/" -;;; -f /your/path/TAGS -e -R /your/path/*.org -;;; -;;; If you are paranoid, you might want to run (org-ctags-create-tags -;;; "/path/to/org/files") at startup, by including the following toplevel form -;;; in .emacs. However this can cause a pause of several seconds if ctags has -;;; to scan lots of files. -;;; -;;; (progn -;;; (message "-- rebuilding tags tables...") -;;; (mapc 'org-create-tags tags-table-list)) +;; +;; Synopsis +;; ======== +;; +;; Allows org-mode to make use of the Emacs `etags' system. Defines tag +;; destinations in org-mode files as any text between <>. This allows the tags-generation program `exuberant ctags' to +;; parse these files and create tag tables that record where these +;; destinations are found. Plain [[links]] in org mode files which do not have +;; <> within the same file will then be interpreted as +;; links to these 'tagged' destinations, allowing seamless navigation between +;; multiple org-mode files. Topics can be created in any org mode file and +;; will always be found by plain links from other files. Other file types +;; recognized by ctags (source code files, latex files, etc) will also be +;; available as destinations for plain links, and similarly, org-mode links +;; will be available as tags from source files. Finally, the function +;; `org-ctags-find-tag-interactive' lets you choose any known tag, using +;; autocompletion, and quickly jump to it. +;; +;; Installation +;; ============ +;; +;; Install org mode +;; Ensure org-ctags.el is somewhere in your emacs load path. +;; Download and install Exuberant ctags -- "http://ctags.sourceforge.net/" +;; Edit your .emacs file (see next section) and load emacs. + +;; To put in your init file (.emacs): +;; ================================== +;; +;; Assuming you already have org mode installed and set up: +;; +;; (setq org-ctags-path-to-ctags "/path/to/ctags/executable") +;; (add-hook 'org-mode-hook +;; (lambda () +;; (define-key org-mode-map "\C-co" 'org-ctags-find-tag-interactive))) +;; +;; By default, with org-ctags loaded, org will first try and visit the tag +;; with the same name as the link; then, if unsuccessful, ask the user if +;; he/she wants to rebuild the 'TAGS' database and try again; then ask if +;; the user wishes to append 'tag' as a new toplevel heading at the end of +;; the buffer; and finally, defer to org's default behavior which is to +;; search the entire text of the current buffer for 'tag'. +;; +;; This behavior can be modified by changing the value of +;; ORG-CTAGS-OPEN-LINK-FUNCTIONS. For example I have the following in my +;; .emacs, which describes the same behavior as the above paragraph with +;; one difference: +;; +;; (setq org-ctags-open-link-functions +;; '(org-ctags-find-tag +;; org-ctags-ask-rebuild-tags-file-then-find-tag +;; org-ctags-ask-append-topic +;; org-ctags-fail-silently)) ; <-- prevents org default behavior +;; +;; +;; Usage +;; ===== +;; +;; 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 in +;; the active directory 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. +;; +;; User-visible functions: +;; - `org-ctags-find-tag-interactive': type a tag (plain link) name and visit +;; it. With autocompletion. Bound to ctrl-O in the above setup. +;; - All the etags functions should work. These include: +;; +;; M-. `find-tag' -- finds the tag at point +;; +;; C-M-. find-tag based on regular expression +;; +;; M-x tags-search RET -- like C-M-. but searches through ENTIRE TEXT +;; of ALL the files referenced in the TAGS file. A quick way to +;; search through an entire 'project'. +;; +;; M-* "go back" from a tag jump. Like `org-mark-ring-goto'. +;; You may need to bind this key yourself with (eg) +;; (global-set-key (kbd "") 'pop-tag-mark) +;; +;; (see etags chapter in Emacs manual for more) +;; +;; +;; Keeping the TAGS file up to date +;; ================================ +;; +;; Tags mode has no way of knowing that you have created new tags by typing in +;; your org-mode buffer. New tags make it into the TAGS file in 3 ways: +;; +;; 1. You re-run (org-ctags-create-tags "directory") to rebuild the file. +;; 2. You put the function `org-ctags-ask-rebuild-tags-file-then-find-tag' in +;; your `org-open-link-functions' list, as is done in the setup +;; above. This will cause the TAGS file to be rebuilt whenever a link +;; cannot be found. This may be slow with large file collections however. +;; 3. You run the following from the command line (all 1 line): +;; +;; ctags --langdef=orgmode --langmap=orgmode:.org +;; --regex-orgmode="/<<([^>]+)>>/\1/d,definition/" +;; -f /your/path/TAGS -e -R /your/path/*.org +;; +;; If you are paranoid, you might want to run (org-ctags-create-tags +;; "/path/to/org/files") at startup, by including the following toplevel form +;; in .emacs. However this can cause a pause of several seconds if ctags has +;; to scan lots of files. +;; +;; (progn +;; (message "-- rebuilding tags tables...") +;; (mapc 'org-ctags-create-tags tags-table-list)) + +;;; Code: (eval-when-compile (require 'cl)) + (require 'org) +(declare-function org-pop-to-buffer-same-window "org-compat" (&optional buffer-or-name norecord label)) + (defgroup org-ctags nil "Options concerning use of ctags within org mode." :tag "Org-Ctags" @@ -146,27 +150,25 @@ "Activate ctags support in org mode?") (defvar org-ctags-tag-regexp "/<<([^>]+)>>/\\1/d,definition/" - "Regexp expression used by ctags external program, that matches -tag destinations in org-mode files. + "Regexp expression used by ctags external program. +The regexp matches tag destinations in org-mode files. Format is: /REGEXP/TAGNAME/FLAGS,TAGTYPE/ See the ctags documentation for more information.") (defcustom org-ctags-path-to-ctags - (case system-type - (windows-nt "ctags.exe") - (darwin "ctags-exuberant") - (t "ctags-exuberant")) - "Full path to the ctags executable file." + (if (executable-find "ctags-exuberant") "ctags-exuberant" "ctags") + "Name of the ctags executable file." :group 'org-ctags + :version "24.1" :type 'file) (defcustom org-ctags-open-link-functions '(org-ctags-find-tag org-ctags-ask-rebuild-tags-file-then-find-tag org-ctags-ask-append-topic) - "List of functions to be prepended to ORG-OPEN-LINK-FUNCTIONS when -ORG-CTAGS is active." + "List of functions to be prepended to ORG-OPEN-LINK-FUNCTIONS when ORG-CTAGS is active." :group 'org-ctags + :version "24.1" :type 'hook :options '(org-ctags-find-tag org-ctags-ask-rebuild-tags-file-then-find-tag @@ -179,8 +181,8 @@ ORG-CTAGS is active." (defvar org-ctags-tag-list nil - "List of all tags in the active TAGS file. Created as a local -variable in each buffer.") + "List of all tags in the active TAGS file. +Created as a local variable in each buffer.") (defcustom org-ctags-new-topic-template "* <<%t>>\n\n\n\n\n\n" @@ -188,6 +190,7 @@ variable in each buffer.") The following patterns are replaced in the string: `%t' - replaced with the capitalized title of the hyperlink" :group 'org-ctags + :version "24.1" :type 'string) @@ -218,12 +221,12 @@ The following patterns are replaced in the string: (add-hook 'org-open-link-functions fn t))) -;;; General utility functions. =============================================== -;;; These work outside org-ctags mode. +;;; General utility functions. =============================================== +;; These work outside org-ctags mode. (defun org-ctags-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 + "TAG is a string. Search the active TAGS file for a matching tag. +If the tag is found, return a list containing the filename, line number, and buffer position where the tag is found." (interactive "sTag: ") (unless tags-file-name @@ -242,7 +245,7 @@ buffer position where the tag is found." ((re-search-backward " \n\\(.*\\),[0-9]+\n") (list (match-string 1) line pos)) (t ; can't find a file name preceding the matched - ; tag?? + ; tag?? (error "Malformed TAGS file: %s" (buffer-name)))))) (t ; tag not found nil)))))) @@ -279,8 +282,8 @@ Return the list." (defun org-ctags-open-file (name &optional title) - "Visit or create a file called `NAME.org', and insert a new topic titled -NAME (or TITLE if supplied)." + "Visit or create a file called `NAME.org', and insert a new topic. +The new topic will be titled NAME (or TITLE if supplied)." (interactive "sFile name: ") (let ((filename (substitute-in-file-name (expand-file-name name)))) (condition-case v @@ -303,7 +306,7 @@ NAME (or TITLE if supplied)." activate compile) "Before trying to find a tag, save our current position on org mark ring." (save-excursion - (if (and (org-mode-p) org-ctags-enabled-p) + (if (and (derived-mode-p 'org-mode) org-ctags-enabled-p) (org-mark-ring-push)))) @@ -349,7 +352,7 @@ If there is no plausible default, return nil." (defun org-ctags-find-tag (name) "This function is intended to be used in ORG-OPEN-LINK-FUNCTIONS. -Look for a tag called `NAME' in the current TAGS table. If it is found, +Look for a tag called `NAME' in the current TAGS table. If it is found, visit the file and location where the tag is found." (interactive "sTag: ") (let ((old-buf (current-buffer)) @@ -368,11 +371,11 @@ visit the file and location where the tag is found." (defun org-ctags-visit-buffer-or-file (name &optional create) "This function is intended to be used in ORG-OPEN-LINK-FUNCTIONS. -Visit buffer named `NAME.org'. If there is no such buffer, visit the file -with the same name if it exists. If the file does not exist, then behaviour +Visit buffer named `NAME.org'. If there is no such buffer, visit the file +with the same name if it exists. If the file does not exist, then behavior depends on the value of CREATE. -If CREATE is nil (default), then return nil. Do not create a new file. +If CREATE is nil (default), then return nil. Do not create a new file. If CREATE is t, create the new file and visit it. If CREATE is the symbol `ask', then ask the user if they wish to create the new file." @@ -383,7 +386,7 @@ the new file." (cond ((get-buffer (concat name ".org")) ;; Buffer is already open - (switch-to-buffer (get-buffer (concat name ".org")))) + (org-pop-to-buffer-same-window (get-buffer (concat name ".org")))) ((file-exists-p filename) ;; File exists but is not open --> open it (message "Opening existing org file `%S'..." @@ -391,7 +394,8 @@ the new file." (org-open-file filename t)) ((or (eql create t) (and (eql create 'ask) - (y-or-n-p (format "File `%s.org' not found; create?" name)))) + (y-or-n-p (format-message + "File `%s.org' not found; create?" name)))) (org-ctags-open-file filename name)) (t ;; File does not exist, and we don't want to create it. nil)))) @@ -406,7 +410,7 @@ asked before creating a new file." (defun org-ctags-append-topic (name &optional narrowp) "This function is intended to be used in ORG-OPEN-LINK-FUNCTIONS. -Append a new toplevel heading to the end of the current buffer. The +Append a new toplevel heading to the end of the current buffer. The heading contains NAME surrounded by <>, thus making the heading a destination for the tag `NAME'." (interactive "sTopic: ") @@ -430,8 +434,8 @@ the heading a destination for the tag `NAME'." "This function is intended to be used in ORG-OPEN-LINK-FUNCTIONS. Wrapper for org-ctags-append-topic, which first asks the user if they want to append a new topic." - (if (y-or-n-p (format "Topic `%s' not found; append to end of buffer?" - name)) + (if (y-or-n-p (format-message + "Topic `%s' not found; append to end of buffer?" name)) (org-ctags-append-topic name narrowp) nil)) @@ -451,19 +455,19 @@ to rebuild (update) the TAGS file." "This function is intended to be used in ORG-OPEN-LINK-FUNCTIONS. Wrapper for org-ctags-rebuild-tags-file-then-find-tag." (if (and (buffer-file-name) - (y-or-n-p - (format - "Tag `%s' not found. Rebuild table `%s/TAGS' and look again?" - name - (file-name-directory (buffer-file-name))))) - (org-ctags-rebuild-tags-file-then-find-tag name) + (y-or-n-p + (format-message + "Tag `%s' not found. Rebuild table `%s/TAGS' and look again?" + name + (file-name-directory (buffer-file-name))))) + (org-ctags-rebuild-tags-file-then-find-tag name) nil)) (defun org-ctags-fail-silently (name) "This function is intended to be used in ORG-OPEN-LINK-FUNCTIONS. Put as the last function in the list if you want to prevent org's default -behaviour of free text search." +behavior of free text search." t) @@ -471,14 +475,14 @@ behaviour of free text search." (defun org-ctags-create-tags (&optional directory-name) - "(Re)create tags file in the directory of the active buffer, -containing tag definitions for all the files in the directory and its -subdirectories which are recognised by ctags. This will include -files ending in `.org' as well as most other source files (.C, -.H, .EL, .LISP, etc). All the resulting tags end up in one file, -called TAGS, located in the directory. This function -may take several seconds to finish if the directory or its -subdirectories contain large numbers of taggable files." + "(Re)create tags file in the directory of the active buffer. +The file will contain tag definitions for all the files in the +directory and its subdirectories which are recognized by ctags. +This will include files ending in `.org' as well as most other +source files (.C, .H, .EL, .LISP, etc). All the resulting tags +end up in one file, called TAGS, located in the directory. This +function may take several seconds to finish if the directory or +its subdirectories contain large numbers of taggable files." (interactive) (assert (buffer-file-name)) (let ((dir-name (or directory-name @@ -509,8 +513,8 @@ subdirectories contain large numbers of taggable files." "History of tags visited by org-ctags-find-tag-interactive.") (defun org-ctags-find-tag-interactive () - "Prompt for the name of a tag, with autocompletion, then visit -the named tag. Uses ido-mode if available. + "Prompt for the name of a tag, with autocompletion, then visit the named tag. +Uses `ido-mode' if available. If the user enters a string that does not match an existing tag, create a new topic." (interactive) @@ -528,12 +532,11 @@ a new topic." (t ;; New tag (run-hook-with-args-until-success - 'org-open-link-functions tag)))))) + 'org-open-link-functions tag)))))) (org-ctags-enable) (provide 'org-ctags) -;;; arch-tag: 4b1ddd5a-8529-4b17-bcde-96a922d26343 ;;; org-ctags.el ends here