| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113 | 
							- ;;; ol.el --- Org links library                      -*- lexical-binding: t; -*-
 
- ;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
 
- ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 
- ;; Keywords: outlines, hypermedia, calendar, wp
 
- ;; This file is 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 of the License, 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.  If not, see <https://www.gnu.org/licenses/>.
 
- ;;; Commentary:
 
- ;; This library provides tooling to handle both external and internal
 
- ;; links.
 
- ;;; Code:
 
- (require 'org-compat)
 
- (require 'org-macs)
 
- (require 'org-fold)
 
- (defvar clean-buffer-list-kill-buffer-names)
 
- (defvar org-agenda-buffer-name)
 
- (defvar org-comment-string)
 
- (defvar org-highlight-links)
 
- (defvar org-id-link-to-org-use-id)
 
- (defvar org-inhibit-startup)
 
- (defvar org-outline-regexp-bol)
 
- (defvar org-src-source-file-name)
 
- (defvar org-time-stamp-formats)
 
- (defvar org-ts-regexp)
 
- (declare-function calendar-cursor-to-date "calendar" (&optional error event))
 
- (declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
 
- (declare-function org-at-heading-p "org" (&optional _))
 
- (declare-function org-back-to-heading "org" (&optional invisible-ok))
 
- (declare-function org-before-first-heading-p "org" ())
 
- (declare-function org-do-occur "org" (regexp &optional cleanup))
 
- (declare-function org-element-at-point "org-element" (&optional pom cached-only))
 
- (declare-function org-element-cache-refresh "org-element" (pos))
 
- (declare-function org-element-context "org-element" (&optional element))
 
- (declare-function org-element-lineage "org-element" (datum &optional types with-self))
 
- (declare-function org-element-link-parser "org-element" ())
 
- (declare-function org-element-property "org-element" (property element))
 
- (declare-function org-element-type "org-element" (element))
 
- (declare-function org-element-update-syntax "org-element" ())
 
- (declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
 
- (declare-function org-find-property "org" (property &optional value))
 
- (declare-function org-get-heading "org" (&optional no-tags no-todo no-priority no-comment))
 
- (declare-function org-id-find-id-file "org-id" (id))
 
- (declare-function org-id-store-link "org-id" ())
 
- (declare-function org-insert-heading "org" (&optional arg invisible-ok top))
 
- (declare-function org-load-modules-maybe "org" (&optional force))
 
- (declare-function org-mark-ring-push "org" (&optional pos buffer))
 
- (declare-function org-mode "org" ())
 
- (declare-function org-occur "org" (regexp &optional keep-previous callback))
 
- (declare-function org-open-file "org" (path &optional in-emacs line search))
 
- (declare-function org-cycle-overview "org-cycle" ())
 
- (declare-function org-restart-font-lock "org" ())
 
- (declare-function org-run-like-in-org-mode "org" (cmd))
 
- (declare-function org-fold-show-context "org-fold" (&optional key))
 
- (declare-function org-src-coderef-format "org-src" (&optional element))
 
- (declare-function org-src-coderef-regexp "org-src" (fmt &optional label))
 
- (declare-function org-src-edit-buffer-p "org-src" (&optional buffer))
 
- (declare-function org-src-source-buffer "org-src" ())
 
- (declare-function org-src-source-type "org-src" ())
 
- (declare-function org-time-stamp-format "org" (&optional long inactive))
 
- (declare-function outline-next-heading "outline" ())
 
- ;;; Customization
 
- (defgroup org-link nil
 
-   "Options concerning links in Org mode."
 
-   :tag "Org Link"
 
-   :group 'org)
 
- (defcustom org-link-parameters nil
 
-   "Alist of properties that defines all the links in Org mode.
 
- The key in each association is a string of the link type.
 
- Subsequent optional elements make up a property list for that
 
- type.
 
- All properties are optional.  However, the most important ones
 
- are, in this order, `:follow', `:export', and `:store', described
 
- below.
 
- `:follow'
 
-   Function used to follow the link, when the `org-open-at-point'
 
-   command runs on it.  It is called with two arguments: the path,
 
-   as a string, and a universal prefix argument.
 
-   Here, you may use `org-link-open-as-file' helper function for
 
-   types similar to \"file\".
 
- `:export'
 
-   Function that accepts four arguments:
 
-   - the path, as a string,
 
-   - the description as a string, or nil,
 
-   - the export back-end,
 
-   - the export communication channel, as a plist.
 
-   When nil, export for that type of link is delegated to the
 
-   back-end.
 
- `:store'
 
-   Function responsible for storing the link.  See the function
 
-   `org-store-link-functions' for a description of the expected
 
-   arguments.
 
- Additional properties provide more specific control over the
 
- link.
 
- `:activate-func'
 
-   Function to run at the end of Font Lock activation.  It must
 
-   accept four arguments:
 
-   - the buffer position at the start of the link,
 
-   - the buffer position at its end,
 
-   - the path, as a string,
 
-   - a boolean, non-nil when the link has brackets.
 
- `:complete'
 
-   Function that inserts a link with completion.  The function
 
-   takes one optional prefix argument.
 
- `:insert-description'
 
-   String or function used as a default when prompting users for a
 
-   link's description.  A string is used as-is, a function is
 
-   called with two arguments: the link location (a string such as
 
-   \"~/foobar\", \"id:some-org-id\" or \"https://www.foo.com\")
 
-   and the description generated by `org-insert-link'.  It should
 
-   return the description to use (this reflects the behaviour of
 
-   `org-link-make-description-function').  If it returns nil, no
 
-   default description is used, but no error is thrown (from the
 
-   user's perspective, this is equivalent to a default description
 
-   of \"\").
 
- `:display'
 
-   Value for `invisible' text property on the hidden parts of the
 
-   link.  The most useful value is `full', which will not fold the
 
-   link in descriptive display.  Default is `org-link'.
 
- `:face'
 
-   Face for the link, or a function returning a face.  The
 
-   function takes one argument, which is the path.
 
-   The default face is `org-link'.
 
- `:help-echo'
 
-   String or function used as a value for the `help-echo' text
 
-   property.  The function is called with one argument, the help
 
-   string to display, and should return a string.
 
- `:htmlize-link'
 
-   Function or plist for the `htmlize-link' text property.  The
 
-   function takes no argument.
 
-   Default is (:uri \"type:path\")
 
- `:keymap'
 
-   Active keymap when point is on the link.  Default is
 
-   `org-mouse-map'.
 
- `:mouse-face'
 
-   Face used when hovering over the link.  Default is
 
-   `highlight'."
 
-   :group 'org-link
 
-   :package-version '(Org . "9.1")
 
-   :type '(alist :tag "Link display parameters"
 
- 		:value-type plist))
 
- (defcustom org-link-descriptive t
 
-   "Non-nil means Org displays descriptive links.
 
- E.g. [[https://orgmode.org][Org website]] is displayed as
 
- \"Org Website\", hiding the link itself and just displaying its
 
- description.  When set to nil, Org displays the full links
 
- literally.
 
- You can interactively set the value of this variable by calling
 
- `org-toggle-link-display' or from the \"Org > Hyperlinks\" menu."
 
-   :group 'org-link
 
-   :type 'boolean
 
-   :safe #'booleanp)
 
- (defcustom org-link-make-description-function nil
 
-   "Function to use for generating link descriptions from links.
 
- This function must take two parameters: the first one is the
 
- link, the second one is the description generated by
 
- `org-insert-link'.  The function should return the description to
 
- use.  If it returns nil, no default description is used, but no
 
- error is thrown (from the user’s perspective, this is equivalent
 
- to a default description of \"\")."
 
-   :group 'org-link
 
-   :type '(choice (const nil) (function))
 
-   :safe #'null)
 
- (defcustom org-link-file-path-type 'adaptive
 
-   "How the path name in file links should be stored.
 
- Valid values are:
 
- relative  Relative to the current directory, i.e. the directory of the file
 
-           into which the link is being inserted.
 
- absolute  Absolute path, if possible with ~ for home directory.
 
- noabbrev  Absolute path, no abbreviation of home directory.
 
- adaptive  Use relative path for files in the current directory and sub-
 
-           directories of it.  For other files, use an absolute path.
 
- Alternatively, users may supply a custom function that takes the
 
- full filename as an argument and returns the path."
 
-   :group 'org-link
 
-   :type '(choice
 
- 	  (const relative)
 
- 	  (const absolute)
 
- 	  (const noabbrev)
 
- 	  (const adaptive)
 
- 	  (function))
 
-   :package-version '(Org . "9.5")
 
-   :safe #'symbolp)
 
- (defcustom org-link-abbrev-alist nil
 
-   "Alist of link abbreviations.
 
- The car of each element is a string, to be replaced at the start of a link.
 
- The cdrs are replacement values, like (\"linkkey\" . REPLACE).  Abbreviated
 
- links in Org buffers can have an optional tag after a double colon, e.g.,
 
-      [[linkkey:tag][description]]
 
- The `linkkey' must be a single word, starting with a letter, followed
 
- by letters, numbers, `-' or `_'.
 
- If REPLACE is a string, the tag will simply be appended to create the link.
 
- If the string contains \"%s\", the tag will be inserted there.  If the string
 
- contains \"%h\", it will cause a url-encoded version of the tag to be inserted
 
- at that point (see the function `url-hexify-string').  If the string contains
 
- the specifier \"%(my-function)\", then the custom function `my-function' will
 
- be invoked: this function takes the tag as its only argument and must return
 
- a string.
 
- REPLACE may also be a function that will be called with the tag as the
 
- only argument to create the link, which should be returned as a string.
 
- See the manual for examples."
 
-   :group 'org-link
 
-   :type '(repeat
 
- 	  (cons (string :tag "Protocol")
 
- 		(choice
 
- 		 (string :tag "Format")
 
- 		 (function))))
 
-   :safe (lambda (val)
 
- 	  (pcase val
 
- 	    (`(,(pred stringp) . ,(pred stringp)) t)
 
- 	    (_ nil))))
 
- (defgroup org-link-follow nil
 
-   "Options concerning following links in Org mode."
 
-   :tag "Org Follow Link"
 
-   :group 'org-link)
 
- (defcustom org-link-translation-function nil
 
-   "Function to translate links with different syntax to Org syntax.
 
- This can be used to translate links created for example by the Planner
 
- or emacs-wiki packages to Org syntax.
 
- The function must accept two parameters, a TYPE containing the link
 
- protocol name like \"rmail\" or \"gnus\" as a string, and the linked path,
 
- which is everything after the link protocol.  It should return a cons
 
- with possibly modified values of type and path.
 
- Org contains a function for this, so if you set this variable to
 
- `org-translate-link-from-planner', you should be able follow many
 
- links created by planner."
 
-   :group 'org-link-follow
 
-   :type '(choice (const nil) (function))
 
-   :safe #'null)
 
- (defcustom org-link-frame-setup
 
-   '((vm . vm-visit-folder-other-frame)
 
-     (vm-imap . vm-visit-imap-folder-other-frame)
 
-     (gnus . org-gnus-no-new-news)
 
-     (file . find-file-other-window)
 
-     (wl . wl-other-frame))
 
-   "Setup the frame configuration for following links.
 
- When following a link with Emacs, it may often be useful to display
 
- this link in another window or frame.  This variable can be used to
 
- set this up for the different types of links.
 
- For VM, use any of
 
-     `vm-visit-folder'
 
-     `vm-visit-folder-other-window'
 
-     `vm-visit-folder-other-frame'
 
- For Gnus, use any of
 
-     `gnus'
 
-     `gnus-other-frame'
 
-     `org-gnus-no-new-news'
 
- For FILE, use any of
 
-     `find-file'
 
-     `find-file-other-window'
 
-     `find-file-other-frame'
 
- For Wanderlust use any of
 
-     `wl'
 
-     `wl-other-frame'
 
- For the calendar, use the variable `calendar-setup'.
 
- For BBDB, it is currently only possible to display the matches in
 
- another window."
 
-   :group 'org-link-follow
 
-   :type '(list
 
- 	  (cons (const vm)
 
- 		(choice
 
- 		 (const vm-visit-folder)
 
- 		 (const vm-visit-folder-other-window)
 
- 		 (const vm-visit-folder-other-frame)))
 
- 	  (cons (const vm-imap)
 
- 		(choice
 
- 		 (const vm-visit-imap-folder)
 
- 		 (const vm-visit-imap-folder-other-window)
 
- 		 (const vm-visit-imap-folder-other-frame)))
 
- 	  (cons (const gnus)
 
- 		(choice
 
- 		 (const gnus)
 
- 		 (const gnus-other-frame)
 
- 		 (const org-gnus-no-new-news)))
 
- 	  (cons (const file)
 
- 		(choice
 
- 		 (const find-file)
 
- 		 (const find-file-other-window)
 
- 		 (const find-file-other-frame)))
 
- 	  (cons (const wl)
 
- 		(choice
 
- 		 (const wl)
 
- 		 (const wl-other-frame)))))
 
- (defcustom org-link-search-must-match-exact-headline 'query-to-create
 
-   "Non-nil means internal fuzzy links can only match headlines.
 
- When nil, the a fuzzy link may point to a target or a named
 
- construct in the document.  When set to the special value
 
- `query-to-create', offer to create a new headline when none
 
- matched.
 
- Spaces and statistics cookies are ignored during heading searches."
 
-   :group 'org-link-follow
 
-   :version "24.1"
 
-   :type '(choice
 
- 	  (const :tag "Use fuzzy text search" nil)
 
- 	  (const :tag "Match only exact headline" t)
 
- 	  (const :tag "Match exact headline or query to create it"
 
- 		 query-to-create))
 
-   :safe #'symbolp)
 
- (defcustom org-link-use-indirect-buffer-for-internals nil
 
-   "Non-nil means use indirect buffer to display infile links.
 
- Activating internal links (from one location in a file to another location
 
- in the same file) normally just jumps to the location.  When the link is
 
- activated with a `\\[universal-argument]' prefix (or with mouse-3), the link \
 
- is displayed in
 
- another window.  When this option is set, the other window actually displays
 
- an indirect buffer clone of the current buffer, to avoid any visibility
 
- changes to the current buffer."
 
-   :group 'org-link-follow
 
-   :type 'boolean
 
-   :safe #'booleanp)
 
- (defcustom org-link-shell-confirm-function 'yes-or-no-p
 
-   "Non-nil means ask for confirmation before executing shell links.
 
- Shell links can be dangerous: just think about a link
 
-      [[shell:rm -rf ~/*][Web Search]]
 
- This link would show up in your Org document as \"Web Search\",
 
- but really it would remove your entire home directory.
 
- Therefore we advise against setting this variable to nil.
 
- Just change it to `y-or-n-p' if you want to confirm with a
 
- single keystroke rather than having to type \"yes\"."
 
-   :group 'org-link-follow
 
-   :type '(choice
 
- 	  (const :tag "with yes-or-no (safer)" yes-or-no-p)
 
- 	  (const :tag "with y-or-n (faster)" y-or-n-p)
 
- 	  (const :tag "no confirmation (dangerous)" nil)))
 
- (defcustom org-link-shell-skip-confirm-regexp ""
 
-   "Regexp to skip confirmation for shell links."
 
-   :group 'org-link-follow
 
-   :version "24.1"
 
-   :type 'regexp)
 
- (defcustom org-link-elisp-confirm-function 'yes-or-no-p
 
-   "Non-nil means ask for confirmation before executing Emacs Lisp links.
 
- Elisp links can be dangerous: just think about a link
 
-      [[elisp:(shell-command \"rm -rf ~/*\")][Web Search]]
 
- This link would show up in your Org document as \"Web Search\",
 
- but really it would remove your entire home directory.
 
- Therefore we advise against setting this variable to nil.
 
- Just change it to `y-or-n-p' if you want to confirm with a
 
- single keystroke rather than having to type \"yes\"."
 
-   :group 'org-link-follow
 
-   :type '(choice
 
- 	  (const :tag "with yes-or-no (safer)" yes-or-no-p)
 
- 	  (const :tag "with y-or-n (faster)" y-or-n-p)
 
- 	  (const :tag "no confirmation (dangerous)" nil)))
 
- (defcustom org-link-elisp-skip-confirm-regexp ""
 
-   "A regexp to skip confirmation for Elisp links."
 
-   :group 'org-link-follow
 
-   :version "24.1"
 
-   :type 'regexp)
 
- (defgroup org-link-store nil
 
-   "Options concerning storing links in Org mode."
 
-   :tag "Org Store Link"
 
-   :group 'org-link)
 
- (defcustom org-link-context-for-files t
 
-   "Non-nil means file links from `org-store-link' contain context.
 
- \\<org-mode-map>
 
- A search string is added to the file name with \"::\" as separator
 
- and used to find the context when the link is activated by the command
 
- `org-open-at-point'.  When this option is t, the entire active region
 
- is be placed in the search string of the file link.  If set to a
 
- positive integer N, only the first N lines of context are stored.
 
- Using a prefix argument to the command `org-store-link' \
 
- \(`\\[universal-argument] \\[org-store-link]')
 
- negates this setting for the duration of the command."
 
-   :group 'org-link-store
 
-   :type '(choice boolean integer)
 
-   :safe (lambda (val) (or (booleanp val) (integerp val))))
 
- (defcustom org-link-email-description-format "Email %c: %s"
 
-   "Format of the description part of a link to an email or Usenet message.
 
- The following %-escapes will be replaced by corresponding information:
 
- %F   full \"From\" field
 
- %f   name, taken from \"From\" field, address if no name
 
- %T   full \"To\" field
 
- %t   first name in \"To\" field, address if no name
 
- %c   correspondent.  Usually \"from NAME\", but if you sent it yourself, it
 
-      will be \"to NAME\".  See also the variable `org-from-is-user-regexp'.
 
- %s   subject
 
- %d   date
 
- %m   message-id.
 
- You may use normal field width specification between the % and the letter.
 
- This is for example useful to limit the length of the subject.
 
- Examples: \"%f on: %.30s\", \"Email from %f\", \"Email %c\""
 
-   :group 'org-link-store
 
-   :package-version '(Org . "9.3")
 
-   :type 'string
 
-   :safe #'stringp)
 
- (defcustom org-link-from-user-regexp
 
-   (let ((mail (and (org-string-nw-p user-mail-address)
 
- 		   (format "\\<%s\\>" (regexp-quote user-mail-address))))
 
- 	(name (and (org-string-nw-p user-full-name)
 
- 		   (format "\\<%s\\>" (regexp-quote user-full-name)))))
 
-     (if (and mail name) (concat mail "\\|" name) (or mail name)))
 
-   "Regexp matched against the \"From:\" header of an email or Usenet message.
 
- It should match if the message is from the user him/herself."
 
-   :group 'org-link-store
 
-   :type 'regexp
 
-   :safe #'stringp)
 
- (defcustom org-link-keep-stored-after-insertion nil
 
-   "Non-nil means keep link in list for entire session.
 
- \\<org-mode-map>
 
- The command `org-store-link' adds a link pointing to the current
 
- location to an internal list.  These links accumulate during a session.
 
- The command `org-insert-link' can be used to insert links into any
 
- Org file (offering completion for all stored links).
 
- When this option is nil, every link which has been inserted once using
 
- `\\[org-insert-link]' will be removed from the list, to make completing the \
 
- unused
 
- links more efficient."
 
-   :group 'org-link-store
 
-   :type 'boolean
 
-   :safe #'booleanp)
 
- ;;; Public variables
 
- (defconst org-target-regexp (let ((border "[^<>\n\r \t]"))
 
- 			      (format "<<\\(%s\\|%s[^<>\n\r]*%s\\)>>"
 
- 				      border border border))
 
-   "Regular expression matching a link target.")
 
- (defconst org-radio-target-regexp (format "<%s>" org-target-regexp)
 
-   "Regular expression matching a radio target.")
 
- (defvar-local org-target-link-regexp nil
 
-   "Regular expression matching radio targets in plain text.")
 
- (defvar org-link-types-re nil
 
-   "Matches a link that has a url-like prefix like \"http:\".")
 
- (defvar org-link-angle-re nil
 
-   "Matches link with angular brackets, spaces are allowed.")
 
- (defvar org-link-plain-re nil
 
-   "Matches plain link, without spaces.
 
- Group 1 must contain the link type (i.e. https).
 
- Group 2 must contain the link path (i.e. //example.com).
 
- Used by `org-element-link-parser'.")
 
- (defvar org-link-bracket-re nil
 
-   "Matches a link in double brackets.")
 
- (defvar org-link-any-re nil
 
-   "Regular expression matching any link.")
 
- (defvar-local org-link-abbrev-alist-local nil
 
-   "Buffer-local version of `org-link-abbrev-alist', which see.
 
- The value of this is taken from the LINK keywords.")
 
- (defvar org-stored-links nil
 
-   "Contains the links stored with `org-store-link'.")
 
- (defvar org-store-link-plist nil
 
-   "Plist with info about the most recently link created with `org-store-link'.")
 
- (defvar org-create-file-search-functions nil
 
-   "List of functions to construct the right search string for a file link.
 
- These functions are called in turn with point at the location to
 
- which the link should point.
 
- A function in the hook should first test if it would like to
 
- handle this file type, for example by checking the `major-mode'
 
- or the file extension.  If it decides not to handle this file, it
 
- should just return nil to give other functions a chance.  If it
 
- does handle the file, it must return the search string to be used
 
- when following the link.  The search string will be part of the
 
- file link, given after a double colon, and `org-open-at-point'
 
- will automatically search for it.  If special measures must be
 
- taken to make the search successful, another function should be
 
- added to the companion hook `org-execute-file-search-functions',
 
- which see.
 
- A function in this hook may also use `setq' to set the variable
 
- `description' to provide a suggestion for the descriptive text to
 
- be used for this link when it gets inserted into an Org buffer
 
- with \\[org-insert-link].")
 
- (defvar org-execute-file-search-functions nil
 
-   "List of functions to execute a file search triggered by a link.
 
- Functions added to this hook must accept a single argument, the
 
- search string that was part of the file link, the part after the
 
- double colon.  The function must first check if it would like to
 
- handle this search, for example by checking the `major-mode' or
 
- the file extension.  If it decides not to handle this search, it
 
- should just return nil to give other functions a chance.  If it
 
- does handle the search, it must return a non-nil value to keep
 
- other functions from trying.
 
- Each function can access the current prefix argument through the
 
- variable `current-prefix-arg'.  Note that a single prefix is used
 
- to force opening a link in Emacs, so it may be good to only use a
 
- numeric or double prefix to guide the search function.
 
- In case this is needed, a function in this hook can also restore
 
- the window configuration before `org-open-at-point' was called using:
 
-     (set-window-configuration org-window-config-before-follow-link)")
 
- (defvar org-open-link-functions nil
 
-   "Hook for functions finding a plain text link.
 
- These functions must take a single argument, the link content.
 
- They will be called for links that look like [[link text][description]]
 
- when LINK TEXT does not have a protocol like \"http:\" and does not look
 
- like a filename (e.g. \"./blue.png\").
 
- These functions will be called *before* Org attempts to resolve the
 
- link by doing text searches in the current buffer - so if you want a
 
- link \"[[target]]\" to still find \"<<target>>\", your function should
 
- handle this as a special case.
 
- When the function does handle the link, it must return a non-nil value.
 
- If it decides that it is not responsible for this link, it must return
 
- nil to indicate that Org can continue with other options like
 
- exact and fuzzy text search.")
 
- ;;; Internal Variables
 
- (defconst org-link--forbidden-chars "]\t\n\r<>"
 
-   "Characters forbidden within a link, as a string.")
 
- (defvar org-link--history nil
 
-   "History for inserted links.")
 
- (defvar org-link--insert-history nil
 
-   "Minibuffer history for links inserted with `org-insert-link'.")
 
- (defvar org-link--search-failed nil
 
-   "Non-nil when last link search failed.")
 
- (defvar-local org-link--link-folding-spec '(org-link
 
-                                             (:global t)
 
-                                             (:ellipsis . nil)
 
-                                             (:isearch-open . t)
 
-                                             (:fragile . org-link--reveal-maybe))
 
-   "Folding spec used to hide invisible parts of links.")
 
- (defvar-local org-link--description-folding-spec '(org-link-description
 
-                                                    (:global t)
 
-                                                    (:ellipsis . nil)
 
-                                                    (:visible . t)
 
-                                                    (:isearch-open . nil)
 
-                                                    (:fragile . org-link--reveal-maybe))
 
-   "Folding spec used to reveal link description.")
 
- ;;; Internal Functions
 
- (defun org-link--try-special-completion (type)
 
-   "If there is completion support for link type TYPE, offer it."
 
-   (let ((fun (org-link-get-parameter type :complete)))
 
-     (if (functionp fun)
 
- 	(funcall fun)
 
-       (read-string "Link (no completion support): " (concat type ":")))))
 
- (defun org-link--prettify (link)
 
-   "Return a human-readable representation of LINK.
 
- The car of LINK must be a raw link.  The cdr of LINK must be
 
- either a link description or nil."
 
-   (let ((desc (or (cadr link) "<no description>")))
 
-     (concat (format "%-45s" (substring desc 0 (min (length desc) 40)))
 
- 	    "<" (car link) ">")))
 
- (defun org-link--decode-compound (hex)
 
-   "Unhexify Unicode hex-chars HEX.
 
- E.g. \"%C3%B6\" is the German o-Umlaut.  Note: this function also
 
- decodes single byte encodings like \"%E1\" (a-acute) if not
 
- followed by another \"%[A-F0-9]{2}\" group."
 
-   (save-match-data
 
-     (let* ((bytes (cdr (split-string hex "%")))
 
- 	   (ret "")
 
- 	   (eat 0)
 
- 	   (sum 0))
 
-       (while bytes
 
- 	(let* ((val (string-to-number (pop bytes) 16))
 
- 	       (shift-xor
 
- 		(if (= 0 eat)
 
- 		    (cond
 
- 		     ((>= val 252) (cons 6 252))
 
- 		     ((>= val 248) (cons 5 248))
 
- 		     ((>= val 240) (cons 4 240))
 
- 		     ((>= val 224) (cons 3 224))
 
- 		     ((>= val 192) (cons 2 192))
 
- 		     (t (cons 0 0)))
 
- 		  (cons 6 128))))
 
- 	  (when (>= val 192) (setq eat (car shift-xor)))
 
- 	  (setq val (logxor val (cdr shift-xor)))
 
- 	  (setq sum (+ (lsh sum (car shift-xor)) val))
 
- 	  (when (> eat 0) (setq eat (- eat 1)))
 
- 	  (cond
 
- 	   ((= 0 eat)			;multi byte
 
- 	    (setq ret (concat ret (char-to-string sum)))
 
- 	    (setq sum 0))
 
- 	   ((not bytes)			; single byte(s)
 
- 	    (setq ret (org-link--decode-single-byte-sequence hex))))))
 
-       ret)))
 
- (defun org-link--decode-single-byte-sequence (hex)
 
-   "Unhexify hex-encoded single byte character sequence HEX."
 
-   (mapconcat (lambda (byte)
 
- 	       (char-to-string (string-to-number byte 16)))
 
- 	     (cdr (split-string hex "%"))
 
- 	     ""))
 
- (defun org-link--fontify-links-to-this-file ()
 
-   "Fontify links to the current file in `org-stored-links'."
 
-   (let ((f (buffer-file-name)) a b)
 
-     (setq a (mapcar (lambda(l)
 
- 		      (let ((ll (car l)))
 
- 			(when (and (string-match "^file:\\(.+\\)::" ll)
 
- 				   (equal f (expand-file-name (match-string 1 ll))))
 
- 			  ll)))
 
- 		    org-stored-links))
 
-     (when (featurep 'org-id)
 
-       (setq b (mapcar (lambda(l)
 
- 			(let ((ll (car l)))
 
- 			  (when (and (string-match "^id:\\(.+\\)$" ll)
 
- 				     (equal f (expand-file-name
 
- 					       (or (org-id-find-id-file
 
- 						    (match-string 1 ll)) ""))))
 
- 			    ll)))
 
- 		      org-stored-links)))
 
-     (mapcar (lambda(l)
 
- 	      (put-text-property 0 (length l) 'face 'font-lock-comment-face l))
 
- 	    (delq nil (append a b)))))
 
- (defun org-link--buffer-for-internals ()
 
-   "Return buffer used for displaying the target of internal links."
 
-   (cond
 
-    ((not org-link-use-indirect-buffer-for-internals) (current-buffer))
 
-    ((string-suffix-p "(Clone)" (buffer-name))
 
-     (message "Buffer is already a clone, not making another one")
 
-     ;; We also do not modify visibility in this case.
 
-     (current-buffer))
 
-    (t		   ;make a new indirect buffer for displaying the link
 
-     (let* ((indirect-buffer-name (concat (buffer-name) "(Clone)"))
 
- 	   (indirect-buffer
 
- 	    (or (get-buffer indirect-buffer-name)
 
- 		(make-indirect-buffer (current-buffer)
 
- 				      indirect-buffer-name
 
- 				      'clone))))
 
-       (with-current-buffer indirect-buffer (org-cycle-overview))
 
-       indirect-buffer))))
 
- (defun org-link--search-radio-target (target)
 
-   "Search a radio target matching TARGET in current buffer.
 
- White spaces are not significant."
 
-   (let ((re (format "<<<%s>>>"
 
- 		    (mapconcat #'regexp-quote
 
- 			       (split-string target)
 
- 			       "[ \t]+\\(?:\n[ \t]*\\)?")))
 
- 	(origin (point)))
 
-     (goto-char (point-min))
 
-     (catch :radio-match
 
-       (while (re-search-forward re nil t)
 
- 	(forward-char -1)
 
- 	(let ((object (org-element-context)))
 
- 	  (when (eq (org-element-type object) 'radio-target)
 
- 	    (goto-char (org-element-property :begin object))
 
- 	    (org-fold-show-context 'link-search)
 
- 	    (throw :radio-match nil))))
 
-       (goto-char origin)
 
-       (user-error "No match for radio target: %s" target))))
 
- (defun org-link--context-from-region ()
 
-   "Return context string from active region, or nil."
 
-   (when (org-region-active-p)
 
-     (let ((context (buffer-substring (region-beginning) (region-end))))
 
-       (when (and (wholenump org-link-context-for-files)
 
- 		 (> org-link-context-for-files 0))
 
- 	(let ((lines (org-split-string context "\n")))
 
- 	  (setq context
 
- 		(mapconcat #'identity
 
- 			   (cl-subseq lines 0 org-link-context-for-files)
 
- 			   "\n"))))
 
-       context)))
 
- (defun org-link--normalize-string (string &optional context)
 
-   "Remove ignored contents from STRING string and return it.
 
- This function removes contiguous white spaces and statistics
 
- cookies.  When optional argument CONTEXT is non-nil, it assumes
 
- STRING is a context string, and also removes special search
 
- syntax around the string."
 
-   (let ((string
 
- 	 (org-trim
 
- 	  (replace-regexp-in-string
 
- 	   (rx (one-or-more (any " \t")))
 
- 	   " "
 
- 	   (replace-regexp-in-string
 
- 	    ;; Statistics cookie regexp.
 
- 	    (rx (seq "[" (0+ digit) (or "%" (seq "/" (0+ digit))) "]"))
 
- 	    " "
 
- 	    string)))))
 
-     (when context
 
-       (while (cond ((and (string-prefix-p "(" string)
 
- 			 (string-suffix-p ")" string))
 
- 		    (setq string (org-trim (substring string 1 -1))))
 
- 		   ((string-match "\\`[#*]+[ \t]*" string)
 
- 		    (setq string (substring string (match-end 0))))
 
- 		   (t nil))))
 
-     string))
 
- (defun org-link--reveal-maybe (region _)
 
-   "Reveal folded link in REGION when needed.
 
- This function is intended to be used as :fragile property of a folding
 
- spec."
 
-   (org-with-point-at (car region)
 
-     (not (org-in-regexp org-link-any-re))))
 
- ;;; Public API
 
- (defun org-link-types ()
 
-   "Return a list of known link types."
 
-   (mapcar #'car org-link-parameters))
 
- (defun org-link-get-parameter (type key)
 
-   "Get TYPE link property for KEY.
 
- TYPE is a string and KEY is a plist keyword.  See
 
- `org-link-parameters' for supported keywords."
 
-   (plist-get (cdr (assoc type org-link-parameters))
 
- 	     key))
 
- (defun org-link-set-parameters (type &rest parameters)
 
-   "Set link TYPE properties to PARAMETERS.
 
- PARAMETERS should be keyword value pairs.  See
 
- `org-link-parameters' for supported keys."
 
-   (when (member type '("coderef" "custom-id" "fuzzy" "radio"))
 
-     (error "Cannot override reserved link type: %S" type))
 
-   (let ((data (assoc type org-link-parameters)))
 
-     (if data (setcdr data (org-combine-plists (cdr data) parameters))
 
-       (push (cons type parameters) org-link-parameters)
 
-       (org-link-make-regexps)
 
-       (when (featurep 'org-element) (org-element-update-syntax)))))
 
- (defun org-link-make-regexps ()
 
-   "Update the link regular expressions.
 
- This should be called after the variable `org-link-parameters' has changed."
 
-   (let ((types-re (regexp-opt (org-link-types) t)))
 
-     (setq org-link-types-re
 
- 	  (concat "\\`" types-re ":")
 
- 	  org-link-angle-re
 
- 	  (format "<%s:\\([^>\n]*\\(?:\n[ \t]*[^> \t\n][^>\n]*\\)*\\)>"
 
- 		  types-re)
 
- 	  org-link-plain-re
 
-           (let* ((non-space-bracket "[^][ \t\n()<>]")
 
- 	         (parenthesis
 
- 		  `(seq "("
 
- 		        (0+ (or (regex ,non-space-bracket)
 
- 			        (seq "("
 
- 				     (0+ (regex ,non-space-bracket))
 
- 				     ")")))
 
- 		        ")")))
 
- 	    ;; Heuristics for an URL link inspired by
 
- 	    ;; https://daringfireball.net/2010/07/improved_regex_for_matching_urls
 
- 	    (rx-to-string
 
- 	     `(seq word-start
 
-                    ;; Link type: match group 1.
 
- 		   (regexp ,types-re)
 
- 		   ":"
 
-                    ;; Link path: match group 2.
 
-                    (group
 
- 		    (1+ (or (regex ,non-space-bracket)
 
- 			    ,parenthesis))
 
- 		    (or (regexp "[^[:punct:] \t\n]")
 
- 		        ?/
 
- 		        ,parenthesis)))))
 
-           org-link-bracket-re
 
-           (rx (seq "[["
 
- 	           ;; URI part: match group 1.
 
- 	           (group
 
- 	            (one-or-more
 
-                      (or (not (any "[]\\"))
 
- 			 (and "\\" (zero-or-more "\\\\") (any "[]"))
 
- 			 (and (one-or-more "\\") (not (any "[]"))))))
 
- 		   "]"
 
- 		   ;; Description (optional): match group 2.
 
- 		   (opt "[" (group (+? anything)) "]")
 
- 		   "]"))
 
- 	  org-link-any-re
 
- 	  (concat "\\(" org-link-bracket-re "\\)\\|\\("
 
- 		  org-link-angle-re "\\)\\|\\("
 
- 		  org-link-plain-re "\\)"))))
 
- (defun org-link-complete-file (&optional arg)
 
-   "Create a file link using completion."
 
-   (let ((file (read-file-name "File: "))
 
- 	(pwd (file-name-as-directory (expand-file-name ".")))
 
- 	(pwd1 (file-name-as-directory (abbreviate-file-name
 
- 				       (expand-file-name ".")))))
 
-     (cond ((equal arg '(16))
 
- 	   (concat "file:"
 
- 		   (abbreviate-file-name (expand-file-name file))))
 
- 	  ((string-match
 
- 	    (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
 
- 	   (concat "file:" (match-string 1 file)))
 
- 	  ((string-match
 
- 	    (concat "^" (regexp-quote pwd) "\\(.+\\)")
 
- 	    (expand-file-name file))
 
- 	   (concat "file:"
 
- 		   (match-string 1 (expand-file-name file))))
 
- 	  (t (concat "file:" file)))))
 
- (defun org-link-email-description (&optional fmt)
 
-   "Return the description part of an email link.
 
- This takes information from `org-store-link-plist' and formats it
 
- according to FMT (default from `org-link-email-description-format')."
 
-   (setq fmt (or fmt org-link-email-description-format))
 
-   (let* ((p org-store-link-plist)
 
- 	 (to (plist-get p :toaddress))
 
- 	 (from (plist-get p :fromaddress))
 
- 	 (table
 
- 	  (list
 
- 	   (cons "%c" (plist-get p :fromto))
 
- 	   (cons "%F" (plist-get p :from))
 
- 	   (cons "%f" (or (plist-get p :fromname) (plist-get p :fromaddress) "?"))
 
- 	   (cons "%T" (plist-get p :to))
 
- 	   (cons "%t" (or (plist-get p :toname) (plist-get p :toaddress) "?"))
 
- 	   (cons "%s" (plist-get p :subject))
 
- 	   (cons "%d" (plist-get p :date))
 
- 	   (cons "%m" (plist-get p :message-id)))))
 
-     (when (string-match "%c" fmt)
 
-       ;; Check if the user wrote this message
 
-       (if (and org-link-from-user-regexp from to
 
- 	       (save-match-data (string-match org-link-from-user-regexp from)))
 
- 	  (setq fmt (replace-match "to %t" t t fmt))
 
- 	(setq fmt (replace-match "from %f" t t fmt))))
 
-     (org-replace-escapes fmt table)))
 
- (defun org-link-store-props (&rest plist)
 
-   "Store link properties.
 
- The properties are pre-processed by extracting names, addresses
 
- and dates."
 
-   (let ((x (plist-get plist :from)))
 
-     (when x
 
-       (let ((adr (mail-extract-address-components x)))
 
- 	(setq plist (plist-put plist :fromname (car adr)))
 
- 	(setq plist (plist-put plist :fromaddress (nth 1 adr))))))
 
-   (let ((x (plist-get plist :to)))
 
-     (when x
 
-       (let ((adr (mail-extract-address-components x)))
 
- 	(setq plist (plist-put plist :toname (car adr)))
 
- 	(setq plist (plist-put plist :toaddress (nth 1 adr))))))
 
-   (let ((x (ignore-errors (date-to-time (plist-get plist :date)))))
 
-     (when x
 
-       (setq plist (plist-put plist :date-timestamp
 
- 			     (format-time-string
 
- 			      (org-time-stamp-format t) x)))
 
-       (setq plist (plist-put plist :date-timestamp-inactive
 
- 			     (format-time-string
 
- 			      (org-time-stamp-format t t) x)))))
 
-   (let ((from (plist-get plist :from))
 
- 	(to (plist-get plist :to)))
 
-     (when (and from to org-link-from-user-regexp)
 
-       (setq plist
 
- 	    (plist-put plist :fromto
 
- 		       (if (string-match org-link-from-user-regexp from)
 
- 			   (concat "to %t")
 
- 			 (concat "from %f"))))))
 
-   (setq org-store-link-plist plist))
 
- (defun org-link-add-props (&rest plist)
 
-   "Add these properties to the link property list."
 
-   (let (key value)
 
-     (while plist
 
-       (setq key (pop plist) value (pop plist))
 
-       (setq org-store-link-plist
 
- 	    (plist-put org-store-link-plist key value)))))
 
- (defun org-link-encode (text table)
 
-   "Return percent escaped representation of string TEXT.
 
- TEXT is a string with the text to escape.  TABLE is a list of
 
- characters that should be escaped."
 
-   (mapconcat
 
-    (lambda (c)
 
-      (if (memq c table)
 
- 	 (mapconcat (lambda (e) (format "%%%.2X" e))
 
- 		    (or (encode-coding-char c 'utf-8)
 
- 			(error "Unable to percent escape character: %c" c))
 
- 		    "")
 
-        (char-to-string c)))
 
-    text ""))
 
- (defun org-link-decode (s)
 
-   "Decode percent-encoded parts in string S.
 
- E.g. \"%C3%B6\" becomes the German o-Umlaut."
 
-   (replace-regexp-in-string "\\(%[0-9A-Za-z]\\{2\\}\\)+"
 
- 			    #'org-link--decode-compound s t t))
 
- (defun org-link-escape (link)
 
-   "Backslash-escape sensitive characters in string LINK."
 
-   (replace-regexp-in-string
 
-    (rx (seq (group (zero-or-more "\\")) (group (or string-end (any "[]")))))
 
-    (lambda (m)
 
-      (concat (match-string 1 m)
 
- 	     (match-string 1 m)
 
- 	     (and (/= (match-beginning 2) (match-end 2)) "\\")))
 
-    link nil t 1))
 
- (defun org-link-unescape (link)
 
-   "Remove escaping backslash characters from string LINK."
 
-   (replace-regexp-in-string
 
-    (rx (group (one-or-more "\\")) (or string-end (any "[]")))
 
-    (lambda (_)
 
-      (concat (make-string (/ (- (match-end 1) (match-beginning 1)) 2) ?\\)))
 
-    link nil t 1))
 
- (defun org-link-make-string (link &optional description)
 
-   "Make a bracket link, consisting of LINK and DESCRIPTION.
 
- LINK is escaped with backslashes for inclusion in buffer."
 
-   (let* ((zero-width-space (string ?\x200B))
 
- 	 (description
 
- 	  (and (org-string-nw-p description)
 
- 	       ;; Description cannot contain two consecutive square
 
- 	       ;; brackets, or end with a square bracket.  To prevent
 
- 	       ;; this, insert a zero width space character between
 
- 	       ;; the brackets, or at the end of the description.
 
- 	       (replace-regexp-in-string
 
- 		"\\(]\\)\\(]\\)"
 
- 		(concat "\\1" zero-width-space "\\2")
 
- 		(replace-regexp-in-string "]\\'"
 
- 					  (concat "\\&" zero-width-space)
 
- 					  (org-trim description))))))
 
-     (if (not (org-string-nw-p link))
 
-         (or description
 
-             (error "Empty link"))
 
-       (format "[[%s]%s]"
 
- 	      (org-link-escape link)
 
- 	      (if description (format "[%s]" description) "")))))
 
- (defun org-store-link-functions ()
 
-   "List of functions that are called to create and store a link.
 
- The functions are defined in the `:store' property of
 
- `org-link-parameters'.
 
- Each function will be called in turn until one returns a non-nil
 
- value.  Each function should check if it is responsible for
 
- creating this link (for example by looking at the major mode).
 
- If not, it must exit and return nil.  If yes, it should return
 
- a non-nil value after calling `org-link-store-props' with a list
 
- of properties and values.  Special properties are:
 
- :type         The link prefix, like \"http\".  This must be given.
 
- :link         The link, like \"http://www.astro.uva.nl/~dominik\".
 
-               This is obligatory as well.
 
- :description  Optional default description for the second pair
 
-               of brackets in an Org mode link.  The user can still change
 
-               this when inserting this link into an Org mode buffer.
 
- In addition to these, any additional properties can be specified
 
- and then used in capture templates."
 
-   (cl-loop for link in org-link-parameters
 
- 	   with store-func
 
- 	   do (setq store-func (org-link-get-parameter (car link) :store))
 
- 	   if store-func
 
- 	   collect store-func))
 
- (defun org-link-expand-abbrev (link)
 
-   "Replace link abbreviations in LINK string.
 
- Abbreviations are defined in `org-link-abbrev-alist'."
 
-   (if (not (string-match "^\\([^:]*\\)\\(::?\\(.*\\)\\)?$" link)) link
 
-     (let* ((key (match-string 1 link))
 
- 	   (as (or (assoc key org-link-abbrev-alist-local)
 
- 		   (assoc key org-link-abbrev-alist)))
 
- 	   (tag (and (match-end 2) (match-string 3 link)))
 
- 	   rpl)
 
-       (if (not as)
 
- 	  link
 
- 	(setq rpl (cdr as))
 
- 	(cond
 
- 	 ((symbolp rpl) (funcall rpl tag))
 
- 	 ((string-match "%(\\([^)]+\\))" rpl)
 
- 	  (replace-match
 
- 	   (save-match-data
 
- 	     (funcall (intern-soft (match-string 1 rpl)) tag))
 
- 	   t t rpl))
 
- 	 ((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
 
- 	 ((string-match "%h" rpl)
 
- 	  (replace-match (url-hexify-string (or tag "")) t t rpl))
 
- 	 (t (concat rpl tag)))))))
 
- (defun org-link-open (link &optional arg)
 
-   "Open a link object LINK.
 
- ARG is an optional prefix argument.  Some link types may handle
 
- it.  For example, it determines what application to run when
 
- opening a \"file\" link.
 
- Functions responsible for opening the link are either hard-coded
 
- for internal and \"file\" links, or stored as a parameter in
 
- `org-link-parameters', which see."
 
-   (let ((type (org-element-property :type link))
 
- 	(path (org-element-property :path link)))
 
-     (pcase type
 
-       ;; Opening a "file" link requires special treatment since we
 
-       ;; first need to integrate search option, if any.
 
-       ("file"
 
-        (let* ((option (org-element-property :search-option link))
 
- 	      (path (if option (concat path "::" option) path)))
 
- 	 (org-link-open-as-file path
 
- 				(pcase (org-element-property :application link)
 
- 				  ((guard arg) arg)
 
- 				  ("emacs" 'emacs)
 
- 				  ("sys" 'system)))))
 
-       ;; Internal links.
 
-       ((or "coderef" "custom-id" "fuzzy" "radio")
 
-        (unless (run-hook-with-args-until-success 'org-open-link-functions path)
 
- 	 (if (not arg) (org-mark-ring-push)
 
- 	   (switch-to-buffer-other-window (org-link--buffer-for-internals)))
 
- 	 (let ((destination
 
- 		(org-with-wide-buffer
 
- 		 (if (equal type "radio")
 
- 		     (org-link--search-radio-target path)
 
- 		   (org-link-search
 
- 		    (pcase type
 
- 		      ("custom-id" (concat "#" path))
 
- 		      ("coderef" (format "(%s)" path))
 
- 		      (_ path))
 
- 		    ;; Prevent fuzzy links from matching themselves.
 
- 		    (and (equal type "fuzzy")
 
- 			 (+ 2 (org-element-property :begin link)))))
 
- 		 (point))))
 
- 	   (unless (and (<= (point-min) destination)
 
- 			(>= (point-max) destination))
 
- 	     (widen))
 
- 	   (goto-char destination))))
 
-       (_
 
-        ;; Look for a dedicated "follow" function in custom links.
 
-        (let ((f (org-link-get-parameter type :follow)))
 
- 	 (when (functionp f)
 
- 	   ;; Function defined in `:follow' parameter may use a single
 
- 	   ;; argument, as it was mandatory before Org 9.4.  This is
 
- 	   ;; deprecated, but support it for now.
 
- 	   (condition-case nil
 
- 	       (funcall (org-link-get-parameter type :follow) path arg)
 
- 	     (wrong-number-of-arguments
 
- 	      (funcall (org-link-get-parameter type :follow) path)))))))))
 
- (defun org-link-open-from-string (s &optional arg)
 
-   "Open a link in the string S, as if it was in Org mode.
 
- Optional argument is passed to `org-open-file' when S is
 
- a \"file\" link."
 
-   (interactive "sLink: \nP")
 
-   (pcase (with-temp-buffer
 
- 	   (let ((org-inhibit-startup nil))
 
- 	     (insert s)
 
- 	     (org-mode)
 
- 	     (goto-char (point-min))
 
- 	     (org-element-link-parser)))
 
-     (`nil (user-error "No valid link in %S" s))
 
-     (link (org-link-open link arg))))
 
- (defun org-link-search (s &optional avoid-pos stealth)
 
-   "Search for a search string S.
 
- If S starts with \"#\", it triggers a custom ID search.
 
- If S is enclosed within parenthesis, it initiates a coderef
 
- search.
 
- If S is surrounded by forward slashes, it is interpreted as
 
- a regular expression.  In Org mode files, this will create an
 
- `org-occur' sparse tree.  In ordinary files, `occur' will be used
 
- to list matches.  If the current buffer is in `dired-mode', grep
 
- will be used to search in all files.
 
- When AVOID-POS is given, ignore matches near that position.
 
- When optional argument STEALTH is non-nil, do not modify
 
- visibility around point, thus ignoring `org-show-context-detail'
 
- variable.
 
- Search is case-insensitive and ignores white spaces.  Return type
 
- of matched result, which is either `dedicated' or `fuzzy'."
 
-   (unless (org-string-nw-p s) (error "Invalid search string \"%s\"" s))
 
-   (let* ((case-fold-search t)
 
- 	 (origin (point))
 
- 	 (normalized (replace-regexp-in-string "\n[ \t]*" " " s))
 
- 	 (starred (eq (string-to-char normalized) ?*))
 
- 	 (words (split-string (if starred (substring s 1) s)))
 
- 	 (s-multi-re (mapconcat #'regexp-quote words "\\(?:[ \t\n]+\\)"))
 
- 	 (s-single-re (mapconcat #'regexp-quote words "[ \t]+"))
 
- 	 type)
 
-     (cond
 
-      ;; Check if there are any special search functions.
 
-      ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
 
-      ((eq (string-to-char s) ?#)
 
-       ;; Look for a custom ID S if S starts with "#".
 
-       (let* ((id (substring normalized 1))
 
- 	     (match (org-find-property "CUSTOM_ID" id)))
 
- 	(if match (progn (goto-char match) (setf type 'dedicated))
 
- 	  (error "No match for custom ID: %s" id))))
 
-      ((string-match "\\`(\\(.*\\))\\'" normalized)
 
-       ;; Look for coderef targets if S is enclosed within parenthesis.
 
-       (let ((coderef (match-string-no-properties 1 normalized))
 
- 	    (re (substring s-single-re 1 -1)))
 
- 	(goto-char (point-min))
 
- 	(catch :coderef-match
 
- 	  (while (re-search-forward re nil t)
 
- 	    (let ((element (org-element-at-point)))
 
- 	      (when (and (memq (org-element-type element)
 
- 			       '(example-block src-block))
 
- 			 (org-match-line
 
- 			  (concat ".*?" (org-src-coderef-regexp
 
- 					 (org-src-coderef-format element)
 
- 					 coderef))))
 
- 		(setq type 'dedicated)
 
- 		(goto-char (match-beginning 2))
 
- 		(throw :coderef-match nil))))
 
- 	  (goto-char origin)
 
- 	  (error "No match for coderef: %s" coderef))))
 
-      ((string-match "\\`/\\(.*\\)/\\'" normalized)
 
-       ;; Look for a regular expression.
 
-       (funcall (if (derived-mode-p 'org-mode) #'org-occur #'org-do-occur)
 
- 	       (match-string 1 s)))
 
-      ;; From here, we handle fuzzy links.
 
-      ;;
 
-      ;; Look for targets, only if not in a headline search.
 
-      ((and (not starred)
 
- 	   (let ((target (format "<<%s>>" s-multi-re)))
 
- 	     (catch :target-match
 
- 	       (goto-char (point-min))
 
- 	       (while (re-search-forward target nil t)
 
- 		 (backward-char)
 
- 		 (let ((context (org-element-context)))
 
- 		   (when (eq (org-element-type context) 'target)
 
- 		     (setq type 'dedicated)
 
- 		     (goto-char (org-element-property :begin context))
 
- 		     (throw :target-match t))))
 
- 	       nil))))
 
-      ;; Look for elements named after S, only if not in a headline
 
-      ;; search.
 
-      ((and (not starred)
 
- 	   (let ((name (format "^[ \t]*#\\+NAME: +%s[ \t]*$" s-single-re)))
 
- 	     (catch :name-match
 
- 	       (goto-char (point-min))
 
- 	       (while (re-search-forward name nil t)
 
- 		 (let* ((element (org-element-at-point))
 
- 			(name (org-element-property :name element)))
 
- 		   (when (and name (equal words (split-string name)))
 
- 		     (setq type 'dedicated)
 
- 		     (beginning-of-line)
 
- 		     (throw :name-match t))))
 
- 	       nil))))
 
-      ;; Regular text search.  Prefer headlines in Org mode buffers.
 
-      ;; Ignore COMMENT keyword, TODO keywords, priority cookies,
 
-      ;; statistics cookies and tags.
 
-      ((and (derived-mode-p 'org-mode)
 
- 	   (let ((title-re
 
- 		  (format "%s.*\\(?:%s[ \t]\\)?.*%s"
 
- 			  org-outline-regexp-bol
 
- 			  org-comment-string
 
- 			  (mapconcat #'regexp-quote words ".+"))))
 
- 	     (goto-char (point-min))
 
- 	     (catch :found
 
- 	       (while (re-search-forward title-re nil t)
 
- 		 (when (equal words
 
- 			      (split-string
 
- 			       (org-link--normalize-string
 
- 				(org-get-heading t t t t))))
 
- 		   (throw :found t)))
 
- 	       nil)))
 
-       (beginning-of-line)
 
-       (setq type 'dedicated))
 
-      ;; Offer to create non-existent headline depending on
 
-      ;; `org-link-search-must-match-exact-headline'.
 
-      ((and (derived-mode-p 'org-mode)
 
- 	   (eq org-link-search-must-match-exact-headline 'query-to-create)
 
- 	   (yes-or-no-p "No match - create this as a new heading? "))
 
-       (goto-char (point-max))
 
-       (unless (bolp) (newline))
 
-       (org-insert-heading nil t t)
 
-       (insert s "\n")
 
-       (beginning-of-line 0))
 
-      ;; Only headlines are looked after.  No need to process
 
-      ;; further: throw an error.
 
-      ((and (derived-mode-p 'org-mode)
 
- 	   (or starred org-link-search-must-match-exact-headline))
 
-       (goto-char origin)
 
-       (error "No match for fuzzy expression: %s" normalized))
 
-      ;; Regular text search.
 
-      ((catch :fuzzy-match
 
- 	(goto-char (point-min))
 
- 	(while (re-search-forward s-multi-re nil t)
 
- 	  ;; Skip match if it contains AVOID-POS or it is included in
 
- 	  ;; a link with a description but outside the description.
 
- 	  (unless (or (and avoid-pos
 
- 			   (<= (match-beginning 0) avoid-pos)
 
- 			   (> (match-end 0) avoid-pos))
 
- 		      (and (save-match-data
 
- 			     (org-in-regexp org-link-bracket-re))
 
- 			   (match-beginning 3)
 
- 			   (or (> (match-beginning 3) (point))
 
- 			       (<= (match-end 3) (point)))
 
- 			   (org-element-lineage
 
- 			    (save-match-data (org-element-context))
 
- 			    '(link) t)))
 
- 	    (goto-char (match-beginning 0))
 
- 	    (setq type 'fuzzy)
 
- 	    (throw :fuzzy-match t)))
 
- 	nil))
 
-      ;; All failed.  Throw an error.
 
-      (t (goto-char origin)
 
- 	(error "No match for fuzzy expression: %s" normalized)))
 
-     ;; Disclose surroundings of match, if appropriate.
 
-     (when (and (derived-mode-p 'org-mode) (not stealth))
 
-       (org-fold-show-context 'link-search))
 
-     type))
 
- (defun org-link-heading-search-string (&optional string)
 
-   "Make search string for the current headline or STRING.
 
- Search string starts with an asterisk.  COMMENT keyword and
 
- statistics cookies are removed, and contiguous spaces are packed
 
- into a single one.
 
- When optional argument STRING is non-nil, assume it a headline,
 
- without any asterisk, TODO or COMMENT keyword, and without any
 
- priority cookie or tag."
 
-   (concat "*"
 
- 	  (org-link--normalize-string
 
- 	   (or string (org-get-heading t t t t)))))
 
- (defun org-link-open-as-file (path arg)
 
-   "Pretend PATH is a file name and open it.
 
- According to \"file\"-link syntax, PATH may include additional
 
- search options, separated from the file name with \"::\".
 
- This function is meant to be used as a possible tool for
 
- `:follow' property in `org-link-parameters'."
 
-   (let* ((option (and (string-match "::\\(.*\\)\\'" path)
 
- 		      (match-string 1 path)))
 
- 	 (file-name (if (not option) path
 
- 		      (substring path 0 (match-beginning 0)))))
 
-     (if (string-match "[*?{]" (file-name-nondirectory file-name))
 
- 	(dired file-name)
 
-       (apply #'org-open-file
 
- 	     file-name
 
- 	     arg
 
- 	     (cond ((not option) nil)
 
- 		   ((string-match-p "\\`[0-9]+\\'" option)
 
- 		    (list (string-to-number option)))
 
- 		   (t (list nil option)))))))
 
- (defun org-link-display-format (s)
 
-   "Replace links in string S with their description.
 
- If there is no description, use the link target."
 
-   (save-match-data
 
-     (replace-regexp-in-string
 
-      org-link-bracket-re
 
-      (lambda (m) (or (match-string 2 m) (match-string 1 m)))
 
-      s nil t)))
 
- (defun org-link-add-angle-brackets (s)
 
-   "Wrap string S within angle brackets."
 
-   (unless (equal (substring s 0 1) "<") (setq s (concat "<" s)))
 
-   (unless (equal (substring s -1) ">") (setq s (concat s ">")))
 
-   s)
 
- ;;; Built-in link types
 
- ;;;; "elisp" link type
 
- (defun org-link--open-elisp (path _)
 
-   "Open a \"elisp\" type link.
 
- PATH is the sexp to evaluate, as a string."
 
-   (if (or (and (org-string-nw-p org-link-elisp-skip-confirm-regexp)
 
- 	       (string-match-p org-link-elisp-skip-confirm-regexp path))
 
- 	  (not org-link-elisp-confirm-function)
 
- 	  (funcall org-link-elisp-confirm-function
 
- 		   (format "Execute %s as Elisp? "
 
- 			   (org-add-props path nil 'face 'org-warning))))
 
-       (message "%s => %s" path
 
- 	       (if (eq ?\( (string-to-char path))
 
- 		   (eval (read path))
 
- 		 (call-interactively (read path))))
 
-     (user-error "Abort")))
 
- (org-link-set-parameters "elisp" :follow #'org-link--open-elisp)
 
- ;;;; "file" link type
 
- (org-link-set-parameters "file" :complete #'org-link-complete-file)
 
- ;;;; "help" link type
 
- (defun org-link--open-help (path _)
 
-   "Open a \"help\" type link.
 
- PATH is a symbol name, as a string."
 
-   (pcase (intern path)
 
-     ((and (pred fboundp) function) (describe-function function))
 
-     ((and (pred boundp) variable) (describe-variable variable))
 
-     (name (user-error "Unknown function or variable: %s" name))))
 
- (defun org-link--store-help ()
 
-   "Store \"help\" type link."
 
-   (when (eq major-mode 'help-mode)
 
-     (let ((symbol
 
-            (save-excursion
 
- 	     (goto-char (point-min))
 
-              ;; In case the help is about the key-binding, store the
 
-              ;; function instead.
 
-              (search-forward "runs the command " (line-end-position) t)
 
-              (read (current-buffer)))))
 
-       (org-link-store-props :type "help"
 
-                             :link (format "help:%s" symbol)
 
-                             :description nil))))
 
- (org-link-set-parameters "help"
 
-                          :follow #'org-link--open-help
 
-                          :store #'org-link--store-help)
 
- ;;;; "http", "https", "mailto", "ftp", and "news" link types
 
- (dolist (scheme '("ftp" "http" "https" "mailto" "news"))
 
-   (org-link-set-parameters scheme
 
- 			   :follow
 
- 			   (lambda (url arg)
 
- 			     (browse-url (concat scheme ":" url) arg))))
 
- ;;;; "shell" link type
 
- (defun org-link--open-shell (path _)
 
-   "Open a \"shell\" type link.
 
- PATH is the command to execute, as a string."
 
-   (if (or (and (org-string-nw-p org-link-shell-skip-confirm-regexp)
 
- 	       (string-match-p org-link-shell-skip-confirm-regexp path))
 
- 	  (not org-link-shell-confirm-function)
 
- 	  (funcall org-link-shell-confirm-function
 
- 		   (format "Execute %s in shell? "
 
- 			   (org-add-props path nil 'face 'org-warning))))
 
-       (let ((buf (generate-new-buffer "*Org Shell Output*")))
 
- 	(message "Executing %s" path)
 
- 	(shell-command path buf)
 
- 	(when (featurep 'midnight)
 
- 	  (setq clean-buffer-list-kill-buffer-names
 
- 		(cons (buffer-name buf)
 
- 		      clean-buffer-list-kill-buffer-names))))
 
-     (user-error "Abort")))
 
- (org-link-set-parameters "shell" :follow #'org-link--open-shell)
 
- ;;; Interactive Functions
 
- ;;;###autoload
 
- (defun org-next-link (&optional search-backward)
 
-   "Move forward to the next link.
 
- If the link is in hidden text, expose it.  When SEARCH-BACKWARD
 
- is non-nil, move backward."
 
-   (interactive)
 
-   (let ((pos (point))
 
- 	(search-fun (if search-backward #'re-search-backward
 
- 		      #'re-search-forward)))
 
-     ;; Tweak initial position.  If last search failed, wrap around.
 
-     ;; Otherwise, make sure we do not match current link.
 
-     (cond
 
-      ((not (and org-link--search-failed (eq this-command last-command)))
 
-       (cond
 
-        ((and (not search-backward) (looking-at org-link-any-re))
 
- 	(goto-char (match-end 0)))
 
-        (search-backward
 
- 	(pcase (org-in-regexp org-link-any-re nil t)
 
- 	  (`(,beg . ,_) (goto-char beg))
 
- 	  (_ nil)))
 
-        (t nil)))
 
-      (search-backward
 
-       (goto-char (point-max))
 
-       (message "Link search wrapped back to end of buffer"))
 
-      (t
 
-       (goto-char (point-min))
 
-       (message "Link search wrapped back to beginning of buffer")))
 
-     (setq org-link--search-failed nil)
 
-     (catch :found
 
-       (while (funcall search-fun org-link-any-re nil t)
 
- 	(let ((context (save-excursion
 
- 			 (unless search-backward (forward-char -1))
 
- 			 (org-element-context))))
 
- 	  (pcase (org-element-lineage context '(link) t)
 
- 	    (`nil nil)
 
- 	    (link
 
- 	     (goto-char (org-element-property :begin link))
 
- 	     (when (org-invisible-p) (org-fold-show-context 'link-search))
 
- 	     (throw :found t)))))
 
-       (goto-char pos)
 
-       (setq org-link--search-failed t)
 
-       (message "No further link found"))))
 
- ;;;###autoload
 
- (defun org-previous-link ()
 
-   "Move backward to the previous link.
 
- If the link is in hidden text, expose it."
 
-   (interactive)
 
-   (org-next-link t))
 
- (defun org-link-descriptive-ensure ()
 
-   "Toggle the literal or descriptive display of links in current buffer if needed."
 
-   (if org-link-descriptive
 
-       (org-fold-core-set-folding-spec-property (car org-link--link-folding-spec) :visible nil)
 
-     (org-fold-core-set-folding-spec-property (car org-link--link-folding-spec) :visible t)))
 
- ;;;###autoload
 
- (defun org-toggle-link-display ()
 
-   "Toggle the literal or descriptive display of links in current buffer."
 
-   (interactive)
 
-   (setq org-link-descriptive (not org-link-descriptive))
 
-   (org-link-descriptive-ensure))
 
- ;;;###autoload
 
- (defun org-store-link (arg &optional interactive?)
 
-   "Store a link to the current location.
 
- \\<org-mode-map>
 
- This link is added to `org-stored-links' and can later be inserted
 
- into an Org buffer with `org-insert-link' (`\\[org-insert-link]').
 
- For some link types, a `\\[universal-argument]' prefix ARG is interpreted.  \
 
- A single
 
- `\\[universal-argument]' negates `org-context-in-file-links' for file links or
 
- `org-gnus-prefer-web-links' for links to Usenet articles.
 
- A `\\[universal-argument] \\[universal-argument]' prefix ARG forces \
 
- skipping storing functions that are not
 
- part of Org core.
 
- A `\\[universal-argument] \\[universal-argument] \\[universal-argument]' \
 
- prefix ARG forces storing a link for each line in the
 
- active region.
 
- Assume the function is called interactively if INTERACTIVE? is
 
- non-nil."
 
-   (interactive "P\np")
 
-   (org-load-modules-maybe)
 
-   (if (and (equal arg '(64)) (org-region-active-p))
 
-       (save-excursion
 
- 	(let ((end (region-end)))
 
- 	  (goto-char (region-beginning))
 
- 	  (set-mark (point))
 
- 	  (while (< (point-at-eol) end)
 
- 	    (move-end-of-line 1) (activate-mark)
 
- 	    (let (current-prefix-arg)
 
- 	      (call-interactively 'org-store-link))
 
- 	    (move-beginning-of-line 2)
 
- 	    (set-mark (point)))))
 
-     (setq org-store-link-plist nil)
 
-     (let (link cpltxt desc search custom-id agenda-link) ;; description
 
-       (cond
 
-        ;; Store a link using an external link type, if any function is
 
-        ;; available. If more than one can generate a link from current
 
-        ;; location, ask which one to use.
 
-        ((and (not (equal arg '(16)))
 
- 	     (let ((results-alist nil))
 
- 	       (dolist (f (org-store-link-functions))
 
- 		 (when (funcall f)
 
- 		   ;; XXX: return value is not link's plist, so we
 
- 		   ;; store the new value before it is modified.  It
 
- 		   ;; would be cleaner to ask store link functions to
 
- 		   ;; return the plist instead.
 
- 		   (push (cons f (copy-sequence org-store-link-plist))
 
- 			 results-alist)))
 
- 	       (pcase results-alist
 
- 		 (`nil nil)
 
- 		 (`((,_ . ,_)) t)	;single choice: nothing to do
 
- 		 (`((,name . ,_) . ,_)
 
- 		  ;; Reinstate link plist associated to the chosen
 
- 		  ;; function.
 
- 		  (apply #'org-link-store-props
 
- 			 (cdr (assoc-string
 
- 			       (completing-read
 
-                                 (format "Store link with (default %s): " name)
 
-                                 (mapcar #'car results-alist)
 
-                                 nil t nil nil (symbol-name name))
 
- 			       results-alist)))
 
- 		  t))))
 
- 	(setq link (plist-get org-store-link-plist :link))
 
-         ;; If store function actually set `:description' property, use
 
-         ;; it, even if it is nil.  Otherwise, fallback to link value.
 
- 	(setq desc (if (plist-member org-store-link-plist :description)
 
-                        (plist-get org-store-link-plist :description)
 
- 		     link)))
 
-        ;; Store a link from a remote editing buffer.
 
-        ((org-src-edit-buffer-p)
 
- 	(let ((coderef-format (org-src-coderef-format))
 
- 	      (format-link
 
- 	       (lambda (label)
 
- 		 (if org-src-source-file-name
 
- 		     (format "file:%s::(%s)" org-src-source-file-name label)
 
- 		   (format "(%s)" label)))))
 
- 	  (cond
 
- 	   ;; Code references do not exist in this type of buffer.
 
- 	   ;; Pretend we're linking from the source buffer directly.
 
- 	   ((not (memq (org-src-source-type) '(example-block src-block)))
 
- 	    (with-current-buffer (org-src-source-buffer)
 
- 	      (org-store-link arg interactive?))
 
- 	    (setq link nil))
 
- 	   ;; A code reference exists.  Use it.
 
- 	   ((save-excursion
 
- 	      (beginning-of-line)
 
- 	      (re-search-forward (org-src-coderef-regexp coderef-format)
 
- 				 (line-end-position)
 
- 				 t))
 
- 	    (setq link (funcall format-link (match-string-no-properties 3))))
 
- 	   ;; No code reference.  Create a new one then store the link
 
- 	   ;; to it, but only in the function is called interactively.
 
- 	   (interactive?
 
- 	    (end-of-line)
 
- 	    (let* ((label (read-string "Code line label: "))
 
- 		   (reference (format coderef-format label))
 
- 		   (gc (- 79 (length reference))))
 
- 	      (if (< (current-column) gc)
 
- 		  (org-move-to-column gc t)
 
- 		(insert " "))
 
- 	      (insert reference)
 
- 	      (setq link (funcall format-link label))))
 
- 	   ;; No code reference, and non-interactive call.  Don't know
 
- 	   ;; what to do.  Give up.
 
- 	   (t (setq link nil)))))
 
-        ;; We are in the agenda, link to referenced location
 
-        ((equal (bound-and-true-p org-agenda-buffer-name) (buffer-name))
 
- 	(let ((m (or (get-text-property (point) 'org-hd-marker)
 
- 		     (get-text-property (point) 'org-marker))))
 
- 	  (when m
 
- 	    (org-with-point-at m
 
- 	      (setq agenda-link (org-store-link nil interactive?))))))
 
-        ((eq major-mode 'calendar-mode)
 
- 	(let ((cd (calendar-cursor-to-date)))
 
- 	  (setq link
 
- 		(format-time-string
 
- 		 (car org-time-stamp-formats)
 
- 		 (org-encode-time 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd))))
 
- 	  (org-link-store-props :type "calendar" :date cd)))
 
-        ((eq major-mode 'w3-mode)
 
- 	(setq cpltxt (if (and (buffer-name)
 
- 			      (not (string-match "Untitled" (buffer-name))))
 
- 			 (buffer-name)
 
- 		       (url-view-url t))
 
- 	      link (url-view-url t))
 
- 	(org-link-store-props :type "w3" :url (url-view-url t)))
 
-        ((eq major-mode 'image-mode)
 
- 	(setq cpltxt (concat "file:"
 
- 			     (abbreviate-file-name buffer-file-name))
 
- 	      link cpltxt)
 
- 	(org-link-store-props :type "image" :file buffer-file-name))
 
-        ;; In dired, store a link to the file of the current line
 
-        ((derived-mode-p 'dired-mode)
 
- 	(let ((file (dired-get-filename nil t)))
 
- 	  (setq file (if file
 
- 			 (abbreviate-file-name
 
- 			  (expand-file-name (dired-get-filename nil t)))
 
- 		       ;; Otherwise, no file so use current directory.
 
- 		       default-directory))
 
- 	  (setq cpltxt (concat "file:" file)
 
- 		link cpltxt)))
 
-        ((setq search (run-hook-with-args-until-success
 
- 		      'org-create-file-search-functions))
 
- 	(setq link (concat "file:" (abbreviate-file-name buffer-file-name)
 
- 			   "::" search))
 
- 	(setq cpltxt (or link))) ;; description
 
-        ((and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 'org-mode))
 
- 	(org-with-limited-levels
 
-          (cond
 
- 	  ;; Store a link using the target at point.
 
- 	  ((org-in-regexp "[^<]<<\\([^<>]+\\)>>[^>]" 1)
 
- 	   (setq cpltxt
 
- 		 (concat "file:"
 
- 			 (abbreviate-file-name
 
- 			  (buffer-file-name (buffer-base-buffer)))
 
- 			 "::" (match-string 1))
 
- 		 link cpltxt))
 
-           ;; Store a link using the CUSTOM_ID property.
 
-           ((setq custom-id (org-entry-get nil "CUSTOM_ID"))
 
-            (setq cpltxt
 
- 		 (concat "file:"
 
- 			 (abbreviate-file-name
 
- 			  (buffer-file-name (buffer-base-buffer)))
 
- 			 "::#" custom-id)
 
- 		 link cpltxt))
 
-           ;; Store a link using (and perhaps creating) the ID property.
 
- 	  ((and (featurep 'org-id)
 
- 		(or (eq org-id-link-to-org-use-id t)
 
- 		    (and interactive?
 
- 			 (or (eq org-id-link-to-org-use-id 'create-if-interactive)
 
- 			     (and (eq org-id-link-to-org-use-id
 
- 				      'create-if-interactive-and-no-custom-id)
 
- 				  (not custom-id))))
 
- 		    (and org-id-link-to-org-use-id (org-entry-get nil "ID"))))
 
- 	   (setq link (condition-case nil
 
- 			  (prog1 (org-id-store-link)
 
- 			    (setq desc (or (plist-get org-store-link-plist
 
- 						      :description)
 
- 					   "")))
 
- 			(error
 
- 			 ;; Probably before first headline, link only to file.
 
- 			 (concat "file:"
 
- 				 (abbreviate-file-name
 
- 				  (buffer-file-name (buffer-base-buffer))))))))
 
- 	  (t
 
- 	   ;; Just link to current headline.
 
- 	   (setq cpltxt (concat "file:"
 
- 				(abbreviate-file-name
 
- 				 (buffer-file-name (buffer-base-buffer)))))
 
- 	   ;; Add a context search string.
 
- 	   (when (org-xor org-link-context-for-files (equal arg '(4)))
 
- 	     (let* ((element (org-element-at-point))
 
- 		    (name (org-element-property :name element))
 
- 		    (context
 
- 		     (cond
 
- 		      ((let ((region (org-link--context-from-region)))
 
- 			 (and region (org-link--normalize-string region t))))
 
- 		      (name)
 
- 		      ((org-before-first-heading-p)
 
- 		       (org-link--normalize-string (org-current-line-string) t))
 
- 		      (t (org-link-heading-search-string)))))
 
- 	       (when (org-string-nw-p context)
 
- 		 (setq cpltxt (format "%s::%s" cpltxt context))
 
- 		 (setq desc
 
- 		       (or name
 
- 			   ;; Although description is not a search
 
- 			   ;; string, use `org-link--normalize-string'
 
- 			   ;; to prettify it (contiguous white spaces)
 
- 			   ;; and remove volatile contents (statistics
 
- 			   ;; cookies).
 
- 			   (and (not (org-before-first-heading-p))
 
- 				(org-link--normalize-string
 
- 				 (org-get-heading t t t t)))
 
- 			   "NONE")))))
 
- 	   (setq link cpltxt)))))
 
-        ((buffer-file-name (buffer-base-buffer))
 
- 	;; Just link to this file here.
 
- 	(setq cpltxt (concat "file:"
 
- 			     (abbreviate-file-name
 
- 			      (buffer-file-name (buffer-base-buffer)))))
 
- 	;; Add a context search string.
 
- 	(when (org-xor org-link-context-for-files (equal arg '(4)))
 
- 	  (let ((context (org-link--normalize-string
 
- 			  (or (org-link--context-from-region)
 
- 			      (org-current-line-string))
 
- 			  t)))
 
- 	    ;; Only use search option if there is some text.
 
- 	    (when (org-string-nw-p context)
 
- 	      (setq cpltxt (format "%s::%s" cpltxt context))
 
- 	      (setq desc "NONE"))))
 
- 	(setq link cpltxt))
 
-        (interactive?
 
- 	(user-error "No method for storing a link from this buffer"))
 
-        (t (setq link nil)))
 
-       ;; We're done setting link and desc, clean up
 
-       (when (consp link) (setq cpltxt (car link) link (cdr link)))
 
-       (setq link (or link cpltxt)
 
- 	    desc (or desc cpltxt))
 
-       (cond ((not desc))
 
- 	    ((equal desc "NONE") (setq desc nil))
 
- 	    (t (setq desc (org-link-display-format desc))))
 
-       ;; Store and return the link
 
-       (if (not (and interactive? link))
 
- 	  (or agenda-link (and link (org-link-make-string link desc)))
 
- 	(if (member (list link desc) org-stored-links)
 
- 	    (message "This link has already been stored")
 
- 	  (push (list link desc) org-stored-links)
 
- 	  (message "Stored: %s" (or desc link))
 
- 	  (when custom-id
 
- 	    (setq link (concat "file:"
 
- 			       (abbreviate-file-name
 
- 				(buffer-file-name (buffer-base-buffer)))
 
- 			       "::#" custom-id))
 
- 	    (push (list link desc) org-stored-links)))
 
- 	(car org-stored-links)))))
 
- ;;;###autoload
 
- (defun org-insert-link (&optional complete-file link-location description)
 
-   "Insert a link.  At the prompt, enter the link.
 
- Completion can be used to insert any of the link protocol prefixes in use.
 
- The history can be used to select a link previously stored with
 
- `org-store-link'.  When the empty string is entered (i.e. if you just
 
- press `RET' at the prompt), the link defaults to the most recently
 
- stored link.  As `SPC' triggers completion in the minibuffer, you need to
 
- use `M-SPC' or `C-q SPC' to force the insertion of a space character.
 
- You will also be prompted for a description, and if one is given, it will
 
- be displayed in the buffer instead of the link.
 
- If there is already a link at point, this command will allow you to edit
 
- link and description parts.
 
- With a `\\[universal-argument]' prefix, prompts for a file to link to.  The \
 
- file name can be
 
- selected using completion.  The path to the file will be relative to the
 
- current directory if the file is in the current directory or a subdirectory.
 
- Otherwise, the link will be the absolute path as completed in the minibuffer
 
- \(i.e. normally ~/path/to/file).  You can configure this behavior using the
 
- option `org-link-file-path-type'.
 
- With a `\\[universal-argument] \\[universal-argument]' prefix, enforce an \
 
- absolute path even if the file is in
 
- the current directory or below.
 
- A `\\[universal-argument] \\[universal-argument] \\[universal-argument]' \
 
- prefix negates `org-link-keep-stored-after-insertion'.
 
- If the LINK-LOCATION parameter is non-nil, this value will be used as
 
- the link location instead of reading one interactively.
 
- If the DESCRIPTION parameter is non-nil, this value will be used
 
- as the default description.  If not, and the chosen link type has
 
- a non-nil `:insert-description' parameter, that is used to
 
- generate a description as described in `org-link-parameters'
 
- docstring.  Otherwise, if `org-link-make-description-function' is
 
- non-nil, this function will be called with the link target, and
 
- the result will be the default link description.  When called
 
- non-interactively, don't allow to edit the default description."
 
-   (interactive "P")
 
-   (let* ((wcf (current-window-configuration))
 
- 	 (origbuf (current-buffer))
 
- 	 (region (when (org-region-active-p)
 
- 		   (buffer-substring (region-beginning) (region-end))))
 
- 	 (remove (and region (list (region-beginning) (region-end))))
 
- 	 (desc region)
 
- 	 (link link-location)
 
- 	 (abbrevs org-link-abbrev-alist-local)
 
- 	 (all-prefixes (append (mapcar #'car abbrevs)
 
- 			       (mapcar #'car org-link-abbrev-alist)
 
- 			       (org-link-types)))
 
-          entry auto-desc)
 
-     (cond
 
-      (link-location)		      ; specified by arg, just use it.
 
-      ((org-in-regexp org-link-bracket-re 1)
 
-       ;; We do have a link at point, and we are going to edit it.
 
-       (setq remove (list (match-beginning 0) (match-end 0)))
 
-       (setq desc (when (match-end 2) (match-string-no-properties 2)))
 
-       (setq link (read-string "Link: "
 
- 			      (org-link-unescape
 
- 			       (match-string-no-properties 1)))))
 
-      ((or (org-in-regexp org-link-angle-re)
 
- 	  (org-in-regexp org-link-plain-re))
 
-       ;; Convert to bracket link
 
-       (setq remove (list (match-beginning 0) (match-end 0))
 
- 	    link (read-string "Link: "
 
- 			      (org-unbracket-string "<" ">" (match-string 0)))))
 
-      ((member complete-file '((4) (16)))
 
-       ;; Completing read for file names.
 
-       (setq link (org-link-complete-file complete-file)))
 
-      (t
 
-       ;; Read link, with completion for stored links.
 
-       (org-link--fontify-links-to-this-file)
 
-       (org-switch-to-buffer-other-window "*Org Links*")
 
-       (with-current-buffer "*Org Links*"
 
- 	(erase-buffer)
 
- 	(insert "Insert a link.
 
- Use TAB to complete link prefixes, then RET for type-specific completion support\n")
 
- 	(when org-stored-links
 
- 	  (insert "\nStored links are available with <up>/<down> or M-p/n \
 
- \(most recent with RET):\n\n")
 
- 	  (insert (mapconcat #'org-link--prettify
 
- 			     (reverse org-stored-links)
 
- 			     "\n")))
 
- 	(goto-char (point-min)))
 
-       (when (get-buffer-window "*Org Links*" 'visible)
 
-         (let ((cw (selected-window)))
 
- 	  (select-window (get-buffer-window "*Org Links*" 'visible))
 
- 	  (with-current-buffer "*Org Links*" (setq truncate-lines t))
 
- 	  (unless (pos-visible-in-window-p (point-max))
 
- 	    (org-fit-window-to-buffer))
 
- 	  (and (window-live-p cw) (select-window cw))))
 
-       (unwind-protect
 
- 	  ;; Fake a link history, containing the stored links.
 
- 	  (let ((org-link--history
 
- 		 (append (mapcar #'car org-stored-links)
 
- 			 org-link--insert-history)))
 
- 	    (setq link
 
- 		  (org-completing-read
 
- 		   "Link: "
 
- 		   (append
 
- 		    (mapcar (lambda (x) (concat x ":")) all-prefixes)
 
- 		    (mapcar #'car org-stored-links))
 
- 		   nil nil nil
 
- 		   'org-link--history
 
- 		   (caar org-stored-links)))
 
- 	    (unless (org-string-nw-p link) (user-error "No link selected"))
 
- 	    (dolist (l org-stored-links)
 
- 	      (when (equal link (cadr l))
 
- 		(setq link (car l))
 
- 		(setq auto-desc t)))
 
- 	    (when (or (member link all-prefixes)
 
- 		      (and (equal ":" (substring link -1))
 
- 			   (member (substring link 0 -1) all-prefixes)
 
- 			   (setq link (substring link 0 -1))))
 
- 	      (setq link (with-current-buffer origbuf
 
- 			   (org-link--try-special-completion link)))))
 
- 	(set-window-configuration wcf)
 
- 	(kill-buffer "*Org Links*"))
 
-       (setq entry (assoc link org-stored-links))
 
-       (or entry (push link org-link--insert-history))
 
-       (setq desc (or desc (nth 1 entry)))))
 
-     (when (funcall (if (equal complete-file '(64)) 'not 'identity)
 
- 		   (not org-link-keep-stored-after-insertion))
 
-       (setq org-stored-links (delq (assoc link org-stored-links)
 
- 				   org-stored-links)))
 
-     (when (and (string-match org-link-plain-re link)
 
- 	       (not (string-match org-ts-regexp link)))
 
-       ;; URL-like link, normalize the use of angular brackets.
 
-       (setq link (org-unbracket-string "<" ">" link)))
 
-     ;; Check if we are linking to the current file with a search
 
-     ;; option If yes, simplify the link by using only the search
 
-     ;; option.
 
-     (when (and (buffer-file-name (buffer-base-buffer))
 
- 	       (let ((case-fold-search nil))
 
- 		 (string-match "\\`file:\\(.+?\\)::" link)))
 
-       (let ((path (match-string-no-properties 1 link))
 
- 	    (search (substring-no-properties link (match-end 0))))
 
- 	(save-match-data
 
- 	  (when (equal (file-truename (buffer-file-name (buffer-base-buffer)))
 
- 		       (file-truename path))
 
- 	    ;; We are linking to this same file, with a search option
 
- 	    (setq link search)))))
 
-     ;; Check if we can/should use a relative path.  If yes, simplify
 
-     ;; the link.
 
-     (let ((case-fold-search nil))
 
-       (when (string-match "\\`\\(file\\|docview\\):" link)
 
- 	(let* ((type (match-string-no-properties 0 link))
 
- 	       (path-start (match-end 0))
 
- 	       (search (and (string-match "::\\(.*\\)\\'" link)
 
- 			    (match-string 1 link)))
 
- 	       (path
 
- 		(if search
 
- 		    (substring-no-properties
 
- 		     link path-start (match-beginning 0))
 
- 		  (substring-no-properties link (match-end 0))))
 
- 	       (origpath path))
 
- 	  (cond
 
- 	   ((or (eq org-link-file-path-type 'absolute)
 
- 		(equal complete-file '(16)))
 
- 	    (setq path (abbreviate-file-name (expand-file-name path))))
 
- 	   ((eq org-link-file-path-type 'noabbrev)
 
- 	    (setq path (expand-file-name path)))
 
- 	   ((eq org-link-file-path-type 'relative)
 
- 	    (setq path (file-relative-name path)))
 
- 	   ((functionp org-link-file-path-type)
 
- 	    (setq path (funcall org-link-file-path-type
 
- 				(expand-file-name path))))
 
- 	   (t
 
- 	    (save-match-data
 
- 	      (if (string-match (concat "^" (regexp-quote
 
- 					     (expand-file-name
 
- 					      (file-name-as-directory
 
- 					       default-directory))))
 
- 				(expand-file-name path))
 
- 		  ;; We are linking a file with relative path name.
 
- 		  (setq path (substring (expand-file-name path)
 
- 					(match-end 0)))
 
- 		(setq path (abbreviate-file-name (expand-file-name path)))))))
 
- 	  (setq link (concat type path (and search (concat "::" search))))
 
- 	  (when (equal desc origpath)
 
- 	    (setq desc path)))))
 
-     (unless auto-desc
 
-       (let* ((type
 
-               (cond
 
-                ((and all-prefixes
 
-                      (string-match (rx-to-string `(: string-start (submatch (or ,@all-prefixes)) ":")) link))
 
-                 (match-string 1 link))
 
-                ((file-name-absolute-p link) "file")
 
-                ((string-match "\\`\\.\\.?/" link) "file")))
 
-              (initial-input
 
- 	      (cond
 
- 	       (description)
 
-                (desc)
 
-                ((org-link-get-parameter type :insert-description)
 
-                 (let ((def (org-link-get-parameter type :insert-description)))
 
-                   (condition-case nil
 
-                       (cond
 
-                        ((stringp def) def)
 
-                        ((functionp def)
 
-                         (funcall def link desc)))
 
-                     (error
 
-                      (message "Can't get link description from org link parameter `:insert-description': %S"
 
- 			      def)
 
- 		     (sit-for 2)
 
-                      nil))))
 
- 	       (org-link-make-description-function
 
-                 (condition-case nil
 
- 		    (funcall org-link-make-description-function link desc)
 
- 		  (error
 
- 		   (message "Can't get link description from %S"
 
- 		            org-link-make-description-function)
 
- 		   (sit-for 2)
 
- 		   nil))))))
 
- 	(setq desc (if (called-interactively-p 'any)
 
- 		       (read-string "Description: " initial-input)
 
- 		     initial-input))))
 
-     (unless (org-string-nw-p desc) (setq desc nil))
 
-     (when remove (apply #'delete-region remove))
 
-     (insert (org-link-make-string link desc))
 
-     ;; Redisplay so as the new link has proper invisible characters.
 
-     (sit-for 0)))
 
- ;;;###autoload
 
- (defun org-insert-all-links (arg &optional pre post)
 
-   "Insert all links in `org-stored-links'.
 
- When a universal prefix, do not delete the links from `org-stored-links'.
 
- When `ARG' is a number, insert the last N link(s).
 
- `PRE' and `POST' are optional arguments to define a string to
 
- prepend or to append."
 
-   (interactive "P")
 
-   (let ((org-link-keep-stored-after-insertion (equal arg '(4)))
 
- 	(links (copy-sequence org-stored-links))
 
- 	(pr (or pre "- "))
 
- 	(po (or post "\n"))
 
- 	(cnt 1) l)
 
-     (if (null org-stored-links)
 
- 	(message "No link to insert")
 
-       (while (and (or (listp arg) (>= arg cnt))
 
- 		  (setq l (if (listp arg)
 
- 			      (pop links)
 
- 			    (pop org-stored-links))))
 
- 	(setq cnt (1+ cnt))
 
- 	(insert pr)
 
- 	(org-insert-link nil (car l) (or (cadr l) "<no description>"))
 
- 	(insert po)))))
 
- ;;;###autoload
 
- (defun org-insert-last-stored-link (arg)
 
-   "Insert the last link stored in `org-stored-links'."
 
-   (interactive "p")
 
-   (org-insert-all-links arg "" "\n"))
 
- ;;;###autoload
 
- (defun org-insert-link-global ()
 
-   "Insert a link like Org mode does.
 
- This command can be called in any mode to insert a link in Org syntax."
 
-   (interactive)
 
-   (org-load-modules-maybe)
 
-   (org-run-like-in-org-mode 'org-insert-link))
 
- ;;;###autoload
 
- (defun org-update-radio-target-regexp ()
 
-   "Find all radio targets in this file and update the regular expression.
 
- Also refresh fontification if needed."
 
-   (interactive)
 
-   (let ((old-regexp org-target-link-regexp)
 
- 	;; Some languages, e.g., Chinese, do not use spaces to
 
- 	;; separate words.  Also allow to surround radio targets with
 
- 	;; line-breakable characters.
 
- 	(before-re "\\(?:^\\|[^[:alnum:]]\\|\\c|\\)\\(")
 
- 	(after-re "\\)\\(?:$\\|[^[:alnum:]]\\|\\c|\\)")
 
- 	(targets
 
- 	 (org-with-wide-buffer
 
- 	  (goto-char (point-min))
 
- 	  (let (rtn)
 
- 	    (while (re-search-forward org-radio-target-regexp nil t)
 
- 	      ;; Make sure point is really within the object.
 
- 	      (backward-char)
 
- 	      (let ((obj (org-element-context)))
 
- 		(when (eq (org-element-type obj) 'radio-target)
 
- 		  (cl-pushnew (org-element-property :value obj) rtn
 
- 			      :test #'equal))))
 
- 	    rtn))))
 
-     (setq targets
 
-           (sort targets
 
-                 (lambda (a b)
 
-                   (> (length a) (length b)))))
 
-     (setq org-target-link-regexp
 
- 	  (and targets
 
- 	       (concat before-re
 
- 		       (mapconcat
 
- 			(lambda (x)
 
- 			  (replace-regexp-in-string
 
- 			   " +" "\\s-+" (regexp-quote x) t t))
 
- 			targets
 
- 			"\\|")
 
- 		       after-re)))
 
-     (unless (equal old-regexp org-target-link-regexp)
 
-       ;; Clean-up cache.
 
-       (let ((regexp (cond ((not old-regexp) org-target-link-regexp)
 
- 			  ((not org-target-link-regexp) old-regexp)
 
- 			  (t
 
- 			   (concat before-re
 
- 				   (mapconcat
 
- 				    (lambda (re)
 
- 				      (substring re (length before-re)
 
- 						 (- (length after-re))))
 
- 				    (list old-regexp org-target-link-regexp)
 
- 				    "\\|")
 
- 				   after-re)))))
 
- 	(when (and (featurep 'org-element)
 
-                    (not (bound-and-true-p org-mode-loading)))
 
- 	  (org-with-point-at 1
 
- 	    (while (re-search-forward regexp nil t)
 
- 	      (org-element-cache-refresh (match-beginning 1))))))
 
-       ;; Re fontify buffer.
 
-       (when (memq 'radio org-highlight-links)
 
- 	(org-restart-font-lock)))))
 
- ;;; Initialize Regexps
 
- (org-link-make-regexps)
 
- (provide 'ol)
 
- ;; Local variables:
 
- ;; generated-autoload-file: "org-loaddefs.el"
 
- ;; End:
 
- ;;; ol.el ends here
 
 
  |