Links, IDs and attachments
Syntax: [[target][description]], [[target]], plain links (https://en.wikipedia.org/wiki/Foo_(bar): balanced parentheses are part of the link, trailing punctuation is not) and <angle> links. Bracket links may span lines. With ui.conceal_links (org-link-descriptive), only the description is shown.
Targets: https://… http://… ftp:… mailto:… opened with vim.ui.open() doi:10.1000/xlinks.doi_server_url+ path file:path ./rel ~/p /abs open a file; add a search option: ::42 ::*Heading ::#custom-id ::(coderef) ::/regexp/ ::some text file:notes/*.org a wildcard (*?{) in the file name lists the matching files (Emacs opens Dired); <CR> opens the file on the line,qcloses the list file+sys:path file+emacs:path system application / always Neovim id:UUID id:UUID::search headline with that ID (the search runs inside its subtree) #custom-id headline with that CUSTOM_ID *Heading headline in the current file (label) coderef in a src/example block <<target>> text dedicated target,#+NAME, headline shell:cmd run in the file's directory (asks first); the output goes to a new*Org Shell Output*buffer, shown unless it is one line (then echoed);cmd &shows it at once and streams;links.shell_output = "terminal"runs it in a terminal instead elisp:(sexp) elisp:command evaluate in a separate Emacs, show the value (asks first); a command is called interactively there help:topic Vim :help man:printf(3) man:ls::-l :Man, with an optional search info:emacs#Top theinfoprogram in a terminal (exported to HTML as a link to the manual's URL inlinks.info_other_documents, else gnu.org or MANUAL.html) bibtex:refs.bib::key a file link to a BibTeX entry (org-bibtex) attachment:name file in the entry's attachment dir abbrev:tag abbrev::tag abbrev#+LINK:orlinks.abbreviations(%s= tag,%h= url-encoded,%(fn)= (fn tag) in Emacs, or a Lua function(tag) as the value) custom:pathlinks.types(see below)
Searches (org-link-search) ignore case and runs of whitespace (a text search also matches across line breaks), and headline searches ignore the TODO keyword, priority, COMMENT, tags and statistics cookies. A fuzzy link tries <<target>>, #+NAME: and headlines. When nothing matches in an Org file, links.search_must_match_exact_headline decides: with "query-to-create" (default) you are asked "No match - create this as a new heading?" (the heading is added at the end of the file, or as the last child of the entry for id:ID::*Heading); with true the failure is reported; with false a plain text search follows, which never lands on the link itself. *Heading searches never fall back to text. ::/regexp/ takes an Emacs regexp: in Org files it shows a sparse tree (org-sparse-tree), elsewhere a location list (like occur); common Emacs syntax is translated to Vim regexps, see org-differences.
An abbreviation such as #+LINK: ex %(my-function) calls the Emacs function with the tag in a separate emacs --batch (babel.emacs_lisp; load the function with its args, e.g. { "-Q", "--batch", "-l", "~/my-links.el" }). Like Emacs, only functions whose org-link-abbrev-safe (or pure) property is t are called; another function, or one that does not return a string, gives a warning and the link is left as written. Results are kept for the session.
<CR>, gx, <prefix>o Open the link, footnote or date at the cursor. <C-c><C-o> The same. On the tags of a headline, show a tags agenda for the tag under the cursor (a count: TODO entries only). Elsewhere on a headline, pick one of the entry's links, or "Open all links"; without links, open the attachment directory when there is one. With a count (C-u), files open in Neovim even when an external app applies, and internal links are shown in another window; with 16 (C-u C-u), files open with the system application.file:andid:links open in another window, splitting when there is none, like Emacs (links.frame_setup). <prefix>ls Store a link to the current location (works in any buffer, org-store-link). In org buffers this is, in order: thestorefunction of a custom link type, anid:link (seelinks.use_id), the<<target>>under the cursor (file:…::target), the#+NAME:of the element at the cursor, the current line before the first heading, or the heading:file:…::#custom-idorfile:…::*Heading. When the entry has a CUSTOM_ID, afile:…::#custom-idlink is stored too. In Visual mode the selection is the search string (links.context_for_filesmay limit its lines). In other files, the current line is the search string (an empty line gives a plainfile:link). Search strings collapse whitespace and drop statistics cookies. In the agenda, the link points to the item's entry; in a src block edit buffer (org-babel), it stores a coderef linkfile:…::(label)and adds a(ref:label)to the line when it has none. Help buffers givehelp:tag, man pagesman:page, netrw/oil listings a link to the file under the cursor, BibTeX filesfile:refs.bib::keydescribed by the authors, year and title (org-bibtex). A count of 4 (C-u) toggleslinks.context_for_files, 16 (C-u C-u) skips customstorefunctions, 64 stores one link per selected line.
<prefix>li Insert a link (org-insert-link). Stored links, their descriptions, link types and file paths (relative to the file's directory) are completed; an empty answer inserts the last stored link. Entering a type alone (file,id:, a custom type) completes it. On a link, edit it (a plain or angle link becomes a bracket link). In Visual mode, the selection becomes the description. Links to the current file become their search option, and file paths followlinks.file_path_type. An inserted stored link is removed from the list (links.keep_stored_after_insertion). With a count of 4 (C-u), pick a file; 16 (C-u C-u) uses an absolute path; 64 invertskeep_stored_after_insertion. <prefix>lL Insert the last stored link and a newline, and forget it (C-c M-l). A count inserts that many. Links without a description get<no description>, like Emacs. <prefix>lA Insert every stored link as a-line and forget them (C-c C-M-l); a count of 4 keeps them. <prefix>lt Toggle concealed link display (org-toggle-link-display): only links change, not emphasis markers. <prefix>ln/lp Next / previous link (takes a count). Links in src and example blocks, comments and verbatim are skipped; repeating a failed search wraps around the buffer. <C-c>& Jump back to where you followed a link from (<C-o> works too). :Org open_at_point_global Follow the Org link at the cursor in any buffer (org-open-at-point-global): a bracket, angle or plain link, a timestamp (the agenda of that day), else a URL or an e-mail address. It has no key, like Emacs; map it withmappings.global.open_at_point_global = "gX". Internal links (headings, targets) are not searched outside Org. :Org occur_link_in_agenda_files Search the agenda files for the link <prefix>ls would store here,[[file:…::*Heading][Heading]](org-occur-link-in-agenda-files); the matches go to the quickfix list. The link is not stored.
<MiddleMouse> Open the link clicked (org-open-at-mouse). <RightMouse> Open the link clicked in Neovim, even whenfile_appsnames another program, internal links in another window (org-find-file-at-mouse). Away from a link both clicks do what they normally do. <LeftMouse> Withlinks.mouse_1_follows_link(org-mouse-1-follows-link, default 450), a click on a link follows it: a click held longer than that many ms, or a drag, only moves the cursor; true follows on any click, "double" on a double click, false never. <Tab> Withlinks.tab_follows_link(org-tab-follows-link), <Tab> on a link follows it instead of cycling. Following a link, footnote or date with <CR>, <C-c><C-o>, <Tab> or the mouse fires theUsereventOrgFollowLink(org-follow-link-hook), withdata.bufnrthe buffer it was followed from:
vim.api.nvim_create_autocmd("User", {
pattern = "OrgFollowLink",
callback = function() vim.cmd("normal! zz") end,
})
Afile:link to a directory opens the directory, or its index.org withlinks.open_directory_means_index_dot_org(org-open-directory-means-index-dot-org). An external program (file_appsor the system application) is not started for a file that doesn't exist ("No such file: …") unlesslinks.open_non_existing_files(org-open-non-existing-files); Neovim opens missing files as new ones. <C-c>' On#+INCLUDE:,#+SETUPFILE:or#+BIBLIOGRAPHY:, visit the file. :Org link_open_from_string [link] Open a link typed at a prompt (or given), as if it were in the buffer (org-link-open-from-string). The text must be one link: "No valid link in ..." / "Garbage after link in ...". Also thelink_open_from_stringaction (unbound).
Radio targets <<<text>>> make every occurrence of "text" a link to them (also in export): case is ignored, the words must stand alone and may be split over lines. Radio links are highlighted; after adding a radio target, <C-c><C-c> on it refreshes the highlighting. Coderefs: a (ref:name) label at the end of a src or example block line (or the block's -l "fmt" format) can be reached with [[(name)]].
Custom link types (org-link-set-parameters) go in links.types, either a function (follow) or a table:
links = { types = { jira = {
follow = function(path, link, count) vim.ui.open("https://jira/" .. path) end,
complete = function() return "jira:" .. vim.fn.input("Issue: ") end,
store = function(interactive) end, -- { link = ..., desc = ... } or nil
export = function(path, desc, backend) end, -- "html", "md", "latex", "ascii"
face = "DiagnosticWarn",
insert_description = function(link, desc) return link:sub(6) end,
preview = function(path, ctx) end, -- image file: see |org-images|
} } }
links.make_description(link, desc) gives other links a default description. links.search_functions run first on search options and links.translation_function(type, path) rewrites links before they open.
IDs are stored inid.locations_file: JSON by default, or Emacs's org-id-locations format (an alist(("~/org/a.org" "id1" "id2") ...)), detected from the file's contents (a new file is JSON when its name ends in.json) or forced withid.locations_format("json" or "emacs"). Setid.locations_file = "~/.emacs.d/.org-id-locations"to share the database with Emacs; file names are written with~like Emacs, or relative to the database withid.locations_file_relative(org-id-locations-file-relative).:Org id_update_locationsrebuilds it from the agenda files, their archive files (id.search_archives, default true),id.extra_files, the loaded org buffers and the files already known; an ID that is not where the database says triggers the same scan. The database also records what each file held when it was last scanned (a" org.nvim-scan"member in JSON, a; org.nvim-scan:comment in Emacs's format, which Emacs ignores), so a rebuild reads again only the files whose modification time or size changed. Refiled and archived entries are recorded at their new place. New IDs followid.method(org-id-method): "uuid" (default), "ts" (a time stamp inid.ts_format) or "org" (a compact time based ID), withid.prefixand a colon in front when set (org-id-prefix).id.include_domain(org-id-include-domain) adds "@" and the host name (a name without a dot gets ".mail-host-address-is-not-set", like Emacs) to "ts" and "org" IDs. Typingid:alone in org-insert-link completes a heading, not an ID (org-id-completion-targets): the headings ofid.completion_targets, refile target specs (org-refile) that default to every heading of the buffer and of the files holding known IDs (files = "id"), as outline paths; the chosen heading gets an ID when it has none. In a buffer without a file only the specs naming files count; with no heading to offer you type the link. Links to headings arefile:links unlesslinks.use_idasks forid:links (IDs are then created in your files). Before the first heading the ID goes into a file-level property drawer at the top of the file (after leading#comments, before#+TITLE), like Emacs 9.8; the link is described by the #+TITLE or the file name, and from a later line it gets that line as search string (id:ID::text).id:links get a search string for a named element or a selection below the heading (id:ID::tbl1,id.link_use_context); withid.link_consider_parent_id, a heading without an ID is linked through its ancestor's ID (id:ID::*Child). <prefix>lI Get or create the entry's ID; with a count (C-u), replace it by a new one. <prefix>lg Go to an entry by ID (org-id-goto, IDs are completed). <prefix>ly Copy the entry's ID, creating it if needed (org-id-copy).:Org id_store_linkstores anid:link whateverlinks.use_idsays.
<prefix>A opens the attachment menu (org-attach): a attach a file (method fromattach.method: cp/mv/ln/lns) c m l y attach by copy / move / hard link / symbolic link u download a URL (curl) b attach the contents of a buffer n create a new file z sync the ATTACH tag with the directory o open an attachment (system app orlinks.file_apps) O open it in Neovim f open the directory with the system app F open the directory in Neovim d delete one D delete all s set the DIR property S remove the DIR property Directories can be attached too (copied recursively with "cp").attach.commandsadds commands to the dispatcher or replaces them (org-attach-commands):{ x = { fn = function(target) ... end, desc = "..." } }, wheretargetis{ bufnr, lnum }of the entry;falseremoves a built-in key. Withattach.expert(org-attach-expert) the dispatcher asks for the key at a one-line prompt instead of showing the menu.
:Org attach_from_file_manager
In a netrw or oil.nvim buffer: attach the marked files
(netrw), the Visual selection (oil) or the file under the
cursor to the entry at the cursor of a window showing an
Org buffer, with attach.method
(org-attach-dired-to-subtree). Map it in those buffers,
e.g. vim.keymap.set("n", "<C-c><C-x>a", ...) in a
FileType netrw autocmd.
The directory is the DIR property (or the older ATTACH_DIR), else it comes from the ID: attach.dir + a folder from attach.id_to_path (org-attach-id-to-path-function-list: "uuid" gives ab/cdef..., "ts" gives 202609/25T..., "fallback" gives __/a/abcdef..., or your own functions); an existing folder wins, also under the default "data/". Parents' DIR / ID count only as attach.use_inheritance says ("selective", the default, follows use_property_inheritance). An entry without either gets an ID (attach.preferred_new_method: "id", "dir" asks for a DIR, "ask", or false). Attaching adds the attach.auto_tag tag (ATTACH) and stores a link (attach.store_link: "attached" an attachment: link, "file" a file: link to the attachment, true to the source, false none). Other options: dir_relative (store DIR relative to the file), sync_delete_empty_dir ("query", true, false) and archive_delete (delete the attachments of archived entries: false, true, "query").
Pasting images and files
:Org yank_media(no default key; Emacs'syank-media) pastes what the system clipboard holds, read with wl-paste (Wayland), xclip (X11) or osascript (macOS): - an image: saved asclipboard-<time stamp>.png(or the name fromyank.image_file_name_function) and linked at the cursor. Withyank.image_save_method = "attach"(the default) it becomes an attachment of the entry ([[attachment:NAME][NAME]]); a directory (relative to the file's) or a function returning one saves it there ([[file:img/NAME.png]]) (org-yank-image-save-method). - files copied in a file manager (GNOME, KDE, MATE, or a Finder file on macOS): handled like dropped files; cut files are moved. When the clipboard holds neither, nothing happens.
Dropping files on the terminal pastes their paths; in an Org buffer a paste made only of existing files (file:// URIs or paths, quoted or escaped) is handled as a drop (yank.dnd_paste, true). yank.dnd_method (org-yank-dnd-method) says what to do: "attach" (with yank.dnd_default_attach_method, else attach.method; an image goes to the yank.image_save_method directory when that is one), "open", "file-link" (insert [[/path/to/file]]) or "ask" (the default; Esc pastes the text instead). Several files get a space after each link.
BibTeX entries (ol-bibtex)
A headline can hold a BibTeX entry: its type in thebtypeproperty (bibtex.type_property_name), its key in CUSTOM_ID (bibtex.key_property) and each field in a property of its name (TITLE, AUTHOR, ...), withbibtex.prefixin front when set. When there is no TITLE, the headline is the title (bibtex.treat_headline_as_title). These actions (unbound, like Emacs;:Org <name>or a mapping) follow ol-bibtex: bibtex_export write the entries of every headline to a .bib file (asked for, default FILE.bib) (org-bibtex) bibtex_export_to_kill_ring copy the entry of the headline to the unnamed register bibtex_check ask for the missing required fields and the key; with a count (C-u) the optional fields too; a choice (editor or author) asks "Field: " first bibtex_check_all the same for every headline bibtex_create a new headline: type, title, required fields (count: optional ones too), key,bibtex.tagsbibtex_create_in_current_entry the same data for the current headline bibtex_read in a .bib buffer: read the entry at the cursor bibtex_read_buffer / bibtex_read_file read every entry of a buffer / file ("Parsed N entries") bibtex_write insert the first entry read as a headline after the cursor line (org-bibtex-write) bibtex_yank insert the BibTeX entry of the unnamed register; with a count (C-u), into the current headline bibtex_import_from_file insert every entry of a file bibtex_search search view of the agenda files for the entries that match a string (STRING +{:btype:}) Written headlines usebibtex.headline_format_function(fields)for their text (default the title). Keys are asked for ("id: ") unlessbibtex.autogen_keysmakes them like Emacs' bibtex-generate-autokey (doe20:_big_title). Withbibtex.tags_are_keywordsthekeywordsfield becomes tags (spaces become_) and tags become keywords (not those inbibtex.tagsorbibtex.no_export_tags; inherited ones too withbibtex.inherit_tags).bibtex.export_arbitrary_fields(with a prefix) exports every prefixed property instead of the fields of the type. Storing a link in a .bib buffer givesfile:refs.bib::keydescribed like "Doe & Roe 2020: Big Title"; following it puts the entry at the top of the window.bibtex:links open likefile:links.
Attachments in git (org-attach-git)
With attach.git = true (Emacs: (require 'org-attach-git)), a change made through org-attach (attach, download, attach a buffer, delete one or all, sync) is committed when the attachment root (attach.dir, relative to the org file) is inside a git work tree: new and modified files are git added, deleted ones git rmed, and a commit "Synchronized attachments" is made. attach.git_dir = "individual-repository" uses the entry's own attachment directory instead (org-attach-git-dir). When the repository has been set up with git annex init, files of at least attach.git_annex_cutoff bytes (32768; false: never) are added with git annex add, and opening an attachment (o/O) whose content is not present runs git annex get (attach.git_annex_auto_get: "ask", true or false). The Emacs hooks are User autocmds: OrgAttachAfterChange (data: { dir }) and OrgAttachOpen (data: { path }).
MobileOrg (org-mobile)
A port of Org Mobile, the protocol MobileOrg-style applications use to view and capture offline. Set mobile.directory to the staging directory the application syncs with (WebDAV, Dropbox, ...; when Neovim cannot write it directly, copy the files in mobile.post_push_hook and mobile.pre_pull_hook).
:Org mobile_push Copymobile.files(default: the agenda files) into the staging directory, named relative toorg_directory, and writeindex.org(#+TODO lines fromtodo_keywordsand the files, #+TAGS, #+ALLPRIORITIES frommobile.allpriorities, links to the files),agendas.org(the agenda views chosen bymobile.agendas: "default" is the week agenda and the TODO list, "custom" theagenda.custom_commands, "all" both, or a list of keys; search, stuck and sparse-tree commands are left out) andchecksums.dat. Agenda entries first get an ID (mobile.force_id_on_agenda_items; else agendas.org refers to them by outline path,olp:). :Org mobile_pull Move the entries ofmobileorg.orgto the end ofmobile.inbox_for_pull(emptying it), then apply the edit requests found there (below) and show the flagged entries of the changed files in an agenda. :Org mobile_apply Apply the requests in the current buffer (Emacs org-mobile-apply). :Org mobile_goto_inbox Open the inbox. :Org mobile_flagged Agenda of the FLAGGED entries (dispatcher?). In the agenda:?shows the flagging note of the entry in another window and copies it to the unnamed register;?again (without moving) offers to remove the FLAGGED tag and the note. <C-c><C-x><CR>g pulls, <C-c><C-x><CR>p pushes.
Requests look like * F(edit:todo) [[id:ID][title]] with ** Old value and ** New value children. Edits of todo (the value "DONEARCHIVE" marks the entry done and archives it), tags, priority, heading and body are applied only when the entry still has the old value (or the new one); mobile.force_mobile_change (true or a list of those kinds) applies them anyway. addheading adds a child, refile moves the subtree to the entry of the new value (an id:/olp: link), delete, archive and archive-sibling do what they say. * F() [[id:...]] adds the FLAGGED tag and keeps the text of the request in the THEFLAGGINGNOTE property. Applied requests are removed from the inbox; the others stay, with the error after their stars ("BAD REFERENCE", "BAD FLAG", or why the edit was refused). Changed files get a #+LAST_MOBILE_CHANGE: line. mobile.action_alist adds actions: { name = function(data, old, new, target) end } (raise an error to refuse).
Encryption: mobile.use_encryption = true stores every staged file encrypted with openssl enc -md md5 -aes-256-cbc and mobile.encryption_password (asked once per session when empty), like Emacs. mobile.checksum_binary (shasum, sha1sum, md5sum or md5, the first found) computes the file checksums. Hooks: mobile.pre_push_hook, post_push_hook, pre_pull_hook, before_process_capture_hook (receives { bufnr, line } of the new entries) and post_pull_hook, plus the User autocmds OrgMobilePrePush, OrgMobilePostPush, OrgMobilePrePull, OrgMobileBeforeProcessCapture and OrgMobilePostPull.