Browse Source

Implemented a module loading system.

This system works by configuring a variable that contains a list of
all available modules.  These will automatically be loaded when the
first buffer is turned into org-mode, or when a global command
is run that needs org-mode code available (such are
org-store-link.
Carsten Dominik 17 years ago
parent
commit
5c339a3c14

+ 8 - 0
CONTRIB/ChangeLog

@@ -1,3 +1,11 @@
+2008-03-14  Carsten Dominik  <dominik@science.uva.nl>
+
+	* lisp/org-depend.el: Add `provide' for the module system.
+
+	* lisp/org-man.el: Add `provide' for the module system.
+
+	* lisp/org-interactive-query.el: Renamed from org-iq.el.
+
 2008-03-05  Bastien Guerry  <bzg@altern.org>
 
 	* lisp/org-elisp-symbol.el (org-elisp-symbol-store-link):

+ 1 - 2
CONTRIB/README

@@ -17,8 +17,7 @@ org-depend.el        --- TODO dependencies for Org-mode
 org-elisp-symbol.el  --- Org links to emacs-lisp symbols
 org-expiry.el 	     --- expiry mechanism for Org entries
 org-id.el 	     --- Global id's for identifying entries
-org-iq.el 	     --- Interactive modification of tags query
-org-irc.el 	     --- Store links to IRC sessions.
+org-interactive-query.el --- Interactive modification of tags query
 org-iswitchb.el      --- use iswitchb to select Org buffer
 org-man.el 	     --- Support for links to manpages in Org-mode
 org-panel.el 	     --- Simple routines for us with bad memory

+ 2 - 0
CONTRIB/lisp/org-depend.el

@@ -232,4 +232,6 @@ this ID property, that entry is also checked."
 (add-hook 'org-trigger-hook 'org-depend-trigger-todo)
 (add-hook 'org-blocker-hook 'org-depend-block-todo)
 
+(provide 'org-depend)
+
 ;;; org-depend.el ends here

+ 310 - 0
CONTRIB/lisp/org-interactive-query.el

@@ -0,0 +1,310 @@
+;;; org-interactive-query.el --- Interactive modification of agenda query
+;;
+;; Copyright 2007 Free Software Foundation, Inc.
+;;
+;; Author: Christopher League <league at contrapunctus dot net>
+;; Version: 1.0
+;; Keywords: org, wp
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, write to the Free Software
+;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;;
+;;; Commentary:
+;;
+
+;; This ibrary implements interactive modification of a tags/todo query
+;; in the org-agenda.  It adds 4 keys to the agenda
+;;
+;; /   add a keyword as a positive selection criterion
+;; \   add a keyword as a newgative selection criterion
+;; =   clear a keyword from the selection string
+;; ;   
+
+(require 'org)
+
+(org-defkey org-agenda-mode-map "=" 'org-agenda-query-clear-cmd)
+(org-defkey org-agenda-mode-map "/" 'org-agenda-query-and-cmd)
+(org-defkey org-agenda-mode-map ";" 'org-agenda-query-or-cmd)
+(org-defkey org-agenda-mode-map "\\" 'org-agenda-query-not-cmd)
+ 
+;;; Agenda interactive query manipulation
+
+(defcustom org-agenda-query-selection-single-key t
+  "Non-nil means, query manipulation exits after first change.
+When nil, you have to press RET to exit it.
+During query selection, you can toggle this flag with `C-c'.
+This variable can also have the value `expert'.  In this case, the window
+displaying the tags menu is not even shown, until you press C-c again."
+  :group 'org-agenda
+  :type '(choice
+	  (const :tag "No" nil)
+	  (const :tag "Yes" t)
+	  (const :tag "Expert" expert)))
+
+(defun org-agenda-query-selection (current op table &optional todo-table)
+  "Fast query manipulation with single keys.
+CURRENT is the current query string, OP is the initial
+operator (one of \"+|-=\"), TABLE is an alist of tags and
+corresponding keys, possibly with grouping information.
+TODO-TABLE is a similar table with TODO keywords, should these
+have keys assigned to them.  If the keys are nil, a-z are
+automatically assigned.  Returns the new query string, or nil to
+not change the current one."
+  (let* ((fulltable (append table todo-table))
+	 (maxlen (apply 'max (mapcar
+			      (lambda (x)
+				(if (stringp (car x)) (string-width (car x)) 0))
+			      fulltable)))
+	 (fwidth (+ maxlen 3 1 3))
+	 (ncol (/ (- (window-width) 4) fwidth))
+	 (expert (eq org-agenda-query-selection-single-key 'expert))
+	 (exit-after-next org-agenda-query-selection-single-key)
+	 (done-keywords org-done-keywords)
+         tbl char cnt e groups ingroup
+	 tg c2 c c1 ntable rtn)
+    (save-window-excursion
+      (if expert
+	  (set-buffer (get-buffer-create " *Org tags*"))
+	(delete-other-windows)
+	(split-window-vertically)
+	(org-switch-to-buffer-other-window (get-buffer-create " *Org tags*")))
+      (erase-buffer)
+      (org-set-local 'org-done-keywords done-keywords)
+      (insert "Query:    " current "\n")
+      (org-agenda-query-op-line op)
+      (insert "\n\n")
+      (org-fast-tag-show-exit exit-after-next)
+      (setq tbl fulltable char ?a cnt 0)
+      (while (setq e (pop tbl))
+	(cond
+	 ((equal e '(:startgroup))
+	  (push '() groups) (setq ingroup t)
+	  (when (not (= cnt 0))
+	    (setq cnt 0)
+	    (insert "\n"))
+	  (insert "{ "))
+	 ((equal e '(:endgroup))
+	  (setq ingroup nil cnt 0)
+	  (insert "}\n"))
+	 (t
+	  (setq tg (car e) c2 nil)
+	  (if (cdr e)
+	      (setq c (cdr e))
+	    ;; automatically assign a character.
+	    (setq c1 (string-to-char
+		      (downcase (substring
+				 tg (if (= (string-to-char tg) ?@) 1 0)))))
+	    (if (or (rassoc c1 ntable) (rassoc c1 table))
+		(while (or (rassoc char ntable) (rassoc char table))
+		  (setq char (1+ char)))
+	      (setq c2 c1))
+	    (setq c (or c2 char)))
+	  (if ingroup (push tg (car groups)))
+	  (setq tg (org-add-props tg nil 'face
+				  (cond
+				   ((not (assoc tg table))
+				    (org-get-todo-face tg))
+				   (t nil))))
+	  (if (and (= cnt 0) (not ingroup)) (insert "  "))
+	  (insert "[" c "] " tg (make-string
+				 (- fwidth 4 (length tg)) ?\ ))
+	  (push (cons tg c) ntable)
+	  (when (= (setq cnt (1+ cnt)) ncol)
+	    (insert "\n")
+	    (if ingroup (insert "  "))
+	    (setq cnt 0)))))
+      (setq ntable (nreverse ntable))
+      (insert "\n")
+      (goto-char (point-min))
+      (if (and (not expert) (fboundp 'fit-window-to-buffer))
+	  (fit-window-to-buffer))
+      (setq rtn
+	    (catch 'exit
+	      (while t
+		(message "[a-z..]:Toggle [SPC]:clear [RET]:accept [TAB]:free%s%s"
+			 (if groups " [!] no groups" " [!]groups")
+			 (if expert " [C-c]:window" (if exit-after-next " [C-c]:single" " [C-c]:multi")))
+		(setq c (let ((inhibit-quit t)) (read-char-exclusive)))
+		(cond
+		 ((= c ?\r) (throw 'exit t))
+		 ((= c ?!)
+		  (setq groups (not groups))
+		  (goto-char (point-min))
+		  (while (re-search-forward "[{}]" nil t) (replace-match " ")))
+		 ((= c ?\C-c)
+		  (if (not expert)
+		      (org-fast-tag-show-exit
+		       (setq exit-after-next (not exit-after-next)))
+		    (setq expert nil)
+		    (delete-other-windows)
+		    (split-window-vertically)
+		    (org-switch-to-buffer-other-window " *Org tags*")
+		    (and (fboundp 'fit-window-to-buffer)
+			 (fit-window-to-buffer))))
+		 ((or (= c ?\C-g)
+		      (and (= c ?q) (not (rassoc c ntable))))
+		  (setq quit-flag t))
+		 ((= c ?\ )
+		  (setq current "")
+		  (if exit-after-next (setq exit-after-next 'now)))
+		 ((= c ?\[)             ; clear left
+                  (org-agenda-query-decompose current)
+                  (setq current (concat "/" (match-string 2 current)))
+		  (if exit-after-next (setq exit-after-next 'now)))
+		 ((= c ?\])             ; clear right
+                  (org-agenda-query-decompose current)
+                  (setq current (match-string 1 current))
+		  (if exit-after-next (setq exit-after-next 'now)))
+		 ((= c ?\t)
+		  (condition-case nil
+		      (setq current (read-string "Query: " current))
+		    (quit))
+		  (if exit-after-next (setq exit-after-next 'now)))
+                 ;; operators
+                 ((or (= c ?/) (= c ?+)) (setq op "+"))
+                 ((or (= c ?\;) (= c ?|)) (setq op "|"))
+                 ((or (= c ?\\) (= c ?-)) (setq op "-"))
+                 ((= c ?=) (setq op "="))
+                 ;; todos
+                 ((setq e (rassoc c todo-table) tg (car e))
+                  (setq current (org-agenda-query-manip
+                                 current op groups 'todo tg))
+                  (if exit-after-next (setq exit-after-next 'now)))
+                 ;; tags
+                 ((setq e (rassoc c ntable) tg (car e))
+                  (setq current (org-agenda-query-manip
+                                 current op groups 'tag tg))
+                  (if exit-after-next (setq exit-after-next 'now))))
+		(if (eq exit-after-next 'now) (throw 'exit t))
+		(goto-char (point-min))
+		(beginning-of-line 1)
+		(delete-region (point) (point-at-eol))
+                (insert "Query:    " current)
+                (beginning-of-line 2)
+                (delete-region (point) (point-at-eol))
+                (org-agenda-query-op-line op)
+		(goto-char (point-min)))))
+      (if rtn current nil))))
+
+(defun org-agenda-query-op-line (op)
+  (insert "Operator: "
+          (org-agenda-query-op-entry (equal op "+") "/+" "and")
+          (org-agenda-query-op-entry (equal op "|") ";|" "or")
+          (org-agenda-query-op-entry (equal op "-") "\\-" "not")
+          (org-agenda-query-op-entry (equal op "=") "=" "clear")))
+
+(defun org-agenda-query-op-entry (matchp chars str)
+  (if matchp
+      (org-add-props (format "[%s %s]  " chars (upcase str))
+          nil 'face 'org-todo)
+    (format "[%s]%s   " chars str)))
+
+(defun org-agenda-query-decompose (current)
+  (string-match "\\([^/]*\\)/?\\(.*\\)" current))
+
+(defun org-agenda-query-clear (current prefix tag)
+  (if (string-match (concat prefix "\\b" (regexp-quote tag) "\\b") current)
+      (replace-match "" t t current)
+    current))
+
+(defun org-agenda-query-manip (current op groups kind tag)
+  "Apply an operator to a query string and a tag.
+CURRENT is the current query string, OP is the operator, GROUPS is a
+list of lists of tags that are mutually exclusive.  KIND is 'tag for a
+regular tag, or 'todo for a TODO keyword, and TAG is the tag or
+keyword string."
+  ;; If this tag is already in query string, remove it.
+  (setq current (org-agenda-query-clear current "[-\\+&|]?" tag))
+  (if (equal op "=") current
+    ;; When using AND, also remove mutually exclusive tags.
+    (if (equal op "+")
+        (loop for g in groups do
+              (if (member tag g)
+                  (mapc (lambda (x)
+                          (setq current
+                                (org-agenda-query-clear current "\\+" x)))
+                        g))))
+    ;; Decompose current query into q1 (tags) and q2 (TODOs).
+    (org-agenda-query-decompose current)
+    (let* ((q1 (match-string 1 current))
+           (q2 (match-string 2 current)))
+      (cond
+       ((eq kind 'tag)
+        (concat q1 op tag "/" q2))
+       ;; It's a TODO; when using AND, drop all other TODOs.
+       ((equal op "+")
+        (concat q1 "/+" tag))
+       (t
+        (concat q1 "/" q2 op tag))))))
+
+(defun org-agenda-query-global-todo-keys (&optional files)
+  "Return alist of all TODO keywords and their fast keys, in all FILES."
+  (let (alist)
+    (unless (and files (car files))
+      (setq files (org-agenda-files)))
+    (save-excursion
+      (loop for f in files do
+            (set-buffer (find-file-noselect f))
+            (loop for k in org-todo-key-alist do
+                  (setq alist (org-agenda-query-merge-todo-key
+                               alist k)))))
+    alist))
+
+(defun org-agenda-query-merge-todo-key (alist entry)
+  (let (e)
+    (cond
+     ;; if this is not a keyword (:startgroup, etc), ignore it
+     ((not (stringp (car entry))))
+     ;; if keyword already exists, replace char if it's null
+     ((setq e (assoc (car entry) alist))
+      (when (null (cdr e)) (setcdr e (cdr entry))))
+     ;; if char already exists, prepend keyword but drop char
+     ((rassoc (cdr entry) alist)
+      (message "TRACE POSITION 2")
+      (setq alist (cons (cons (car entry) nil) alist)))
+     ;; else, prepend COPY of entry
+     (t
+      (setq alist (cons (cons (car entry) (cdr entry)) alist)))))
+  alist)
+
+(defun org-agenda-query-generic-cmd (op)
+  "Activate query manipulation with OP as initial operator."
+  (let ((q (org-agenda-query-selection org-agenda-query-string op
+                                       org-tag-alist 
+                                       (org-agenda-query-global-todo-keys))))
+    (when q
+      (setq org-agenda-query-string q)
+      (org-agenda-redo))))
+
+(defun org-agenda-query-clear-cmd ()
+  "Activate query manipulation, to clear a tag from the string."
+  (interactive)
+  (org-agenda-query-generic-cmd "="))
+
+(defun org-agenda-query-and-cmd ()
+  "Activate query manipulation, initially using the AND (+) operator."
+  (interactive)
+  (org-agenda-query-generic-cmd "+"))
+
+(defun org-agenda-query-or-cmd ()
+  "Activate query manipulation, initially using the OR (|) operator."
+  (interactive)
+  (org-agenda-query-generic-cmd "|"))
+
+(defun org-agenda-query-not-cmd ()
+  "Activate query manipulation, initially using the NOT (-) operator."
+  (interactive)
+  (org-agenda-query-generic-cmd "-"))
+
+(provide 'org-interactive-query)

+ 2 - 0
CONTRIB/lisp/org-iq.el

@@ -306,3 +306,5 @@ keyword string."
   "Activate query manipulation, initially using the NOT (-) operator."
   (interactive)
   (org-agenda-query-generic-cmd "-"))
+
+(provide 'org-interactive-query)

+ 25 - 0
CONTRIB/lisp/org-man.el

@@ -1,4 +1,29 @@
 ;;; org-man.el - Support for links to manpages in Org-mode
+;;
+;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Keywords: outlines, hypermedia, calendar, wp
+;; Homepage: http://orgmode.org
+;; Version: 1.0
+;;
+;; This file is not yet part of GNU Emacs.
+;;
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
 
 (require 'org)
 

+ 9 - 0
ChangeLog

@@ -1,3 +1,12 @@
+2008-03-14  Carsten Dominik  <dominik@science.uva.nl>
+
+	* org.el (org-modules-loaded): New variable.
+	(org-load-modules-maybe, org-set-modules): New function.
+	(org-modules): New option.
+	(org-mode, org-cycle, orgstruct-mode, org-run-like-in-org-mode)
+	(orgtbl-mode, org-store-link, org-insert-link-global)
+	(org-open-at-point): Call `org-load-modules-maybe'.
+
 2008-03-13  Phil Jackson  <phil@shellarchive.co.uk>
 
 	* org-irc.el: New function to ensure port number is always

+ 15 - 0
ORGWEBPAGE/Changes.org

@@ -9,6 +9,19 @@
 
 ** Details
 
+*** Loading modules
+
+    Org-mode has now a system for loading modules by simply
+    configuring an option that lists all the modules you want to
+    use.  Customize the variable `org-modules'.  That variable
+    lists modules that are part of the Org-mode core (and in this
+    way part of Emacs), as well as contributed packages that will
+    only be available when you have installed them properly (most
+    likely by downloading the distribution and adding
+    CONTRIB/lisp to your load path.
+
+*** Misc
+
    - When an entry already has a scheduling or deadline time
      stamp, calling `C-c C-s' or `C-c C-d', respectively, will no
      use that old date as the default, and you can can use the
@@ -19,6 +32,8 @@
      This was an omission in the earlier implementation, spotted
      by Wanrong Lin.  Thanks!
 
+
+
 * Version 5.23
 
 ** Overview

+ 58 - 24
org.el

@@ -156,28 +156,56 @@ With prefix arg HERE, insert it at point."
   :group 'org
   :type 'hook)
 
-;(defcustom org-default-extensions '(org-irc)
-;  "Extensions that should always be loaded together with org.el.
-;If the description starts with <A>, this means the extension
-;will be autoloaded when needed, preloading is not necessary.
-;FIXME: this does not ork correctly, ignore it for now."
-;  :group 'org
-;  :type
-;  '(set :greedy t
-;	(const :tag "    Mouse support (org-mouse.el)" org-mouse)
-;	(const :tag "<A> Publishing (org-publish.el)" org-publish)
-;	(const :tag "<A> LaTeX export (org-export-latex.el)" org-export-latex)
-;	(const :tag "    IRC/ERC links (org-irc.el)" org-irc)
-;	(const :tag "    Apple Mail message links under OS X (org-mac-message.el)" org-mac-message)))
-;
-;(defun org-load-default-extensions ()
-;  "Load all extensions listed in `org-default-extensions'."
-;  (mapc (lambda (ext) 
-;	  (condition-case nil (require ext)
-;	    (error (message "Problems while trying to load feature `%s'" ext))))
-;	org-default-extensions))
-
-;(eval-after-load "org" '(org-load-default-extensions))
+(defvar org-modules-loaded nil
+  "Have the modules been loaded already?")
+
+(defun org-load-modules-maybe (&optional force)
+  "Load all extensions listed in `org-default-extensions'."
+  (when (or force (not org-modules-loaded))
+    (mapc (lambda (ext) 
+	    (condition-case nil (require ext)
+	      (error (message "Problems while trying to load feature `%s'" ext))))
+	  org-modules)
+    (setq org-modules-loaded t)))
+
+(defun org-set-modules (var value)
+  "Set VAR to VALUE and call `org-load-modules-maybe' with the force flag."
+  (set var value)
+  (when (featurep 'org)
+    (org-load-modules-maybe 'force)))
+
+(defcustom org-modules '(org-irc)
+  "Extensions that should always be loaded together with org.el.
+If the description starts with <A>, this means the extension
+will be autoloaded when needed, preloading is not necessary.
+If a description starts with <C>, the file is not part of emacs
+and loading it will require that you have downloaded and properly installed
+the org-mode distribution."
+  :group 'org
+  :set 'org-set-modules
+  :type
+  '(set :greedy t
+	(const :tag "A  export-latex:      LaTeX export" org-export-latex)
+	(const :tag "   irc:               IRC/ERC links" org-irc)
+	(const :tag "   mac-message:       Apple Mail message links under OS X" org-mac-message)
+	(const :tag "   mouse:             Mouse support" org-mouse)
+	(const :tag "A  publish:           Publishing" org-publish)
+	(const :tag "C  annotate-file:     Annotate a file with org syntax" org-annotate-file)
+	(const :tag "C  bibtex:            Org links to BibTeX entries" org-bibtex)
+	(const :tag "C  depend:            TODO dependencies for Org-mode" org-depend)
+	(const :tag "C  elisp-symbol:      Org links to emacs-lisp symbols" org-elisp-symbol)
+	(const :tag "C  expiry:            Expiry mechanism for Org entries" org-expiry)
+	(const :tag "C  id:                Global id's for identifying entries" org-id)
+	(const :tag "C  interactive-query: Interactive modification of tags query" org-interactive-query)
+	(const :tag "C  iswitchb:          Use iswitchb to select Org buffer" org-iswitchb)
+	(const :tag "C  mairix:            Hook mairix search into Org for different MUAs" org-mairix)
+	(const :tag "C  man:               Support for links to manpages in Org-mode" org-man)
+	(const :tag "C  mew:               Support for links to messages in Mew" org-mew)
+	(const :tag "C  panel:             Simple routines for us with bad memory" org-panel)
+	(const :tag "C  registry:          A registry for Org links" org-registry)
+	(const :tag "C  org2rem:           Convert org appointments into reminders" org2rem)
+	(const :tag "C  screen:            Visit screen sessions through Org-mode links" org-screen)
+	(const :tag "C  toc:               Table of contents for Org-mode buffer" org-toc)))
 
 ;; FIXME: Needs a separate group...
 (defcustom org-completion-fallback-command 'hippie-expand
@@ -5087,6 +5115,7 @@ The following commands are available:
     (define-key org-mode-map [menu-bar hide] 'undefined)
     (define-key org-mode-map [menu-bar show] 'undefined))
 
+  (org-load-modules-maybe)
   (easy-menu-add org-org-menu)
   (easy-menu-add org-tbl-menu)
   (org-install-agenda-files-menu)
@@ -5818,6 +5847,7 @@ If KWD is a number, get the corresponding match group."
   no headline in line 1, this function will act as if called with prefix arg.
   But only if also the variable `org-cycle-global-at-bob' is t."
   (interactive "P")
+  (org-load-modules-maybe)
   (let* ((outline-regexp
 	  (if (and (org-mode-p) org-cycle-include-plain-lists)
 	      "\\(?:\\*+ \\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) \\)"
@@ -7918,6 +7948,7 @@ M-RET       Insert new heading/item
 S-M-RET     Insert new TODO heading / Chekbox item
 C-c C-c     Set tags / toggle checkbox"
   nil " OrgStruct" nil
+  (org-load-modules-maybe)
   (and (orgstruct-setup) (defun orgstruct-setup () nil)))
 
 ;;;###autoload
@@ -8057,6 +8088,7 @@ Possible values in the list of contexts are `table', `headline', and `item'."
 
 ;;;###autoload
 (defun org-run-like-in-org-mode (cmd)
+  (org-load-modules-maybe)
   (unless org-local-vars
     (setq org-local-vars (org-get-local-variables)))
   (eval (list 'let org-local-vars
@@ -11459,6 +11491,7 @@ table editor in arbitrary modes.")
 (defun orgtbl-mode (&optional arg)
   "The `org-mode' table editor as a minor mode for use in other modes."
   (interactive)
+  (org-load-modules-maybe)
   (if (org-mode-p)
       ;; Exit without error, in case some hook functions calls this
       ;; by accident in org-mode.
@@ -12177,7 +12210,7 @@ For some link types, a prefix arg is interpreted:
 For links to usenet articles, arg negates `org-usenet-links-prefer-google'.
 For file links, arg negates `org-context-in-file-links'."
   (interactive "P")
-  (condition-case nil (require 'org-irc) (error nil))
+  (org-load-modules-maybe)
   (setq org-store-link-plist nil)  ; reset
   (let (link cpltxt desc description search txt)
     (cond
@@ -12597,6 +12630,7 @@ This is the list that is used before handing over to the browser.")
   "Insert a link like Org-mode does.
 This command can be called in any mode to insert a link in Org-mode syntax."
   (interactive)
+  (org-load-modules-maybe)
   (org-run-like-in-org-mode 'org-insert-link))
 
 (defun org-insert-link (&optional complete-file)
@@ -12832,7 +12866,7 @@ the end of the current subtree.
 Normally, files will be opened by an appropriate application.  If the
 optional argument IN-EMACS is non-nil, Emacs will visit the file."
   (interactive "P")
-  (condition-case nil (require 'org-irc) (error nil))
+  (org-load-modules-maybe)
   (move-marker org-open-link-marker (point))
   (setq org-window-config-before-follow-link (current-window-configuration))
   (org-remove-occur-highlights nil nil t)