I'm writing an extension to open a custom link type in Org-mode with Kiwix URL. (Kiwix is an offline Wikipedia program). Here is my kiwix.el source code.

I created a wiki: link type for Org-mode.

Here is the link formats:

  • [[wiki:(library):query]]
  • [[wiki:query]]


  • wiki:(zh):%E7%A6%85%E5%AE%97
  • wiki:(en):linux
  • wiki:linux

And here is the elisp regexp:


Here is my current function to handle the link:

(defun org-wiki-link-open (link)
  "Open LINK in external wiki program."
  (cond ((string-match "\\(wiki\\):\\((\\(.*\\)):\\)?\\(.*\\)"  link) ; [[wiki:(library):query]]
         (let* ((type (match-string 1 link))
                ;; convert between libraries full name and abbrev.
                (library (cdr (assoc
                               (match-string 3 link)
                (query (match-string 4 link))
                (url (concat kiwix-server-url library "/A/" (url-encode-url (capitalize query)) ".html")))
           (browse-url url)))
        ((string-match "\\(wiki\\):\\(.*\\)"  link) ; [[wiki:query]]
         (let* ((type (match-string 1 link))
                (query (match-string 4 link))
                (url (concat kiwix-server-url kiwix-default-library "/A/" (url-encode-url (capitalize query)) ".html")))
           (browse-url url)))))

(defun org-wiki-link-export (link description format)
  "Export the wiki LINK with DESCRIPTION for FORMAT from Org files."
  (let* ((type (when (string-match "\\(.+\\):(\\(.+\\)?):\\(.*\\)" link)
                 (match-string 1 link)))
         (library (when (string-match "\\(.+\\):(\\(.+\\)?):\\(.*\\)" link)
                    (match-string 2 link)))
         ;; query need to be convert to URL encoding: "禅宗" https://zh.wikipedia.org/wiki/%E7%A6%85%E5%AE%97
         (query (url-encode-url
                 (or description
                     (when (string-match "\\(.+\\):(\\(.+\\)?):\\(.*\\)" link)
                       (match-string 3 link)))))
         ;; "http://en.wikipedia.org/wiki/Linux"
         ;;         --
         ;;          ^- library: en, zh
         (path (concat "http://" library ".wikipedia.org/wiki/" query))
         (desc query))
    (when (stringp path)
       ((eq format 'html) (format "<a href=\"%s\">%s</a>" path desc))
       ((eq format 'latex) (format "\\href{%s}{%s}" path desc))
       (t path)))))

(org-add-link-type "wiki" 'org-wiki-link-open 'org-wiki-link-export)

But this regexp is wrong, can't open those example links correctly.

  • [[wiki:(en):Linux][Linux (wiki)]]
  • [[wiki:Linux][Linux]]
  • [[wiki:(zh):%E7%A6%85%E5%AE%97][禅宗]]

So I hope someone can help me to improve this regexp pattern and my function code.

1 Answer 1


Your regexp should be \\(wiki\\):\\(?:(\\([^:]*\\)):\\)?\\([^] \n\t\r]*\\).

You have with that:

  • group 1: wiki
  • non capturing group (\(?:...\)) for optional library
  • group 2: library (en or zh)
  • group 3: link? (match everything but ], space, tab, carriage return, linefeed by using [^] \n\t\r]*)

So, you have one group less (your code should be adapted to that).

As an optimization you should string-match once and use subsequent match-string for each group of interest.

  • If I optimize the string-match, how to write the function org-wiki-link-open? Jul 26, 2016 at 1:33
  • The function org-wiki-link-export could be optimized, org-wiki-link-open looks ok.
    – theldoria
    Jul 26, 2016 at 5:04
  • I checked the new function, which is in latest code now (I mentioned the repo in question). But it does now open link now. Weird. Maybe this is not in question scope, but I think should not post a new question. Jul 26, 2016 at 10:30
  • You have (match-string 4 link) if library was not given, should be (match-string 3 link).
    – theldoria
    Jul 26, 2016 at 10:49
  • Also org-wiki-link-exportis different to previous version. Check your library extract there. In the previous version you had it with parentheses and colon included. Maybe it's now a bit better? But what if library was not given?
    – theldoria
    Jul 26, 2016 at 10:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.