commit 4be4c56239c224094e717dcd57068f58f99c2dfc Author: Carsten Dominik Date: Thu Jan 31 10:30:03 2008 +0100 version 4.12a diff --git a/README b/README new file mode 100644 index 000000000..39ffe5c9f --- /dev/null +++ b/README @@ -0,0 +1,18 @@ +The is the distribution of org-mode, version 3.14 + +The homepage of org-mode is at http://www.astro.uva.nl/~domnik/Tools/org/ + +INSTALLATION +------------ + +The installation instructions are in the documentation, org.pdf + +FILES IN THE DISTRIBUTION +------------------------- + +org.el The Emacs lisp code +org.texi Documentation source file +org.pdf Documentation in PDF format +org Documentation in Info format +orgcard.pdf Refcard, PDF format +orgcard.tex TeX source for refcard.pdf diff --git a/org b/org new file mode 100644 index 000000000..d88a8e50d --- /dev/null +++ b/org @@ -0,0 +1,3730 @@ +This is org, produced by makeinfo version 4.8 from org.texi. + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Org Mode: (org). outline-based notes management and organizer +END-INFO-DIR-ENTRY + + This manual is for Org-mode (version 4.12). + + Copyright (C) 2004, 2005, 2006 Free Software Foundation + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.1 or any later version published by the Free Software + Foundation; with no Invariant Sections, with the Front-Cover texts + being "A GNU Manual," and with the Back-Cover Texts as in (a) + below. A copy of the license is included in the section entitled + "GNU Free Documentation License." + + (a) The FSF's Back-Cover Text is: "You have freedom to copy and + modify this GNU Manual, like GNU software. Copies published by + the Free Software Foundation raise funds for GNU development." + + +File: org, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) + +Org Mode Manual +*************** + +This manual is for Org-mode (version 4.12). + + Copyright (C) 2004, 2005, 2006 Free Software Foundation + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.1 or any later version published by the Free Software + Foundation; with no Invariant Sections, with the Front-Cover texts + being "A GNU Manual," and with the Back-Cover Texts as in (a) + below. A copy of the license is included in the section entitled + "GNU Free Documentation License." + + (a) The FSF's Back-Cover Text is: "You have freedom to copy and + modify this GNU Manual, like GNU software. Copies published by + the Free Software Foundation raise funds for GNU development." + +* Menu: + +* Introduction:: Getting started +* Document Structure:: A tree works like your brain +* Tables:: Pure magic for quick formatting +* Hyperlinks:: Notes in context +* TODO items:: Every tree branch can be a TODO item +* Timestamps:: Assign date and time to items +* Agenda Views:: Collecting information into views +* Exporting:: Sharing and publishing of notes +* Miscellaneous:: All the rest which did not fit elsewhere +* Index:: The fast road to specific information +* Key Index:: Key bindings and where they are described + + --- The Detailed Node Listing --- + +Introduction + +* Summary:: Brief summary of what Org-mode does +* Installation and Activation:: How to install Org-mode +* Feedback:: Bug reports, ideas, patches etc. + +Document Structure + +* Outlines:: Org-mode is based on outline-mode +* Headlines:: How to typeset org-tree headlines +* Visibility cycling:: Show and hide, much simplified +* Motion:: Jumping to other headlines +* Structure editing:: Changing sequence and level of headlines +* Archiving:: Move done task trees to a different place +* Sparse trees:: Matches embedded in context +* Tags:: Tagging headlines and matching sets of tags +* Plain Lists:: Editing hand-formatted lists + +Tables + +* Built-in table editor:: Simple tables +* Table calculations:: Compute a field from other fields +* orgtbl-mode:: The table editor as minor mode +* table.el:: Complex tables + +Calculations in tables + +* Formula syntax:: How to write a formula +* Column formulas:: Formulas valid for all fields in a column +* Advanced features:: Field names, parameters and automatic recalc +* Named-field formulas:: Formulas valid in single fields +* Editing/debugging formulas:: Changing a stored formula +* Appetizer:: Taste the power of calc + +Hyperlinks + +* Internal Links:: Links to other places in the current file +* External Links:: URL-like links to the world +* Managing links:: Creating, inserting and following +* Search Options:: Linking to a specific location +* Remember:: Org-trees store quick notes + +Internal Links + +* Radio targets:: Make targets trigger links in plain text. +* CamelCase links:: Activating CamelCase words as links + +TODO items + +* TODO basics:: Marking and displaying TODO entries +* Progress Logging:: Document your productivity +* TODO extensions:: Workflow and assignments +* Priorities:: Some things are more important than others + +Extended use of TODO keywords + +* Workflow states:: From TODO to DONE in steps +* TODO types:: I do this, Fred the rest +* Per file keywords:: Different files, different requirements + +Timestamps + +* Time stamps:: Assigning a time to a tree entry +* Creating timestamps:: Commands which insert timestamps + +Agenda Views + +* Agenda files:: Files being searched for agenda information +* Agenda dispatcher:: Keyboard access to agenda views +* Weekly/Daily Agenda:: The calendar page with current tasks +* Global TODO list:: All unfinished action items +* Matching headline tags:: Structured information with fine-tuned search +* Timeline:: Time-sorted view for single file +* Agenda commands:: Remote editing of org trees + +The weekly/daily agenda + +* Categories:: Not all tasks are equal +* Time-of-day specifications:: How the agenda knows the time +* Calendar/Diary integration:: Integrating Anniversaries and more +* Sorting of agenda items:: The order of things + +Exporting + +* ASCII export:: Export as a structured ASCII file +* HTML export:: Export as an HTML file +* iCalendar export:: Create calendar entries. + +HTML export + +* HTML formatting:: Interpretation of the buffer content +* Export options:: How to influence exports +* Comment lines:: Lines which will not be exported + +Miscellaneous + +* Completion:: M-TAB knows what you need +* Customization:: Adapting Org-mode to your taste +* Clean view:: Getting rid of leading stars in the outline +* TTY keys:: Using Org-mode on a tty +* FAQ:: Frequently asked questions +* Interaction:: Other Emacs packages +* Bugs:: Things which do not work perfectly +* Acknowledgments:: These people provided feedback and more + + +File: org, Node: Introduction, Next: Document Structure, Prev: Top, Up: Top + +1 Introduction +************** + +* Menu: + +* Summary:: Brief summary of what Org-mode does +* Installation and Activation:: How to install Org-mode +* Feedback:: Bug reports, ideas, patches etc. + + +File: org, Node: Summary, Next: Installation and Activation, Prev: Introduction, Up: Introduction + +1.1 Summary +=========== + +Org-mode is a mode for keeping notes, maintaining ToDo lists, and doing +project planning with a fast and effective plain-text system. + + Org-mode develops organizational tasks around NOTES files that +contain information about projects as plain text. Org-mode is +implemented on top of outline-mode, which makes it possible to keep the +content of large files well structured. Visibility cycling and +structure editing help to work with the tree. Tables are easily +created with a built-in table editor. Org-mode supports ToDo items, +deadlines, time stamps, and scheduling. It dynamically compiles +entries into an agenda that utilizes and smoothly integrates much of +the Emacs calendar and diary. Plain text URL-like links connect to +websites, emails, Usenet messages, BBDB entries, and any files related +to the projects. For printing and sharing of notes, an Org-mode file +can be exported as a structured ASCII file, as HTML, or (todo and +agenda items only) as an iCalendar file. + + Org-mode keeps simple things simple. When first fired up, it should +feel like a simple but easy to use outliner. Complexity is not +imposed, but a large amount of functionality is available when you need +it. Org-mode can be used on different levels and in different ways, +for example + + * as an outline extension with visibility cycling and structure editing + * as an ASCII system and table editor for taking structured notes + * as an ASCII table editor with spreadsheet-like capabilities + * as a simple hypertext system, with HTML export + * as a TODO list editor + * as a full agenda and planner with deadlines and work scheduling + + The Org-mode table editor can be integrated into any major mode by +activating the minor Orgtbl-mode. + + There is a website for Org-mode which provides links to the newest +version of Org-mode, as well as additional information, screen shots +and example files. This page is located at +`http://www.astro.uva.nl/~dominik/Tools/org/'. + + +File: org, Node: Installation and Activation, Next: Feedback, Prev: Summary, Up: Introduction + +1.2 Installation and Activation +=============================== + +If Org-mode is part of the Emacs distribution or an XEmacs package, you +only need to copy the following lines to your `.emacs' file. The last +two lines define _global_ keys for the commands `org-store-link' and +`org-agenda' - please choose suitable keys yourself. + + ;; The following lines are always needed. Choose your own keys. + (add-to-list 'auto-mode-alist '("\\.org$" . org-mode)) + (define-key global-map "\C-cl" 'org-store-link) + (define-key global-map "\C-ca" 'org-agenda) + + If you have downloaded Org-mode from the Web, you must byte-compile +`org.el' and put it on your load path. In addition to the Emacs Lisp +lines above, you also need to add the following lines to `.emacs': + + ;; These lines only if org-mode is not part of the X/Emacs distribution. + (autoload 'org-mode "org" "Org mode" t) + (autoload 'org-diary "org" "Diary entries from Org mode") + (autoload 'org-agenda "org" "Multi-file agenda from Org mode" t) + (autoload 'org-store-link "org" "Store a link to the current location" t) + (autoload 'orgtbl-mode "org" "Org tables as a minor mode" t) + (autoload 'turn-on-orgtbl "org" "Org tables as a minor mode") + + With this setup, all files with extension `.org' will be put into +Org-mode. As an alternative, make the first line of a file look like +this: + + MY PROJECTS -*- mode: org; -*- + +which will select Org-mode for this buffer no matter what the file's +name is. See also the variable `org-insert-mode-line-in-empty-file''. + + +File: org, Node: Feedback, Prev: Installation and Activation, Up: Introduction + +1.3 Feedback +============ + +If you find problems with Org-mode, or if you have questions, remarks, +or ideas about it, please contact the maintainer Carsten Dominik at +. + + For bug reports, please provide as much information as possible, +including the version information of Emacs (`C-h v emacs-version +') and Org-mode (`M-x org-version'), as well as the Org-mode +related setup in `.emacs'. If an error occurs, a traceback can be very +useful. Often a small example file helps, along with clear information +about: + 1. What exactly did you do? + + 2. What did you expect to happen? + + 3. What happened instead? + Thanks for helping to improve this mode. + + +File: org, Node: Document Structure, Next: Tables, Prev: Introduction, Up: Top + +2 Document Structure +******************** + +Org-mode is based on outline mode and provides flexible commands to +edit the structure of the document. + +* Menu: + +* Outlines:: Org-mode is based on outline-mode +* Headlines:: How to typeset org-tree headlines +* Visibility cycling:: Show and hide, much simplified +* Motion:: Jumping to other headlines +* Structure editing:: Changing sequence and level of headlines +* Archiving:: Move done task trees to a different place +* Sparse trees:: Matches embedded in context +* Tags:: Tagging headlines and matching sets of tags +* Plain Lists:: Editing hand-formatted lists + + +File: org, Node: Outlines, Next: Headlines, Prev: Document Structure, Up: Document Structure + +2.1 Outlines +============ + +Org-mode is implemented on top of outline-mode. Outlines allow to +organize a document in a hierarchical structure, which (at least for +me) is the best representation of notes and thoughts. Overview over +this structure is achieved by folding (hiding) large parts of the +document to show only the general document structure and the parts +currently being worked on. Org-mode greatly simplifies the use of +outlines by compressing the entire show/hide functionality into a +single command `org-cycle', which is bound to the key. + + +File: org, Node: Headlines, Next: Visibility cycling, Prev: Outlines, Up: Document Structure + +2.2 Headlines +============= + +Headlines define the structure of an outline tree. The Headlines in +Org-mode start with one or more stars, on the left margin. For example + + * Top level headline + ** Second level + *** 3rd level + some text + *** 3rd level + more text + * Another top level headline + Some people find the many stars too noisy and would prefer an +outline that has whitespace followed by a single star as headline +starters. *Note Clean view:: describes a setup to realize this. + + +File: org, Node: Visibility cycling, Next: Motion, Prev: Headlines, Up: Document Structure + +2.3 Visibility cycling +====================== + +Outlines make it possible to hide parts of the text in the buffer. +Org-mode uses a single command bound to the key to change the +visibility in the buffer. + +`' + Rotate current subtree between the states + ,-> FOLDED -> CHILDREN -> SUBTREE --. + '-----------------------------------' + At the beginning of the buffer (or when called with `C-u'), this + does the same as the command `S-' below. + +`S-' + Rotate the entire buffer between the states + ,-> OVERVIEW -> CONTENTS -> SHOW ALL --. + '--------------------------------------' + Note that inside tables, `S-' jumps to the previous field. + +`C-c C-a' + Show all. + + When Emacs first visits an Org-mode file, the global state is set to +OVERVIEW, i.e. only the top level headlines are visible. This can be +configured through the variable `org-startup-folded', or on a per-file +basis by adding one of the following lines anywhere in the buffer: + + #+STARTUP: fold + #+STARTUP: nofold + #+STARTUP: content + + +File: org, Node: Motion, Next: Structure editing, Prev: Visibility cycling, Up: Document Structure + +2.4 Motion +========== + +The following commands jump to other headlines in the buffer. + +`C-c C-n' + Next heading. + +`C-c C-p' + Previous heading. + +`C-c C-f' + Next heading same level. + +`C-c C-b' + Previous heading same level. + +`C-c C-u' + Backward to higher level heading. + +`C-c C-j' + Jump to a different place without changing the current outline + visibility. Shows the document structure in a temporary buffer, + where you can use visibility cycling () to find your + destination. After pressing , the cursor moves to the + selected location in the original buffer, and the headings + hierarchy above it is made visible. + + +File: org, Node: Structure editing, Next: Archiving, Prev: Motion, Up: Document Structure + +2.5 Structure editing +===================== + +`M-' + Insert new heading with same level as current. If the cursor is + in a plain list item, a new item is created. To force creation of + a new headline, use a prefix arg, or first press to get to + the beginning of the next line. + +`M-S-' + Insert new TODO entry with same level as current heading. + +`M-' + Promote current heading by one level + +`M-' + Demote current heading by one level + +`M-S-' + Promote the current subtree by one level + +`M-S-' + Demote the current subtree by one level + +`M-S-' + Move subtree up (swap with previous subtree of same level) + +`M-S-' + Move subtree down (swap with next subtree of same level) + +`C-c C-x C-w' +`C-c C-x C-k' + Kill subtree, i.e. remove it from buffer but save in kill ring. + +`C-c C-x M-w' + Copy subtree to kill ring. + +`C-c C-x C-y' + Yank subtree from kill ring. This does modify the level of the + subtree to make sure the tree fits in nicely at the yank position. + The yank level can also be specified with a prefix arg, or by + yanking after a headline marker like `****'. + + When there is an active region (transient-mark-mode), promotion and +demotion work on all headlines in the region. To select a region of +headlines, it is best to place both point and mark at the beginning of a +line, mark at the beginning of the first headline, and point at the line +just after the last headline to change. Note that when the cursor is +inside a table (*note Tables::), the Meta-Cursor keys have different +functionality. + + +File: org, Node: Archiving, Next: Sparse trees, Prev: Structure editing, Up: Document Structure + +2.6 Archiving +============= + +When a project represented by a (sub)tree is finished, you may want to +move the tree to an archive place, either in the same file under a +special top-level heading, or even to a different file. +`C-c $' + Archive the subtree starting at the cursor position to the location + given by `org-archive-location'. + + The default archive is a file in the same directory as the current +file, with the name derived by appending `_archive' to the current file +name. For information and examples on how to change this, see the +documentation string of the variable `org-archive-location'. If you +are also using the Org-mode agenda, archiving to a different file is a +good way to keep archived trees from contributing agenda items. + + +File: org, Node: Sparse trees, Next: Tags, Prev: Archiving, Up: Document Structure + +2.7 Sparse trees +================ + +An important feature of Org-mode is the ability to construct _sparse +trees_ for selected information in an outline tree. A sparse tree +means that the entire document is folded as much as possible, but the +selected information is made visible along with the headline structure +above it(1). Just try it out and you will see immediately how it works. + + Org-mode contains several commands creating such trees. The most +basic one is `org-occur': + +`C-c /' + Occur. Prompts for a regexp and shows a sparse tree with all + matches. If the match is in a headline, the headline is made + visible. If the match is in the body of an entry, headline and + body are made visible. In order to provide minimal context, also + the full hierarchy of headlines above the match is shown, as well + as the headline following the match. Each match is also + highlighted, the highlights disappear when the buffer is changed + with an editing command. + For frequently used sparse trees of specific search strings, you can +use the variable `org-agenda-custom-commands' to define fast keyboard +access to specific sparse trees. These commands will then be +accessible through the agenda dispatcher (*note Agenda dispatcher::). +For example + (setq org-agenda-custom-commands + '(("f" occur-tree "FIXME"))) + will define the key `C-c a f' as a shortcut for creating a sparse +tree matching the string `FIXME'. + + Other commands are using sparse trees as well. For example `C-c +C-v' creates a sparse TODO tree (*note TODO basics::). + + To print a sparse tree, you can use the Emacs command +`ps-print-buffer-with-faces' which does not print invisible parts of +the document (2). Or you can use the command `C-c C-x v' to copy the +visible part of the document to another file (extension `.txt') which +then can be printed in any desired way. + + ---------- Footnotes ---------- + + (1) See also the variables `org-show-hierarchy-above' and +`org-show-following-heading'. + + (2) This does not work under XEmacs, because XEmacs uses selective +display for outlining, not text properties + + +File: org, Node: Tags, Next: Plain Lists, Prev: Sparse trees, Up: Document Structure + +2.8 Tags +======== + +If you wish to implement a tag system to cross-correlate information, +this can be done as well in Org-mode. Every headline can contain a +list of tags, at the end of the headline. Tags are normal words +containing letters, numbers, `_', and `@'. Tags must be preceded and +followed by a single colon; like `:WORK:'. Several tags can be +specified like `:WORK:URGENT:'. + + Tags make use of the hierarchical structure of outline trees. If a +heading has a certain tag, all subheadings will inherit the tag as +well. For example, in the list + + * Meeting with the French group :WORK: + ** Summary by Frank :BOSS:NOTES: + *** TODO Prepare slides for him :ACTION: + the final heading will have the tags `:WORK:', `:BOSS:', `:NOTES:', +and `:ACTION:'. When executing tag searches and Org-mode finds that a +certain headline matches the search criterion, it will not check any +sublevel headline, assuming that these likely also match, and that the +list of matches can become very long. You can influence inheritance +and searching using the variables `org-use-tag-inheritance' and +`org-tags-match-list-sublevels'. + + Tags can simply be typed into the buffer. After a colon, `M-' +offers completion on all tags being used in the current buffer. There +are also special commands for inserting tags, and for executing +searches based on tags. + +`C-c C-c' + Enter new tags for the current headline. The minibuffer will + prompt for a list of tags and offer completion with respect to all + other tags used in the current buffer. Several tags, separated by + colons, may be specified at the prompt. After pressing , the + tags will be inserted and aligned to `org-tags-column'. When + called with a `C-u' prefix, align all tags in the current buffer + to that column, just to make things look nice. TAGS are + automatically realigned after promotion, demotion, and TODO state + changes (*note TODO basics::). + +`C-c \' + Create a sparse tree with all headlines matching a tags search. + +`C-c a m' + Create a global list of tag matches from all agenda files. *Note + Matching headline tags::. + +`C-c a M' + Create a global list of tag matches from all agenda files, but + check only TODO items and force checking subitems (see variable + `org-tags-match-list-sublevels'). + + A tags search string can use Boolean operators `&' for AND and `|' +for OR. `&' binds more strongly than `|'. Parenthesis are currently no +implemented. A tag may also be preceded by `-', to select against it, +and `+' is syntactic sugar for positive selection. The AND operator +`&' is optional when `+' or `-' is present. For example, `+WORK-BOSS' +would select all headlines that are tagged `:WORK:', but discard those +also tagged `:BOSS:'. The search string `WORK|LAPTOP' selects all +lines tagged `:WORK:' or `:LAPTOP:'. The string `WORK|LAPTOP&NIGHT' +requires that the `:LAPTOP:' lines are also tagged `NIGHT'. + + +File: org, Node: Plain Lists, Prev: Tags, Up: Document Structure + +2.9 Plain Lists +=============== + +Headlines define the structure of the Org-mode file, and also lists +(for example TODO items (*note TODO items::) should be created using +headline levels. However, when taking notes, the plain text is +sometimes easier to read with hand-formatted lists. Org-mode supports +editing such lists, and the HTML exporter (*note Exporting::) does +parse and format them. + + Org-mode knows ordered and unordered lists. Unordered list items +start with `-', `+', or `*'(1) as bullets. Ordered list items start +with `1.' or `1)'. Items belonging to the same list must have the same +indentation on the first line. In particular, if an ordered list +reaches number `10.', also the 2-digit numbers must be written +left-aligned with the other numbers in the list. Indentation also +determines the end of a list item. It ends before the next line that +is indented like the bullet/number, or less. For example: + + ** Lord of the Rings + My favorite scenes are (in this order) + 1. Eowyns fight with the witch king + + this was already my favorite scene in the book + + I really like Miranda Otto. + 2. The attack of the Rohirrim + 3. Peter Jackson being shot by Legolas + - on DVD only + He makes a really funny face when it happens. + + Org-mode supports these lists by tuning filling and wrapping commands +to correctly deal with them. Furthermore, the following commands act +on items when the cursor is in the first line of an item (the line with +the bullet or number). + +`' + Items can be folded just like headline levels if you set the + variable `org-cycle-include-plain-lists'. The level of an item is + then given by the indentation of the bullet/number. However, + items are always subordinate to real headlines, the hierarchies + remain completely separated. + +`M-' + Insert new item at current level. With prefix arg, for a new + heading. + +`M-S-' +`M-S-' + Move the item including subitems up/down (swap with previous/next + item of same indentation). If the list is ordered, renumbering is + automatic. + +`M-S-' +`M-S-' + Decrease/increase the indentation of the item, including subitems. + Initially, the item tree is selected based on current indentation. + When these commands are executed several times in direct + succession, the initially selected region is used, even if the new + indentation would imply a different hierarchy. To use the new + hierarchy, break the command chain with a cursor motion or so. + +`C-c C-c' + Renumber the ordered list at the cursor. + + ---------- Footnotes ---------- + + (1) When using `*' as a bullet, lines must be indented or they will +be seen as top-level headlines. Also, when you are hiding leading +stars to get a clean outline view, plain list items starting with a +star are visually indistinguishable from true headlines. In short: +Even though `*' is supported, it may be better to not use it for plain +list items + + +File: org, Node: Tables, Next: Hyperlinks, Prev: Document Structure, Up: Top + +3 Tables +******** + +Org-mode has a very fast and intuitive table editor built-in. +Spreadsheet-like calculations are supported in connection with the +Emacs `calc' package. + +* Menu: + +* Built-in table editor:: Simple tables +* Table calculations:: Compute a field from other fields +* orgtbl-mode:: The table editor as minor mode +* table.el:: Complex tables + + +File: org, Node: Built-in table editor, Next: Table calculations, Prev: Tables, Up: Tables + +3.1 The built-in table editor +============================= + +Org-mode makes it easy to format tables in plain ASCII. Any line with +`|' as the first non-white character is considered part of a table. +`|' is also the column separator. A table might look like this: + + | Name | Phone | Age | + |-------+-------+-----| + | Peter | 1234 | 17 | + | Anna | 4321 | 25 | + + A table is re-aligned automatically each time you press or + or `C-c C-c' inside the table. also moves to the next +field ( to the next row) and creates new table rows at the end of +the table or before horizontal lines. The indentation of the table is +set by the first line. Any line starting with `|-' is considered as a +horizontal separator line and will be expanded on the next re-align to +span the whole table width. So, to create the above table, you would +only type + + |Name|Phone|Age + |- + and then press to align the table and start filling in fields. + + When typing text into a field, Org-mode treats , , +and all character keys in a special way, so that inserting and deleting +avoids shifting other fields. Also, when typing _immediately after the +cursor was moved into a new field with `', `S-' or `'_, +the field is automatically made blank. If this behavior is too +unpredictable for you, configure the variables +`org-enable-table-editor' and `org-table-auto-blank-field'. + +Creation and conversion +....................... + +`M-x org-table-create' + Creates an empty Org-mode table. However, it is much easier to + just start typing, like `|Name|Phone|Age |- ' + +`C-c C-c' + Convert region to table. Works when the cursor is not in an + existing table, and when there is a region defined. If every line + contains at least one TAB character, the function assumes that the + material is tab separated. If not, lines are split at whitespace + into fields. You can use a prefix argument to indicate how many + consecutive spaces are at least required to indicate a field + separator (default: just one). + +Re-aligning and field motion +............................ + +`C-c C-c' + Re-align the table without moving the cursor. + +`' + Re-align the table, move to the next field. Creates a new row if + necessary. + +`S-' + Re-align, move to previous field. + +`' + Re-align the table and move down to next row. Creates a new row if + necessary. At the beginning or end of a line, still does + NEWLINE, so it can be used to split a table. + +Column and row editing +...................... + +`M-' +`M-' + Move the current column left/right + +`M-S-' + Kill the current column. + +`M-S-' + Insert a new column to the left of the cursor position. + +`M-' +`M-' + Move the current row up/down + +`M-S-' + Kill the current row or horizontal line. + +`M-S-' + Insert a new row above (with arg: below) the current row. + +`C-c -' + Insert a horizontal line below current row. With prefix arg, the + line is created above the current line. + +`C-c ^' + Sort the table lines in the region. Point and mark must be in the + first and last line to be included, and must be in the column that + should be used for sorting. The command prompts for numerical + versus alphanumerical sorting. + +Regions +....... + +`C-c C-x M-w' + Copy a rectangular region from a table to a special clipboard. + Point and mark determine edge fields of the rectangle. The + process ignores horizontal separator lines. + +`C-c C-x C-w' + Copy a rectangular region from a table to a special clipboard, and + blank all fields in the rectangle. So this is the "cut" operation. + +`C-c C-x C-y' + Paste a rectangular region into a table. The upper right corner + ends up in the current field. All involved fields will be + overwritten. If the rectangle does not fit into the present table, + the table is enlarged as needed. The process ignores horizontal + separator lines. + +`C-c C-q' + Wrap several fields in a column like a paragraph. If there is an + active region, and both point and mark are in the same column, the + text in the column is wrapped to minimum width for the given + number of lines. A prefix ARG may be used to change the number of + desired lines. If there is no region, the current field is split + at the cursor position and the text fragment to the right of the + cursor is prepended to the field one line down. If there is no + region, but you specify a prefix ARG, the current field gets + blank, and the content is appended to the field above. + +Calculations +............ + +`C-c =' + Install a new formula for the current column and replace current + field with the result of the formula. + +`C-u C-c =' + Install a new formula for the current field, which must be a named + field. Evaluate the formula and replace the field content with the + result. + +`C-c '' + Edit all formulas associated with the current table in a separate + buffer. + +`C-c *' + Recalculate the current row by applying the stored formulas from + left to right. When called with a `C-u' prefix, recalculate the + entire table, starting with the first non-header line (i.e. below + the first horizontal separator line). For details, see *Note + Table calculations::. + +`C-#' + Rotate the calculation mark in first column through the states `', + `#', `*', `!', `$'. For the meaning of these marks see *Note + Advanced features::. When there is an active region, change all + marks in the region. + +`C-c ?' + Which table column is the cursor in? Displays number >0 in echo + area. + +`C-c +' + Sum the numbers in the current column, or in the rectangle defined + by the active region. The result is shown in the echo area and can + be inserted with `C-y'. + +`S-' + When current field is empty, copy from first non-empty field above. + When not empty, copy current field down to next row and move cursor + along with it. Depending on the variable + `org-table-copy-increment', integer field values will be + incremented during copy. This key is also used by CUA-mode (*note + Interaction::). + +Miscellaneous +............. + +`C-c |' + Toggle the visibility of vertical lines in tables. The lines are + still there, only made invisible with a text property. Any `|' + added by hand will become invisible on the next align. + +`M-x org-table-import' + Import a file as a table. The table should be TAB- or whitespace + separated. Useful for example to import an Excel table or data + from a database, because these programs generally can write + TAB-separated text files. This command works by inserting the + file into the buffer and then converting the region to a table. + Any prefix argument is passed on to the converter, which uses it + to determine the separator. + +`M-x org-table-export' + Export the table as a TAB-separated file. Useful for data + exchange with for example Excel or database programs. + + + If you don't like the automatic table editor because it gets into +your way in lines which you would like to start with `|', you can turn +it off with + (setq org-enable-table-editor nil) + The only table command which then still works is `C-c C-c' to do a +manual re-align. + + +File: org, Node: Table calculations, Next: orgtbl-mode, Prev: Built-in table editor, Up: Tables + +3.2 Calculations in tables +========================== + +The table editor makes use of the Emacs `calc' package to implement +spreadsheet-like capabilities. Org-mode has two levels of complexity +for table calculations. On the basic level, tables do only horizontal +computations, so a field can be computed from other fields _in the same +row_, and Org-mode assumes that there is only one formula for each +column. This is very efficient to work with and enough for many tasks. +On the complex level, columns and individual fields can be named for +easier referencing in formulas, individual named fields can have their +own formula associated with them, and recalculation can be automated. + +* Menu: + +* Formula syntax:: How to write a formula +* Column formulas:: Formulas valid for all fields in a column +* Advanced features:: Field names, parameters and automatic recalc +* Named-field formulas:: Formulas valid in single fields +* Editing/debugging formulas:: Changing a stored formula +* Appetizer:: Taste the power of calc + + +File: org, Node: Formula syntax, Next: Column formulas, Prev: Table calculations, Up: Table calculations + +3.2.1 Formula syntax +-------------------- + +A formula can be any algebraic expression understood by the Emacs +`calc' package. Note that `calc' has the slightly non-standard +conversion that `/' has lower precedence than `*', so that `a/b*c' is +interpreted as `a/(b*c)'. Before evaluation by `calc-eval' (*note +calc-eval: (calc)Calling Calc from Your Lisp Programs.), variable +substitution takes place: + + $ refers to the current field + $3 refers to the field in column 3 of the current row + $3..$7 a vector of the fields in columns 3-7 of current row + $P1..$P3 vector of column range, using column names + &2 second data field above the current, in same column + &5-2 vector from fifth to second field above current + &III-II vector of fields between 2nd and 3rd hline above + &III vector of fields between third hline above and current field + $name a named field, parameter or constant + + The range vectors can be directly fed into the calc vector functions +like `vmean' and `vsum'. + + `$name' is interpreted as the name of a column, parameter or +constant. Constants are defined globally through the variable +`org-table-formula-constants'. If you have the `constants.el' package, +it will also be used to resolve constants, including natural constants +like `$h' for Planck's constant, units like `$km' for kilometers. +Column names and parameters can be specified in special table lines. +These are described below, see *Note Advanced features::. + + A formula can contain an optional mode string after a semicolon. +This string consists of flags to influence calc's modes(1) during +execution, e.g. `p20' to switch the internal precision to 20 digits, +`n3', `s3', `e2' or `f4' to switch to normal, scientific, engineering, +or fix display format, respectively, and `D', `R', `F', and `S' to turn +on degrees, radians, fraction and symbolic modes, respectively. In +addition, you may provide a `printf' format specifier to reformat the +final result. A few examples: + $1+$2 Sum of first and second field + $1+$2;%.2f Same, format result to two decimals + exp($2)+exp($1) Math functions can be used + $;%.1f Reformat current cell to 1 decimal + ($3-32)*5/9 Degrees F -> C conversion + $c/$1/$cm Hz -> cm conversion, using `constants.el' + tan($1);Dp3s1 Compute in degrees, precision 3, display SCI 1 + sin($1);Dp3%.1e Same, but use printf specifier for display + vmean($2..$7) Compute column range mean, using vector function + vsum(&III) Sum numbers from 3rd hline above to here + taylor($3,x=7,2) taylor series of $3, at x=7, second degree + + ---------- Footnotes ---------- + + (1) By default, Org-mode uses the standard calc modes (precision 12, +angular units degrees, fraction and symbolic modes off). However, the +display format has been changed to `(float 5)' to keep tables compact. +The default settings can be configured using the variable +`org-calc-default-modes'. + + +File: org, Node: Column formulas, Next: Advanced features, Prev: Formula syntax, Up: Table calculations + +3.2.2 Column formulas +--------------------- + +To apply a formula to a field, type it directly into the field, +preceded by an equal sign, like `=$1+$2'. When you press or + or `C-c C-c' with the cursor still in the field, the formula will +be stored as the formula for the current column, evaluated and the +current field replaced with the result. If the field contains only +`=', the previously stored formula for this column is used. + + For each column, Org-mode will remember the most recently used +formula. The information is stored in a special line starting with +`#+TBLFM' directly below the table. When adding/deleting/moving +columns with the appropriate commands, the stored equations will be +modified accordingly. When a column used in a calculation is removed, +references to this column become invalid and will cause an error upon +applying the equation. + + Instead of typing an equation into the field, you may also use the +command `C-c ='. It prompts for a formula (with default taken from the +`#+TBLFM:' line) and applies it to the current field. A numerical +prefix (e.g. `C-5 C-c =') will apply it to that many subsequent fields +in the current column. + + To recompute all the fields in a line, use the command `C-c *'. It +re-applies all stored equations to the current row, from left to right. +With a `C-u' prefix, this will be done to every line in the table, so +use this command it you want to make sure the entire table is +up-to-date. `C-u C-c C-c' is another way to update the entire table. +Global updating does not touch the line(s) above the first horizontal +separator line, assuming that this is the table header. + + +File: org, Node: Advanced features, Next: Named-field formulas, Prev: Column formulas, Up: Table calculations + +3.2.3 Advanced features +----------------------- + +If you want want the recalculation of fields to happen automatically, +or if you want to be able to assign a formula to an individual field +(instead of an entire column) you need to reserve the first column of +the table for special marking characters. Here is an example of a +table that collects exam results of students and makes use of these +features: + |---+---------+--------+--------+--------+-------+------| + | | Student | Prob 1 | Prob 2 | Prob 3 | Total | Note | + |---+---------+--------+--------+--------+-------+------| + | ! | | P1 | P2 | P3 | Tot | | + | # | Maximum | 10 | 15 | 25 | 50 | 10.0 | + | ^ | | m1 | m2 | m3 | mt | | + |---+---------+--------+--------+--------+-------+------| + | # | Peter | 10 | 8 | 23 | 41 | 8.2 | + | # | Sara | 6 | 14 | 19 | 39 | 7.8 | + | # | Sam | 2 | 4 | 3 | 9 | 1.8 | + |---+---------+--------+--------+--------+-------+------| + | | Average | | | | 29.7 | | + | ^ | | | | | at | | + | $ | max=50 | | | | | | + |---+---------+--------+--------+--------+-------+------| + #+TBLFM: $6=vsum($P1..$P3)::$7=10*$Tot/$max;%.1f::$at=vmean(&II);%.1f + +Important: Please note that for these special tables, recalculating the +table with `C-u C-c *' does only affect rows which are marked `#' or +`*', and named fields. The column formulas are not applied in rows +with empty first field. + + The marking characters have the following meaning: +`!' + The fields in this line define names for the columns, so that you + may refer to a column as `$Tot' instead of `$6'. + +`^' + This row defines names for the fields _above_ the row. With such + a definition, any formula in the table may use `$m1' to refer to + the value `10'. Also, named fields can have their own formula + associated with them. + +`_' + Similar to `^', but defines names for the fields in the row + _below_. + +`$' + Fields in this row can define _parameters_ for formulas. For + example, if a field in a `$' row contains `max=50', then formulas + in this table can refer to the value 50 using `$max'. Parameters + work exactly like constants, only that they can be defined on a + per-table basis. Changing a parameter and then recalculating the + table can be useful. + +`#' + Fields in this row are automatically recalculated when pressing + or or `S-' in this row. Also, this row is + selected for a global recalculation with `C-u C-c *'. Unmarked + lines will be left alone by this command. + +`*' + Selects this line for global recalculation with `C-u C-c *', but + not for automatic recalculation. Use this when automatic + recalculation slows down editing too much. + +`' + Unmarked lines are exempted from recalculation with `C-u C-c *'. + All lines that should be recalculated should be marked with `#' or + `*'. + + +File: org, Node: Named-field formulas, Next: Editing/debugging formulas, Prev: Advanced features, Up: Table calculations + +3.2.4 Named-field formulas +-------------------------- + +A named field can have its own formula associated with it. In the +example above, this is used for the `at' field that contains the +average result of the students. To enter a formula for a named field, +just type it onto the buffer, preceded by `:='. Or use `C-u C-c ='. +This equation will be stored below the table like `$name=...'. Any +recalculation in the table (even if only requested for the current +line) will also update all named field formulas. + + +File: org, Node: Editing/debugging formulas, Next: Appetizer, Prev: Named-field formulas, Up: Table calculations + +3.2.5 Editing and debugging formulas +------------------------------------ + +To edit a column or field formula, you can use the commands `C-c =' and +`C-u C-c =', respectively. The currently active expression is then +presented as default in the minibuffer, were it may be edited. + + Note that making a table field blank does not remove the formula +associated with the field - during the next recalculation the field +will be filled again. To remove a formula from a field, you have to +give an empty reply when prompted for the formula, or to edit the +`#+TBLFM' line. + + You may edit the `#+TBLFM' directly and re-apply the changed +equations with `C-c C-c' in that line, or with the normal recalculation +commands in the table. + + In particular for large tables with many formulas, it is convenient +to use the command `C-c '' to edit the formulas of the current table in +a separate buffer. That buffer will show the formulas one per line, +and you are free to edit, add and remove formulas. Press `C-c ?' on a +`$...' expression to get information about its interpretation. +Exiting the buffer with `C-c C-c' only stores the modified formulas +below the table. Exiting with `C-u C-c C-c' also applies them to the +entire table. `C-c C-q' exits without installing the changes. + + When the evaluation of a formula leads to an error, the field content +becomes the string `#ERROR'. If you would like see what is going on +during variable substitution and calculation in order to find a bug, +turn on formula debugging in the menu and repeat the calculation by +pressing, for example by pressing `C-c = ' in a field. Detailed +information will be displayed. + + +File: org, Node: Appetizer, Prev: Editing/debugging formulas, Up: Table calculations + +3.2.6 Appetizer +--------------- + +Finally, just to wet your appetite on what can be done with the +fantastic `calc' package, here is a table that computes the Taylor +series for a couple of functions (homework: try that with Excel :-) + + |---+-------------+---+-----+--------------------------------------| + | | Func | n | x | Result | + |---+-------------+---+-----+--------------------------------------| + | # | exp(x) | 1 | x | 1 + x | + | # | exp(x) | 2 | x | 1 + x + x^2 / 2 | + | # | exp(x) | 3 | x | 1 + x + x^2 / 2 + x^3 / 6 | + | # | x^2+sqrt(x) | 2 | x=0 | x*(0.5 / 0) + x^2 (2 - 0.25 / 0) / 2 | + | # | x^2+sqrt(x) | 2 | x=1 | 2 + 2.5 x - 2.5 + 0.875 (x - 1)^2 | + | * | tan(x) | 3 | x | 0.0175 x + 1.77e-6 x^3 | + |---+-------------+---+-----+--------------------------------------| + #+TBLFM: $5=taylor($2,$4,$3);n3 + + +File: org, Node: orgtbl-mode, Next: table.el, Prev: Table calculations, Up: Tables + +3.3 The Orgtbl minor mode +========================= + +If you like the intuitive way the Org-mode table editor works, you +might want to use it also in other modes like text-mode or mail-mode. +The minor mode Orgtbl-mode makes this possible. You can always toggle +the mode with `M-x orgtbl-mode'. To turn it on by default, for example +in mail mode, use + (add-hook 'mail-mode-hook 'turn-on-orgtbl) + + +File: org, Node: table.el, Prev: orgtbl-mode, Up: Tables + +3.4 The `table.el' package +========================== + +Complex ASCII tables with automatic line wrapping, column- and +row-spanning, and alignment can be created using the Emacs table +package by Takaaki Ota (`http://sourceforge.net/projects/table', and +also part of Emacs 22). When or `C-c C-c' is pressed in such a +table, Org-mode will call `table-recognize-table' and move the cursor +into the table. Inside a table, the keymap of Org-mode is inactive. +In order to execute Org-mode-related commands, leave the table. + +`C-c C-c' + Recognize `table.el' table. Works when the cursor is in a + table.el table. + +`C-c ~' + Insert a table.el table. If there is already a table at point, + this command converts it between the table.el format and the + Org-mode format. See the documentation string of the command + `org-convert-table' for the restrictions under which this is + possible. + + +File: org, Node: Hyperlinks, Next: TODO items, Prev: Tables, Up: Top + +4 Hyperlinks +************ + +Just like HMTL, Org-mode provides links inside a file, and external +links to other files, Usenet articles, emails and much more. + +* Menu: + +* Internal Links:: Links to other places in the current file +* External Links:: URL-like links to the world +* Managing links:: Creating, inserting and following +* Search Options:: Linking to a specific location +* Remember:: Org-trees store quick notes + + +File: org, Node: Internal Links, Next: External Links, Prev: Hyperlinks, Up: Hyperlinks + +4.1 Internal Links +================== + +Strings inside double brackets like `[[My Target]]' are links that lead +to a text search in the current file. The link can be followed with +`C-c C-o' or with a mouse click (*note Managing links::). The +preferred match for such a link is a dedicated target: The same string +in double angular brackets. Targets may be located anywhere, often it +is convenient to put them into a comment line, for example + # <> + + If no dedicated target exists, Org-mode will search for the words in +the link, in the above example for `my target'. Links starting with a +star like `*My Target' restrict the search to headlines. When +searching, Org-mode will first try an exact match, but then move on to +more and more lenient searches. For example, the link `[[*My +Targets]]' will find any of the following + ** My targets + ** TODO my targets are bright + ** my 20 targets are + It is therefore often not necessary to set a dedicated target. To +insert a link targeting a headline, in-buffer completion can be used. +Just type a star followed by a few optional letters into the buffer and +press `M-'. All headlines in the current buffer will be offered +as completions. *Note Managing links::, for more commands creating +links. + + Following a link pushes a mark onto Org-mode's own mark ring. You +can return to the previous position with `C-c &'. Using this command +several times in direct succession goes back to positions recorded +earlier. + +* Menu: + +* Radio targets:: Make targets trigger links in plain text. +* CamelCase links:: Activating CamelCase words as links + + +File: org, Node: Radio targets, Next: CamelCase links, Prev: Internal Links, Up: Internal Links + +4.1.1 Radio targets +------------------- + +You can configure Org-mode to link any occurrences of certain target +names in normal text. So without explicitly creating a link, the text +connects to the target radioing its position. Radio targets are +enclosed by triple angular brackets. For example, a target `<<>>' causes each occurrence of `my target' in normal text to +become activated as a link. The Org-mode file is scanned automatically +for radio targets only when the file is first loaded into Emacs. To +update the target list during editing, press `C-c C-c' with the cursor +on or at a target. + + +File: org, Node: CamelCase links, Prev: Radio targets, Up: Internal Links + +4.1.2 CamelCase words as links +------------------------------ + +As an alternative to `[[...]]' links, Org-mode also supports CamelCase +words as links. This feature is not turned on by default because of +the occasional inconsistencies this system suffers from. To activate +CamelCase words as links, and to make headline completion offer +CamelCase version of headlines, the following customization is needed: + (setq org-activate-camels t + org-file-link-context-use-camel-case t) + + +File: org, Node: External Links, Next: Managing links, Prev: Internal Links, Up: Hyperlinks + +4.2 External Links +================== + +Org-mode supports links to files, websites, Usenet and email messages; +and BBDB database entries. Links are just plain-text URL-like +locators, optionally enclosed by angular brackets. The following list +shows examples for each link type. + + on the web + file, absolute path + file, relative path + Usenet link + Mail link + VM folder link + VM message link + VM on remote machine + WANDERLUST folder link + WANDERLUST message link + MH-E folder link + MH-E message link + RMAIL folder link + RMAIL message link + GNUS group link + GNUS article link + BBDB link + (1) A shell command + + A link may contain space characters and is terminated by `>' or by +the end of a line. In tables, the end of a table field also terminates +a link. Angle brackets around a link are not required, but are +recommended to avoid problems with punctuation and other text following +the link. See also the variable `org-allow-space-in-links'. + + ---------- Footnotes ---------- + + (1) Note that `<' and `>' cannot be part of a link, and therefore of +a shell command. If you need redirection, use @{ and @} instead. + + +File: org, Node: Managing links, Next: Search Options, Prev: External Links, Up: Hyperlinks + +4.3 Managing links +================== + +Org-mode provides methods to create a link in the correct syntax, to +insert it into an org-mode file, and to follow the link. + +`C-c l' + Store a link to the current location. This is a _global_ command + which can be used in any buffer to create a link. The link will be + stored for later insertion into an Org-mode buffer (see below). + For VM, RMAIL, WANDERLUST, GNUS and BBDB buffers, the link will + point to the current article/entry. For W3 and W3M buffer, the + link goes to the current URL. For Org-mode files, the current + headline is targeted. For any other files, the link will point to + the file, with a search string (*note Search Options::) pointing + to the contents of the current line. If there is an active + region, the selected words will form the basis of the search + string. The key binding `C-c l' is only a suggestion - see *Note + Installation and Activation::. + +`C-c C-l' + Insert a link. This prompts for a link to be inserted into the + buffer. You can just type a link, using one of the link type + prefixes mentioned in the examples above. Through completion, all + links stored during the current session can be accessed. When + called with prefix arg, you can use file name completion to enter + a file link. The link will be formatted as given in the variable + `org-link-format' and inserted into the buffer. Note that you + don't have to use this command to insert a link. Links in + Org-mode are plain text, and you can type or paste them straight + into the buffer. + +`C-c C-o' + Open link at point. This will launch a web browser for URLs (using + `browse-url-at-point'), run vm/gnus/bbdb for the corresponding + links, and execute the command in a shell link. When the cursor + is on a CamelCase link, this commands runs the corresponding + search. When the cursor is on a TAGS list in a headline, it + creates the corresponding TAGS view. Furthermore, it will visit + text files in `file:' links with Emacs and select a suitable + application for non-text files. Classification of files is based + on file extension only. See option `org-file-apps'. If there is + no link at point, the current subtree will be searched for one. + If you want to override the default application and visit the file + with Emacs, use a `C-u' prefix. If the cursor is on a time stamp, + compiles the agenda for that date. + + *IMPORTANT*: Be careful not to use any dangerous commands in a + shell link. + +`mouse-2' +`mouse-1' + On links, `mouse-2' will open the link just like `C-c C-o' would. + Under Emacs 22, also `mouse-1' will follow a link. + +`mouse-3' + Like `mouse-2', but force file links to be opened with Emacs. + +`C-c %' + Push the current position onto the mark ring, to be able to return + easily. Commands following an internal link do this automatically. + +`C-c &' + Jump back to a recorded position. A position is recorded by the + commands following internal links, and by `C-c %'. Using this + command several times in direct succession moves through a ring of + previously recorded positions. + + +File: org, Node: Search Options, Next: Remember, Prev: Managing links, Up: Hyperlinks + +4.4 Search options in file links +================================ + +File links can contain additional information to make Emacs jump to a +particular location in the file when following a link. This can be a +line number or a search option after a double(1) colon. For example: + + + + + Here is what these options do. + +`255' + Jump to line 255. + +`My Target' + Search for a link target `<>', or do a text search for + `my target', similar to the search in internal links, see *Note + Internal Links::. + +`*My Target' + In an Org-mode file, restrict search to headlines. + +`/regexp/' + Do a regular expression search for `regexp'. This uses the Emacs + command `occur' to list all matches in a separate window. If the + target file is in Org-mode, `org-occur' is used to create a sparse + tree with the matches. + + As a degenerate case, a file link with an empty file name can be used +to search the current file. For example, `' does a +search for `find me' in the current file, just like `[[find me]]' would. + + ---------- Footnotes ---------- + + (1) For backward compatibility, line numbers can also follow a +single colon. + + +File: org, Node: Remember, Prev: Search Options, Up: Hyperlinks + +4.5 Remember +============ + +Another way to create org entries with links to other files is through +the _Remember_ package by John Wiegley. _Remember_ lets you store +quick notes with little interruption of your work flow. See +`http://www.emacswiki.org/cgi-bin/wiki/RememberMode' for more +information. The notes produced by _Remember_ can be stored in +different ways, and Org-mode files are a good target. Org-mode allows +to file away notes either to a default file, or directly to the correct +location in your Org-mode outline tree. The following customization(1) +will tell _Remember_ to use org files as target, and to create +annotations compatible with Org-mode links. + + (autoload 'org-remember-annotation "org") + (autoload 'org-remember-apply-template "org") + (autoload 'org-remember-handler "org") + (setq org-directory "~/path/to/my/orgfiles/") + (setq org-default-notes-file "~/.notes") + (setq remember-annotation-functions '(org-remember-annotation)) + (setq remember-handler-functions '(org-remember-handler)) + (add-hook 'remember-mode-hook 'org-remember-apply-template) + + In combination with Org-mode, you can use templates to generate +different types of remember notes. For example, if you would like to +use one template to create general TODO entries, and another one for +journal entries, you could use: + + (setq org-remember-templates + '((?t "* TODO %?\n %i\n %a" "~/org/TODO.org") + (?j "* %U %?\n\n %i\n %a" "~/org/JOURNAL.org"))) + In these entries, the character specifies how to select the +template, the first string specifies the template, and the second string +specifies a default file (overruling `org-default-notes-file') as a +target for this note. + + When you call `M-x remember' to remember something, org will prompt +for a key to select the template and then prepare the buffer like + * TODO + + or + * [2006-03-21 Tue 15:37] + + + +See the variable `org-remember-templates' for more details. + + When you are finished composing a note with remember, you have to +press `C-c C-c' to exit remember-mode and to file the note away. The +handler first prompts for a target file - if you press , the value +of `org-default-notes-file' is used. Then the command offers the +headings tree of the selected file. You can either immediately press + to get the note appended to the file. Or you can use vertical +cursor motion ( and ) and visibility cycling () to find +a better place. Pressing or or leads to the +following result. + +Cursor Key Note gets inserted +position +buffer-start as level 2 heading at end of file +on headline as sublevel of the heading at cursor + as same level, before current heading + as same level, after current heading +not on at cursor position, level taken from context. +headline Or use prefix arg to specify level + manually. + + So a fast way to store the note is to press `C-c C-c ' to +append it to the default file. Even shorter would be `C-u C-c C-c', +which does the same without even showing the tree. But with little +extra effort, you can push it directly to the correct location. + + Before inserting the text into a tree, the function ensures that the +text has a headline, i.e. a first line that starts with a `*'. If not, +a headline is constructed from the current date and some additional +data. If the variable `org-adapt-indentation' is non-nil, the entire +text is also indented so that it starts in the same column as the +headline (after the asterisks). + + ---------- Footnotes ---------- + + (1) The three autoload forms are only necessary if `org.el' is not +part of the Emacs distribution or an XEmacs package. + + +File: org, Node: TODO items, Next: Timestamps, Prev: Hyperlinks, Up: Top + +5 TODO items +************ + +Org-mode does not maintain TODO lists as a separate document. TODO +items are an integral part of the notes file, because TODO items +usually come up while taking notes! With Org-mode, you simply mark any +entry in a tree as being a TODO item. In this way, the information is +not duplicated, and the entire context from which the item emerged is +always present when you check. + + Of course, this technique causes TODO items to be scattered +throughout your file. Org-mode provides methods to give you an +overview over all things you have to do. + +* Menu: + +* TODO basics:: Marking and displaying TODO entries +* Progress Logging:: Document your productivity +* TODO extensions:: Workflow and assignments +* Priorities:: Some things are more important than others + + +File: org, Node: TODO basics, Next: Progress Logging, Prev: TODO items, Up: TODO items + +5.1 Basic TODO functionality +============================ + +Any headline can become a TODO item by starting it with the word TODO, +for example + + *** TODO Write letter to Sam Fortune + +The most important commands to work with TODO entries are: + +`C-c C-t' + Rotate the TODO state of the current item between + ,-> (unmarked) -> TODO -> DONE --. + '--------------------------------' + The same rotation can also be done "remotely" from the timeline and + agenda buffers with the `t' command key (*note Agenda commands::). + +`C-c C-v' + View TODO items in a _sparse tree_ (*note Sparse trees::). Folds + the entire buffer, but shows all TODO items and the headings + hierarchy above them. With prefix arg, show also the DONE + entries. With numerical prefix N, show the tree for the Nth + keyword in the variable `org-todo-keywords'. + +`C-c a t' + Show the global TODO list. This collects the TODO items from all + agenda files (*note Agenda Views::) into a single buffer. The + buffer is in `agenda-mode', so there are commands to examine and + manipulate the TODO entries directly from that buffer (*note + Agenda commands::). *Note Global TODO list::, for more + information. + +``org-agenda-include-all-todo'' + If you would like to have all your TODO items listed as part of + your agenda, customize the variable `org-agenda-include-all-todo'. + + +File: org, Node: Progress Logging, Next: TODO extensions, Prev: TODO basics, Up: TODO items + +5.2 Progress Logging +==================== + +If you want to keep track of _when_ a certain TODO item was finished, +turn on logging with + (setq org-log-done t) + Then each time you turn a TODO entry into DONE using either `C-c +C-t' in the Org-mode buffer or `t' in the agenda buffer, a line +`CLOSED: [timestamp]' will be inserted just after the headline. If you +turn the entry back into a TODO item again through further state +cycling, that line will be removed again. In the timeline (*note +Timeline::) and in the agenda (*note Weekly/Daily Agenda::), you can +then use the `L' key to display the TODO items closed on each day, +giving you an overview of what has been done on a day. + + +File: org, Node: TODO extensions, Next: Priorities, Prev: Progress Logging, Up: TODO items + +5.3 Extended use of TODO keywords +================================= + +The default implementation of TODO entries is just two states: TODO +and DONE. You can, however, use the TODO feature for more complicated +things by configuring the variables `org-todo-keywords' and +`org-todo-interpretation'. Using special setup, you can even use TODO +keywords in different ways in different org files. + +* Menu: + +* Workflow states:: From TODO to DONE in steps +* TODO types:: I do this, Fred the rest +* Per file keywords:: Different files, different requirements + + +File: org, Node: Workflow states, Next: TODO types, Prev: TODO extensions, Up: TODO extensions + +5.3.1 TODO keywords as workflow states +-------------------------------------- + +You can use TODO keywords to indicate different states in the process +of working on an item, for example + + (setq org-todo-keywords '("TODO" "FEEDBACK" "VERIFY" "DONE") + org-todo-interpretation 'sequence) + + Changing these variables becomes only effective in a new Emacs +session. With this setup, the command `C-c C-t' will cycle an entry +from TODO to FEEDBACK, then to VERIFY, and finally to DONE. You may +also use a prefix argument to quickly select a specific state. For +example `C-3 C-c C-t' will change the state immediately to VERIFY. If +you define many keywords, you can use in-buffer completion (see *Note +Completion::) to insert these words into the buffer. + + +File: org, Node: TODO types, Next: Per file keywords, Prev: Workflow states, Up: TODO extensions + +5.3.2 TODO keywords as types +---------------------------- + +The second possibility is to use TODO keywords to indicate different +types of action items. For example, you might want to indicate that +items are for "work" or "home". If you are into David Allen's _Getting +Things DONE_, you might want to use todo types `NEXTACTION', `WAITING', +`MAYBE'. Or, when you work with several people on a single project, +you might want to assign action items directly to persons, by using +their names as TODO keywords. This would be set up like this: + + (setq org-todo-keywords '("Fred" "Sara" "Lucy" "Mike" "DONE") + org-todo-interpretation 'type) + + In this case, different keywords do not indicate a sequence, but +rather different types. So it is normally not useful to change from +one type to another. Therefore, in this case the behavior of the +command `C-c C-t' is changed slightly(1). When used several times in +succession, it will still cycle through all names. But when you return +to the item after some time and execute `C-c C-t' again, it will switch +from each name directly to DONE. Use prefix arguments or completion to +quickly select a specific name. You can also review the items of a +specific TODO type in a sparse tree by using a numeric prefix to `C-c +C-v'. For example, to see all things Lucy has to do, you would use +`C-3 C-c C-v'. To collect collect Lucy's items from all agenda files +into a single buffer, you would use the prefix arg as well when +creating the global todo list: `C-3 C-c t'. + + ---------- Footnotes ---------- + + (1) This is also true for the `t' command in the timeline and agenda +buffers. + + +File: org, Node: Per file keywords, Prev: TODO types, Up: TODO extensions + +5.3.3 Setting up TODO keywords for individual files +--------------------------------------------------- + +It can be very useful to use different aspects of the TODO mechanism in +different files, which is not possible with the global settings +described above. For file-local settings, you need to add special +lines to the file which set the keywords and interpretation for that +file only. For example, to set one of the two examples discussed +above, you need one of the following lines, starting in column zero +anywhere in the file: + + #+SEQ_TODO: TODO FEEDBACK VERIFY DONE + #+TYP_TODO: Fred Sara Lucy Mike DONE + +To make sure you are using the correct keyword, type `#+' into the +buffer and then use `M-' completion. + + Remember that the last keyword must always mean that the item is DONE +(you may use a different word, though). Also note that in each file, +only one of the two aspects of TODO keywords can be used. After +changing one of these lines, use `C-c C-c' with the cursor still in the +line to make the changes known to Org-mode(1). + + If you want to use very many keywords, for example when working with +a large group of people, you may split the names over several lines: + + #+TYP_TODO: Fred Sara Lucy Mike + #+TYP_TODO: Luis George Jules Jessica + #+TYP_TODO: Kim Arnold Peter + #+TYP_TODO: DONE + + ---------- Footnotes ---------- + + (1) Org-mode parses these lines only when Org-mode is activated +after visiting a file. `C-c C-c' with the cursor in a line starting +with `#+' is simply restarting Org-mode, making sure that these changes +will be respected. + + +File: org, Node: Priorities, Prev: TODO extensions, Up: TODO items + +5.4 Priorities +============== + +If you use Org-mode extensively to organize your work, you may end up +with a number of TODO entries so large that you'd like to prioritize +them. This can be done by placing a _priority cookie_ into the +headline, like this + + *** TODO [#A] Write letter to Sam Fortune + +With its standard setup, Org-mode supports priorities `A', `B', and +`C'. `A' is the highest priority. An entry without a cookie is +treated as priority `B'. Priorities make a difference only in the +agenda (*note Weekly/Daily Agenda::). + +`C-c ,' + Set the priority of the current item. The command prompts for a + priority character `A', `B' or `C'. When you press instead, + the priority cookie is removed from the headline. The priorities + can also be changed "remotely" from the timeline and agenda buffer + with the `,' command (*note Agenda commands::). + +`S-' +`S-' + Increase/decrease priority of current item. Note that these keys + are also used to modify time stamps (*note Creating timestamps::). + Furthermore, these keys are also used by CUA-mode (*note + Interaction::). + + +File: org, Node: Timestamps, Next: Agenda Views, Prev: TODO items, Up: Top + +6 Timestamps +************ + +Items can be labeled with timestamps to make them useful for project +planning. + +* Menu: + +* Time stamps:: Assigning a time to a tree entry +* Creating timestamps:: Commands which insert timestamps + + +File: org, Node: Time stamps, Next: Creating timestamps, Prev: Timestamps, Up: Timestamps + +6.1 Time stamps, deadlines and scheduling +========================================= + +A time stamp is a specification of a date (possibly with time) in a +special format, either `<2003-09-16 Tue>' or `<2003-09-16 Tue 09:39>'. +A time stamp can appear anywhere in the headline or body of an org-tree +entry. Its presence allows to show entries on specific dates in the +agenda (*note Weekly/Daily Agenda::). We distinguish: + +TIMESTAMP + A simple time stamp just assigns a date/time to an item. In the + timeline and agenda displays, the headline of the entry will be + shown exactly on that date. + +TIMERANGE + Two time stamps connected by `--' denote a time range. The + headline will be shown on the first and last day of the range, and + on any dates that are displayed and fall in the range. Here is an + example: + + ** Meeting in Amsterdam + <2004-08-23 Mon>--<2004-08-26 Thu> + +DEADLINE + If a time stamp is preceded by the word `DEADLINE:', the task + (most likely a TODO item) is supposed to be finished on that date, + and it will be listed then. In addition, the compilation for + _today_ will carry a warning about the approaching or missed + deadline, starting `org-deadline-warning-days' before the due + date, and continuing until the entry is marked DONE. An example: + + *** TODO write article about the Earth for the Guide + The editor in charge is + DEADLINE: <2004-02-29 Sun> + +SCHEDULED + If a time stamp is preceded by the word `SCHEDULED:', it means you + are planning to start working on that task on the given date. The + headline will be listed under the given date. In addition, a + reminder that the scheduled date has passed will be present in the + compilation for _today_, until the entry is marked DONE. I.e., the + task will automatically be forwarded. + + +File: org, Node: Creating timestamps, Prev: Time stamps, Up: Timestamps + +6.2 Creating timestamps +======================= + +For Org-mode to recognize time stamps, they need to be in the specific +format. All commands listed below produce time stamps in the correct +format. + +`C-c .' + Prompt for a date and insert a corresponding time stamp. When the + cursor is at a previously used time stamp, it is updated to NOW. + When this command is used twice in succession, a time range is + inserted. + +`C-u C-c .' + Like `C-c .', but use the alternative format which contains date + and time. The default time can be rounded to to multiples of 5 + minutes, see the option `org-time-stamp-rounding-minutes'. + +`C-c !' + Like `C-c .', but insert an inactive time stamp not triggering the + agenda. + +`C-c <' + Insert a time stamp corresponding to the cursor date in the + Calendar. + +`C-c >' + Access the Emacs calendar for the current date. If there is a + timestamp in the current line, goto the corresponding date instead. + +`C-c C-o' + Access the agenda for the date given by the time stamp at point + (*note Weekly/Daily Agenda::). + +`C-c C-d' + Insert `DEADLINE' keyword along with a stamp. + +`C-c C-w' + Create a sparse tree with all deadlines that are either past-due, + or which will become due within `org-deadline-warning-days'. With + `C-u' prefix, show all deadlines in the file. With a numeric + prefix, check that many days. For example, `C-1 C-c C-w' shows + all deadlines due tomorrow. + +`C-c C-s' + Insert `SCHEDULED' keyword along with a stamp. + +`S-' +`S-' + Change date at cursor by one day. These key bindings conflict with + CUA-mode (*note Interaction::). + +`S-' +`S-' + Change the item under the cursor in a timestamp. The cursor can + be on a year, month, day, hour or minute. Note that if the cursor + is not at a time stamp, these same keys modify the priority of an + item. (*note Priorities::). The key bindings also conflict with + CUA-mode (*note Interaction::). + +`C-c C-y' + Evaluate a time range by computing the difference between start and + end. With prefix arg, insert result after the time range (in a + table: into the following column). + + When Org-mode prompts for a date/time, the function reading your +input will replace anything you choose not to specify with the current +date and time. For details, see the documentation string of +`org-read-date'. Also, a calender will pop up to allow selecting a +date. The calendar can be fully controlled from the minibuffer, and a +date can be selected with the following commands: + +`<' + Scroll calendar backwards by one month. + +`>' + Scroll calendar forwards by one month. + +`mouse-1' + Select date by clicking on it. + +`S-' + One day forward. + +`S-' + One day back. + +`S-' + One week forward. + +`S-' + One week back. + +`M-S-' + One month forward. + +`M-S-' + One month back. + +`' + Choose date in calendar (only if nothing typed into minibuffer). + + +File: org, Node: Agenda Views, Next: Exporting, Prev: Timestamps, Up: Top + +7 Agenda Views +************** + +Due to the way Org-mode works, TODO items and time-stamped items can be +scattered throughout a file or even a number of files. To get an +overview over open action items, or over events that are important for +a particular date, this information must be collected, sorted and +displayed in an organized way. + + Org-mode can select items based on various criteria, and display them +in a separate buffer. Three different views are provided: + * an _agenda_ that is like a calendar and shows information for + specific dates + + * a _TODO list_ that covers all unfinished action items, and + + * a _tags view_ that shows information based on the tags associated + with headlines in the outline tree. + The extracted information is displayed in a special _agenda buffer_. +This buffer is read-only, but provides commands to visit the +corresponding locations in the original Org-mode files, and even to +edit these files remotely. + +* Menu: + +* Agenda files:: Files being searched for agenda information +* Agenda dispatcher:: Keyboard access to agenda views +* Weekly/Daily Agenda:: The calendar page with current tasks +* Global TODO list:: All unfinished action items +* Matching headline tags:: Structured information with fine-tuned search +* Timeline:: Time-sorted view for single file +* Agenda commands:: Remote editing of org trees + + +File: org, Node: Agenda files, Next: Agenda dispatcher, Prev: Agenda Views, Up: Agenda Views + +7.1 Agenda files +================ + +The information to be shown is collected from all _agenda files_, the +files listed in the variable `org-agenda-files'. Thus even if you only +work with a single Org-mode file, this file should be put into that +list(1). You can customize `org-agenda-files', but the easiest way to +maintain it is through the following commands + +`C-c [' + Add current file to the list of agenda files. The file is added to + the front of the list. If it was already in the list, it is moved + to the front. With prefix arg, file is added/moved to the end. + +`C-c ]' + Remove current file from the list of agenda files. + +`C-,' + Cycle through agenda file list. + The Org menu contains the current list of files and can be used to +visit any of them. + + ---------- Footnotes ---------- + + (1) When using the dispatcher pressing `1' before selecting a +command will actually limit the command to the current file, and ignore +`org-agenda-files' until the next dispatcher command. + + +File: org, Node: Agenda dispatcher, Next: Weekly/Daily Agenda, Prev: Agenda files, Up: Agenda Views + +7.2 The agenda dispatcher +========================= + +The views are created through a dispatcher that should be bound to a +global key, for example `C-c a' (*note Installation and Activation::). +In the following we will assume that `C-c a' is indeed how the +dispatcher is accessed and list keyboard access to commands +accordingly. After pressing `C-c a', an additional letter is required +to execute a command. The dispatcher offers the following default +commands: +`a' + Create the calendar-like agenda (*note Weekly/Daily Agenda::). + +`t / T' + Create a list of all TODO items (*note Global TODO list::). + +`m / M' + Create a list of headline matching a TAGS expression (*note + Matching headline tags::). + + You can also define custom commands that will be accessible through +the dispatcher, just like the default commands. Custom commands are +global searches for tags and specific TODO keywords, or a variety of +sparse tree creating commands (*note Sparse trees::). As sparse trees +are only defined for a single org-mode file, these latter commands act +on the current buffer instead of the list of agenda files. + + Custom commands are configured in the variable +`org-agenda-custom-commands'. You can customize this variable, for +example by pressing `C-c a C'. You can also directly set it with Emacs +Lisp in `.emacs'. For example: + (setq org-agenda-custom-commands + '(("w" todo "WAITING") + ("u" tags "+BOSS-URGENT") + ("U" tags-tree "+BOSS-URGENT") + ("f" occur-tree "\\"))) + will define `C-c a w' as a global search for TODO entries with +`WAITING' as todo keyword, `C-c a u' as a global tags search for +headlines marked `:BOSS:' but not `:URGENT:', `C-c a U' to do the same +search but only in the current buffer and display the result as a +sparse tree, and `C-c a f' to create a sparse tree with all entries +containing the word `FIXME'. For more information, look at the +documentation string of the variable `org-agenda-custom-commands'. + + +File: org, Node: Weekly/Daily Agenda, Next: Global TODO list, Prev: Agenda dispatcher, Up: Agenda Views + +7.3 The weekly/daily agenda +=========================== + +The purpose of the weekly/daily _agenda_ is to act like a page of a +paper agenda, showing all the tasks for the current week or day. + +`C-c a a' + Compile an agenda for the current week from a list of org files. + The agenda shows the entries for each day. With a `C-u' prefix (or + when the variable `org-agenda-include-all-todo' is `t'), all + unfinished TODO items (also those without a date) are also listed + at the beginning of the buffer, before the first date. + + Remote editing from the agenda buffer means for example that you can +change the dates of deadlines and appointments from the agenda buffer. +The commands available in the Agenda buffer are listed in *Note Agenda +commands::. + +* Menu: + +* Categories:: Not all tasks are equal +* Time-of-day specifications:: How the agenda knows the time +* Calendar/Diary integration:: Integrating Anniversaries and more +* Sorting of agenda items:: The order of things + + +File: org, Node: Categories, Next: Time-of-day specifications, Prev: Weekly/Daily Agenda, Up: Weekly/Daily Agenda + +7.3.1 Categories +---------------- + +In the agenda buffer, each entry is preceded by a _category_, which is +derived from the file name. The category can also be set with a +special line anywhere in the buffer, looking like this: + #+CATEGORY: Thesis + If there are several such lines in a file, each specifies the +category for the text below it. The display in the agenda buffer looks +best if the category is not longer than 10 characters. + + +File: org, Node: Time-of-day specifications, Next: Calendar/Diary integration, Prev: Categories, Up: Weekly/Daily Agenda + +7.3.2 Time-of-Day Specifications +-------------------------------- + +Org-mode checks each agenda item for a time-of-day specification. The +time can be part of the time stamp that triggered inclusion into the +agenda, for example as in `<2005-05-10 Tue 19:00>'. Time ranges can be +specified with two time stamps, like +`<2005-05-10 Tue 20:30>--<2005-05-10 Tue 22:15>'. + + In the headline of the entry itself, a time(range) may also appear as +plain text (like `12:45' or a `8:30-1pm'. If the agenda integrates the +Emacs diary (*note Calendar/Diary integration::), time specifications +in diary entries are recognized as well. + + For agenda display, Org-mode extracts the time and displays it in a +standard 24 hour format as part of the prefix. The example times in +the previous paragraphs would end up in the agenda like this: + + 8:30-13:00 Arthur Dent lies in front of the bulldozer + 12:45...... Ford Prefect arrives and takes Arthur to the pub + 19:00...... The Vogon reads his poem + 20:30-22:15 Marwin escorts the Hitchhikers to the bridge + + If the agenda is in single-day mode, or for the display of today, the +timed entries are embedded in a time grid, like + + 8:00...... ------------------ + 8:30-13:00 Arthur Dent lies in front of the bulldozer + 10:00...... ------------------ + 12:00...... ------------------ + 12:45...... Ford Prefect arrives and takes Arthur to the pub + 14:00...... ------------------ + 16:00...... ------------------ + 18:00...... ------------------ + 19:00...... The Vogon reads his poem + 20:00...... ------------------ + 20:30-22:15 Marwin escorts the Hitchhikers to the bridge + + The time grid can be turned on and off with the variable +`org-agenda-use-time-grid', and can be configured with +`org-agenda-time-grid'. + + +File: org, Node: Calendar/Diary integration, Next: Sorting of agenda items, Prev: Time-of-day specifications, Up: Weekly/Daily Agenda + +7.3.3 Calendar/Diary integration +-------------------------------- + +Emacs contains the calendar and diary by Edward M. Reingold. The +calendar displays a three-month calendar with holidays from different +countries and cultures. The diary allows to keep track of +anniversaries, lunar phases, sunrise/set, recurrent appointments +(weekly, monthly) and more. In this way, it is quite complementary to +Org-mode. It can be very useful to combine output from Org-mode with +the diary. + + In order to include entries from the Emacs diary into Org-mode's +agenda, you only need to customize the variable + + (setq org-agenda-include-diary t) + After that, everything will happen automatically. All diary entries +including holidays, anniversaries etc will be included in the agenda +buffer created by Org-mode. , , and can be used from +the agenda buffer to jump to the diary file, in order to edit existing +diary entries. The `i' command to insert new entries for the current +date works in the agenda buffer, as well as the commands `S', `M', and +`C' to display Sunrise/Sunset times, show lunar phases and to convert +to other calendars, respectively. `c' can be used to switch back and +forth between calendar and agenda. + + +File: org, Node: Sorting of agenda items, Prev: Calendar/Diary integration, Up: Weekly/Daily Agenda + +7.3.4 Sorting of agenda items +----------------------------- + +The entries for each day are sorted. The default order is to first +collect all items containing an explicit time-of-day specification. +These entries will be shown at the beginning of the list, as a +_schedule_ for the day. After that, items remain grouped in +categories, in the sequence given by `org-agenda-files'. Within each +category, items are sorted by priority (*note Priorities::). + + The priority is a numerical quantity composed of the base priority +(2000 for priority `A', 1000 for `B', and 0 for `C'), plus additional +increments for overdue scheduled or deadline items. + + Sorting can be customized using the variable +`org-agenda-sorting-strategy'. + + +File: org, Node: Global TODO list, Next: Matching headline tags, Prev: Weekly/Daily Agenda, Up: Agenda Views + +7.4 The global TODO list +======================== + +The global TODO list contains all unfinished TODO items, formatted and +collected into a single place. + +`C-c a t' + Show the global TODO list. This collects the TODO items from all + agenda files (*note Agenda Views::) into a single buffer. The + buffer is in `agenda-mode', so there are commands to examine and + manipulate the TODO entries directly from that buffer (*note + Agenda commands::). *Note Global TODO list::, for more + information. + +`C-c a T' + Like the above, but allow to select a specific TODO keyword. You + can also do this by specifying a prefix argument to `C-c a t'. + With a `C-u' prefix you are prompted for a keyword. With a numeric + prefix, the Nth keyword in `org-todo-keywords' is selected. The + `r' key in the agenda buffer regenerates it, and you can give a + prefix argument to this command to change the selected TODO + keyword, for example `3 r'. If you often need a search for a + specific keyword, define a custom command for it (*note Agenda + dispatcher::). + + Remote editing of TODO items means that you can change the state of a +TODO entry with a single key press. The commands available in the TODO +list are described in *Note Agenda commands::. + + +File: org, Node: Matching headline tags, Next: Timeline, Prev: Global TODO list, Up: Agenda Views + +7.5 Matching headline tags +========================== + +If headlines in the agenda files are marked with _tags_ (*note Tags::), +you can select headlines based on the tags that apply to them and +collect them into an agenda buffer. + +`C-c a m' + Produce a list of all headlines that match a given set of tags. + The command prompts for a selection criterion, which is a boolean + logic expression with tags, like `+WORK+URGENT-WITHBOSS' or + `WORK|HOME' (*note Tags::). If you often need a specific search, + define a custom command for it (*note Agenda dispatcher::). + +`C-c a M' + Like `C-c a m', but only select headlines that are also TODO items + and force checking subitems (see variable + `org-tags-match-list-sublevels'. + + The commands available in the tags list are described in *Note +Agenda commands::. + + +File: org, Node: Timeline, Next: Agenda commands, Prev: Matching headline tags, Up: Agenda Views + +7.6 Timeline for a single file +============================== + +The timeline is not really an agenda view, because it only summarizes +items from a single Org-mode file. But it also uses the agenda buffer +and provides similar commands, so we discuss it here. The timeline +shows all time-stamped items in a single Org-mode file (or the selected +part of it), in _time-sorted view_. The main purpose of this command +is to give an overview over events in a project. + +`C-c C-r' + Show a time-sorted view of the org file, with all time-stamped + items. When called with a `C-u' prefix, all unfinished TODO + entries (scheduled or not) are also listed under the current date. + The commands available in the timeline buffer are listed in *Note +Agenda commands::. + + +File: org, Node: Agenda commands, Prev: Timeline, Up: Agenda Views + +7.7 Commands in the agenda buffer +================================= + +Entries in the agenda buffer are linked back to the org file or diary +file where they originate. You are not allowed to edit the agenda +buffer itself, but commands are provided to show and jump to the +original entry location, and to edit the org-files "remotely" from the +agenda buffer. In this way, all information is stored only once, and +you don't risk that your agenda and note files diverge. + + Some commands can be executed with mouse clicks on agenda lines. For +the other commands, the cursor needs to be in the desired line. + +Motion +...... + +`n' + Next line (same as ). + +`p' + Previous line (same as ). + +View/GoTo org file +.................. + +`mouse-3' +`' + Display the original location of the item in another window. + +`L' + Display original location and recenter that window. + +`mouse-2' +`mouse-1' +`' + Go to the original location of the item in another window. Under + Emacs 22, also `mouse-1' will works for this. + +`' + Go to the original location of the item and delete other windows. + +`f' + Toggle Follow mode. In Follow mode, as you move the cursor through + the agenda buffer, the other window always shows the corresponding + location in the org file. + +`l' + Toggle Logbook mode. In Logbook mode, entries that where marked + DONE while logging was on (variable `org-log-done') are shown in + the agenda. + +Change display +.............. + +`o' + Delete other windows. + +`w' + Switch to weekly view (7 days displayed together) + +`d' + Switch to daily view (just one day displayed) + +`D' + Toggle the inclusion of diary entries. See *Note Calendar/Diary + integration::. + +`g' + Toggle the time grid on and off. See also the variables + `org-agenda-use-time-grid' and `org-agenda-time-grid'. + +`r' + Recreate the agenda buffer, for example to reflect the changes + after modification of the time stamps of items with S- and + S-. When the buffer is the global todo list, a prefix + argument is interpreted to create a selective list for a specific + TODO keyword. + +`' + Display the following `org-agenda-ndays' days. For example, if + the display covers a week, switch to the following week. With + prefix arg, go forward that many times `org-agenda-ndays' days. + +`' + Display the previous dates. + +`.' + Goto today. + +Remote editing +.............. + +`0-9' + Digit argument. + +`t' + Change the TODO state of the item, both in the agenda and in the + original org file. + +`T' + Show all tags assiciated with the current item. Because of + inheritance, this may be more than the tags listed in the line + itself. + +`:' + Set tags for the current headline. + +`,' + Set the priority for the current item. Org-mode prompts for the + priority character. If you reply with , the priority cookie + is removed from the entry. + +`p' + Display weighted priority of current item. + +`+' +`S-' + Increase the priority of the current item. The priority is + changed in the original buffer, but the agenda is not resorted. + Use the `r' key for this. + +`-' +`S-' + Decrease the priority of the current item. + +`S-' + Change the time stamp associated with the current line by one day + into the future. With prefix argument, change it by that many + days. For example, `3 6 5 S-' will change it by a year. + The stamp is changed in the original org file, but the change is + not directly reflected in the agenda buffer. Use the `r' key to + update the buffer. + +`S-' + Change the time stamp associated with the current line by one day + into the past. + +`>' + Change the time stamp associated with the current line to today. + The key `>' has been chosen, because it is the same as `S-.' on my + keyboard. + +`i' + Insert a new entry into the diary. Prompts for the type of entry + (day, weekly, monthly, yearly, anniversary, cyclic) and creates a + new entry in the diary, just like `i d' etc. would do in the + calendar. The date is taken from the cursor position. + +Calendar commands +................. + +`c' + Open the Emacs calendar and move to the date at the agenda cursor. + +`c' + When in the calendar, compute and show the Org-mode agenda for the + date at the cursor. + +`M' + Show the phases of the moon for three month around current date. + +`S' + Show sunrise and sunset times. The geographical location must be + set with calendar variables, see documentation of the Emacs + calendar. + +`C' + Convert the date at cursor into many other cultural and historic + calendars. + +`H' + Show holidays for three month around the cursor date. + +`C-c C-x C-c' + Export a single iCalendar file containing entries from all agenda + files. + +Quit and Exit +............. + +`q' + Quit Agenda, remove the agenda buffer. + +`x' + Exit agenda, remove the agenda buffer and all buffers loaded by + Emacs for the compilation of the agenda. Buffers created by the + user to visit org files will not be removed. + + + +File: org, Node: Exporting, Next: Miscellaneous, Prev: Agenda Views, Up: Top + +8 Exporting +*********** + +For printing and sharing of notes, Org-mode documents can be exported +as ASCII or HTML files. To incorporate entries with associated times +like deadlines or appointments into a desktop calendar program like +iCal, Org-mode can also produce extracts in the iCalendar format. + +* Menu: + +* ASCII export:: Export as a structured ASCII file +* HTML export:: Export as an HTML file +* iCalendar export:: Create calendar entries. + + +File: org, Node: ASCII export, Next: HTML export, Prev: Exporting, Up: Exporting + +8.1 ASCII export +================ + +`C-c C-x a' + Export as ASCII file. If there is an active region, only the + region will be exported. For an org file `myfile.org', the ASCII + file will be `myfile.txt'. The file will be overwritten without + warning. + + In the exported version, the first 3 outline levels will become +headlines, defining a general document structure. Additional levels +will be exported as itemize lists. If you want that transition to occur +at a different level, specify it with a prefix argument. For example, + C-1 C-c C-x a org-export-as-ascii + creates only top level headlines and does the rest as items. Lines +starting with `#' and subtrees starting with the word `COMMENT' will +not be exported. + + +File: org, Node: HTML export, Next: iCalendar export, Prev: ASCII export, Up: Exporting + +8.2 HTML export +=============== + +Org-mode contains an HTML exporter with extensive HTML formatting, in +ways similar to John Grubers _markdown_ language, but with additional +support for tables. + +`C-c C-x h' + Export as HTML file `myfile.html'. + +`C-c C-x b' + Export as HTML file and open it with a browser. + +`C-c C-x t' + Insert template with export options, see below. + +`C-c :' + Toggle fixed-width for entry (QUOTE) or region, see below. + + In the exported version, the first 3 outline levels will become +headlines, defining a general document structure. Additional levels +will be exported as itemize lists. If you want that transition to occur +at a different level, specify it with a prefix argument. For example, + C-2 C-c C-x b + creates two levels of headings and does the rest as items. + +* Menu: + +* HTML formatting:: Interpretation of the buffer content +* Export options:: How to influence exports +* Comment lines:: Lines which will not be exported + + +File: org, Node: HTML formatting, Next: Export options, Prev: HTML export, Up: HTML export + +8.2.1 HTML formatting +--------------------- + +Not all text is transferred literally to the exported HTML file. The +exporter implements the following interpretation: + + * Hand-formatted lists with `-', `*' or `+' as bullet, or with `1.' + or `2)' as enumerator will be recognized and transformed into HTML + lists. See *Note Plain Lists::. + + * You can make words *bold*, /italic/, and _underlined_ + + * Simple TeX-like math constructs are interpreted: + + - `10^22' and `J_n' are super- and subscripts. You can quote + `^' and `_' with a backslash: `\_' and `\^' + + - `\alpha' indicates a Greek letter, `\to' an arrow. You can + use completion for these macros, just type `\' and maybe a few + letters, and press `M-' to see possible completions. + + * Tables are transformed into HTML tables. Data fields before the + first horizontal separator line will be formatted as table header + fields. + + * If a headline starts with the word `QUOTE', the text below the + headline will be typeset as fixed-width, to allow quoting of + computer codes etc. Lines starting with `:' are also typeset in + fixed-width font. + + * If you want to include HTML tags which should be interpreted as + such, mark them with a `@' like in `@bold text@'. Plain + `<' and `>' are always transformed to `<' and `>' in HTML + export. + + If these conversions conflict with your habits of typing ASCII text, +they can all be turned off with corresponding variables. + + +File: org, Node: Export options, Next: Comment lines, Prev: HTML formatting, Up: HTML export + +8.2.2 Export options +-------------------- + +The exporter recognizes special lines in the buffer which provide +additional information. These lines may be put anywhere in the file. +The whole set of lines can be inserted into the buffer with `C-c C-x +t'. For individual lines, a good way to make sure the keyword is +correct is to type `#+' and then use `M-' completion (*note +Completion::). + + #+TITLE: the title to be shown (default is the buffer name) + #+AUTHOR: the author (default taken from `user-full-name') + #+EMAIL: his/her email address (default from `user-mail-address') + #+LANGUAGE: language for HTML, e.g. `en' (`org-export-default-language') + #+TEXT: Some descriptive text to be inserted at the beginning. + #+TEXT: Several lines may be given. + #+OPTIONS: H:2 num:t toc:t \n:nil t ::t |:t ^:t *:nil TeX:t + The OPTIONS line is a compact form to specify export settings. Here +you can + H: set the number of headline levels for export + num: turn on/off section-numbers + toc: turn on/off table of contents + \n: turn on/off linebreak-preservation + @: turn on/off quoted html tags + :: turn on/off fixed-width sections + |: turn on/off tables + ^: turn on/off TeX-like syntax for sub- and superscripts. + *: turn on/off emphasized text (bold, italic, underlined) + TeX: turn on/off TeX macros + + You can also give style information for the exported file. The +default specification can be configured through the option +`org-export-html-style'. If you want to use a file-local style, you +may use file variables, best wrapped into a COMMENT section at the end +of the outline tree. For example: + + * COMMENT HTML style specifications + + # Local Variables: + # org-export-html-style: " " + # End: *** + + Remember to execute `M-x normal-mode' after changing this to make +the new style visible to Emacs. + + +File: org, Node: Comment lines, Prev: Export options, Up: HTML export + +8.2.3 Comment lines +------------------- + +Lines starting with `#' in column zero are treated as comments and will +never be exported. Also entire subtrees starting with the word +`COMMENT' will never be exported. Finally, any text before the first +headline will not be exported either. This applies also for ASCII +export. + +`C-c ;' + Toggle the COMMENT keyword at the beginning of an entry. + + +File: org, Node: iCalendar export, Prev: HTML export, Up: Exporting + +8.3 iCalendar export +==================== + +Some people like to use Org-mode for keeping track of projects, but +still prefer a standard calendar application for anniversaries and +appointments. In this case it can be useful to have deadlines and +other time-stamped items in Org-mode files show up in the calendar +application. Org-mode can export calendar information in the standard +iCalendar format. + +`C-c C-x i' + Create iCalendar entries for the current file and store them in + the same directory, using a file extension `.ics'. + +`C-c C-x C-i' + Like `C-c C-x i', but do this for all files in `org-agenda-files'. + For each of these files, a separate iCalendar file will be + written. + +`C-c C-x c' + Create a single large iCalendar file from all files in + `org-agenda-files' and write it to the file given by + `org-combined-agenda-icalendar-file'. + + How this calendar is best read and updated, depends on the +application you are using. For example, when using iCal under Apple +MacOS X, you could create a new calendar `OrgMode' (the default name +for the calendar created by `C-c C-x c', see the variables +`org-icalendar-combined-name' and +`org-combined-agenda-icalendar-file'). Then set Org-mode to overwrite +the corresponding file `~/Library/Calendars/OrgMode.ics'. You may even +use AppleScript to make iCal re-read the calendar files each time a new +version of `OrgMode.ics' is produced. Here is the setup needed for +this: + + (setq org-combined-agenda-icalendar-file + "~/Library/Calendars/OrgMode.ics") + (add-hook 'org-after-save-iCalendar-file-hook + (lambda () + (shell-command + "osascript -e 'tell application \"iCal\" to reload calendars'"))) + + +File: org, Node: Miscellaneous, Next: Index, Prev: Exporting, Up: Top + +9 Miscellaneous +*************** + +* Menu: + +* Completion:: M-TAB knows what you need +* Customization:: Adapting Org-mode to your taste +* Clean view:: Getting rid of leading stars in the outline +* TTY keys:: Using Org-mode on a tty +* FAQ:: Frequently asked questions +* Interaction:: Other Emacs packages +* Bugs:: Things which do not work perfectly +* Acknowledgments:: These people provided feedback and more + + +File: org, Node: Completion, Next: Customization, Prev: Miscellaneous, Up: Miscellaneous + +9.1 Completion +============== + +Org-mode supports in-buffer completion. This type of completion does +not make use of the minibuffer. You simply type a few letters into the +buffer and use the key to complete text right there. + +`M-' + Complete word at point + * At the beginning of a headline, complete TODO keywords. + + * After `\', complete TeX symbols supported by the exporter. + + * After `*', complete CamelCase versions of all headlines in the + buffer. + + * After `:', complete tags used elsewhere in the buffer. + + * After `#+', complete the special keywords like `TYP_TODO' or + `OPTIONS' which set file-specific options for Org-mode. When + the option keyword is already complete, pressing `M-' + again will insert example settings for this keyword. + + * Elsewhere, complete dictionary words using ispell. + + +File: org, Node: Customization, Next: Clean view, Prev: Completion, Up: Miscellaneous + +9.2 Customization +================= + +There are more than 100 variables that can be used to customize +Org-mode. For the sake of compactness of the manual, we are not +describing the variables here. A structured overview of customization +variables is available with `M-x org-customize'. Or select `Browse Org +Group' from the `Org->Customization' menu. + + +File: org, Node: Clean view, Next: TTY keys, Prev: Customization, Up: Miscellaneous + +9.3 A cleaner outline view +========================== + +Some people find it noisy and distracting that the Org-mode headlines +are starting with a potentially large number of stars. For example in +the example tree from *Note Headlines::: + + * Top level headline + ** Second level + *** 3rd level + some text + *** 3rd level + more text + * Another top level headline + +Unfortunately this is deeply ingrained into the code of Org-mode and +cannot be easily changed. You can, however, modify the display in such +a way that all leading stars become invisible and the outline more easy +to read. To do this, customize the variable `org-hide-leading-stars' +like this: + + (setq org-hide-leading-stars t) + +or change this on a per-file basis with one of the lines (anywhere in +the buffer) + + #+STARTUP: showstars + #+STARTUP: hidestars + Press `C-c C-c' with the cursor in a `STARTUP' line to activate the +modifications. + + With stars hidden, the tree becomes: + + * Top level headline + * Second level + * 3rd level + some text + * 3rd level + more text + * Another top level headline + +Note that the leading stars are not truly replaced by whitespace, they +are only fontified with the face `org-hide' that uses the background +color as font color. If are are not using either white or black +background, you may have to customize this face to get the wanted +effect. Another possibility is to set this font such that the extra +stars are almost invisible, for example using the color `grey90' on a +white background. + + Things become cleaner still if you skip all the even levels and use +only odd levels 1, 3, 5..., effectively adding two stars to go from one +outline level to the next: + + * Top level headline + * Second level + * 3rd level + some text + * 3rd level + more text + * Another top level headline + +In order to make the structure editing and export commands handle this +convention correctly, use + + (setq org-odd-levels-only t) + +or set this on a per-file basis with one of the following lines (don't +forget to press `C-c C-c' with the cursor in the startup line to +activate changes immediately). + + #+STARTUP: odd + #+STARTUP: oddeven + + You can convert an Org-mode file from single-star-per-level to +double-star-per-level convention with `M-x org-convert-to-odd-levels +RET' in that file. There is no command for the back conversion because +such a command might merge levels and in this way destroy the structure +of the tree. + + +File: org, Node: TTY keys, Next: FAQ, Prev: Clean view, Up: Miscellaneous + +9.4 Using org-mode on a tty +=========================== + +Org-mode uses a number of keys that are not accessible on a tty. This +applies to most special keys like cursor keys, and , when +these are combined with modifier keys like and/or . +Org-mode uses these bindings because it needs to provide keys for a +large number of commands, and because these keys appeared particularly +easy to remember. In order to still be able to access the core +functionality of Org-mode on a tty, alternative bindings are provided. +Here is a complete list of these bindings, which are obviously more +cumbersome to use. Note that sometimes a work-around can be better. +For example changing a time stamp is really only fun with `S-' +keys. On a tty you would rather use `C-c .' to re-insert the +timestamp. + +Default Alternative 1 Alternative 2 +`S-' `C-u ' +`M-' `C-c C-x l' ` ' +`M-S-'`C-c C-x L' +`M-' `C-c C-x r' ` + ' +`M-S-'`C-c C-x R' +`M-' `C-c C-x u' ` ' +`M-S-' `C-c C-x U' +`M-' `C-c C-x d' ` ' +`M-S-'`C-c C-x D' +`S-' `C-c C-x c' +`M-' `C-c C-x m' ` ' +`M-S-' `C-c C-x M' +`S-' `C-c C-x + ' +`S-' `C-c C-x + ' +`S-' `C-c C-x + ' +`S-' `C-c C-x + ' + + +File: org, Node: FAQ, Next: Interaction, Prev: TTY keys, Up: Miscellaneous + +9.5 Frequently asked questions +============================== + + 1. Org-mode seems to be a useful default mode for the various + `README' files I have scattered through my directories. How do I + turn it on for all `README' files? + (add-to-list 'auto-mode-alist '("README$" . org-mode)) + + 2. All these stars are driving me mad, I just find the Emacs outlines + unreadable. Can't you just put white space and a single star as a + starter for headlines? + See *Note Clean view::. + + 3. I would like to have two windows on the same Org-mode file, but + with different outline visibility. Is that possible? + In GNU Emacs, you may use _indirect buffers_ which do exactly + this. See the documentation on the command + `make-indirect-buffer'. In XEmacs, this is currently not possible + because of the different outline implementation. + + 4. Is there an easy way to insert links to web locations? + Sure, just type or paste them into the buffer. A plain-text + URL-like string is directly interpreted as a link. + + 5. When I export my TODO list, every TODO item becomes a separate + section. How do I enforce these items to be exported as an + itemized list? + If you plan to use ASCII or HTML export, make sure things you want + to be exported as item lists are level 4 at least, even if that + does mean there is a level jump. For example + + * Todays top priorities + **** TODO write a letter to xyz + **** TODO Finish the paper + **** Pick up kids at the school + + Alternatively, if you need a specific value for the heading/item + transition in a particular file, use the `+OPTIONS' line to + configure the `H' switch. + + +OPTIONS: H:2; ... + + 6. I would like to export only a subtree of my file to HTML. How? + If you want to export a subtree, mark the subtree as region and + then export. Marking can be done with `C-c @ C-x C-x', for + example. + + 7. Org-mode takes over the S-cursor keys. I also want to use + CUA-mode, is there a way to fix this conflict? + Yes, see *Note Interaction:: + + 8. Is there an easy way to insert an empty table template with a + default number of rows and columns? + To insert an empty table template, just type `|-' and use . + The default size can be changed with the variable + `org-table-default-size'. However, just starting to type the + first line is usually much easier. + + 9. One of my table columns has started to fill up with `#ERROR'. + What is going on? + Org-mode tried to compute the column from other fields using a + formula stored in the `#+TBLFMT:' line just below the table, and + the evaluation of the formula fails. Fix the fields used in the + formula, or fix the formula, or remove it! + + 10. When I am in the last column of a table and just above a + horizontal line in the table, pressing TAB creates a new table line + before the horizontal line. How can I quickly move to the line + below the horizontal line instead? + Press (to get on the separator line) and then . Or + configure the variable `org-table-tab-jumps-over-hlines'. + + 11. How can I change the indentation of an entire table without fixing + every line by hand? + The indentation of a table is set by the first line. So just fix + the indentation of the first line and realign with . + + 12. Is it possible to include entries from org-mode files into my + emacs diary? + Since the org-mode agenda is much more powerful and can contain the + diary (*note Calendar/Diary integration::), you should think twice + before deciding to do this. Inegrating org-mode information into + the diary is, however, possible. The following steps are + necessary: Autoload the function `org-diary' as shown above under + *Note Installation and Activation::. You also need to use _fancy + diary display_ by setting in `.emacs': + + (add-hook 'diary-display-hook 'fancy-diary-display) + + Then include the following line into your `~/diary' file, in order + to get the entries from all files listed in the variable + `org-agenda-files': + + &%%(org-diary) + You may also select specific files with + + &%%(org-diary) ~/path/to/some/org-file.org + &%%(org-diary) ~/path/to/another/org-file.org + + If you now launch the calendar and press `d' to display a diary, + the headlines of entries containing a timestamp, date range, + schedule, or deadline referring to the selected date will be + listed. Just like in Org-mode's agenda view, the diary for + _today_ contains additional entries for overdue deadlines and + scheduled items. See also the documentation of the `org-diary' + function. + + + +File: org, Node: Interaction, Next: Bugs, Prev: FAQ, Up: Miscellaneous + +9.6 Interaction with other packages +=================================== + +Org-mode can cooperate with the following packages: + +`org-mouse.el' by Piotr Zielinski + This package implements extended mouse functionality for Org-mode. + It allows to cycle visibility and to edit the document structure + with the mouse. It also provides a context-sensitive menu that + changes depending on the context of a mouse-click. Use a search + engine to find this package on the web. + +`table.el' by Takaaki Ota + Org mode cooperates with table.el, see *Note table.el::. + `table.el' is part of Emacs 22. + +`calc.el' by Dave Gillespie + Org-mode uses the calc package for implementing spreadsheet + functionality in its tables (*note Table calculations::). + Org-modes checks for the availability of calc by looking for the + function `calc-eval' which should be autoloaded in your setup if + calc has been installed properly. As of Emacs 22, calc is part of + the Emacs distribution. Another possibility for interaction + between the two packages is using calc for embedded calculations. + *Note Embedded Mode: (calc)Embedded Mode. + +`constants.el' by Carsten Dominik + In a table formula (*note Table calculations::), it is possible to + use names for natural constants or units. Instead of defining you + own constants in the variable `org-table-formula-constants', + install the `constants' package which defines a large number of + constants and units, and lets you use unit prefixes like `M' for + `Mega' etc. You will need version 2.0 of this package, available + at `http://www.astro.uva.nl/~dominik/Tools'. Org-mode checks for + the function `constants-get', which has to be autoloaded in your + setup. See the installation instructions in the file + `constants.el'. + +`CUA.el' by Kim. F. Storm + Keybindings in Org-mode conflict with the `S-' keys used + by CUA-mode (as well as pc-select-mode and s-region-mode) to + select and extend the region. If you want to use one of these + packages along with Org-mode, configure the variable + `org-CUA-compatible'. When set, Org-mode will move the following + keybindings in org-mode files, and in the agenda buffer (but not + during date selection). + S-UP -> M-p S-DOWN -> M-n + S-LEFT -> M-- S-RIGHT -> M-+ + S-RET -> C-S-RET + Yes, these are unfortunately more difficult to remember. If you + want to have other replacement keys, look at the variable + `org-disputed-keys'. + +`remember.el' by John Wiegley + Org mode cooperates with remember, see *Note Remember::. + `Remember.el' is not part of Emacs, find it on the web. + +`planner.el' by John Wiegley + Planner is another tool to plan work and keep track of tasks. + Planner uses a multi-file approach with project pages and day + pages. Is based on Emacs-Wiki. If Planner is your primary tool, + it can be useful to display the agenda entries resulting from org + files in day-pages of the planner. This can be done through the + diary of the calendar: Integrate org files into the diary as + described above, and then turn on the diary support of planner. + Planner is not part of Emacs, find it on the web. + + +File: org, Node: Bugs, Next: Acknowledgments, Prev: Interaction, Up: Miscellaneous + +9.7 Bugs +======== + +Here is a list of things which should work differently, but which I +have found too hard to fix. + + * Text in an entry protected with the `QUOTE' keyword should not + autowrap. + + * When the application called by `C-c C-o' to open a file link fails + (for example because the application does not exits or refuses to + open the file), it does so silently. No error message is + displayed. + + * Plain list items should be able to hold a TODO item. + Unfortunately this has so many technical problems that I will only + consider this change for the next major release (5.0). + + * The remote-editing commands in the agenda buffer cannot be undone + with `undo' called from within the agenda buffer. But you can go + to the corresponding buffer (using or and execute + `undo' there. + + * Recalculating a table line applies the formulas from left to right. + If a formula uses _calculated_ fields further down the row, + multiple recalculation may be needed to get all fields consistent. + + * Under XEmacs, if Org-mode entries are included into the diary, it + is not possible to jump back from the diary to the org file. + Apparently, the text properties are lost when the + fancy-diary-display is used. However, from Org-mode's timeline + and agenda buffers (created with `C-c C-r' and `C-c a'), things do + work correctly. + + * You can only make a single word boldface or italic. To emphasize + several words in a row, each must have the emphasize markers, like + in `*three* *bold* *words*'. + + * The exporters work well, but could be made more efficient. + + +File: org, Node: Acknowledgments, Prev: Bugs, Up: Miscellaneous + +9.8 Acknowledgments +=================== + +Org-mode was written by Carsten Dominik, who still maintains it at the +Org-mode homepage `http://www.astro.uva.nl/~dominik/Tools/org/'. The +following people (in alphabetic order) have helped the development +along with ideas, suggestions and patches. Many thanks to all of you, +Org-mode would not be what it is without your input. + + * Thomas Baumann contributed the code for links to the MH-E email + system. + + * Alex Bochannek provided a patch for rounding time stamps. + + * Charles Cave's suggestion sparked the implementation of templates + for Remember. + + * Pavel Chalmoviansky influenced the agenda treatment of items with + specified time. + + * Sacha Chua suggested to copy linking code from Planner (we did take + some). + + * Christian Egli converted the documentation into TeXInfo format, + patched CSS formatting into the HTML exporter, and inspired the + agenda. + + * Kai Grossjohann pointed out key-binding conflicts caused by + Org-mode. + + * Stefan Monnier provided a patch to keep the Emacs-Lisp compiler + happy. + + * Tim O'Callaghan suggested in-file links, search options for + general file links, and TAGS. + + * Oliver Oppitz suggested multi-state TODO items. + + * Pete Phillips helped the development of the TAGS feature. + + * Matthias Rempe (Oelde) provided ideas, Windows support, and quality + control. + + * Kevin Rogers contributed code to access VM files on remote hosts. + + * Philip Rooke created the Org-mode reference card and provided lots + of feedback. + + * Christian Schlauer proposed angular brackets around links, among + other things. + + * Linking to VM/BBDB/GNUS was inspired by Tom Shannon's + `organizer-mode.el'. + + * Ju"rgen Vollmer contributed code generating the table of contents + in HTML output. + + * Chris Wallace provided a patch implementing the `QUOTE' keyword. + + * David Wainberg suggested archiving, and improvements to the linking + system. + + * Scheduling TODO items was inspired by John Wiegley's `planner.el'. + + * Carsten Wimmer suggested some changes and helped fix a bug in + linking to GNUS. + + * Roland Winkler requested additional keybindings to make Org-mode + work on a tty. + + * Piotr Zielinski wrote `org-mouse.el' and showed how to follow links + with mouse-1. + + +File: org, Node: Index, Next: Key Index, Prev: Miscellaneous, Up: Top + +10 Index +******** + +[index] +* Menu: + +* acknowledgments: Acknowledgments. (line 6) +* active region <1>: HTML export. (line 10) +* active region <2>: ASCII export. (line 6) +* active region <3>: Built-in table editor. + (line 166) +* active region: Structure editing. (line 46) +* agenda: Weekly/Daily Agenda. (line 6) +* agenda commands, custom: Agenda dispatcher. (line 6) +* agenda dispatcher: Agenda dispatcher. (line 6) +* agenda files, removing buffers: Agenda commands. (line 186) +* agenda views: Agenda Views. (line 6) +* agenda, for single file: Timeline. (line 6) +* applescript, for calendar update: iCalendar export. (line 38) +* archive locations: Archiving. (line 13) +* archiving: Archiving. (line 6) +* ASCII export: ASCII export. (line 6) +* author: Feedback. (line 6) +* autoload: Installation and Activation. + (line 6) +* BBDB links: External Links. (line 6) +* bold text: HTML formatting. (line 13) +* bug reports: Feedback. (line 6) +* bugs: Bugs. (line 6) +* calc package: Table calculations. (line 6) +* calc.el: Interaction. (line 17) +* calculations, in tables <1>: Table calculations. (line 6) +* calculations, in tables: Built-in table editor. + (line 136) +* calendar integration: Calendar/Diary integration. + (line 6) +* calendar, for selecting date: Creating timestamps. (line 68) +* CamelCase link completion: Completion. (line 6) +* CamelCase links: Internal Links. (line 6) +* CamelCase links, completion of: CamelCase links. (line 6) +* category: Categories. (line 6) +* children, subtree visibility state: Visibility cycling. (line 10) +* clean outline view: Clean view. (line 6) +* column formula: Column formulas. (line 6) +* commands, in agenda buffer: Agenda commands. (line 6) +* comment lines: Comment lines. (line 6) +* completion, of CamelCase links <1>: Completion. (line 6) +* completion, of CamelCase links: CamelCase links. (line 6) +* completion, of dictionary words: Completion. (line 6) +* completion, of file names: Managing links. (line 23) +* completion, of links: Managing links. (line 23) +* completion, of option keywords <1>: Completion. (line 6) +* completion, of option keywords: Export options. (line 6) +* Completion, of option keywords: Per file keywords. (line 17) +* completion, of tags <1>: Completion. (line 6) +* completion, of tags: Tags. (line 34) +* completion, of TeX symbols <1>: Completion. (line 6) +* completion, of TeX symbols: HTML formatting. (line 17) +* completion, of TODO keywords <1>: Completion. (line 6) +* completion, of TODO keywords: Workflow states. (line 12) +* constants, in calculations: Formula syntax. (line 26) +* constants.el: Interaction. (line 27) +* contents, global visibility state: Visibility cycling. (line 17) +* copying, of subtrees: Structure editing. (line 6) +* creating timestamps: Creating timestamps. (line 6) +* CUA.el: Interaction. (line 39) +* custom agenda commands: Agenda dispatcher. (line 6) +* customization: Customization. (line 6) +* cutting, of subtrees: Structure editing. (line 6) +* cycling, of TODO states: TODO basics. (line 13) +* cycling, visibility: Visibility cycling. (line 6) +* date stamps: Time stamps. (line 6) +* date, reading in minibuffer: Creating timestamps. (line 68) +* DEADLINE keyword: Time stamps. (line 27) +* deadlines: Time stamps. (line 6) +* demotion, of subtrees: Structure editing. (line 6) +* diary entries, creating from agenda: Agenda commands. (line 145) +* diary integration: Calendar/Diary integration. + (line 6) +* dictionary word completion: Completion. (line 6) +* dispatching agenda commands: Agenda dispatcher. (line 6) +* document structure: Document Structure. (line 6) +* DONE, final TODO keyword: Per file keywords. (line 20) +* editing tables: Tables. (line 6) +* editing, of table formulas: Editing/debugging formulas. + (line 6) +* emphasized text: Export options. (line 21) +* evaluate time range: Creating timestamps. (line 63) +* exporting: Exporting. (line 6) +* exporting a subtree: FAQ. (line 46) +* exporting, not: Comment lines. (line 6) +* extended TODO keywords: TODO extensions. (line 6) +* external links: External Links. (line 6) +* FAQ: FAQ. (line 6) +* feedback: Feedback. (line 6) +* file links: External Links. (line 6) +* file links, searching: Search Options. (line 6) +* file name completion: Managing links. (line 23) +* files, adding to agenda list: Agenda files. (line 12) +* filing subtrees: Archiving. (line 6) +* fixed width: HTML formatting. (line 28) +* fixed-width sections: Export options. (line 21) +* folded, subtree visibility state: Visibility cycling. (line 10) +* folding, sparse trees: Sparse trees. (line 6) +* following links: Managing links. (line 35) +* format specifier: Formula syntax. (line 34) +* formula editing: Editing/debugging formulas. + (line 6) +* formula syntax: Formula syntax. (line 6) +* formula, for named table field: Named-field formulas. + (line 6) +* formula, for table column: Column formulas. (line 6) +* formula, in tables: Built-in table editor. + (line 136) +* global keybindings: Installation and Activation. + (line 6) +* global TODO list: Global TODO list. (line 6) +* global visibility states: Visibility cycling. (line 17) +* GNUS links: External Links. (line 6) +* hand-formatted lists: HTML formatting. (line 9) +* headline levels: Export options. (line 21) +* headline levels, for exporting <1>: HTML export. (line 22) +* headline levels, for exporting: ASCII export. (line 12) +* headline navigation: Motion. (line 6) +* headline tagging: Tags. (line 6) +* headline, promotion and demotion: Structure editing. (line 6) +* headlines: Headlines. (line 6) +* hide text: Visibility cycling. (line 6) +* hiding leading stars: Clean view. (line 6) +* HTML export: HTML export. (line 6) +* HTML tags: HTML formatting. (line 33) +* hyperlinks: Hyperlinks. (line 6) +* iCalendar export: iCalendar export. (line 6) +* indentation, of tables: FAQ. (line 77) +* indirect buffers: FAQ. (line 18) +* inheritance, of tags: Tags. (line 13) +* inserting links: Managing links. (line 23) +* installation: Installation and Activation. + (line 6) +* internal links: Internal Links. (line 6) +* introduction: Introduction. (line 6) +* italic text: HTML formatting. (line 13) +* jumping, to headlines: Motion. (line 6) +* keybindings, global: Installation and Activation. + (line 6) +* keyword options: Per file keywords. (line 6) +* linebreak preservation: Export options. (line 21) +* link completion: Managing links. (line 23) +* links, external: External Links. (line 6) +* links, internal: Internal Links. (line 6) +* links, returning to: Managing links. (line 65) +* lists, hand-formatted: HTML formatting. (line 9) +* lists, ordered: Plain Lists. (line 6) +* lists, plain: Plain Lists. (line 6) +* logging, of progress: Progress Logging. (line 6) +* maintainer: Feedback. (line 6) +* make-indirect-buffer: FAQ. (line 18) +* mark ring: Managing links. (line 61) +* marking characters, tables: Advanced features. (line 34) +* matching, of tags: Matching headline tags. + (line 6) +* matching, tags: Tags. (line 6) +* MH-E links: External Links. (line 6) +* minor mode for tables: orgtbl-mode. (line 6) +* mode, for calc: Formula syntax. (line 34) +* motion, between headlines: Motion. (line 6) +* name, of column or field: Formula syntax. (line 26) +* named field formula: Named-field formulas. + (line 6) +* names as TODO keywords: TODO types. (line 6) +* occur, command: Sparse trees. (line 6) +* option keyword completion: Completion. (line 6) +* options, for customization: Customization. (line 6) +* options, for export: Export options. (line 6) +* ordered lists: Plain Lists. (line 6) +* org-agenda, command: Weekly/Daily Agenda. (line 9) +* org-mode, turning on: Installation and Activation. + (line 28) +* org-mouse.el: Interaction. (line 8) +* orgtbl-mode: orgtbl-mode. (line 6) +* outline tree: Headlines. (line 6) +* outline-mode: Outlines. (line 6) +* outlines: Outlines. (line 6) +* overview, global visibility state: Visibility cycling. (line 17) +* packages, interaction with other: Interaction. (line 6) +* pasting, of subtrees: Structure editing. (line 6) +* per file keywords: Per file keywords. (line 6) +* plain lists: Plain Lists. (line 6) +* planner.el: Interaction. (line 58) +* printing sparse trees: Sparse trees. (line 37) +* priorities: Priorities. (line 6) +* priorities, of agenda items: Sorting of agenda items. + (line 6) +* progress logging: Progress Logging. (line 6) +* promotion, of subtrees: Structure editing. (line 6) +* quoted html tags: Export options. (line 21) +* ranges, time: Time stamps. (line 6) +* recomputing table fields: Column formulas. (line 27) +* region, active <1>: HTML export. (line 10) +* region, active <2>: ASCII export. (line 6) +* region, active <3>: Built-in table editor. + (line 166) +* region, active: Structure editing. (line 46) +* remember.el <1>: Interaction. (line 39) +* remember.el: Remember. (line 6) +* RMAIL links: External Links. (line 6) +* SCHEDULED keyword: Time stamps. (line 39) +* scheduling: Time stamps. (line 6) +* search option in file links: Search Options. (line 6) +* section-numbers: Export options. (line 21) +* SHELL links: External Links. (line 6) +* show all, command: Visibility cycling. (line 23) +* show all, global visibility state: Visibility cycling. (line 17) +* show hidden text: Visibility cycling. (line 6) +* single file summary: Timeline. (line 6) +* sorting, of agenda items: Sorting of agenda items. + (line 6) +* sparse tree, for deadlines: Creating timestamps. (line 38) +* sparse tree, for TODO: TODO basics. (line 18) +* sparse tree, tag based: Tags. (line 6) +* sparse trees: Sparse trees. (line 6) +* spreadsheet capabilities: Table calculations. (line 6) +* storing links: Managing links. (line 9) +* structure editing: Structure editing. (line 6) +* structure of document: Document Structure. (line 6) +* subtree visibility states: Visibility cycling. (line 10) +* subtree, cut and paste: Structure editing. (line 6) +* subtree, subtree visibility state: Visibility cycling. (line 10) +* subtrees, cut and paste: Structure editing. (line 6) +* summary: Summary. (line 6) +* syntax, of formulas: Formula syntax. (line 6) +* table editor, builtin: Built-in table editor. + (line 6) +* table editor, table.el: table.el. (line 6) +* table of contents: Export options. (line 21) +* table, empty template: FAQ. (line 56) +* table.el <1>: Interaction. (line 13) +* table.el: table.el. (line 6) +* tables <1>: Export options. (line 21) +* tables: Tables. (line 6) +* tables, export to HTML: HTML formatting. (line 24) +* tag completion: Completion. (line 6) +* tags: Tags. (line 6) +* tags view: Matching headline tags. + (line 6) +* templates, for remember: Remember. (line 26) +* TeX interpretation: HTML formatting. (line 15) +* TeX macros: Export options. (line 21) +* TeX symbol completion: Completion. (line 6) +* TeX-like syntax for sub- and superscripts: Export options. (line 21) +* thanks: Acknowledgments. (line 6) +* time stamps: Time stamps. (line 6) +* time, reading in minibuffer: Creating timestamps. (line 68) +* time-sorted view: Timeline. (line 6) +* timeline, single file: Timeline. (line 6) +* timerange: Time stamps. (line 18) +* timestamp: Time stamps. (line 12) +* timestamps, creating: Creating timestamps. (line 6) +* TODO items: TODO items. (line 6) +* TODO keywords completion: Completion. (line 6) +* TODO list, global: Global TODO list. (line 6) +* TODO types: TODO types. (line 6) +* TODO workflow: Workflow states. (line 6) +* transient-mark-mode <1>: HTML export. (line 10) +* transient-mark-mode <2>: ASCII export. (line 6) +* transient-mark-mode <3>: Built-in table editor. + (line 166) +* transient-mark-mode: Structure editing. (line 46) +* trees, sparse: Sparse trees. (line 6) +* trees, visibility: Visibility cycling. (line 6) +* tty keybindings: TTY keys. (line 6) +* types as TODO keywords: TODO types. (line 6) +* underlined text: HTML formatting. (line 13) +* URL links: External Links. (line 6) +* URL, paste into buffer: FAQ. (line 24) +* USENET links: External Links. (line 6) +* variables, for customization: Customization. (line 6) +* vectors, in table calculations: Formula syntax. (line 23) +* visibility cycling: Visibility cycling. (line 6) +* visible text, printing: Sparse trees. (line 37) +* VM links: External Links. (line 6) +* WANDERLUST links: External Links. (line 6) +* workflow states as TODO keywords: Workflow states. (line 6) + + +File: org, Node: Key Index, Prev: Index, Up: Top + +11 Key Index +************ + +[index] +* Menu: + +* +: Agenda commands. (line 118) +* ,: Agenda commands. (line 110) +* -: Agenda commands. (line 124) +* .: Agenda commands. (line 89) +* :: Agenda commands. (line 107) +* <: Creating timestamps. (line 75) +* : Agenda commands. (line 86) +* <1>: Agenda commands. (line 41) +* <2>: Creating timestamps. (line 100) +* : Built-in table editor. + (line 65) +* : Agenda commands. (line 81) +* : Agenda commands. (line 28) +* <1>: Agenda commands. (line 35) +* <2>: Built-in table editor. + (line 58) +* <3>: Plain Lists. (line 37) +* : Visibility cycling. (line 10) +* > <1>: Agenda commands. (line 140) +* >: Creating timestamps. (line 76) +* C: Agenda commands. (line 169) +* c: Agenda commands. (line 154) +* C-#: Built-in table editor. + (line 156) +* C-,: Agenda files. (line 18) +* C-c !: Creating timestamps. (line 21) +* C-c $: Archiving. (line 9) +* C-c %: Managing links. (line 61) +* C-c &: Managing links. (line 65) +* C-c ' <1>: Editing/debugging formulas. + (line 20) +* C-c ': Built-in table editor. + (line 145) +* C-c *: Built-in table editor. + (line 149) +* C-c +: Built-in table editor. + (line 166) +* C-c ,: Priorities. (line 18) +* C-c -: Built-in table editor. + (line 93) +* C-c .: Creating timestamps. (line 10) +* C-c /: Sparse trees. (line 15) +* C-c :: HTML export. (line 17) +* C-c ;: Comment lines. (line 12) +* C-c <: Creating timestamps. (line 25) +* C-c =: Built-in table editor. + (line 136) +* C-c >: Creating timestamps. (line 29) +* C-c ? <1>: Editing/debugging formulas. + (line 20) +* C-c ?: Built-in table editor. + (line 162) +* C-c [: Agenda files. (line 12) +* C-c \: Tags. (line 42) +* C-c ]: Agenda files. (line 15) +* C-c ^: Built-in table editor. + (line 97) +* C-c a a: Weekly/Daily Agenda. (line 9) +* C-c a C: Agenda dispatcher. (line 30) +* C-c a M: Matching headline tags. + (line 15) +* C-c a m: Matching headline tags. + (line 10) +* C-c a M: Tags. (line 49) +* C-c a m: Tags. (line 45) +* C-c a T: Global TODO list. (line 15) +* C-c a t <1>: Global TODO list. (line 9) +* C-c a t: TODO basics. (line 25) +* C-c C-a: Visibility cycling. (line 23) +* C-c C-b: Motion. (line 15) +* C-c C-c <1>: table.el. (line 6) +* C-c C-c <2>: Editing/debugging formulas. + (line 16) +* C-c C-c <3>: Built-in table editor. + (line 43) +* C-c C-c <4>: Plain Lists. (line 61) +* C-c C-c: Tags. (line 33) +* C-c C-d: Creating timestamps. (line 37) +* C-c C-f: Motion. (line 12) +* C-c C-j: Motion. (line 21) +* C-c C-l: Managing links. (line 23) +* C-c C-n: Motion. (line 8) +* C-c C-o <1>: Creating timestamps. (line 33) +* C-c C-o: Managing links. (line 35) +* C-c C-p: Motion. (line 9) +* C-c C-q <1>: Editing/debugging formulas. + (line 20) +* C-c C-q: Built-in table editor. + (line 120) +* C-c C-r: Timeline. (line 13) +* C-c C-s: Creating timestamps. (line 47) +* C-c C-t: TODO basics. (line 13) +* C-c C-u: Motion. (line 18) +* C-c C-v: TODO basics. (line 18) +* C-c C-w: Creating timestamps. (line 38) +* C-c C-x a: ASCII export. (line 6) +* C-c C-x b: HTML export. (line 11) +* C-c C-x c: iCalendar export. (line 20) +* C-c C-x C-c: Agenda commands. (line 176) +* C-c C-x C-i: iCalendar export. (line 15) +* C-c C-x C-k: Structure editing. (line 31) +* C-c C-x C-w <1>: Built-in table editor. + (line 109) +* C-c C-x C-w: Structure editing. (line 31) +* C-c C-x C-y <1>: Built-in table editor. + (line 113) +* C-c C-x C-y: Structure editing. (line 38) +* C-c C-x h: HTML export. (line 10) +* C-c C-x i: iCalendar export. (line 13) +* C-c C-x M-w <1>: Built-in table editor. + (line 106) +* C-c C-x M-w: Structure editing. (line 35) +* C-c C-x t: HTML export. (line 14) +* C-c C-x v: Sparse trees. (line 37) +* C-c C-y: Creating timestamps. (line 63) +* C-c l: Managing links. (line 9) +* C-c |: Built-in table editor. + (line 182) +* C-c ~: table.el. (line 18) +* C-u C-c .: Creating timestamps. (line 16) +* C-u C-c =: Built-in table editor. + (line 140) +* D: Agenda commands. (line 66) +* d: Agenda commands. (line 63) +* f: Agenda commands. (line 44) +* g: Agenda commands. (line 70) +* H: Agenda commands. (line 173) +* i: Agenda commands. (line 145) +* l: Agenda commands. (line 49) +* L: Agenda commands. (line 32) +* M: Agenda commands. (line 161) +* M-: Built-in table editor. + (line 83) +* M- <1>: Built-in table editor. + (line 73) +* M-: Structure editing. (line 13) +* M- <1>: Plain Lists. (line 42) +* M-: Structure editing. (line 6) +* M- <1>: Built-in table editor. + (line 73) +* M-: Structure editing. (line 16) +* M- <1>: Completion. (line 10) +* M- <2>: Per file keywords. (line 17) +* M-: Tags. (line 28) +* M-: Built-in table editor. + (line 83) +* M-S- <1>: Built-in table editor. + (line 90) +* M-S- <2>: Plain Lists. (line 46) +* M-S-: Structure editing. (line 28) +* M-S- <1>: Creating timestamps. (line 97) +* M-S- <2>: Built-in table editor. + (line 77) +* M-S- <3>: Plain Lists. (line 52) +* M-S-: Structure editing. (line 19) +* M-S-: Structure editing. (line 10) +* M-S- <1>: Creating timestamps. (line 94) +* M-S- <2>: Built-in table editor. + (line 80) +* M-S- <3>: Plain Lists. (line 52) +* M-S-: Structure editing. (line 22) +* M-S- <1>: Built-in table editor. + (line 87) +* M-S- <2>: Plain Lists. (line 46) +* M-S-: Structure editing. (line 25) +* mouse-1 <1>: Agenda commands. (line 35) +* mouse-1 <2>: Creating timestamps. (line 79) +* mouse-1: Managing links. (line 53) +* mouse-2 <1>: Agenda commands. (line 35) +* mouse-2: Managing links. (line 53) +* mouse-3 <1>: Agenda commands. (line 28) +* mouse-3: Managing links. (line 58) +* n: Agenda commands. (line 19) +* o: Agenda commands. (line 57) +* P: Agenda commands. (line 115) +* p: Agenda commands. (line 20) +* q: Agenda commands. (line 183) +* r <1>: Agenda commands. (line 74) +* r: Global TODO list. (line 21) +* S: Agenda commands. (line 164) +* S- <1>: Agenda commands. (line 124) +* S- <2>: Creating timestamps. (line 55) +* S-: Priorities. (line 25) +* S- <1>: Agenda commands. (line 136) +* S-: Creating timestamps. (line 50) +* S-: Built-in table editor. + (line 171) +* S- <1>: Agenda commands. (line 128) +* S-: Creating timestamps. (line 50) +* S- <1>: Built-in table editor. + (line 62) +* S-: Visibility cycling. (line 17) +* S- <1>: Agenda commands. (line 118) +* S- <2>: Creating timestamps. (line 55) +* S-: Priorities. (line 25) +* T: Agenda commands. (line 102) +* t: Agenda commands. (line 98) +* w: Agenda commands. (line 60) +* x: Agenda commands. (line 186) + + + +Tag Table: +Node: Top959 +Node: Introduction6836 +Node: Summary7150 +Node: Installation and Activation9261 +Node: Feedback10931 +Node: Document Structure11705 +Node: Outlines12547 +Node: Headlines13207 +Node: Visibility cycling13832 +Node: Motion15019 +Node: Structure editing15803 +Node: Archiving17534 +Node: Sparse trees18394 +Ref: Sparse trees-Footnote-120416 +Ref: Sparse trees-Footnote-220508 +Node: Tags20622 +Node: Plain Lists23713 +Ref: Plain Lists-Footnote-126454 +Node: Tables26811 +Node: Built-in table editor27298 +Node: Table calculations34833 +Node: Formula syntax36016 +Ref: Formula syntax-Footnote-138940 +Node: Column formulas39239 +Node: Advanced features41001 +Node: Named-field formulas44262 +Node: Editing/debugging formulas44902 +Node: Appetizer46679 +Node: orgtbl-mode47781 +Node: table.el48271 +Node: Hyperlinks49248 +Node: Internal Links49814 +Node: Radio targets51563 +Node: CamelCase links52278 +Node: External Links52851 +Ref: External Links-Footnote-154777 +Node: Managing links54916 +Node: Search Options58247 +Ref: Search Options-Footnote-159560 +Node: Remember59641 +Ref: Remember-Footnote-163525 +Node: TODO items63649 +Node: TODO basics64572 +Node: Progress Logging66084 +Node: TODO extensions66871 +Node: Workflow states67559 +Node: TODO types68426 +Ref: TODO types-Footnote-170092 +Node: Per file keywords70174 +Ref: Per file keywords-Footnote-171627 +Node: Priorities71855 +Node: Timestamps73064 +Node: Time stamps73393 +Node: Creating timestamps75404 +Node: Agenda Views78536 +Node: Agenda files80063 +Ref: Agenda files-Footnote-180987 +Node: Agenda dispatcher81179 +Node: Weekly/Daily Agenda83305 +Node: Categories84432 +Node: Time-of-day specifications84997 +Node: Calendar/Diary integration86973 +Node: Sorting of agenda items88349 +Node: Global TODO list89181 +Node: Matching headline tags90593 +Node: Timeline91536 +Node: Agenda commands92409 +Node: Exporting97650 +Node: ASCII export98222 +Node: HTML export99057 +Node: HTML formatting100173 +Node: Export options101805 +Node: Comment lines103997 +Node: iCalendar export104467 +Node: Miscellaneous106262 +Node: Completion106887 +Node: Customization107881 +Node: Clean view108327 +Node: TTY keys110974 +Node: FAQ112573 +Node: Interaction117456 +Node: Bugs120856 +Node: Acknowledgments122598 +Node: Index125018 +Node: Key Index145222 + +End Tag Table diff --git a/org.el b/org.el new file mode 100644 index 000000000..3aba8c55f --- /dev/null +++ b/org.el @@ -0,0 +1,13032 @@ +;;; org.el --- Outline-based notes management and organize +;; Carstens outline-mode for keeping track of everything. +;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. +;; +;; Author: Carsten Dominik +;; Keywords: outlines, hypermedia, calendar, wp +;; Homepage: http://www.astro.uva.nl/~dominik/Tools/org/ +;; Version: 4.12 +;; +;; 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 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Commentary: +;; +;; Org-mode is a mode for keeping notes, maintaining ToDo lists, and doing +;; project planning with a fast and effective plain-text system. +;; +;; Org-mode develops organizational tasks around a NOTES file that contains +;; information about projects as plain text. Org-mode is implemented on top +;; of outline-mode - ideal to keep the content of large files well structured. +;; It supports ToDo items, deadlines and time stamps, which can be extracted +;; to create a daily/weekly agenda that also integrates the diary of the Emacs +;; calendar. Tables are easily created with a built-in table editor. Plain +;; text URL-like links connect to websites, emails (VM, RMAIL, WANDERLUST), +;; Usenet messages (Gnus), BBDB entries, and any files related to the +;; projects. For printing and sharing of notes, an Org-mode file (or a part +;; of it) can be exported as a structured ASCII file, or as HTML. +;; +;; Installation +;; ------------ +;; If Org-mode is part of the Emacs distribution or an XEmacs package, you +;; only need to copy the following lines to your .emacs file. The last two +;; lines define *global* keys for the commands `org-store-link' and +;; `org-agenda' - please choose suitable keys yourself. +;; +;; (add-to-list 'auto-mode-alist '("\\.org$" . org-mode)) +;; (define-key global-map "\C-cl" 'org-store-link) +;; (define-key global-map "\C-ca" 'org-agenda) +;; +;; If you have downloaded Org-mode from the Web, you must byte-compile +;; org.el and put it on your load path. In addition to the Emacs Lisp +;; lines above, you also need to add the following lines to .emacs: +;; +;; (autoload 'org-mode "org" "Org mode" t) +;; (autoload 'org-diary "org" "Diary entries from Org mode") +;; (autoload 'org-agenda "org" "Multi-file agenda from Org mode" t) +;; (autoload 'org-store-link "org" "Store a link to the current location" t) +;; (autoload 'orgtbl-mode "org" "Org tables as a minor mode" t) +;; (autoload 'turn-on-orgtbl "org" "Org tables as a minor mode") +;; +;; This setup will put all files with extension ".org" into Org-mode. As +;; an alternative, make the first line of a file look like this: +;; +;; MY PROJECTS -*- mode: org; -*- +;; +;; which will select Org-mode for this buffer no matter what the file's +;; name is. +;; +;; Documentation +;; ------------- +;; The documentation of Org-mode can be found in the TeXInfo file. The +;; distribution also contains a PDF version of it. At the homepage of +;; Org-mode, you can read the same text online as HTML. There is also an +;; excellent reference card made by Philip Rooke. This card can be found +;; in the etc/ directory of Emacs 22. +;; +;; Changes since version 4.00: +;; --------------------------- +;; Version 4.12 +;; - Templates for remember buffer. Note that the remember setup changes. +;; To set up templates, see `org-remember-templates'. +;; - The time in new time stamps can be rounded, see new option +;; `org-time-stamp-rounding-minutes'. +;; - Bug fixes (there are *always* more bugs). +;; +;; Version 4.10 +;; - Bug fixes. +;; +;; Version 4.09 +;; - Bug fixes. +;; - Small improvements to font-lock support. +;; - MHE support finalized. +;; +;; Version 4.08 +;; - Bug fixes. +;; - Improved MHE support +;; +;; Version 4.07 +;; - Bug fixes. +;; - Leading stars in headlines can be hidden, so make the outline look +;; cleaner. +;; - Mouse-1 can be used to follow links. +;; +;; Version 4.06 +;; - HTML exporter treats targeted internal links. +;; - Bug fixes. +;; +;; Version 4.05 +;; - Changes to internal link system (thanks to David Wainberg for ideas). +;; - in-file links: [[Search String]] instead of +;; - automatic links to "radio targets". +;; - CamelCase not longer active by default, configure org-activate-camels +;; if you want to turn it back on. +;; - After following a link, `C-c &' jumps back to it. +;; - MH-E link support (thanks to Thomas Baumann). +;; - Special table lines are no longer exported. +;; - Bug fixes and minor improvements. +;; +;; Version 4.04 +;; - Cleanup tags display in agenda. +;; - Bug fixes. +;; +;; Version 4.03 +;; - Table alignment fixed for use with wide characters. +;; - `C-c -' leaves cursor in current table line. +;; - The current TAG can be incorporated into the agenda prefix. +;; See option `org-agenda-prefix-format' for details. +;; +;; Version 4.02 +;; - Minor bug fixes and improvements around tag searches. +;; - XEmacs compatibility fixes. +;; +;; Version 4.01 +;; - Tags can also be set remotely from agenda buffer. +;; - Boolean logic for tag searches. +;; - Additional agenda commands can be configured through the variable +;; `org-agenda-custom-commands'. +;; - Minor bug fixes. +;; +;;; Code: + +(eval-when-compile (require 'cl) (require 'calendar)) +(require 'outline) +(require 'time-date) +(require 'easymenu) + +(defvar calc-embedded-close-formula) ; defined by the calc package +(defvar calc-embedded-open-formula) ; defined by the calc package +(defvar font-lock-unfontify-region-function) ; defined by font-lock.el + +;;; Customization variables + +(defvar org-version "4.12" + "The version number of the file org.el.") +(defun org-version () + (interactive) + (message "Org-mode version %s" org-version)) + +;; The following two constants are for compatibility with different Emacs +;; versions (Emacs versus XEmacs) and with different versions of outline.el. +;; The compatibility code in org.el is based on these two constants. +(defconst org-xemacs-p (featurep 'xemacs) + "Are we running XEmacs?") +(defconst org-noutline-p (featurep 'noutline) + "Are we using the new outline mode?") + +(defgroup org nil + "Outline-based notes management and organizer." + :tag "Org" + :group 'outlines + :group 'hypermedia + :group 'calendar) + +(defgroup org-startup nil + "Options concerning startup of Org-mode." + :tag "Org Startup" + :group 'org) + +(defcustom org-CUA-compatible nil + "Non-nil means use alternative key bindings for S-. +Org-mode used S- for changing timestamps and priorities. +S- is also used for example by `CUA-mode' to select text. +If you want to use Org-mode together with `CUA-mode', Org-mode needs to use +alternative bindings. Setting this variable to t will replace the following +keys both in Org-mode and in the Org-agenda buffer. + +S-RET -> C-S-RET +S-up -> M-p +S-down -> M-n +S-left -> M-- +S-right -> M-+ + +If you do not like the alternative keys, take a look at the variable +`org-disputed-keys'. + +This option is only relevant at load-time of Org-mode. Changing it requires +a restart of Emacs to become effective." + :group 'org-startup + :type 'boolean) + +(defvar org-disputed-keys + '((S-up [(shift up)] [(meta ?p)]) + (S-down [(shift down)] [(meta ?n)]) + (S-left [(shift left)] [(meta ?-)]) + (S-right [(shift right)] [(meta ?+)]) + (S-return [(shift return)] [(control shift return)])) + "Keys for which Org-mode and other modes compete. +This is an alist, cars are symbols for lookup, 1st element is the default key, +second element will be used when `org-CUA-compatible' is t.") + +(defun org-key (key) + "Select a key according to `org-CUA-compatible'." + (nth (if org-CUA-compatible 2 1) + (or (assq key org-disputed-keys) + (error "Invalid Key %s in `org-key'" key)))) + +(defcustom org-startup-folded t + "Non-nil means, entering Org-mode will switch to OVERVIEW. +This can also be configured on a per-file basis by adding one of +the following lines anywhere in the buffer: + + #+STARTUP: fold + #+STARTUP: nofold + #+STARTUP: content" + :group 'org-startup + :type '(choice + (const :tag "nofold: show all" nil) + (const :tag "fold: overview" t) + (const :tag "content: all headlines" content))) + +(defcustom org-startup-truncated t + "Non-nil means, entering Org-mode will set `truncate-lines'. +This is useful since some lines containing links can be very long and +uninteresting. Also tables look terrible when wrapped." + :group 'org-startup + :type 'boolean) + +(defcustom org-startup-with-deadline-check nil + "Non-nil means, entering Org-mode will run the deadline check. +This means, if you start editing an org file, you will get an +immediate reminder of any due deadlines. +This can also be configured on a per-file basis by adding one of +the following lines anywhere in the buffer: + + #+STARTUP: dlcheck + #+STARTUP: nodlcheck" + :group 'org-startup + :type 'boolean) + +(defcustom org-insert-mode-line-in-empty-file nil + "Non-nil means insert the first line setting Org-mode in empty files. +When the function `org-mode' is called interactively in an empty file, this +normally means that the file name does not automatically trigger Org-mode. +To ensure that the file will always be in Org-mode in the future, a +line enforcing Org-mode will be inserted into the buffer, if this option +has been set." + :group 'org-startup + :type 'boolean) + +(defgroup org-keywords nil + "Options concerning TODO items in Org-mode." + :tag "Org Keywords" + :group 'org) + +(defcustom org-todo-keywords '("TODO" "DONE") + "List of TODO entry keywords. +\\By default, this is '(\"TODO\" \"DONE\"). The last entry in the list is +considered to mean that the entry is \"done\". All the other mean that +action is required, and will make the entry show up in todo lists, diaries +etc. +The command \\[org-todo] cycles an entry through these states, and an +additional state where no keyword is present. For details about this +cycling, see also the variable `org-todo-interpretation' +Changes become only effective after restarting Emacs." + :group 'org-keywords + :type '(repeat (string :tag "Keyword"))) + +(defcustom org-todo-interpretation 'sequence + "Controls how TODO keywords are interpreted. +\\Possible values are `sequence' and `type'. +This variable is only relevant if `org-todo-keywords' contains more than two +states. There are two ways how these keywords can be used: + +- As a sequence in the process of working on a TODO item, for example + (setq org-todo-keywords '(\"TODO\" \"STARTED\" \"VERIFY\" \"DONE\") + org-todo-interpretation 'sequence) + +- As different types of TODO items, for example + (setq org-todo-keywords '(\"URGENT\" \"RELAXED\" \"REMIND\" \"FOR_TOM\" \"DONE\") + org-todo-interpretation 'type) + +When the states are interpreted as a sequence, \\[org-todo] always cycles +to the next state, in order to walk through all different states. So with +\\[org-todo], you turn an empty entry into the state TODO. When you started +working on the item, you use \\[org-todo] again to switch it to \"STARTED\", +later to VERIFY and finally to DONE. + +When the states are interpreted as types, \\[org-todo] still cycles through +when it is called several times in direct succession, in order to initially +select the type. However, if not called immediately after a previous +\\[org-todo], it switches from each type directly to DONE. So with the +above example, you could use `\\[org-todo] \\[org-todo]' to label an entry +RELAXED. If you later return to this entry and press \\[org-todo] again, +RELAXED will not be changed REMIND, but directly to DONE. + +You can create a large number of types. To initially select a +type, it is then best to use \\[universal-argument] \\[org-todo] in order to specify the +type with completion. Of course, you can also type the keyword +directly into the buffer. M-TAB completes TODO keywords at the +beginning of a headline." + :group 'org-keywords + :type '(choice (const sequence) + (const type))) + +(defcustom org-default-priority ?B + "The default priority of TODO items. +This is the priority an item get if no explicit priority is given." + :group 'org-keywords + :type 'character) + +(defcustom org-lowest-priority ?C + "The lowest priority of TODO items. A character like ?A, ?B etc." + :group 'org-keywords + :type 'character) + +(defcustom org-deadline-string "DEADLINE:" + "String to mark deadline entries. +A deadline is this string, followed by a time stamp. Should be a word, +terminated by a colon. You can insert a schedule keyword and +a timestamp with \\[org-deadline]. +Changes become only effective after restarting Emacs." + :group 'org-keywords + :type 'string) + +(defcustom org-scheduled-string "SCHEDULED:" + "String to mark scheduled TODO entries. +A schedule is this string, followed by a time stamp. Should be a word, +terminated by a colon. You can insert a schedule keyword and +a timestamp with \\[org-schedule]. +Changes become only effective after restarting Emacs." + :group 'org-keywords + :type 'string) + +(defcustom org-closed-string "CLOSED:" + "String used as the prefix for timestamps logging closing a TODO entry." + :group 'org-keywords + :type 'string) + +(defcustom org-comment-string "COMMENT" + "Entries starting with this keyword will never be exported. +An entry can be toggled between COMMENT and normal with +\\[org-toggle-comment]. +Changes become only effective after restarting Emacs." + :group 'org-keywords + :type 'string) + +(defcustom org-quote-string "QUOTE" + "Entries starting with this keyword will be exported in fixed-width font. +Quoting applies only to the text in the entry following the headline, and does +not extend beyond the next headline, even if that is lower level. +An entry can be toggled between QUOTE and normal with +\\[org-toggle-fixed-width-section]." + :group 'org-keywords + :type 'string) + +(defcustom org-after-todo-state-change-hook nil + "Hook which is run after the state of a TODO item was changed. +The new state (a string with a TODO keyword, or nil) is available in the +Lisp variable `state'." + :group 'org-keywords + :type 'hook) + +;; Variables for pre-computed regular expressions, all buffer local +(defvar org-todo-kwd-priority-p nil + "Do TODO items have priorities?") +(make-variable-buffer-local 'org-todo-kwd-priority-p) +(defvar org-todo-kwd-max-priority nil + "Maximum priority of TODO items.") +(make-variable-buffer-local 'org-todo-kwd-max-priority) +(defvar org-ds-keyword-length 12 + "Maximum length of the Deadline and SCHEDULED keywords.") +(make-variable-buffer-local 'org-ds-keyword-length) +(defvar org-done-string nil + "The last string in `org-todo-keywords', indicating an item is DONE.") +(make-variable-buffer-local 'org-done-string) +(defvar org-todo-regexp nil + "Matches any of the TODO state keywords.") +(make-variable-buffer-local 'org-todo-regexp) +(defvar org-not-done-regexp nil + "Matches any of the TODO state keywords except the last one.") +(make-variable-buffer-local 'org-not-done-regexp) +(defvar org-todo-line-regexp nil + "Matches a headline and puts TODO state into group 2 if present.") +(make-variable-buffer-local 'org-todo-line-regexp) +(defvar org-nl-done-regexp nil + "Matches newline followed by a headline with the DONE keyword.") +(make-variable-buffer-local 'org-nl-done-regexp) +(defvar org-looking-at-done-regexp nil + "Matches the DONE keyword a point.") +(make-variable-buffer-local 'org-looking-at-done-regexp) +(defvar org-deadline-regexp nil + "Matches the DEADLINE keyword.") +(make-variable-buffer-local 'org-deadline-regexp) +(defvar org-deadline-time-regexp nil + "Matches the DEADLINE keyword together with a time stamp.") +(make-variable-buffer-local 'org-deadline-time-regexp) +(defvar org-deadline-line-regexp nil + "Matches the DEADLINE keyword and the rest of the line.") +(make-variable-buffer-local 'org-deadline-line-regexp) +(defvar org-scheduled-regexp nil + "Matches the SCHEDULED keyword.") +(make-variable-buffer-local 'org-scheduled-regexp) +(defvar org-scheduled-time-regexp nil + "Matches the SCHEDULED keyword together with a time stamp.") +(make-variable-buffer-local 'org-scheduled-time-regexp) + +(defvar org-category nil + "Variable used by org files to set a category for agenda display. +Such files should use a file variable to set it, for example + + -*- mode: org; org-category: \"ELisp\" + +or contain a special line + +#+CATEGORY: ELisp + +If the file does not specify a category, then file's base name +is used instead.") +(make-variable-buffer-local 'org-category) + +(defgroup org-time nil + "Options concerning time stamps and deadlines in Org-mode." + :tag "Org Time" + :group 'org) + +(defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>") + "Formats for `format-time-string' which are used for time stamps. +It is not recommended to change this constant.") + +(defcustom org-time-stamp-rounding-minutes 0 + "Number of minutes to round time stamps to upon insertion. +When zero, insert the time unmodified. Useful rounding numbers +should be factors of 60, so for example 5, 10, 15. +When this is not zero, you can still force an exact time-stamp by using +a double prefix argument to a time-stamp command like `C-c .' or `C-c !'." + :group 'org-time + :type 'integer) + +(defcustom org-deadline-warning-days 30 + "No. of days before expiration during which a deadline becomes active. +This variable governs the display in the org file." + :group 'org-time + :type 'number) + +(defcustom org-popup-calendar-for-date-prompt t + "Non-nil means, pop up a calendar when prompting for a date. +In the calendar, the date can be selected with mouse-1. However, the +minibuffer will also be active, and you can simply enter the date as well. +When nil, only the minibuffer will be available." + :group 'org-time + :type 'boolean) + +(defcustom org-calendar-follow-timestamp-change t + "Non-nil means, make the calendar window follow timestamp changes. +When a timestamp is modified and the calendar window is visible, it will be +moved to the new date." + :group 'org-time + :type 'boolean) + +(defcustom org-log-done nil + "When set, insert a (non-active) time stamp when TODO entry is marked DONE. +When the state of an entry is changed from nothing to TODO, remove a previous +closing date." + :group 'org-time + :type 'boolean) + +(defgroup org-agenda nil + "Options concerning agenda display Org-mode." + :tag "Org Agenda" + :group 'org) + +(defcustom org-agenda-files nil + "A list of org files for agenda/diary display. +Entries are added to this list with \\[org-agenda-file-to-front] and removed with +\\[org-remove-file]. You can also use customize to edit the list." + :group 'org-agenda + :type '(repeat file)) + +(defcustom org-agenda-custom-commands '(("w" todo "WAITING")) + "Custom commands for the agenda. +These commands will be offered on the splash screen displayed by the +agenda dispatcher \\[org-agenda]. Each entry is a list of 3 items: + +key The key (a single char as a string) to be associated with the command. +type The command type, any of the following symbols: + todo Entries with a specific TODO keyword, in all agenda files. + tags Tags match in all agenda files. + todo-tree Sparse tree of specific TODO keyword in *current* file. + tags-tree Sparse tree with all tags matches in *current* file. + occur-tree Occur sparse tree for current file. +match What to search for: + - a single keyword for TODO keyword searches + - a tags match expression for tags searches + - a regular expression for occur searches" + :group 'org-agenda + :type '(repeat + (list (string :tag "Key") + (choice :tag "Type" + (const :tag "Tags search in all agenda files" tags) + (const :tag "TODO keyword search in all agenda files" todo) + (const :tag "Tags sparse tree in current buffer" tags-tree) + (const :tag "TODO keyword tree in current buffer" todo-tree) + (const :tag "Occur tree in current buffer" occur-tree)) + (string :tag "Match")))) + +(defcustom org-select-timeline-window t + "Non-nil means, after creating a timeline, move cursor into Timeline window. +When nil, cursor will remain in the current window." + :group 'org-agenda + :type 'boolean) + +(defcustom org-select-agenda-window t + "Non-nil means, after creating an agenda, move cursor into Agenda window. +When nil, cursor will remain in the current window." + :group 'org-agenda + :type 'boolean) + +(defcustom org-fit-agenda-window t + "Non-nil means, change window size of agenda to fit content." + :group 'org-agenda + :type 'boolean) + +(defcustom org-agenda-show-all-dates t + "Non-nil means, `org-agenda' shows every day in the selected range. +When nil, only the days which actually have entries are shown." + :group 'org-agenda + :type 'boolean) + +;; FIXME: First day of month works only for current month because it would +;; require a variable ndays treatment. +(defcustom org-agenda-start-on-weekday 1 + "Non-nil means, start the overview always on the specified weekday. +0 Denotes Sunday, 1 denotes Monday etc. +When nil, always start on the current day." + :group 'org-agenda + :type '(choice (const :tag "Today" nil) + (const :tag "First day of month" t) + (number :tag "Weekday No."))) + +(defcustom org-agenda-ndays 7 + "Number of days to include in overview display." + :group 'org-agenda + :type 'number) + +(defcustom org-agenda-include-all-todo t + "Non-nil means, the agenda will always contain all TODO entries. +When nil, date-less entries will only be shown if `org-agenda' is called +with a prefix argument. +When non-nil, the TODO entries will be listed at the top of the agenda, before +the entries for specific days." + :group 'org-agenda + :type 'boolean) + +(defcustom org-agenda-include-diary nil + "If non-nil, include in the agenda entries from the Emacs Calendar's diary." + :group 'org-agenda + :type 'boolean) + +(defcustom org-calendar-to-agenda-key [?c] + "The key to be installed in `calendar-mode-map' for switching to the agenda. +The command `org-calendar-goto-agenda' will be bound to this key. The +default is the character `c' because then `c' can be used to switch back and +forth between agenda and calendar." + :group 'org-agenda + :type 'sexp) + +(defcustom org-agenda-sorting-strategy '(time-up category-keep priority-down) + "Sorting structure for the agenda items of a single day. +This is a list of symbols which will be used in sequence to determine +if an entry should be listed before another entry. The following +symbols are recognized: + +time-up Put entries with time-of-day indications first, early first +time-down Put entries with time-of-day indications first, late first +category-keep Keep the default order of categories, corresponding to the + sequence in `org-agenda-files'. +category-up Sort alphabetically by category, A-Z. +category-down Sort alphabetically by category, Z-A. +priority-up Sort numerically by priority, high priority last. +priority-down Sort numerically by priority, high priority first. + +The different possibilities will be tried in sequence, and testing stops +if one comparison returns a \"not-equal\". For example, the default + '(time-up category-keep priority-down) +means: Pull out all entries having a specified time of day and sort them, +in order to make a time schedule for the current day the first thing in the +agenda listing for the day. Of the entries without a time indication, keep +the grouped in categories, don't sort the categories, but keep them in +the sequence given in `org-agenda-files'. Within each category sort by +priority. + +Leaving out `category-keep' would mean that items will be sorted across +categories by priority." + :group 'org-agenda + :type '(repeat + (choice + (const time-up) + (const time-down) + (const category-keep) + (const category-up) + (const category-down) + (const priority-up) + (const priority-down)))) + +(defcustom org-agenda-prefix-format " %-12:c%?-12t% s" + "Format specification for the prefix of items in the agenda buffer. +This format works similar to a printf format, with the following meaning: + + %c the category of the item, \"Diary\" for entries from the diary, or + as given by the CATEGORY keyword or derived from the file name. + %T the first tag of the item. + %t the time-of-day specification if one applies to the entry, in the + format HH:MM + %s Scheduling/Deadline information, a short string + +All specifiers work basically like the standard `%s' of printf, but may +contain two additional characters: A question mark just after the `%' and +a whitespace/punctuation character just before the final letter. + +If the first character after `%' is a question mark, the entire field +will only be included if the corresponding value applies to the +current entry. This is useful for fields which should have fixed +width when present, but zero width when absent. For example, +\"%?-12t\" will result in a 12 character time field if a time of the +day is specified, but will completely disappear in entries which do +not contain a time. + +If there is punctuation or whitespace character just before the final +format letter, this character will be appended to the field value if +the value is not empty. For example, the format \"%-12:c\" leads to +\"Diary: \" if the category is \"Diary\". If the category were be +empty, no additional colon would be interted. + +The default value of this option is \" %-12:c%?-12t% s\", meaning: +- Indent the line with two space characters +- Give the category in a 12 chars wide field, padded with whitespace on + the right (because of `-'). Append a colon if there is a category + (because of `:'). +- If there is a time-of-day, put it into a 12 chars wide field. If no + time, don't put in an empty field, just skip it (because of '?'). +- Finally, put the scheduling information and append a whitespace. + +As another example, if you don't want the time-of-day of entries in +the prefix, you could use: + + (setq org-agenda-prefix-format \" %-11:c% s\") + +See also the variables `org-agenda-remove-times-when-in-prefix' and +`org-agenda-remove-tags-when-in-prefix'." + :type 'string + :group 'org-agenda) + +(defcustom org-timeline-prefix-format " % s" + "Like `org-agenda-prefix-format', but for the timeline of a single file." + :type 'string + :group 'org-agenda) + +(defvar org-prefix-format-compiled nil + "The compiled version of the most recently used prefix format. +Depending on which command was used last, this may be the compiled version +of `org-agenda-prefix-format' or `org-timeline-prefix-format'.") + +(defcustom org-agenda-use-time-grid t + "Non-nil means, show a time grid in the agenda schedule. +A time grid is a set of lines for specific times (like every two hours between +8:00 and 20:00). The items scheduled for a day at specific times are +sorted in between these lines. +For details about when the grid will be shown, and what it will look like, see +the variable `org-agenda-time-grid'." + :group 'org-agenda + :type 'boolean) + +(defcustom org-agenda-time-grid + '((daily today require-timed) + "----------------" + (800 1000 1200 1400 1600 1800 2000)) + + "The settings for time grid for agenda display. +This is a list of three items. The first item is again a list. It contains +symbols specifying conditions when the grid should be displayed: + + daily if the agenda shows a single day + weekly if the agenda shows an entire week + today show grid on current date, independent of daily/weekly display + require-timed show grid only if at least on item has a time specification + +The second item is a string which will be places behing the grid time. + +The third item is a list of integers, indicating the times that should have +a grid line." + :group 'org-agenda + :type + '(list + (set :greedy t :tag "Grid Display Options" + (const :tag "Show grid in single day agenda display" daily) + (const :tag "Show grid in weekly agenda display" weekly) + (const :tag "Always show grid for today" today) + (const :tag "Show grid only if any timed entries are present" + require-timed) + (const :tag "Skip grid times already present in an entry" + remove-match)) + (string :tag "Grid String") + (repeat :tag "Grid Times" (integer :tag "Time")))) + +(defcustom org-agenda-remove-times-when-in-prefix t + "Non-nil means, remove duplicate time specifications in agenda items. +When the format `org-agenda-prefix-format' contains a `%t' specifier, a +time-of-day specification in a headline or diary entry is extracted and +placed into the prefix. If this option is non-nil, the original specification +\(a timestamp or -range, or just a plain time(range) specification like +11:30-4pm) will be removed for agenda display. This makes the agenda less +cluttered. +The option can be t or nil. It may also be the symbol `beg', indicating +that the time should only be removed what it is located at the beginning of +the headline/diary entry." + :group 'org-agenda + :type '(choice + (const :tag "Always" t) + (const :tag "Never" nil) + (const :tag "When at beginning of entry" beg))) + +(defcustom org-sort-agenda-notime-is-late t + "Non-nil means, items without time are considered late. +This is only relevant for sorting. When t, items which have no explicit +time like 15:30 will be considered as 24:01, i.e. later than any items which +do have a time. When nil, the default time is before 0:00. You can use this +option to decide if the schedule for today should come before or after timeless +agenda entries." + :group 'org-agenda + :type 'boolean) + +(defcustom org-agenda-remove-tags-when-in-prefix nil + "Non-nil means, the tags from copy of headline in agenda. +When this is the symbol `prefix', only remove tags when +`org-agenda-prefix-format' contains a `%T' specifier." + :group 'org-agenda + :type '(choice + (const :tag "Always" t) + (const :tag "Never" nil) + (const :tag "When prefix format contains %T" prefix))) + +(defgroup org-structure nil + "Options concerning structure editing in Org-mode." + :tag "Org Structure" + :group 'org) + +(defcustom org-cycle-include-plain-lists nil + "Non-nil means, include plain lists into visibility cycling. +This means that during cycling, plain list items will *temporarily* be +interpreted as outline headlines with a level given by 1000+i where i is the +indentation of the bullet. In all other operations, plain list items are +not seen as headlines. For example, you cannot assign a TODO keyword to +such an item." + :group 'org-structure + :type 'boolean) + +(defcustom org-cycle-emulate-tab t + "Where should `org-cycle' emulate TAB. +nil Never +white Only in completely white lines +t Everywhere except in headlines" + :group 'org-structure + :type '(choice (const :tag "Never" nil) + (const :tag "Only in completely white lines" white) + (const :tag "Everywhere except in headlines" t) + )) + +(defcustom org-cycle-hook '(org-optimize-window-after-visibility-change) + "Hook that is run after `org-cycle' has changed the buffer visibility. +The function(s) in this hook must accept a single argument which indicates +the new state that was set by the most recent `org-cycle' command. The +argument is a symbol. After a global state change, it can have the values +`overview', `content', or `all'. After a local state change, it can have +the values `folded', `children', or `subtree'." + :group 'org-structure + :type 'hook) + +(defcustom org-highlight-sparse-tree-matches t + "Non-nil means, highlight all matches that define a sparse tree. +The highlights will automatically disappear the next time the buffer is +changed by an edit command." + :group 'org-structure + :type 'boolean) + +(defcustom org-show-hierarchy-above t + "Non-nil means, show full hierarchy when showing a spot in the tree. +Turning this off makes sparse trees more compact, but also less clear." + :group 'org-structure + :type 'boolean) + +(defcustom org-show-following-heading t + "Non-nil means, show heading following match in `org-occur'. +When doing an `org-occur' it is useful to show the headline which +follows the match, even if they do not match the regexp. This makes it +easier to edit directly inside the sparse tree. However, if you use +`org-occur' mainly as an overview, the following headlines are +unnecessary clutter." + :group 'org-structure + :type 'boolean) + +(defcustom org-occur-hook '(org-first-headline-recenter) + "Hook that is run after `org-occur' has constructed a sparse tree. +This can be used to recenter the window to show as much of the structure +as possible." + :group 'org-structure + :type 'hook) + +(defcustom org-odd-levels-only nil + "Non-nil means, skip even levels and only use odd levels for the outline. +This has the effect that two stars are being added/taken away in +promotion/demotion commands. It also influences how levels are +handled by the exporters. +Changing it requires restart of `font-lock-mode' to become effective +for fontification also in regions already fontified." + :group 'org-structure + :group 'org-font-lock + :type 'boolean) + +(defcustom org-adapt-indentation t + "Non-nil means, adapt indentation when promoting and demoting. +When this is set and the *entire* text in an entry is indented, the +indentation is increased by one space in a demotion command, and +decreased by one in a promotion command. If any line in the entry +body starts at column 0, indentation is not changed at all." + :group 'org-structure + :type 'boolean) + +(defcustom org-plain-list-ordered-item-terminator t + "The character that makes a line with leading number an ordered list item. +Valid values are ?. and ?\). To get both terminators, use t. While +?. may look nicer, it creates the danger that a line with leading +number may be incorrectly interpreted as an item. ?\) therefore is +the safe choice." + :group 'org-structure + :type '(choice (const :tag "dot like in \"2.\"" ?.) + (const :tag "paren like in \"2)\"" ?\)) + (const :tab "both" t))) + +(defcustom org-auto-renumber-ordered-lists t + "Non-nil means, automatically renumber ordered plain lists. +Renumbering happens when the sequence have been changed with +\\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands, +use \\[org-ctrl-c-ctrl-c] to trigger renumbering." + :group 'org-structure + :type 'boolean) + +(defcustom org-enable-fixed-width-editor t + "Non-nil means, lines starting with \":\" are treated as fixed-width. +This currently only means, they are never auto-wrapped. +When nil, such lines will be treated like ordinary lines. +See also the QUOTE keyword." + :group 'org-structure + :type 'boolean) + +(defcustom org-archive-location "%s_archive::" + "The location where subtrees should be archived. +This string consists of two parts, separated by a double-colon. + +The first part is a file name - when omitted, archiving happens in the same +file. %s will be replaced by the current file name (without directory part). +Archiving to a different file is useful to keep archived entries from +contributing to the Org-mode Agenda. + +The part after the double colon is a headline. The archived entries will be +filed under that headline. When omitted, the subtrees are simply filed away +at the end of the file, as top-level entries. + +Here are a few examples: +\"%s_archive::\" + If the current file is Projects.org, archive in file + Projects.org_archive, as top-level trees. This is the default. + +\"::* Archived Tasks\" + Archive in the current file, under the top-level headline + \"* Archived Tasks\". + +\"~/org/archive.org::\" + Archive in file ~/org/archive.org (absolute path), as top-level trees. + +\"basement::** Finished Tasks\" + Archive in file ./basement (relative path), as level 3 trees + below the level 2 heading \"** Finished Tasks\". + +You may set this option on a per-file basis by adding to the buffer a +line like + +#+ARCHIVE: basement::** Finished Tasks" + :group 'org-structure + :type 'string) + +(defcustom org-archive-mark-done t + "Non-nil means, mark archived entries as DONE." + :group 'org-structure + :type 'boolean) + +(defcustom org-archive-stamp-time t + "Non-nil means, add a time stamp to archived entries. +The time stamp will be added directly after the TODO state keyword in the +first line, so it is probably best to use this in combinations with +`org-archive-mark-done'." + :group 'org-structure + :type 'boolean) + +(defgroup org-tags nil + "Options concerning startup of Org-mode." + :tag "Org Tags" + :group 'org) + +(defcustom org-tags-column 48 + "The column to which tags should be indented in a headline. +If this number is positive, it specifies the column. If it is negative, +it means that the tags should be flushright to that column. For example, +-79 works well for a normal 80 character screen." + :group 'org-tags + :type 'integer) + +(defcustom org-auto-align-tags t + "Non-nil means, realign tags after pro/demotion of TODO state change. +These operations change the length of a headline and therefore shift +the tags around. With this options turned on, after each such operation +the tags are again aligned to `org-tags-column'." + :group 'org-tags + :type 'boolean) + +(defcustom org-use-tag-inheritance t + "Non-nil means, tags in levels apply also for sublevels. +When nil, only the tags directly given in a specific line apply there. +If you turn off this option, you very likely want to turn on the +companion option `org-tags-match-list-sublevels'." + :group 'org-tags + :type 'boolean) + +(defcustom org-tags-match-list-sublevels nil + "Non-nil means list also sublevels of headlines matching tag search. +Because of tag inheritance (see variable `org-use-tag-inheritance'), +the sublevels of a headline matching a tag search often also match +the same search. Listing all of them can create very long lists. +Setting this variable to nil causes subtrees to be skipped. +This option is off by default, because inheritance in on. If you turn +inheritance off, you very likely want to turn this option on. + +As a special case, if the tag search is restricted to TODO items, the +value of this variable is ignored and sublevels are always checked, to +make sure all corresponding TODO items find their way into the list." + :group 'org-tags + :type 'boolean) + +(defvar org-tags-history nil + "History of minibuffer reads for tags.") +(defvar org-last-tags-completion-table nil + "The last used completion table for tags.") + +(defgroup org-link nil + "Options concerning links in Org-mode." + :tag "Org Link" + :group 'org) + +(defcustom org-tab-follows-link nil + "Non-nil means, on links TAB will follow the link. +Needs to be set before org.el is loaded." + :group 'org-link + :type 'boolean) + +(defcustom org-return-follows-link nil + "Non-nil means, on links RET will follow the link. +Needs to be set before org.el is loaded." + :group 'org-link + :type 'boolean) + +(defcustom org-mark-ring-length 4 + "Number of different positions to be recorded in the ring +Changing this requires a restart of Emacs to work correctly." + :group 'org-link + :type 'interger) + +(defcustom org-link-format "<%s>" + "Default format for linkes in the buffer. +This is a format string for printf, %s will be replaced by the link text. +If you want to make sure that your link is always properly terminated, +include angle brackets into this format, like \"<%s>\". Some people also +recommend an additional URL: prefix, so the format would be \"\"." + :group 'org-link + :type '(choice + (const :tag "\"%s\" (e.g. http://www.there.com)" "%s") + (const :tag "\"<%s>\" (e.g. )" "<%s>") + (const :tag "\"\" (e.g. )" "") + (string :tag "Other" :value "<%s>"))) + +(defcustom org-allow-space-in-links t + "Non-nil means, file names in links may contain space characters. +When nil, it becomes possible to put several links into a line. +Note that in tables, a link never extends accross fields, so in a table +it is always possible to put several links into a line. +Changing this variable requires a restart of Emacs of become effective." + :group 'org-link + :type 'boolean) + +(defcustom org-radio-targets t + "Non-nil means activate text matching a link target. +Radio targets are strings in triple angular brackets, like <<>>. +When this option is set, any occurrence of \"my target\" in normal text +becomes a link." + :group 'org-link + :type 'boolean) + +(defcustom org-activate-camels nil + "Non-nil means, treat words in CamelCase as in-file links. +Changing this requires restart of Emacs to become effective." + :group 'org-link + :type 'boolean) + +(defcustom org-context-in-file-links t + "Non-nil means, file links from `org-store-link' contain context. +A search string will be 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'. +Using a prefix arg to the command \\[org-store-link] (`org-store-link') +negates this setting for the duration of the command." + :group 'org-link + :type 'boolean) + +(defcustom org-file-link-context-use-camel-case nil + "Non-nil means, use CamelCase to store a search context in a file link. +When nil, the search string simply consists of the words of the string." + :group 'org-link + :type 'boolean) + +(defcustom org-keep-stored-link-after-insertion nil + "Non-nil means, keep link in list for entire session. + +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-mode 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 + :type 'boolean) + +(defcustom org-link-frame-setup + '((vm . vm-visit-folder-other-frame) + (gnus . gnus-other-frame) + (file . find-file-other-window)) + "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-frame' +For Gnus, use any of + `gnus' + `gnus-other-frame' +For FILE, use any of + `find-file' + `find-file-other-window' + `find-file-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 + :type '(list + (cons (const vm) + (choice + (const vm-visit-folder) + (const vm-visit-folder-other-window) + (const vm-visit-folder-other-frame))) + (cons (const gnus) + (choice + (const gnus) + (const gnus-other-frame))) + (cons (const file) + (choice + (const find-file) + (const find-file-other-window) + (const find-file-other-frame))))) + +(defcustom org-usenet-links-prefer-google nil + "Non-nil means, `org-store-link' will create web links to Google groups. +When nil, Gnus will be used for such links. +Using a prefix arg to the command \\[org-store-link] (`org-store-link') +negates this setting for the duration of the command." + :group 'org-link + :type 'boolean) + +(defcustom org-open-non-existing-files nil + "Non-nil means, `org-open-file' will open non-existing file. +When nil, an error will be generated." + :group 'org-link + :type 'boolean) + +(defcustom org-confirm-shell-links t + "Non-nil means, ask for confirmation before executing shell links. +The default is true, to keep new users from shooting into their own foot." + :group 'org-link + :type 'boolean) + +(defconst org-file-apps-defaults-gnu + '((t . mailcap)) + "Default file applications on a UNIX or GNU/Linux system. +See `org-file-apps'.") + +(defconst org-file-apps-defaults-macosx + '((t . "open %s") + ("ps" . "gv %s") + ("ps.gz" . "gv %s") + ("eps" . "gv %s") + ("eps.gz" . "gv %s") + ("dvi" . "xdvi %s") + ("fig" . "xfig %s")) + "Default file applications on a MacOS X system. +The system \"open\" is known as a default, but we use X11 applications +for some files for which the OS does not have a good default. +See `org-file-apps'.") + +(defconst org-file-apps-defaults-windowsnt + '((t . (w32-shell-execute "open" file))) + "Default file applications on a Windows NT system. +The system \"open\" is used for most files. +See `org-file-apps'.") + +(defcustom org-file-apps + '( + ("txt" . emacs) + ("tex" . emacs) + ("ltx" . emacs) + ("org" . emacs) + ("el" . emacs) + ) + "External applications for opening `file:path' items in a document. +Org-mode uses system defaults for different file types, but +you can use this variable to set the application for a given file +extension. The entries in this list are cons cells with a file extension +and the corresponding command. Possible values for the command are: + `emacs' The file will be visited by the current Emacs process. + `default' Use the default application for this file type. + string A command to be executed by a shell; %s will be replaced + by the path to the file. + sexp A Lisp form which will be evaluated. The file path will + be available in the Lisp variable `file'. +For more examples, see the system specific constants +`org-file-apps-defaults-macosx' +`org-file-apps-defaults-windowsnt' +`org-file-apps-defaults-gnu'." + :group 'org-link + :type '(repeat + (cons (choice :value "" + (string :tag "Extension") + (const :tag "Default for unrecognized files" t) + (const :tag "Links to a directory" directory)) + (choice :value "" + (const :tag "Visit with Emacs" emacs) + (const :tag "Use system default" default) + (string :tag "Command") + (sexp :tag "Lisp form"))))) + +(defcustom org-mhe-search-all-folders nil + "Non-nil means, that the search for the mh-message will be extended to +all folders if the message cannot be found in the folder given in the link. +Searching all folders is very effective with one of the search engines +supported by MH-E, but will be slow with pick." + :group 'org-link + :type 'boolean) + +(defgroup org-remember nil + "Options concerning interaction with remember.el." + :tag "Org Remember" + :group 'org) + +(defcustom org-directory "~/org" + "Directory with org files. +This directory will be used as default to prompt for org files. +Used by the hooks for remember.el." + :group 'org-remember + :type 'directory) + +(defcustom org-default-notes-file "~/.notes" + "Default target for storing notes. +Used by the hooks for remember.el. This can be a string, or nil to mean +the value of `remember-data-file'." + :group 'org-remember + :type '(choice + (const :tag "Default from remember-data-file" nil) + file)) + +(defcustom org-remember-templates nil + "Templates for the creation of remember buffers. +When nil, just let remember make the buffer. +When not nil, this is a list of 3-element lists. In each entry, the first +element is a character, a unique key to select this template. +The second element is the template. The third element is optional and can +specify a destination file for remember items created with this template. +The default file is given by `org-default-notes-file'. + +The template specifies the structure of the remember buffer. It should have +a first line starting with a star, to act as the org-mode headline. +Furthermore, the following %-escapes will be replaced with content: + %t time stamp, date only + %T time stamp with date and time + %u inactive time stamp, date only + %U inactive time stamp with date and time + %n user name + %a annotation, normally the link created with org-store-link + %i initial content, the region when remember is called with C-u. + If %i is indented, the entire inserted text will be indented as well. + %? This will be removed, and the cursor placed at this position." + :group 'org-remember + :type '(repeat :tag "enabled" + (list :value (?a "\n" nil) + (character :tag "Selection Key") + (string :tag "Template") + (file :tag "Destination file (optional)")))) + +(defcustom org-reverse-note-order nil + "Non-nil means, store new notes at the beginning of a file or entry. +When nil, new notes will be filed to the end of a file or entry." + :group 'org-remember + :type '(choice + (const :tag "Reverse always" t) + (const :tag "Reverse never" nil) + (repeat :tag "By file name regexp" + (cons regexp boolean)))) + +(defgroup org-table nil + "Options concerning tables in Org-mode." + :tag "Org Table" + :group 'org) + +(defcustom org-enable-table-editor 'optimized + "Non-nil means, lines starting with \"|\" are handled by the table editor. +When nil, such lines will be treated like ordinary lines. + +When equal to the symbol `optimized', the table editor will be optimized to +do the following: +- Use automatic overwrite mode in front of whitespace in table fields. + This make the structure of the table stay in tact as long as the edited + field does not exceed the column width. +- Minimize the number of realigns. Normally, the table is aligned each time + TAB or RET are pressed to move to another field. With optimization this + happens only if changes to a field might have changed the column width. +Optimization requires replacing the functions `self-insert-command', +`delete-char', and `backward-delete-char' in Org-mode buffers, with a +slight (in fact: unnoticeable) speed impact for normal typing. Org-mode is +very good at guessing when a re-align will be necessary, but you can always +force one with \\[org-ctrl-c-ctrl-c]. + +If you would like to use the optimized version in Org-mode, but the +un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'. + +This variable can be used to turn on and off the table editor during a session, +but in order to toggle optimization, a restart is required. + +See also the variable `org-table-auto-blank-field'." + :group 'org-table + :type '(choice + (const :tag "off" nil) + (const :tag "on" t) + (const :tag "on, optimized" optimized))) + +;; FIXME: We could have a third option which makes it jump only over the first +;; hline in a table. +(defcustom org-table-tab-jumps-over-hlines t + "Non-nil means, tab in the last column of a table with jump over a hline. +If a horizontal separator line is following the current line, +`org-table-next-field' can either create a new row before that line, or jump +over the line. When this option is nil, a new line will be created before +this line." + :group 'org-table + :type 'boolean) + +(defcustom org-table-auto-blank-field t + "Non-nil means, automatically blank table field when starting to type into it. +This only happens when typing immediately after a field motion +command (TAB, S-TAB or RET). +Only relevant when `org-enable-table-editor' is equal to `optimized'." + :group 'org-table + :type 'boolean) + +(defcustom org-table-default-size "5x2" + "The default size for newly created tables, Columns x Rows." + :group 'org-table + :type 'string) + +(defcustom org-table-automatic-realign t + "Non-nil means, automatically re-align table when pressing TAB or RETURN. +When nil, aligning is only done with \\[org-table-align], or after column +removal/insertion." + :group 'org-table + :type 'boolean) + +(defcustom org-table-spaces-around-separators '(1 . 1) + "The number of spaces to be placed before and after separators." + :group 'org-table + :type '(cons (number :tag "Before \"|\"") (number :tag " After \"|\""))) + +(defcustom org-table-spaces-around-invisible-separators '(1 . 2) + "The number of spaces to be placed before and after separators. +This option applies when the column separators have been made invisible." + :group 'org-table + :type '(cons (number :tag "Before \"|\"") (number :tag " After \"|\""))) + +(defcustom org-table-number-regexp "^[<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*$" + "Regular expression for recognizing numbers in table columns. +If a table column contains mostly numbers, it will be aligned to the +right. If not, it will be aligned to the left. + +The default value of this option is a regular expression which allows +anything which looks remotely like a number as used in scientific +context. For example, all of the following will be considered a +number: + 12 12.2 2.4e-08 2x10^12 4.034+-0.02 2.7(10) >3.5 + +Other options offered by the customize interface are more restrictive." + :group 'org-table + :type '(choice + (const :tag "Positive Integers" + "^[0-9]+$") + (const :tag "Integers" + "^[-+]?[0-9]+$") + (const :tag "Floating Point Numbers" + "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.[0-9]*\\)$") + (const :tag "Floating Point Number or Integer" + "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.?[0-9]*\\)$") + (const :tag "Exponential, Floating point, Integer" + "^[-+]?[0-9.]+\\([eEdD][-+0-9]+\\)?$") + (const :tag "Very General Number-Like" + "^[<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*$") + (string :tag "Regexp:"))) + +(defcustom org-table-number-fraction 0.5 + "Fraction of numbers in a column required to make the column align right. +In a column all non-white fields are considered. If at least this +fraction of fields is matched by `org-table-number-fraction', +alignment to the right border applies." + :group 'org-table + :type 'number) + +(defcustom org-export-highlight-first-table-line t + "Non-nil means, highlight the first table line. +In HTML export, this means use instead of . +In tables created with table.el, this applies to the first table line. +In Org-mode tables, all lines before the first horizontal separator +line will be formatted with tags." + :group 'org-table + :type 'boolean) + +(defcustom org-table-tab-recognizes-table.el t + "Non-nil means, TAB will automatically notice a table.el table. +When it sees such a table, it moves point into it and - if necessary - +calls `table-recognize-table'." + :group 'org-table + :type 'boolean) + +(defgroup org-table-calculation nil + "Options concerning tables in Org-mode." + :tag "Org Table Calculation" + :group 'org) + +(defcustom org-table-copy-increment t + "Non-nil means, increment when copying current field with \\[org-table-copy-down]." + :group 'org-table-calculation + :type 'boolean) + +(defcustom org-calc-default-modes + '(calc-internal-prec 12 + calc-float-format (float 5) + calc-angle-mode deg + calc-prefer-frac nil + calc-symbolic-mode nil + calc-date-format (YYYY "-" MM "-" DD " " Www (" " HH ":" mm)) + calc-display-working-message t + ) + "List with Calc mode settings for use in calc-eval for table formulas. +The list must contain alternating symbols (Calc modes variables and values). +Don't remove any of the default settings, just change the values. Org-mode +relies on the variables to be present in the list." + :group 'org-table-calculation + :type 'plist) + +(defcustom org-table-formula-evaluate-inline t + "Non-nil means, TAB and RET evaluate a formula in current table field. +If the current field starts with an equal sign, it is assumed to be a formula +which should be evaluated as described in the manual and in the documentation +string of the command `org-table-eval-formula'. This feature requires the +Emacs calc package. +When this variable is nil, formula calculation is only available through +the command \\[org-table-eval-formula]." + :group 'org-table-calculation + :type 'boolean) + + +(defcustom org-table-formula-use-constants t + "Non-nil means, interpret constants in formulas in tables. +A constant looks like `$c' or `$Grav' and will be replaced before evaluation +by the value given in `org-table-formula-constants', or by a value obtained +from the `constants.el' package." + :group 'org-table-calculation + :type 'boolean) + +(defcustom org-table-formula-constants nil + "Alist with constant names and values, for use in table formulas. +The car of each element is a name of a constant, without the `$' before it. +The cdr is the value as a string. For example, if you'd like to use the +speed of light in a formula, you would configure + + (setq org-table-formula-constants '((\"c\" . \"299792458.\"))) + +and then use it in an equation like `$1*$c'." + :group 'org-table-calculation + :type '(repeat + (cons (string :tag "name") + (string :tag "value")))) + +(defcustom org-table-formula-numbers-only nil + "Non-nil means, calculate only with numbers in table formulas. +Then all input fields will be converted to a number, and the result +must also be a number. When nil, calc's full potential is available +in table calculations, including symbolics etc." + :group 'org-table-calculation + :type 'boolean) + +(defcustom org-table-allow-automatic-line-recalculation t + "Non-nil means, lines marked with |#| or |*| will be recomputed automatically. +Automatically means, when TAB or RET or C-c C-c are pressed in the line." + :group 'org-table-calculation + :type 'boolean) + +(defgroup org-export nil + "Options for exporting org-listings." + :tag "Org Export" + :group 'org) + +(defcustom org-export-language-setup + '(("en" "Author" "Date" "Table of Contents") + ("da" "Ophavsmand" "Dato" "Indhold") + ("de" "Autor" "Datum" "Inhaltsverzeichnis") + ("es" "Autor" "Fecha" "\xccndice") + ("fr" "Auteur" "Date" "Table des Mati\xe8res") + ("it" "Autore" "Data" "Indice") + ("nl" "Auteur" "Datum" "Inhoudsopgave") + ("nn" "Forfattar" "Dato" "Innhold") ;; nn = Norsk (nynorsk) + ("sv" "F\xf6rfattarens" "Datum" "Inneh\xe5ll")) + "Terms used in export text, translated to different languages. +Use the variable `org-export-default-language' to set the language, +or use the +OPTION lines for a per-file setting." + :group 'org-export + :type '(repeat + (list + (string :tag "HTML language tag") + (string :tag "Author") + (string :tag "Date") + (string :tag "Table of Contents")))) + +(defcustom org-export-default-language "en" + "The default language of HTML export, as a string. +This should have an association in `org-export-language-setup'." + :group 'org-export + :type 'string) + +(defcustom org-export-html-style +"" + "The default style specification for exported HTML files. +Since there are different ways of setting style information, this variable +needs to contain the full HTML structure to provide a style, including the +surrounding HTML tags. The style specifications should include definitions +for new classes todo, done, title, and deadline. For example, legal values +would be: + + + +or, if you want to keep the style in a file, + + + +As the value of this option simply gets inserted into the HTML header, +you can \"misuse\" it to add arbitrary text to the header." + :group 'org-export + :type 'string) + +(defcustom org-export-headline-levels 3 + "The last level which is still exported as a headline. +Inferior levels will produce itemize lists when exported. +Note that a numeric prefix argument to an exporter function overrides +this setting. + +This option can also be set with the +OPTIONS line, e.g. \"H:2\"." + :group 'org-export + :type 'number) + +(defcustom org-export-with-section-numbers t + "Non-nil means, add section numbers to headlines when exporting. + +This option can also be set with the +OPTIONS line, e.g. \"num:t\"." + :group 'org-export + :type 'boolean) + +(defcustom org-export-with-toc t + "Non-nil means, create a table of contents in exported files. +The TOC contains headlines with levels up to`org-export-headline-levels'. + +Headlines which contain any TODO items will be marked with \"(*)\" in +ASCII export, and with red color in HTML output. + +In HTML output, the TOC will be clickable. + +This option can also be set with the +OPTIONS line, e.g. \"toc:nil\"." + :group 'org-export + :type 'boolean) + +(defcustom org-export-plain-list-max-depth 20 + "Maximum depth of hand-formatted lists in HTML export. + +Org-mode parses hand-formatted enumeration and bullet lists and +transforms them to HTML open export. Different indentation of the +bullet or number indicates different list nesting levels. To avoid +confusion, only a single level is allowed by default. When this is +larger than 1, deeper indentation leads to deeper list nesting. For +example, the default value of 3 allows the following list to be +formatted correctly in HTML: + + * Fruit + - Apple + - Banana + 1. from Africa + 2. from South America + - Pineapple + * Bread + * Dairy products" + :group 'org-export + :type 'integer) + +(defcustom org-export-preserve-breaks nil + "Non-nil means, preserve all line breaks when exporting. +Normally, in HTML output paragraphs will be reformatted. In ASCII +export, line breaks will always be preserved, regardless of this variable. + +This option can also be set with the +OPTIONS line, e.g. \"\\n:t\"." + :group 'org-export + :type 'boolean) + +(defcustom org-export-html-inline-images t + "Non-nil means, inline images into exported HTML pages. +The link will still be to the original location of the image file. +So if you are moving the page, lets say to your public HTML site, +you will have to move the image and maybe change the link." + :group 'org-export + :type 'boolean) + +(defcustom org-export-html-expand t + "Non-nil means, for HTML export, treat @<...> as HTML tag. +When nil, these tags will be exported as plain text and therefore +not be interpreted by a browser. + +This option can also be set with the +OPTIONS line, e.g. \"@:nil\"." + :group 'org-export + :type 'boolean) + +(defcustom org-export-with-fixed-width t + "Non-nil means, lines starting with \":\" will be in fixed width font. +This can be used to have pre-formatted text, fragments of code etc. For +example: + : ;; Some Lisp examples + : (while (defc cnt) + : (ding)) +will be looking just like this in also HTML. In ASCII export, this option +has no effect. + +This option can also be set with the +OPTIONS line, e.g. \"::nil\"." + :group 'org-export + :type 'boolean) + +(defcustom org-export-with-tables t + "If non-nil, lines starting with \"|\" define a table. +For example: + + | Name | Address | Birthday | + |-------------+----------+-----------| + | Arthur Dent | England | 29.2.2100 | + +In ASCII export, this option has no effect. + +This option can also be set with the +OPTIONS line, e.g. \"|:nil\"." + :group 'org-export + :type 'boolean) + +(defcustom org-export-table-remove-special-lines t + "Remove special lines and marking characters in calculating tables. +This removes the special marking character column from tables that are set +up for spreadsheet calculations. It also removes the entire lines +marked with `!', `_', or `^'. The lines with `$' are kept, because +the values of constants may be useful to have." + :group 'org-export + :type 'boolean) + +(defcustom org-export-prefer-native-exporter-for-tables nil + "Non-nil means, always export tables created with table.el natively. +Natively means, use the HTML code generator in table.el. +When nil, Org-mode's own HTML generator is used when possible (i.e. if +the table does not use row- or column-spanning). This has the +advantage, that the automatic HTML conversions for math symbols and +sub/superscripts can be applied. Org-mode's HTML generator is also +much faster." + :group 'org-export + :type 'boolean) + +(defcustom org-export-html-table-tag + "" + "The HTML tag used to start a table. +This must be a
tag, but you may change the options like +borders and spacing." + :group 'org-export + :type 'string) + +(defcustom org-export-with-emphasize t + "Non-nil means, interpret *word*, /word/, and _word_ as emphasized text. +If the export target supports emphasizing text, the word will be +typeset in bold, italic, or underlined, respectively. Works only for +single words, but you can say: I *really* *mean* *this*. +In ASCII export, this option has no effect. + +This option can also be set with the +OPTIONS line, e.g. \"*:nil\"." + :group 'org-export + :type 'boolean) + +(defcustom org-match-sexp-depth 3 + "Number of stacked braces for sub/superscript matching. +This has to be set before loading org.el to be effective." + :group 'org-export + :type 'integer) + +;; FIXME: Should () parens be removed as well in sub/superscripts? +(defcustom org-export-with-sub-superscripts t + "Non-nil means, interpret \"_\" and \"^\" for export. +When this option is turned on, you can use TeX-like syntax for sub- and +superscripts. Several characters after \"_\" or \"^\" will be +considered as a single item - so grouping with {} is normally not +needed. For example, the following things will be parsed as single +sub- or superscripts. + + 10^24 or 10^tau several digits will be considered 1 item. + 10^-12 or 10^-tau a leading sign with digits or a word + x^2-y^3 will be read as x^2 - y^3, because items are + terminated by almost any nonword/nondigit char. + x_{i^2} or x^(2-i) braces or parenthesis do grouping. + +Still, ambiguity is possible - so when in doubt use {} to enclose the +sub/superscript. +In ASCII export, this option has no effect. + +This option can also be set with the +OPTIONS line, e.g. \"^:nil\"." + :group 'org-export + :type 'boolean) + +(defcustom org-export-with-TeX-macros t + "Non-nil means, interpret simple TeX-like macros when exporting. +For example, HTML export converts \\alpha to α and \\AA to Å. +No only real TeX macros will work here, but the standard HTML entities +for math can be used as macro names as well. For a list of supported +names in HTML export, see the constant `org-html-entities'. +In ASCII export, this option has no effect. + +This option can also be set with the +OPTIONS line, e.g. \"TeX:nil\"." + :group 'org-export + :type 'boolean) + +(defcustom org-export-html-with-timestamp nil + "If non-nil, write `org-export-html-html-helper-timestamp' +into the exported HTML text. Otherwise, the buffer will just be saved +to a file." + :group 'org-export + :type 'boolean) + +(defcustom org-export-html-html-helper-timestamp + "


\n" + "The HTML tag used as timestamp delimiter for HTML-helper-mode." + :group 'org-export + :type 'string) + +(defcustom org-export-ascii-show-new-buffer t + "Non-nil means, popup buffer containing the exported ASCII text. +Otherwise the buffer will just be saved to a file and stay hidden." + :group 'org-export + :type 'boolean) + +(defcustom org-export-html-show-new-buffer nil + "Non-nil means, popup buffer containing the exported html text. +Otherwise, the buffer will just be saved to a file and stay hidden." + :group 'org-export + :type 'boolean) + +(defcustom org-combined-agenda-icalendar-file "~/org.ics" + "The file name for the iCalendar file covering all agenda files. +This file is created with the command \\[org-export-icalendar-all-agenda-files]." + :group 'org-export + :type 'file) + +(defcustom org-icalendar-include-todo nil + "Non-nil means, export to iCalendar files should also cover TODO items." + :group 'org-export + :type 'boolean) + +(defcustom org-icalendar-combined-name "OrgMode" + "Calendar name for the combined iCalendar representing all agenda files." + :group 'org-export + :type 'string) + +(defgroup org-font-lock nil + "Faces and settings for highlighting in Org-mode." + :tag "Org Font Lock" + :group 'org) + +(defcustom org-level-color-stars-only nil + "Non-nil means fontify only the stars in each headline. +When nil, the entire headline is fontified. +Changing it requires restart of `font-lock-mode' to become effective +also in regions already fontified." + :group 'org-font-lock + :type 'boolean) + +(defcustom org-hide-leading-stars nil + "Non-nil means, hide the first N-1 stars in a headline. +This works by using the face `org-hide' for these stars. This +face is white for a light background, and black for a dark +background. You may have to customize the face `org-hide' to +make this work. +Changing it requires restart of `font-lock-mode' to become effective +also in regions already fontified." + :group 'org-font-lock + :type 'boolean) + +(defcustom org-fontify-done-headline nil + "Non-nil means, change the face of a headline if it is marked DONE. +Normally, only the TODO/DONE keyword indicates the state of a headline. +When this is non-nil, the headline after the keyword is set to the +`org-headline-done' as an additional indication." + :group 'org-font-lock + :type 'boolean) + +(defcustom org-fontify-emphasized-text t + "Non-nil means fontify *bold*, /italic/ and _underlined_ text. +Changing this variable requires a restart of Emacs to take effect." + :group 'org-font-lock + :type 'boolean) + +(defface org-hide + '( + (((type tty) (class color)) (:foreground "white")) + (((class color) (background light)) (:foreground "white")) + (((class color) (background dark)) (:foreground "black")) +; (((class color) (backgro6und light)) (:foreground "grey90")) +; (((class color) (background dark)) (:foreground "grey10")) + (t (:inverse-video nil))) + "Face used for level 1 headlines." + :group 'org-font-lock) + +(defface org-level-1 ;; font-lock-function-name-face + '((((type tty) (class color)) (:foreground "blue" :weight bold)) + (((class color) (background light)) (:foreground "Blue")) + (((class color) (background dark)) (:foreground "LightSkyBlue")) + (t (:inverse-video t :bold t))) + "Face used for level 1 headlines." + :group 'org-font-lock) + +(defface org-level-2 ;; font-lock-variable-name-face + '((((type tty) (class color)) (:foreground "yellow" :weight light)) + (((class color) (background light)) (:foreground "DarkGoldenrod")) + (((class color) (background dark)) (:foreground "LightGoldenrod")) + (t (:bold t :italic t))) + "Face used for level 2 headlines." + :group 'org-font-lock) + +(defface org-level-3 ;; font-lock-keyword-face + '((((type tty) (class color)) (:foreground "cyan" :weight bold)) + (((class color) (background light)) (:foreground "Purple")) + (((class color) (background dark)) (:foreground "Cyan")) + (t (:bold t))) + "Face used for level 3 headlines." + :group 'org-font-lock) + +(defface org-level-4 ;; font-lock-comment-face + '((((type tty pc) (class color) (background light)) (:foreground "red")) + (((type tty pc) (class color) (background dark)) (:foreground "red1")) + (((class color) (background light)) (:foreground "Firebrick")) + (((class color) (background dark)) (:foreground "chocolate1")) + (t (:bold t :italic t))) + "Face used for level 4 headlines." + :group 'org-font-lock) + +(defface org-level-5 ;; font-lock-type-face + '((((type tty) (class color)) (:foreground "green")) + (((class color) (background light)) (:foreground "ForestGreen")) + (((class color) (background dark)) (:foreground "PaleGreen")) + (t (:bold t :underline t))) + "Face used for level 5 headlines." + :group 'org-font-lock) + +(defface org-level-6 ;; font-lock-constant-face + '((((type tty) (class color)) (:foreground "magenta")) + (((class color) (background light)) (:foreground "CadetBlue")) + (((class color) (background dark)) (:foreground "Aquamarine")) + (t (:bold t :underline t))) + "Face used for level 6 headlines." + :group 'org-font-lock) + +(defface org-level-7 ;; font-lock-builtin-face + '((((type tty) (class color)) (:foreground "blue" :weight light)) + (((class color) (background light)) (:foreground "Orchid")) + (((class color) (background dark)) (:foreground "LightSteelBlue")) + (t (:bold t))) + "Face used for level 7 headlines." + :group 'org-font-lock) + +(defface org-level-8 ;; font-lock-string-face + '((((type tty) (class color)) (:foreground "green")) + (((class color) (background light)) (:foreground "RosyBrown")) + (((class color) (background dark)) (:foreground "LightSalmon")) + (t (:italic t))) + "Face used for level 8 headlines." + :group 'org-font-lock) + +(defface org-special-keyword ;; font-lock-string-face + '((((type tty) (class color)) (:foreground "green")) + (((class color) (background light)) (:foreground "RosyBrown")) + (((class color) (background dark)) (:foreground "LightSalmon")) + (t (:italic t))) + "Face used for special keywords." + :group 'org-font-lock) + +(defface org-warning ;; font-lock-warning-face + '((((type tty) (class color)) (:foreground "red")) + (((class color) (background light)) (:foreground "Red" :bold t)) + (((class color) (background dark)) (:foreground "Red1" :bold t)) +; (((class color) (background dark)) (:foreground "Pink" :bold t)) + (t (:inverse-video t :bold t))) + "Face for deadlines and TODO keywords." + :group 'org-font-lock) + +(defface org-headline-done ;; font-lock-string-face + '((((type tty) (class color)) (:foreground "green")) + (((class color) (background light)) (:foreground "RosyBrown")) + (((class color) (background dark)) (:foreground "LightSalmon")) + (t (:italic t))) + "Face used to indicate that a headline is DONE. See also the variable +`org-fontify-done-headline'." + :group 'org-font-lock) + +;; Inheritance does not yet work for xemacs. So we just copy... + +(defface org-deadline-announce + '((((type tty) (class color)) (:foreground "blue" :weight bold)) + (((class color) (background light)) (:foreground "Blue")) + (((class color) (background dark)) (:foreground "LightSkyBlue")) + (t (:inverse-video t :bold t))) + "Face for upcoming deadlines." + :group 'org-font-lock) + +(defface org-scheduled-today + '((((type tty) (class color)) (:foreground "green")) + (((class color) (background light)) (:foreground "DarkGreen")) + (((class color) (background dark)) (:foreground "PaleGreen")) + (t (:bold t :underline t))) + "Face for items scheduled for a certain day." + :group 'org-font-lock) + +(defface org-scheduled-previously + '((((type tty pc) (class color) (background light)) (:foreground "red")) + (((type tty pc) (class color) (background dark)) (:foreground "red1")) + (((class color) (background light)) (:foreground "Firebrick")) + (((class color) (background dark)) (:foreground "chocolate1")) + (t (:bold t :italic t))) + "Face for items scheduled previously, and not yet done." + :group 'org-font-lock) + +(defface org-formula + '((((type tty pc) (class color) (background light)) (:foreground "red")) + (((type tty pc) (class color) (background dark)) (:foreground "red1")) + (((class color) (background light)) (:foreground "Firebrick")) + (((class color) (background dark)) (:foreground "chocolate1")) + (t (:bold t :italic t))) + "Face for formulas." + :group 'org-font-lock) + +(defface org-link + '((((type tty) (class color)) (:foreground "cyan" :weight bold)) + (((class color) (background light)) (:foreground "Purple")) + (((class color) (background dark)) (:foreground "Cyan")) + (t (:bold t))) + "Face for links." + :group 'org-font-lock) + +(defface org-tag + '((((type tty) (class color)) (:foreground "cyan" :weight bold)) + (((class color) (background light)) (:foreground "Purple" :weight bold)) + (((class color) (background dark)) (:foreground "Cyan" :weight bold)) + (t (:bold t))) + "Face for tags." + :group 'org-font-lock) + +(defface org-done ;; font-lock-type-face + '((((type tty) (class color)) (:foreground "green")) + (((class color) (background light)) (:foreground "ForestGreen" :bold t)) + (((class color) (background dark)) (:foreground "PaleGreen" :bold t)) + (t (:bold t :underline t))) + "Face used for DONE." + :group 'org-font-lock) + +(defface org-table ;; font-lock-function-name-face + '((((type tty) (class color)) (:foreground "blue" :weight bold)) + (((class color) (background light)) (:foreground "Blue")) + (((class color) (background dark)) (:foreground "LightSkyBlue")) + (t (:inverse-video t :bold t))) + "Face used for tables." + :group 'org-font-lock) + +(defface org-time-grid ;; font-lock-variable-name-face + '((((type tty) (class color)) (:foreground "yellow" :weight light)) + (((class color) (background light)) (:foreground "DarkGoldenrod")) + (((class color) (background dark)) (:foreground "LightGoldenrod")) + (t (:bold t :italic t))) + "Face used for time grids." + :group 'org-font-lock) + +(defvar org-level-faces + '(org-level-1 org-level-2 org-level-3 org-level-4 + org-level-5 org-level-6 org-level-7 org-level-8 + )) +(defvar org-n-levels (length org-level-faces)) + +(defun org-set-regexps-and-options () + "Precompute regular expressions for current buffer." + (when (eq major-mode 'org-mode) + (let ((re (org-make-options-regexp + '("CATEGORY" "SEQ_TODO" "PRI_TODO" "TYP_TODO" + "STARTUP" "ARCHIVE"))) + (splitre "[ \t]+") + kwds int key value cat arch) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (while (re-search-forward re nil t) + (setq key (match-string 1) value (match-string 2)) + (cond + ((equal key "CATEGORY") + (if (string-match "[ \t]+$" value) + (setq value (replace-match "" t t value))) + (setq cat (intern value))) + ((equal key "SEQ_TODO") + (setq int 'sequence + kwds (append kwds (org-split-string value splitre)))) + ((equal key "PRI_TODO") + (setq int 'priority + kwds (append kwds (org-split-string value splitre)))) + ((equal key "TYP_TODO") + (setq int 'type + kwds (append kwds (org-split-string value splitre)))) + ((equal key "STARTUP") + (let ((opts (org-split-string value splitre)) + (set '(("fold" org-startup-folded t) + ("nofold" org-startup-folded nil) + ("content" org-startup-folded content) + ("hidestars" org-hide-leading-stars t) + ("showstars" org-hide-leading-stars nil) + ("odd" org-odd-levels-only t) + ("oddeven" org-odd-levels-only nil) + ("dlcheck" org-startup-with-deadline-check t) + ("nodlcheck" org-startup-with-deadline-check nil))) + l var val) + (while (setq l (assoc (pop opts) set)) + (setq var (nth 1 l) val (nth 2 l)) + (set (make-local-variable var) val)))) + ((equal key "ARCHIVE") + (string-match " *$" value) + (setq arch (replace-match "" t t value)) + (remove-text-properties 0 (length arch) + '(face t fontified t) arch))) + ))) + (and cat (set (make-local-variable 'org-category) cat)) + (and kwds (set (make-local-variable 'org-todo-keywords) kwds)) + (and arch (set (make-local-variable 'org-archive-location) arch)) + (and int (set (make-local-variable 'org-todo-interpretation) int))) + ;; Compute the regular expressions and other local variables + (setq org-todo-kwd-priority-p (equal org-todo-interpretation 'priority) + org-todo-kwd-max-priority (1- (length org-todo-keywords)) + org-ds-keyword-length (+ 2 (max (length org-deadline-string) + (length org-scheduled-string))) + org-done-string + (nth (1- (length org-todo-keywords)) org-todo-keywords) + org-todo-regexp + (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords + "\\|") "\\)\\>") + org-not-done-regexp + (concat "\\<\\(" + (mapconcat 'regexp-quote + (nreverse (cdr (reverse org-todo-keywords))) + "\\|") + "\\)\\>") + org-todo-line-regexp + (concat "^\\(\\*+\\)[ \t]*\\(" + (mapconcat 'regexp-quote org-todo-keywords "\\|") + "\\)? *\\(.*\\)") + org-nl-done-regexp + (concat "[\r\n]\\*+[ \t]+" org-done-string "\\>") + org-looking-at-done-regexp (concat "^" org-done-string "\\>") + org-deadline-regexp (concat "\\<" org-deadline-string) + org-deadline-time-regexp + (concat "\\<" org-deadline-string " *<\\([^>]+\\)>") + org-deadline-line-regexp + (concat "\\<\\(" org-deadline-string "\\).*") + org-scheduled-regexp + (concat "\\<" org-scheduled-string) + org-scheduled-time-regexp + (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")) + (org-set-font-lock-defaults))) + +;; Tell the compiler about dynamically scoped variables, +;; and variables from other packages +(defvar zmacs-regions) ; XEmacs regions +(defvar original-date) ; dynamically scoped in calendar +(defvar org-old-auto-fill-inhibit-regexp) ; local variable used by `orgtbl-mode' +(defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized +(defvar org-html-entities) ; defined later in this file +(defvar org-goto-start-pos) ; dynamically scoped parameter +(defvar org-time-was-given) ; dynamically scoped parameter +(defvar org-ts-what) ; dynamically scoped parameter +(defvar mark-active) ; Emacs only, not available in XEmacs. +(defvar timecnt) ; dynamically scoped parameter +(defvar levels-open) ; dynamically scoped parameter +(defvar title) ; dynamically scoped parameter +(defvar author) ; dynamically scoped parameter +(defvar email) ; dynamically scoped parameter +(defvar text) ; dynamically scoped parameter +(defvar entry) ; dynamically scoped parameter +(defvar date) ; dynamically scoped parameter +(defvar language) ; dynamically scoped parameter +(defvar options) ; dynamically scoped parameter +(defvar ans1) ; dynamically scoped parameter +(defvar ans2) ; dynamically scoped parameter +(defvar starting-day) ; local variable +(defvar include-all-loc) ; local variable +(defvar vm-message-pointer) ; from vm +(defvar vm-folder-directory) ; from vm +(defvar wl-summary-buffer-elmo-folder) ; from wanderlust +(defvar wl-summary-buffer-folder-name) ; from wanderlust +(defvar gnus-group-name) ; from gnus +(defvar gnus-article-current) ; from gnus +(defvar w3m-current-url) ; from w3m +(defvar mh-progs) ; from MH-E +(defvar mh-current-folder) ; from MH-E +(defvar mh-show-folder-buffer) ; from MH-E +(defvar mh-index-folder) ; from MH-E +(defvar mh-searcher) ; from MH-E +(defvar org-selected-point) ; dynamically scoped parameter +(defvar calendar-mode-map) ; from calendar.el +(defvar last-arg) ; local variable +(defvar remember-save-after-remembering) ; from remember.el +(defvar remember-data-file) ; from remember.el +(defvar annotation) ; from remember.el, dynamically scoped in `remember-mode' +(defvar initial) ; from remember.el, dynamically scoped in `remember-mode' + +;;; Define the mode + +(defvar org-mode-map (copy-keymap outline-mode-map) + "Keymap for Org-mode.") + +(defvar org-struct-menu) ; defined later in this file +(defvar org-org-menu) ; defined later in this file +(defvar org-tbl-menu) ; defined later in this file + +;; We use a before-change function to check if a table might need +;; an update. +(defvar org-table-may-need-update t + "Indicates that a table might need an update. +This variable is set by `org-before-change-function'. +`org-table-align' sets it back to nil.") +(defvar org-mode-hook nil) +(defvar org-inhibit-startup nil) ; Dynamically-scoped param. +(defvar org-agenda-keep-modes nil) ; Dynamically-scoped param. + + +;;;###autoload +(define-derived-mode org-mode outline-mode "Org" + "Outline-based notes management and organizer, alias +\"Carsten's outline-mode for keeping track of everything.\" + +Org-mode develops organizational tasks around a NOTES file which +contains information about projects as plain text. Org-mode is +implemented on top of outline-mode, which is ideal to keep the content +of large files well structured. It supports ToDo items, deadlines and +time stamps, which magically appear in the diary listing of the Emacs +calendar. Tables are easily created with a built-in table editor. +Plain text URL-like links connect to websites, emails (VM), Usenet +messages (Gnus), BBDB entries, and any files related to the project. +For printing and sharing of notes, an Org-mode file (or a part of it) +can be exported as a structured ASCII or HTML file. + +The following commands are available: + +\\{org-mode-map}" + (easy-menu-add org-org-menu) + (easy-menu-add org-tbl-menu) + (org-install-agenda-files-menu) + (setq outline-regexp "\\*+") +; (setq outline-regexp "\\(?:\\*+\\|[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\) \\)") + (setq outline-level 'org-outline-level) + (if org-startup-truncated (setq truncate-lines t)) + (org-set-regexps-and-options) + (set (make-local-variable 'font-lock-unfontify-region-function) + 'org-unfontify-region) + ;; Activate before-change-function + (set (make-local-variable 'org-table-may-need-update) t) + (org-add-hook 'before-change-functions 'org-before-change-function nil + 'local) + ;; Paragraphs and auto-filling + (org-set-autofill-regexps) + (org-update-radio-target-regexp) + ;; Settings for Calc embedded mode + (set (make-local-variable 'calc-embedded-open-formula) "|\\|\n") + (set (make-local-variable 'calc-embedded-close-formula) "|\\|\n") + (if (and org-insert-mode-line-in-empty-file + (interactive-p) + (= (point-min) (point-max))) + (insert " -*- mode: org -*-\n\n")) + + ;; Get rid of Outline menus, they are not needed + ;; Need to do this here because define-derived-mode sets up + ;; the keymap so late. + (if org-xemacs-p + (progn + (delete-menu-item '("Headings")) + (delete-menu-item '("Show")) + (delete-menu-item '("Hide")) + (set-menubar-dirty-flag)) + (define-key org-mode-map [menu-bar headings] 'undefined) + (define-key org-mode-map [menu-bar hide] 'undefined) + (define-key org-mode-map [menu-bar show] 'undefined)) + + (unless org-inhibit-startup + (if org-startup-with-deadline-check + (call-interactively 'org-check-deadlines) + (cond + ((eq org-startup-folded t) + (org-cycle '(4))) + ((eq org-startup-folded 'content) + (let ((this-command 'org-cycle) (last-command 'org-cycle)) + (org-cycle '(4)) (org-cycle '(4)))))))) + +(defsubst org-current-line (&optional pos) + (+ (if (bolp) 1 0) (count-lines (point-min) (or pos (point))))) + +(defun org-current-time () + "Current time, possibly rounded to `org-time-stamp-rounding-minutes'." + (if (> org-time-stamp-rounding-minutes 0) + (let ((r org-time-stamp-rounding-minutes) + (time (decode-time))) + (apply 'encode-time + (append (list 0 (* r (floor (+ .5 (/ (float (nth 1 time)) r))))) + (nthcdr 2 time)))) + (current-time))) + +;; FIXME: Do we need to copy? +(defun org-string-props (string &rest properties) + "Add PROPERTIES to string." + (add-text-properties 0 (length string) properties string) + string) + +;;; Font-Lock stuff + +(defvar org-mouse-map (make-sparse-keymap)) +(define-key org-mouse-map + (if org-xemacs-p [button2] [mouse-2]) 'org-open-at-mouse) +(define-key org-mouse-map + (if org-xemacs-p [button3] [mouse-3]) 'org-find-file-at-mouse) +(define-key org-mouse-map [follow-link] 'mouse-face) +(when org-tab-follows-link + (define-key org-mouse-map [(tab)] 'org-open-at-point) + (define-key org-mouse-map "\C-i" 'org-open-at-point)) +(when org-return-follows-link + (define-key org-mouse-map [(return)] 'org-open-at-point) + (define-key org-mouse-map "\C-m" 'org-open-at-point)) + +(require 'font-lock) + +(defconst org-non-link-chars "\t\n\r|<>\000") +(defconst org-link-regexp + (if org-allow-space-in-links + (concat + "\\(https?\\|ftp\\|mailto\\|file\\|news\\|bbdb\\|vm\\|wl\\|mhe\\|rmail\\|gnus\\|shell\\):\\([^" org-non-link-chars "]+[^ " org-non-link-chars "]\\)") + (concat + "\\(https?\\|ftp\\|mailto\\|file\\|news\\|bbdb\\|vm\\|wl\\|mhe\\|rmail\\|gnus\\|shell\\):\\([^ " org-non-link-chars "]+\\)") + ) + "Regular expression for matching links.") +(defconst org-link-maybe-angles-regexp + (concat "?") + "Matches a link and optionally surrounding angle brackets.") +(defconst org-protected-link-regexp + (concat "\000" org-link-regexp "\000") + "Matches a link and optionally surrounding angle brackets.") + +(defconst org-bracket-link-regexp + "\\[\\[\\([^]]+\\)\\]\\(\\[\\([^]]+\\)\\]\\)?\\]" + "Matches a link in double brackets.") + +(defconst org-ts-lengths + (cons (length (format-time-string (car org-time-stamp-formats))) + (length (format-time-string (cdr org-time-stamp-formats)))) + "This holds the lengths of the two different time formats.") +(defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^\r\n>]*?\\)>" + "Regular expression for fast time stamp matching.") +(defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^\r\n>]*?\\)[]>]" + "Regular expression for fast time stamp matching.") +(defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\([^0-9>\r\n]*\\)\\(\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)" + "Regular expression matching time strings for analysis.") +(defconst org-ts-regexp2 (concat "<" org-ts-regexp1 ">") + "Regular expression matching time stamps, with groups.") +(defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp) + "Regular expression matching a time stamp range.") +(defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?" + org-ts-regexp "\\)?") + "Regular expression matching a time stamp or time stamp range.") + +(defun org-activate-links (limit) + "Run through the buffer and add overlays to links." + (if (re-search-forward org-link-regexp limit t) + (progn + (add-text-properties (match-beginning 0) (match-end 0) + (list 'mouse-face 'highlight + 'keymap org-mouse-map)) + t))) + +(defun org-activate-links2 (limit) + "Run through the buffer and add overlays to links." + (if (re-search-forward org-bracket-link-regexp limit t) + (progn + (add-text-properties (match-beginning 0) (match-end 0) + (list 'mouse-face 'highlight + 'keymap org-mouse-map)) + t))) + +(defun org-activate-dates (limit) + "Run through the buffer and add overlays to dates." + (if (re-search-forward org-tsr-regexp limit t) + (progn + (add-text-properties (match-beginning 0) (match-end 0) + (list 'mouse-face 'highlight + 'keymap org-mouse-map)) + t))) + +(defvar org-target-link-regexp nil + "Regular expression matching radio targets in plain text.") +(defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>" + "Regular expression matching a link target.") +(defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>" + "Regular expression matching a link target.") + +(defun org-activate-target-links (limit) + "Run through the buffer and add overlays to target matches." + (when (and org-radio-targets org-target-link-regexp) + (let ((case-fold-search t)) + (if (re-search-forward org-target-link-regexp limit t) + (progn + (add-text-properties (match-beginning 0) (match-end 0) + (list 'mouse-face 'highlight + 'keymap org-mouse-map + 'org-linked-text t)) + t))))) + +(defun org-update-radio-target-regexp () + "Find all radio targets in this file and update the regular expression." + (interactive) + (when org-radio-targets + (setq org-target-link-regexp + (org-make-target-link-regexp (org-all-targets 'radio))) + (font-lock-mode -1) + (font-lock-mode 1))) + +(defun org-all-targets (&optional radio) + "Return a list of all targets in this file. +With optional argument RADIO, only find radio targets." + (let ((re (if radio org-radio-target-regexp org-target-regexp)) + rtn) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward re nil t) + (add-to-list 'rtn (downcase + (if (fboundp 'match-string-no-properties) + (match-string-no-properties 1) + (match-string 1))))) + rtn))) + +(defun org-make-target-link-regexp (targets) + "Make regular expression matching all strings in TARGETS. +The regular expression finds the targets also if there is a line break +between words." + (and targets + (concat + "\\<\\(" + (mapconcat + (lambda (x) + (while (string-match " +" x) + (setq x (replace-match "\\s-+" t t x))) + x) + targets + "\\|") + "\\)\\>"))) + +(defvar org-camel-regexp "\\*?\\<[A-Z]+[a-z]+[A-Z][a-zA-Z]*\\>" + "Matches CamelCase words, possibly with a star before it.") + +(defun org-activate-camels (limit) + "Run through the buffer and add overlays to dates." + (if org-activate-camels + (if (re-search-forward org-camel-regexp limit t) + (progn + (add-text-properties (match-beginning 0) (match-end 0) + (list 'mouse-face 'highlight + 'keymap org-mouse-map)) + t)))) + +(defun org-activate-tags (limit) + (if (re-search-forward "[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \r\n]" limit t) + (progn + (add-text-properties (match-beginning 1) (match-end 1) + (list 'mouse-face 'highlight + 'keymap org-mouse-map)) + t))) + +(defun org-font-lock-level () + (save-excursion + (org-back-to-heading t) + (- (match-end 0) (match-beginning 0)))) + +(defun org-outline-level () + (save-excursion + (looking-at outline-regexp) + (if (match-beginning 1) + (+ (org-get-string-indentation (match-string 1)) 1000) + (- (match-end 0) (match-beginning 0))))) + +(defvar org-font-lock-keywords nil) + +(defun org-set-font-lock-defaults () + (let* ((em org-fontify-emphasized-text) + (org-font-lock-extra-keywords + (list + '("^\\(\\**\\)\\(\\*\\)\\(.*\\)" (1 (org-get-level-face 1)) + (2 (org-get-level-face 2)) (3 (org-get-level-face 3))) + '(org-activate-links (0 'org-link t)) + '(org-activate-links2 (0 'org-link t)) + '(org-activate-target-links (0 'org-link t)) + '(org-activate-dates (0 'org-link t)) + '(org-activate-camels (0 'org-link t)) + '(org-activate-tags (1 'org-tag t)) + (list (concat "^\\*+[ \t]*" org-not-done-regexp) + '(1 'org-warning t)) + (list (concat "\\[#[A-Z]\\]") '(0 'org-special-keyword t)) + (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t)) + (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword t)) + (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t)) + (if em '("\\(\\W\\|^\\)\\(\\*\\w+\\*\\)\\(\\W\\|$\\)" 2 'bold)) + (if em '("\\(\\W\\|^\\)\\(/\\w+/\\)\\(\\W\\|$\\)" 2 'italic)) + (if em '("\\(\\W\\|^\\)\\(_\\w+_\\)\\(\\W\\|$\\)" 2 'underline)) + (list (concat "^\\*+[ \t]*\\<\\(" org-comment-string + "\\|" org-quote-string "\\)\\>") + '(1 'org-special-keyword t)) + '("^#.*" (0 'font-lock-comment-face t)) + (if org-fontify-done-headline + (list (concat "^[*]+ +\\<\\(" org-done-string "\\)\\(.*\\)\\>") + '(1 'org-done t) '(2 'org-headline-done t)) + (list (concat "^[*]+ +\\<\\(" org-done-string "\\)\\>") + '(1 'org-done t))) + '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)" + (1 'org-table t)) + '("^[ \t]*\\(:.*\\)" (1 'org-table t)) + '("| *\\(:?=[^|\n]*\\)" (1 'org-formula t)) + '("^[ \t]*| *\\([#!$*_^]\\) *|" (1 'org-formula t)) + ))) + (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords)) + ;; Now set the full font-lock-keywords + (set (make-local-variable 'org-font-lock-keywords) + org-font-lock-extra-keywords) + (set (make-local-variable 'font-lock-defaults) + '(org-font-lock-keywords t nil nil backward-paragraph)) + (kill-local-variable 'font-lock-keywords) nil)) + +(defvar org-m nil) +(defvar org-l nil) +(defvar org-f nil) +(defun org-get-level-face (n) + "Get the right face for match N in font-lock matching of healdines." + (setq org-l (- (match-end 2) (match-beginning 1))) + (if org-odd-levels-only (setq org-l (1+ (/ org-l 2)))) + (setq org-f (nth (1- (% org-l org-n-levels)) org-level-faces)) + (cond + ((eq n 1) (if org-hide-leading-stars 'org-hide org-f)) + ((eq n 2) org-f) + (t (if org-level-color-stars-only nil org-f)))) + +(defun org-unfontify-region (beg end &optional maybe_loudly) + "Remove fontification and activation overlays from links." + (font-lock-default-unfontify-region beg end) + (let* ((buffer-undo-list t) + (inhibit-read-only t) (inhibit-point-motion-hooks t) + (inhibit-modification-hooks t) + deactivate-mark buffer-file-name buffer-file-truename) + (remove-text-properties beg end + '(mouse-face nil keymap nil org-linked-text nil)))) + +;;; Visibility cycling + +(defvar org-cycle-global-status nil) +(defvar org-cycle-subtree-status nil) +(defun org-cycle (&optional arg) + "Visibility cycling for Org-mode. + +- When this function is called with a prefix argument, rotate the entire + buffer through 3 states (global cycling) + 1. OVERVIEW: Show only top-level headlines. + 2. CONTENTS: Show all headlines of all levels, but no body text. + 3. SHOW ALL: Show everything. + +- When point is at the beginning of a headline, rotate the subtree started + by this line through 3 different states (local cycling) + 1. FOLDED: Only the main headline is shown. + 2. CHILDREN: The main headline and the direct children are shown. + From this state, you can move to one of the children + and zoom in further. + 3. SUBTREE: Show the entire subtree, including body text. + +- When there is a numeric prefix, go up to a heading with level ARG, do + a `show-subtree' and return to the previous cursor position. If ARG + is negative, go up that many levels. + +- When point is not at the beginning of a headline, execute + `indent-relative', like TAB normally does. See the option + `org-cycle-emulate-tab' for details. + +- Special case: if point is the the beginning of the buffer and there is + no headline in line 1, this function will act as if called with prefix arg." + (interactive "P") + + (if (or (and (bobp) (not (looking-at outline-regexp))) + (equal arg '(4))) + ;; special case: use global cycling + (setq arg t)) + + (let ((outline-regexp + (if org-cycle-include-plain-lists + "\\*+\\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) " + outline-regexp))) + + (cond + + ((org-at-table-p 'any) + ;; Enter the table or move to the next field in the table + (or (org-table-recognize-table.el) + (progn + (org-table-justify-field-maybe) + (org-table-next-field)))) + + ((eq arg t) ;; Global cycling + + (cond + ((and (eq last-command this-command) + (eq org-cycle-global-status 'overview)) + ;; We just created the overview - now do table of contents + ;; This can be slow in very large buffers, so indicate action + (message "CONTENTS...") + (save-excursion + ;; Visit all headings and show their offspring + (goto-char (point-max)) + (catch 'exit + (while (and (progn (condition-case nil + (outline-previous-visible-heading 1) + (error (goto-char (point-min)))) + t) + (looking-at outline-regexp)) + (show-branches) + (if (bobp) (throw 'exit nil)))) + (message "CONTENTS...done")) + (setq org-cycle-global-status 'contents) + (run-hook-with-args 'org-cycle-hook 'contents)) + + ((and (eq last-command this-command) + (eq org-cycle-global-status 'contents)) + ;; We just showed the table of contents - now show everything + (show-all) + (message "SHOW ALL") + (setq org-cycle-global-status 'all) + (run-hook-with-args 'org-cycle-hook 'all)) + + (t + ;; Default action: go to overview + (hide-sublevels 1) + (message "OVERVIEW") + (setq org-cycle-global-status 'overview) + (run-hook-with-args 'org-cycle-hook 'overview)))) + + ((integerp arg) + ;; Show-subtree, ARG levels up from here. + (save-excursion + (org-back-to-heading) + (outline-up-heading (if (< arg 0) (- arg) + (- (funcall outline-level) arg))) + (org-show-subtree))) + + ((save-excursion (beginning-of-line 1) (looking-at outline-regexp)) + ;; At a heading: rotate between three different views + (org-back-to-heading) + (let ((goal-column 0) eoh eol eos) + ;; First, some boundaries + (save-excursion + (org-back-to-heading) + (save-excursion + (beginning-of-line 2) + (while (and (not (eobp)) ;; this is like `next-line' + (get-char-property (1- (point)) 'invisible)) + (beginning-of-line 2)) (setq eol (point))) + (outline-end-of-heading) (setq eoh (point)) + (org-end-of-subtree t) (setq eos (point)) + (outline-next-heading)) + ;; Find out what to do next and set `this-command' + (cond + ((= eos eoh) + ;; Nothing is hidden behind this heading + (message "EMPTY ENTRY") + (setq org-cycle-subtree-status nil)) + ((>= eol eos) + ;; Entire subtree is hidden in one line: open it + (org-show-entry) + (show-children) + (message "CHILDREN") + (setq org-cycle-subtree-status 'children) + (run-hook-with-args 'org-cycle-hook 'children)) + ((and (eq last-command this-command) + (eq org-cycle-subtree-status 'children)) + ;; We just showed the children, now show everything. + (org-show-subtree) + (message "SUBTREE") + (setq org-cycle-subtree-status 'subtree) + (run-hook-with-args 'org-cycle-hook 'subtree)) + (t + ;; Default action: hide the subtree. + (hide-subtree) + (message "FOLDED") + (setq org-cycle-subtree-status 'folded) + (run-hook-with-args 'org-cycle-hook 'folded))))) + + ;; TAB emulation + (buffer-read-only (org-back-to-heading)) + ((if (and (eq org-cycle-emulate-tab 'white) + (save-excursion (beginning-of-line 1) (looking-at "[ \t]+$"))) + t + (eq org-cycle-emulate-tab t)) + (if (and (looking-at "[ \n\r\t]") + (string-match "^[ \t]*$" (buffer-substring + (point-at-bol) (point)))) + (progn + (beginning-of-line 1) + (and (looking-at "[ \t]+") (replace-match "")))) + (indent-relative)) + + (t (save-excursion + (org-back-to-heading) + (org-cycle)))))) + +(defun org-optimize-window-after-visibility-change (state) + "Adjust the window after a change in outline visibility. +This function is the default value of the hook `org-cycle-hook'." + (cond + ((eq state 'overview) (org-first-headline-recenter 1)) + ((eq state 'content) nil) + ((eq state 'all) nil) + ((eq state 'folded) nil) + ((eq state 'children) (or (org-subtree-end-visible-p) (recenter 1))) + ((eq state 'subtree) (or (org-subtree-end-visible-p) (recenter 1))))) + +(defun org-subtree-end-visible-p () + "Is the end of the current subtree visible?" + (pos-visible-in-window-p + (save-excursion (org-end-of-subtree t) (point)))) + +(defun org-first-headline-recenter (&optional N) + "Move cursor to the first headline and recenter the headline. +Optional argument N means, put the headline into the Nth line of the window." + (goto-char (point-min)) + (when (re-search-forward (concat "^" outline-regexp) nil t) + (beginning-of-line) + (recenter (prefix-numeric-value N)))) + +(defvar org-goto-window-configuration nil) +(defvar org-goto-marker nil) +(defvar org-goto-map (make-sparse-keymap)) +(let ((cmds '(isearch-forward isearch-backward)) cmd) + (while (setq cmd (pop cmds)) + (substitute-key-definition cmd cmd org-goto-map global-map))) +(define-key org-goto-map "\C-m" 'org-goto-ret) +(define-key org-goto-map [(left)] 'org-goto-left) +(define-key org-goto-map [(right)] 'org-goto-right) +(define-key org-goto-map [(?q)] 'org-goto-quit) +(define-key org-goto-map [(control ?g)] 'org-goto-quit) +(define-key org-goto-map "\C-i" 'org-cycle) +(define-key org-goto-map [(tab)] 'org-cycle) +(define-key org-goto-map [(down)] 'outline-next-visible-heading) +(define-key org-goto-map [(up)] 'outline-previous-visible-heading) +(define-key org-goto-map "n" 'outline-next-visible-heading) +(define-key org-goto-map "p" 'outline-previous-visible-heading) +(define-key org-goto-map "f" 'outline-forward-same-level) +(define-key org-goto-map "b" 'outline-backward-same-level) +(define-key org-goto-map "u" 'outline-up-heading) +(define-key org-goto-map "\C-c\C-n" 'outline-next-visible-heading) +(define-key org-goto-map "\C-c\C-p" 'outline-previous-visible-heading) +(define-key org-goto-map "\C-c\C-f" 'outline-forward-same-level) +(define-key org-goto-map "\C-c\C-b" 'outline-backward-same-level) +(define-key org-goto-map "\C-c\C-u" 'outline-up-heading) +(let ((l '(1 2 3 4 5 6 7 8 9 0))) + (while l (define-key org-goto-map (int-to-string (pop l)) 'digit-argument))) + +(defconst org-goto-help +"Select a location to jump to, press RET +\[Up]/[Down]=next/prev headline TAB=cycle visibility RET=select [Q]uit") + +(defun org-goto () + "Go to a different location of the document, keeping current visibility. + +When you want to go to a different location in a document, the fastest way +is often to fold the entire buffer and then dive into the tree. This +method has the disadvantage, that the previous location will be folded, +which may not be what you want. + +This command works around this by showing a copy of the current buffer in +overview mode. You can dive into the tree in that copy, to find the +location you want to reach. When pressing RET, the command returns to the +original buffer in which the visibility is still unchanged. It then jumps +to the new location, making it and the headline hierarchy above it visible." + (interactive) + (let* ((org-goto-start-pos (point)) + (selected-point + (org-get-location (current-buffer) org-goto-help))) + (if selected-point + (progn + (org-mark-ring-push org-goto-start-pos) + (goto-char selected-point) + (if (or (org-invisible-p) (org-invisible-p2)) + (org-show-hierarchy-above))) + (error "Quit")))) + +(defun org-get-location (buf help) + "Let the user select a location in the Org-mode buffer BUF. +This function uses a recursive edit. It returns the selected position +or nil." + (let (org-selected-point) + (save-excursion + (save-window-excursion + (delete-other-windows) + (switch-to-buffer (get-buffer-create "*org-goto*")) + (with-output-to-temp-buffer "*Help*" + (princ help)) + (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*")) + (setq buffer-read-only nil) + (erase-buffer) + (insert-buffer-substring buf) + (let ((org-startup-truncated t) + (org-startup-folded t) + (org-startup-with-deadline-check nil)) + (org-mode)) + (setq buffer-read-only t) + (if (boundp 'org-goto-start-pos) + (goto-char org-goto-start-pos) + (goto-char (point-min))) + (org-beginning-of-line) + (message "Select location and press RET") + ;; now we make sure that during selection, ony very few keys work + ;; and that it is impossible to switch to another window. + (let ((gm (current-global-map)) + (overriding-local-map org-goto-map)) + (unwind-protect + (progn + (use-global-map org-goto-map) + (recursive-edit)) + (use-global-map gm))))) + (kill-buffer "*org-goto*") + org-selected-point)) + +;; FIXME: It may not be a good idea to temper with the prefix argument... +(defun org-goto-ret (&optional arg) + "Finish `org-goto' by going to the new location." + (interactive "P") + (setq org-selected-point (point) + current-prefix-arg arg) + (throw 'exit nil)) + +(defun org-goto-left () + "Finish `org-goto' by going to the new location." + (interactive) + (if (org-on-heading-p) + (progn + (beginning-of-line 1) + (setq org-selected-point (point) + current-prefix-arg (- (match-end 0) (match-beginning 0))) + (throw 'exit nil)) + (error "Not on a heading"))) + +(defun org-goto-right () + "Finish `org-goto' by going to the new location." + (interactive) + (if (org-on-heading-p) + (progn + (outline-end-of-subtree) + (or (eobp) (forward-char 1)) + (setq org-selected-point (point) + current-prefix-arg (- (match-end 0) (match-beginning 0))) + (throw 'exit nil)) + (error "Not on a heading"))) + +(defun org-goto-quit () + "Finish `org-goto' without cursor motion." + (interactive) + (setq org-selected-point nil) + (throw 'exit nil)) + +;;; Promotion, Demotion, Inserting new headlines + +(defvar org-ignore-region nil + "To temporarily disable the active region.") + +(defun org-insert-heading (&optional force-heading) + "Insert a new heading or item with same depth at point." + (interactive "P") + (when (or force-heading (not (org-insert-item))) + (let* ((head (save-excursion + (condition-case nil + (org-back-to-heading) + (error (outline-next-heading))) + (prog1 (match-string 0) + (funcall outline-level))))) + (unless (bolp) (newline)) + (insert head) + (unless (eolp) + (save-excursion (newline-and-indent))) + (unless (equal (char-before) ?\ ) + (insert " ")) + (run-hooks 'org-insert-heading-hook)))) + +(defun org-insert-item () + "Insert a new item at the current level. +Return t when things worked, nil when we are not in an item." + (when (save-excursion + (condition-case nil + (progn + (org-beginning-of-item) + (org-at-item-p) + t) + (error nil))) + (unless (bolp) (newline)) + (insert (match-string 0)) + (org-maybe-renumber-ordered-list) + t)) + +(defun org-insert-todo-heading (arg) + "Insert a new heading with the same level and TODO state as current heading. +If the heading has no TODO state, or if the state is DONE, use the first +state (TODO by default). Also with prefix arg, force first state." + (interactive "P") + (org-insert-heading) + (save-excursion + (org-back-to-heading) + (outline-previous-heading) + (looking-at org-todo-line-regexp)) + (if (or arg + (not (match-beginning 2)) + (equal (match-string 2) org-done-string)) + (insert (car org-todo-keywords) " ") + (insert (match-string 2) " "))) + +(defun org-promote-subtree () + "Promote the entire subtree. +See also `org-promote'." + (interactive) + (save-excursion + (org-map-tree 'org-promote))) + +(defun org-demote-subtree () + "Demote the entire subtree. See `org-demote'. +See also `org-promote'." + (interactive) + (save-excursion + (org-map-tree 'org-demote))) + +(defun org-do-promote () + "Promote the current heading higher up the tree. +If the region is active in `transient-mark-mode', promote all headings +in the region." + (interactive) + (save-excursion + (if (org-region-active-p) + (org-map-region 'org-promote (region-beginning) (region-end)) + (org-promote))) + (org-fix-position-after-promote)) + +(defun org-do-demote () + "Demote the current heading lower down the tree. +If the region is active in `transient-mark-mode', demote all headings +in the region." + (interactive) + (save-excursion + (if (org-region-active-p) + (org-map-region 'org-demote (region-beginning) (region-end)) + (org-demote))) + (org-fix-position-after-promote)) + +(defun org-fix-position-after-promote () + "Make sure that after pro/demotion cursor position is right." + (and (equal (char-after) ?\ ) + (equal (char-before) ?*) + (forward-char 1))) + +(defun org-get-legal-level (level change) + "Rectify a level change under the influence of `org-odd-levels-only' +LEVEL is a current level, CHANGE is by how much the level should be +modified. Even if CHANGE is nil, LEVEL may be returned modified because +even level numbers will become the next higher odd number." + (if org-odd-levels-only + (cond ((not change) (1+ (* 2 (/ level 2)))) + ((> change 0) (1+ (* 2 (/ (+ level (* 2 change)) 2)))) + ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2)))))) + (max 1 (+ level change)))) + +(defun org-promote () + "Promote the current heading higher up the tree. +If the region is active in `transient-mark-mode', promote all headings +in the region." + (org-back-to-heading t) + (let* ((level (save-match-data (funcall outline-level))) + (up-head (make-string (org-get-legal-level level -1) ?*)) + (diff (abs (- level (length up-head))))) + (if (= level 1) (error "Cannot promote to level 0. UNDO to recover")) + (replace-match up-head nil t) + ;; Fixup tag positioning + (and org-auto-align-tags (org-set-tags nil t)) + (if org-adapt-indentation + (org-fixup-indentation (if (> diff 1) "^ " "^ ") "" + (if (> diff 1) "^ ? ?\\S-" "^ ?\\S-"))))) + +(defun org-demote () + "Demote the current heading lower down the tree. +If the region is active in `transient-mark-mode', demote all headings +in the region." + (org-back-to-heading t) + (let* ((level (save-match-data (funcall outline-level))) + (down-head (make-string (org-get-legal-level level 1) ?*)) + (diff (abs (- level (length down-head))))) + (replace-match down-head nil t) + ;; Fixup tag positioning + (and org-auto-align-tags (org-set-tags nil t)) + (if org-adapt-indentation + (org-fixup-indentation "^ " (if (> diff 1) " " " ") "^\\S-")))) + +(defun org-map-tree (fun) + "Call FUN for every heading underneath the current one." + (org-back-to-heading) + (let ((level (funcall outline-level))) + (save-excursion + (funcall fun) + (while (and (progn + (outline-next-heading) + (> (funcall outline-level) level)) + (not (eobp))) + (funcall fun))))) + +(defun org-map-region (fun beg end) + "Call FUN for every heading between BEG and END." + (let ((org-ignore-region t)) + (save-excursion + (setq end (copy-marker end)) + (goto-char beg) + (if (and (re-search-forward (concat "^" outline-regexp) nil t) + (< (point) end)) + (funcall fun)) + (while (and (progn + (outline-next-heading) + (< (point) end)) + (not (eobp))) + (funcall fun))))) + +(defun org-fixup-indentation (from to prohibit) + "Change the indentation in the current entry by re-replacing FROM with TO. +However, if the regexp PROHIBIT matches at all, don't do anything. +This is being used to change indentation along with the length of the +heading marker. But if there are any lines which are not indented, nothing +is changed at all." + (save-excursion + (let ((end (save-excursion (outline-next-heading) + (point-marker)))) + (unless (save-excursion (re-search-forward prohibit end t)) + (while (re-search-forward from end t) + (replace-match to) + (beginning-of-line 2))) + (move-marker end nil)))) + +;;; Vertical tree motion, cutting and pasting of subtrees + +(defun org-move-subtree-up (&optional arg) + "Move the current subtree up past ARG headlines of the same level." + (interactive "p") + (org-move-subtree-down (- (prefix-numeric-value arg)))) + +(defun org-move-subtree-down (&optional arg) + "Move the current subtree down past ARG headlines of the same level." + (interactive "p") + (setq arg (prefix-numeric-value arg)) + (let ((movfunc (if (> arg 0) 'outline-get-next-sibling + 'outline-get-last-sibling)) + (ins-point (make-marker)) + (cnt (abs arg)) + beg end txt folded) + ;; Select the tree + (org-back-to-heading) + (setq beg (point)) + (save-match-data + (save-excursion (outline-end-of-heading) + (setq folded (org-invisible-p))) + (outline-end-of-subtree)) + (outline-next-heading) + (setq end (point)) + ;; Find insertion point, with error handling + (goto-char beg) + (while (> cnt 0) + (or (and (funcall movfunc) (looking-at outline-regexp)) + (progn (goto-char beg) + (error "Cannot move past superior level or buffer limit"))) + (setq cnt (1- cnt))) + (if (> arg 0) + ;; Moving forward - still need to move over subtree + (progn (outline-end-of-subtree) + (outline-next-heading) + (if (not (or (looking-at (concat "^" outline-regexp)) + (bolp))) + (newline)))) + (move-marker ins-point (point)) + (setq txt (buffer-substring beg end)) + (delete-region beg end) + (insert txt) + (goto-char ins-point) + (if folded (hide-subtree)) + (move-marker ins-point nil))) + +(defvar org-subtree-clip "" + "Clipboard for cut and paste of subtrees. +This is actually only a copy of the kill, because we use the normal kill +ring. We need it to check if the kill was created by `org-copy-subtree'.") + +(defvar org-subtree-clip-folded nil + "Was the last copied subtree folded? +This is used to fold the tree back after pasting.") + +(defun org-cut-subtree () + "Cut the current subtree into the clipboard. +This is a short-hand for marking the subtree and then cutting it." + (interactive) + (org-copy-subtree 'cut)) + +(defun org-copy-subtree (&optional cut) + "Cut the current subtree into the clipboard. +This is a short-hand for marking the subtree and then copying it. +If CUT is non nil, actually cut the subtree." + (interactive) + (let (beg end folded) + (org-back-to-heading) + (setq beg (point)) + (save-match-data + (save-excursion (outline-end-of-heading) + (setq folded (org-invisible-p))) + (outline-end-of-subtree)) + (if (equal (char-after) ?\n) (forward-char 1)) + (setq end (point)) + (goto-char beg) + (when (> end beg) + (setq org-subtree-clip-folded folded) + (if cut (kill-region beg end) (copy-region-as-kill beg end)) + (setq org-subtree-clip (current-kill 0)) + (message "%s: Subtree with %d characters" + (if cut "Cut" "Copied") + (length org-subtree-clip))))) + +(defun org-paste-subtree (&optional level tree) + "Paste the clipboard as a subtree, with modification of headline level. +The entire subtree is promoted or demoted in order to match a new headline +level. By default, the new level is derived from the visible headings +before and after the insertion point, and taken to be the inferior headline +level of the two. So if the previous visible heading is level 3 and the +next is level 4 (or vice versa), level 4 will be used for insertion. +This makes sure that the subtree remains an independent subtree and does +not swallow low level entries. + +You can also force a different level, either by using a numeric prefix +argument, or by inserting the heading marker by hand. For example, if the +cursor is after \"*****\", then the tree will be shifted to level 5. + +If you want to insert the tree as is, just use \\[yank]. + +If optional TREE is given, use this text instead of the kill ring." + (interactive "P") + (unless (org-kill-is-subtree-p tree) + (error + (substitute-command-keys + "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway"))) + (let* ((txt (or tree (current-kill 0))) + (^re (concat "^\\(" outline-regexp "\\)")) + (re (concat "\\(" outline-regexp "\\)")) + (^re_ (concat "\\(" outline-regexp "\\)[ \t]*")) + + (old-level (if (string-match ^re txt) + (- (match-end 0) (match-beginning 0)) + -1)) + (force-level (cond (level (prefix-numeric-value level)) + ((string-match + ^re_ (buffer-substring (point-at-bol) (point))) + (- (match-end 0) (match-beginning 0))) + (t nil))) + (previous-level (save-excursion + (condition-case nil + (progn + (outline-previous-visible-heading 1) + (if (looking-at re) + (- (match-end 0) (match-beginning 0)) + 1)) + (error 1)))) + (next-level (save-excursion + (condition-case nil + (progn + (outline-next-visible-heading 1) + (if (looking-at re) + (- (match-end 0) (match-beginning 0)) + 1)) + (error 1)))) + (new-level (or force-level (max previous-level next-level))) + (shift (if (or (= old-level -1) + (= new-level -1) + (= old-level new-level)) + 0 + (- new-level old-level))) + (shift1 shift) + (delta (if (> shift 0) -1 1)) + (func (if (> shift 0) 'org-demote 'org-promote)) + (org-odd-levels-only nil) + beg end) + ;; Remove the forces level indicator + (if force-level + (delete-region (point-at-bol) (point))) + ;; Make sure we start at the beginning of an empty line + (if (not (bolp)) (insert "\n")) + (if (not (looking-at "[ \t]*$")) + (progn (insert "\n") (backward-char 1))) + ;; Paste + (setq beg (point)) + (insert txt) + (setq end (point)) + (goto-char beg) + ;; Shift if necessary + (if (= shift 0) + (message "Pasted at level %d, without shift" new-level) + (save-restriction + (narrow-to-region beg end) + (while (not (= shift 0)) + (org-map-region func (point-min) (point-max)) + (setq shift (+ delta shift))) + (goto-char (point-min)) + (message "Pasted at level %d, with shift by %d levels" + new-level shift1))) + (if (and (eq org-subtree-clip (current-kill 0)) + org-subtree-clip-folded) + ;; The tree was folded before it was killed/copied + (hide-subtree)))) + +(defun org-kill-is-subtree-p (&optional txt) + "Check if the current kill is an outline subtree, or a set of trees. +Returns nil if kill does not start with a headline, or if the first +headline level is not the largest headline level in the tree. +So this will actually accept several entries of equal levels as well, +which is OK for `org-paste-subtree'. +If optional TXT is given, check this string instead of the current kill." + (let* ((kill (or txt (current-kill 0) "")) + (start-level (and (string-match (concat "\\`" outline-regexp) kill) + (- (match-end 0) (match-beginning 0)))) + (re (concat "^" outline-regexp)) + (start 1)) + (if (not start-level) + nil ;; does not even start with a heading + (catch 'exit + (while (setq start (string-match re kill (1+ start))) + (if (< (- (match-end 0) (match-beginning 0)) start-level) + (throw 'exit nil))) + t)))) + +;;; Plain list items + +(defun org-at-item-p () + "Is point in a line starting a hand-formatted item?" + (let ((llt org-plain-list-ordered-item-terminator)) + (save-excursion + (goto-char (point-at-bol)) + (looking-at + (cond + ((eq llt t) "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)") + ((= llt ?.) "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)") + ((= llt ?\)) "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)") + (t (error "Invalid value of `org-plain-list-ordered-item-terminator'"))))))) + +(defun org-get-indentation () + "Get the indentation of the current line, interpreting tabs." + (save-excursion + (beginning-of-line 1) + (skip-chars-forward " \t") + (current-column))) + +(defun org-beginning-of-item () + "Go to the beginning of the current hand-formatted item. +If the cursor is not in an item, throw an error." + (let ((pos (point)) + (limit (save-excursion (org-back-to-heading) + (beginning-of-line 2) (point))) + ind ind1) + (if (org-at-item-p) + (beginning-of-line 1) + (beginning-of-line 1) + (skip-chars-forward " \t") + (setq ind (current-column)) + (if (catch 'exit + (while t + (beginning-of-line 0) + (if (< (point) limit) (throw 'exit nil)) + (unless (looking-at " \t]*$") + (skip-chars-forward " \t") + (setq ind1 (current-column)) + (if (< ind1 ind) + (throw 'exit (org-at-item-p)))))) + nil + (goto-char pos) + (error "Not in an item"))))) + +(defun org-end-of-item () + "Go to the end of the current hand-formatted item. +If the cursor is not in an item, throw an error." + (let ((pos (point)) + (limit (save-excursion (outline-next-heading) (point))) + (ind (save-excursion + (org-beginning-of-item) + (skip-chars-forward " \t") + (current-column))) + ind1) + (if (catch 'exit + (while t + (beginning-of-line 2) + (if (>= (point) limit) (throw 'exit t)) + (unless (looking-at "[ \t]*$") + (skip-chars-forward " \t") + (setq ind1 (current-column)) + (if (<= ind1 ind) (throw 'exit t))))) + (beginning-of-line 1) + (goto-char pos) + (error "Not in an item")))) + +(defun org-move-item-down (arg) + "Move the plain list item at point down, i.e. swap with following item. +Subitems (items with larger indentation) are considered part of the item, +so this really moves item trees." + (interactive "p") + (let (beg end ind ind1 (pos (point)) txt) + (org-beginning-of-item) + (setq beg (point)) + (setq ind (org-get-indentation)) + (org-end-of-item) + (setq end (point)) + (setq ind1 (org-get-indentation)) + (if (and (org-at-item-p) (= ind ind1)) + (progn + (org-end-of-item) + (setq txt (buffer-substring beg end)) + (save-excursion + (delete-region beg end)) + (setq pos (point)) + (insert txt) + (goto-char pos) + (org-maybe-renumber-ordered-list)) + (goto-char pos) + (error "Cannot move this item further down")))) + +(defun org-move-item-up (arg) + "Move the plain list item at point up, i.e. swap with previous item. +Subitems (items with larger indentation) are considered part of the item, +so this really moves item trees." + (interactive "p") + (let (beg end ind ind1 (pos (point)) txt) + (org-beginning-of-item) + (setq beg (point)) + (setq ind (org-get-indentation)) + (org-end-of-item) + (setq end (point)) + (goto-char beg) + (catch 'exit + (while t + (beginning-of-line 0) + (if (looking-at "[ \t]*$") + nil + (if (<= (setq ind1 (org-get-indentation)) ind) + (throw 'exit t))))) + (condition-case nil + (org-beginning-of-item) + (error (goto-char beg) + (error "Cannot move this item further up"))) + (setq ind1 (org-get-indentation)) + (if (and (org-at-item-p) (= ind ind1)) + (progn + (setq txt (buffer-substring beg end)) + (save-excursion + (delete-region beg end)) + (setq pos (point)) + (insert txt) + (goto-char pos) + (org-maybe-renumber-ordered-list)) + (goto-char pos) + (error "Cannot move this item further up")))) + +(defun org-maybe-renumber-ordered-list () + "Renumber the ordered list at point if setup allows it. +This tests the user option `org-auto-renumber-ordered-lists' before +doing the renumbering." + (and org-auto-renumber-ordered-lists + (org-at-item-p) + (match-beginning 3) + (org-renumber-ordered-list 1))) + +(defun org-get-string-indentation (s) + "What indentation has S due to SPACE and TAB at the beginning of the string?" + (let ((n -1) (i 0) (w tab-width) c) + (catch 'exit + (while (< (setq n (1+ n)) (length s)) + (setq c (aref s n)) + (cond ((= c ?\ ) (setq i (1+ i))) + ((= c ?\t) (setq i (* (/ (+ w i) w) w))) + (t (throw 'exit t))))) + i)) + +(defun org-renumber-ordered-list (arg) + "Renumber an ordered plain list. +Cursor next to be in the first line of an item, the line that starts +with something like \"1.\" or \"2)\"." + (interactive "p") + (unless (and (org-at-item-p) + (match-beginning 3)) + (error "This is not an ordered list")) + (let ((line (org-current-line)) + (col (current-column)) + (ind (org-get-string-indentation + (buffer-substring (point-at-bol) (match-beginning 3)))) + ;; (term (substring (match-string 3) -1)) + ind1 (n (1- arg))) + ;; find where this list begins + (catch 'exit + (while t + (catch 'next + (beginning-of-line 0) + (if (looking-at "[ \t]*$") (throw 'next t)) + (skip-chars-forward " \t") (setq ind1 (current-column)) + (if (or (< ind1 ind) + (and (= ind1 ind) + (not (org-at-item-p)))) + (throw 'exit t))))) + ;; Walk forward and replace these numbers + (catch 'exit + (while t + (catch 'next + (beginning-of-line 2) + (if (eobp) (throw 'exit nil)) + (if (looking-at "[ \t]*$") (throw 'next nil)) + (skip-chars-forward " \t") (setq ind1 (current-column)) + (if (> ind1 ind) (throw 'next t)) + (if (< ind1 ind) (throw 'exit t)) + (if (not (org-at-item-p)) (throw 'exit nil)) + (if (not (match-beginning 3)) + (error "unordered bullet in ordered list. Press \\[undo] to recover")) + (delete-region (match-beginning 3) (1- (match-end 3))) + (goto-char (match-beginning 3)) + (insert (format "%d" (setq n (1+ n))))))) + (goto-line line) + (move-to-column col))) + +(defvar org-last-indent-begin-marker (make-marker)) +(defvar org-last-indent-end-marker (make-marker)) + +(defun org-outdent-item (arg) + "Outdent a local list item." + (interactive "p") + (org-indent-item (- arg))) + +(defun org-indent-item (arg) + "Indent a local list item." + (interactive "p") + (unless (org-at-item-p) + (error "Not on an item")) + (let (beg end ind ind1) + (if (memq last-command '(org-shiftmetaright org-shiftmetaleft)) + (setq beg org-last-indent-begin-marker + end org-last-indent-end-marker) + (org-beginning-of-item) + (setq beg (move-marker org-last-indent-begin-marker (point))) + (org-end-of-item) + (setq end (move-marker org-last-indent-end-marker (point)))) + (goto-char beg) + (skip-chars-forward " \t") (setq ind (current-column)) + (if (< (+ arg ind) 0) (error "Cannot outdent beyond margin")) + (while (< (point) end) + (beginning-of-line 1) + (skip-chars-forward " \t") (setq ind1 (current-column)) + (delete-region (point-at-bol) (point)) + (indent-to-column (+ ind1 arg)) + (beginning-of-line 2)) + (goto-char beg))) + +;;; Archiving + +(defun org-archive-subtree () + "Move the current subtree to the archive. +The archive can be a certain top-level heading in the current file, or in +a different file. The tree will be moved to that location, the subtree +heading be marked DONE, and the current time will be added." + (interactive) + ;; Save all relevant TODO keyword-relatex variables + (let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler + (tr-org-todo-keywords org-todo-keywords) + (tr-org-todo-interpretation org-todo-interpretation) + (tr-org-done-string org-done-string) + (tr-org-todo-regexp org-todo-regexp) + (tr-org-todo-line-regexp org-todo-line-regexp) + (this-buffer (current-buffer)) + file heading buffer level newfile-p) + (if (string-match "\\(.*\\)::\\(.*\\)" org-archive-location) + (progn + (setq file (format (match-string 1 org-archive-location) + (file-name-nondirectory buffer-file-name)) + heading (match-string 2 org-archive-location))) + (error "Invalid `org-archive-location'")) + (if (> (length file) 0) + (setq newfile-p (not (file-exists-p file)) + buffer (find-file-noselect file)) + (setq buffer (current-buffer))) + (unless buffer + (error "Cannot access file \"%s\"" file)) + (if (and (> (length heading) 0) + (string-match "^\\*+" heading)) + (setq level (match-end 0)) + (setq heading nil level 0)) + (save-excursion + ;; We first only copy, in case something goes wrong + ;; we need to protect this-command, to avoid kill-region sets it, + ;; which would lead to duplication of subtrees + (let (this-command) (org-copy-subtree)) + (set-buffer buffer) + ;; Enforce org-mode for the archive buffer + (if (not (eq major-mode 'org-mode)) + ;; Force the mode for future visits. + (let ((org-insert-mode-line-in-empty-file t)) + (call-interactively 'org-mode))) + (when newfile-p + (goto-char (point-max)) + (insert (format "\nArchived entries from file %s\n\n" + (buffer-file-name this-buffer)))) + ;; Force the TODO keywords of the original buffer + (let ((org-todo-line-regexp tr-org-todo-line-regexp) + (org-todo-keywords tr-org-todo-keywords) + (org-todo-interpretation tr-org-todo-interpretation) + (org-done-string tr-org-done-string) + (org-todo-regexp tr-org-todo-regexp) + (org-todo-line-regexp tr-org-todo-line-regexp)) + (goto-char (point-min)) + (if heading + (progn + (if (re-search-forward + (concat "\\(^\\|\r\\)" + (regexp-quote heading) "[ \t]*\\($\\|\r\\)") + nil t) + (goto-char (match-end 0)) + ;; Heading not found, just insert it at the end + (goto-char (point-max)) + (or (bolp) (insert "\n")) + (insert "\n" heading "\n") + (end-of-line 0)) + ;; Make the heading visible, and the following as well + (let ((org-show-following-heading t)) (org-show-hierarchy-above)) + (if (re-search-forward + (concat "^" (regexp-quote (make-string level ?*)) "[ \t]") + nil t) + (progn (goto-char (match-beginning 0)) (insert "\n") + (beginning-of-line 0)) + (goto-char (point-max)) (insert "\n"))) + (goto-char (point-max)) (insert "\n")) + ;; Paste + (org-paste-subtree (1+ level)) + ;; Mark the entry as done, i.e. set to last work in org-todo-keywords + (if org-archive-mark-done + (org-todo (length org-todo-keywords))) + ;; Move cursor to right after the TODO keyword + (when org-archive-stamp-time + (beginning-of-line 1) + (looking-at org-todo-line-regexp) + (goto-char (or (match-end 2) (match-beginning 3))) + (insert "(" (format-time-string (cdr org-time-stamp-formats) + (org-current-time)) + ")")) + ;; Save the buffer, if it is not the same buffer. + (if (not (eq this-buffer buffer)) (save-buffer)))) + ;; Here we are back in the original buffer. Everything seems to have + ;; worked. So now cut the tree and finish up. + (let (this-command) (org-cut-subtree)) + (if (looking-at "[ \t]*$") (kill-line)) + (message "Subtree archived %s" + (if (eq this-buffer buffer) + (concat "under heading: " heading) + (concat "in file: " (abbreviate-file-name file)))))) + +;;; Completion + +(defun org-complete (&optional arg) + "Perform completion on word at point. +At the beginning of a headline, this completes TODO keywords as given in +`org-todo-keywords'. +If the current word is preceded by a backslash, completes the TeX symbols +that are supported for HTML support. +If the current word is preceded by \"#+\", completes special words for +setting file options. +At all other locations, this simply calls `ispell-complete-word'." + (interactive "P") + (catch 'exit + (let* ((end (point)) + (beg1 (save-excursion + (if (equal (char-before (point)) ?\ ) (backward-char 1)) + (skip-chars-backward "a-zA-Z_@0-9") + (point))) + (beg (save-excursion + (if (equal (char-before (point)) ?\ ) (backward-char 1)) + (skip-chars-backward "a-zA-Z0-9_:$") + (point))) + (camel (equal (char-before beg) ?*)) + (tag (equal (char-before beg1) ?:)) + (texp (equal (char-before beg) ?\\)) + (opt (equal (buffer-substring (max (point-at-bol) (- beg 2)) + beg) + "#+")) + (completion-ignore-case opt) + (type nil) + (tbl nil) + (table (cond + (opt + (setq type :opt) + (mapcar (lambda (x) + (string-match "^#\\+\\(\\([A-Z_]+:?\\).*\\)" x) + (cons (match-string 2 x) (match-string 1 x))) + (org-split-string (org-get-current-options) "\n"))) + (texp + (setq type :tex) + org-html-entities) + ((string-match "\\`\\*+[ \t]*\\'" + (buffer-substring (point-at-bol) beg)) + (setq type :todo) + (mapcar 'list org-todo-keywords)) + (camel + (setq type :camel) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward org-todo-line-regexp nil t) + (push (list + (if org-file-link-context-use-camel-case + (org-make-org-heading-camel (match-string 3) t) + (org-make-org-heading-search-string + (match-string 3) t))) + tbl))) + tbl) + (tag (setq type :tag beg beg1) + (org-get-buffer-tags)) + (t (progn (ispell-complete-word arg) (throw 'exit nil))))) + (pattern (buffer-substring-no-properties beg end)) + (completion (try-completion pattern table))) + (cond ((eq completion t) + (if (equal type :opt) + (insert (substring (cdr (assoc (upcase pattern) table)) + (length pattern))))) + ((null completion) + (message "Can't find completion for \"%s\"" pattern) + (ding)) + ((not (string= pattern completion)) + (delete-region beg end) + (if (string-match " +$" completion) + (setq completion (replace-match "" t t completion))) + (insert completion) + (if (get-buffer-window "*Completions*") + (delete-window (get-buffer-window "*Completions*"))) + (if (assoc completion table) + (if (eq type :todo) (insert " ") + (if (eq type :tag) (insert ":")))) + (if (and (equal type :opt) (assoc completion table)) + (message "%s" (substitute-command-keys + "Press \\[org-complete] again to insert example settings")))) + (t + (message "Making completion list...") + (let ((list (sort (all-completions pattern table) 'string<))) + (with-output-to-temp-buffer "*Completions*" + (condition-case nil + ;; Protection needed for XEmacs and emacs 21 + (display-completion-list list pattern) + (error (display-completion-list list))))) + (message "Making completion list...%s" "done")))))) + +;;; Comments, TODO and DEADLINE + +(defun org-toggle-comment () + "Change the COMMENT state of an entry." + (interactive) + (save-excursion + (org-back-to-heading) + (if (looking-at (concat outline-regexp + "\\( +\\<" org-comment-string "\\>\\)")) + (replace-match "" t t nil 1) + (if (looking-at outline-regexp) + (progn + (goto-char (match-end 0)) + (insert " " org-comment-string)))))) + +(defvar org-last-todo-state-is-todo nil + "This is non-nil when the last TODO state change led to a TODO state. +If the last change removed the TODO tag or switched to DONE, then +this is nil.") + +(defun org-todo (&optional arg) + "Change the TODO state of an item. +The state of an item is given by a keyword at the start of the heading, +like + *** TODO Write paper + *** DONE Call mom + +The different keywords are specified in the variable `org-todo-keywords'. +By default the available states are \"TODO\" and \"DONE\". +So for this example: when the item starts with TODO, it is changed to DONE. +When it starts with DONE, the DONE is removed. And when neither TODO nor +DONE are present, add TODO at the beginning of the heading. + +With prefix arg, use completion to determine the new state. With numeric +prefix arg, switch to that state." + (interactive "P") + (save-excursion + (org-back-to-heading) + (if (looking-at outline-regexp) (goto-char (match-end 0))) + (or (looking-at (concat " +" org-todo-regexp " *")) + (looking-at " *")) + (let* ((this (match-string 1)) + (completion-ignore-case t) + (member (member this org-todo-keywords)) + (tail (cdr member)) + (state (cond + ((equal arg '(4)) + ;; Read a state with completion + (completing-read "State: " (mapcar (lambda(x) (list x)) + org-todo-keywords) + nil t)) + ((eq arg 'right) + (if this + (if tail (car tail) nil) + (car org-todo-keywords))) + ((eq arg 'left) + (if (equal member org-todo-keywords) + nil + (if this + (nth (- (length org-todo-keywords) (length tail) 2) + org-todo-keywords) + org-done-string))) + (arg + ;; user requests a specific state + (nth (1- (prefix-numeric-value arg)) + org-todo-keywords)) + ((null member) (car org-todo-keywords)) + ((null tail) nil) ;; -> first entry + ((eq org-todo-interpretation 'sequence) + (car tail)) + ((memq org-todo-interpretation '(type priority)) + (if (eq this-command last-command) + (car tail) + (if (> (length tail) 0) org-done-string nil))) + (t nil))) + (next (if state (concat " " state " ") " "))) + (replace-match next t t) + (setq org-last-todo-state-is-todo + (not (equal state org-done-string))) + (when org-log-done + (if (equal state org-done-string) + (org-log-done) + (if (not this) + (org-log-done t)))) + ;; Fixup tag positioning + (and org-auto-align-tags (org-set-tags nil t)) + (run-hooks 'org-after-todo-state-change-hook))) + ;; Fixup cursor location if close to the keyword + (if (and (outline-on-heading-p) + (not (bolp)) + (save-excursion (beginning-of-line 1) + (looking-at org-todo-line-regexp)) + (< (point) (+ 2 (or (match-end 2) (match-end 1))))) + (progn + (goto-char (or (match-end 2) (match-end 1))) + (just-one-space)))) + +(defun org-log-done (&optional undone) + "Add a time stamp logging that a TODO entry has been closed. +When UNDONE is non-nil, remove such a time stamp again." + (interactive) + (let (beg end col) + (save-excursion + (org-back-to-heading t) + (setq beg (point)) + (looking-at (concat outline-regexp " *")) + (goto-char (match-end 0)) + (setq col (current-column)) + (outline-next-heading) + (setq end (point)) + (goto-char beg) + (when (re-search-forward (concat + "[\r\n]\\([ \t]*" + (regexp-quote org-closed-string) + " *\\[.*?\\][^\n\r]*[\n\r]?\\)") end t) + (delete-region (match-beginning 1) (match-end 1))) + (unless undone + (org-back-to-heading t) + (skip-chars-forward "^\n\r") + (goto-char (min (1+ (point)) (point-max))) + (when (not (member (char-before) '(?\r ?\n))) + (insert "\n")) + (indent-to col) + (insert org-closed-string " " + (format-time-string + (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]") + (org-current-time)) + "\n"))))) + +(defun org-show-todo-tree (arg) + "Make a compact tree which shows all headlines marked with TODO. +The tree will show the lines where the regexp matches, and all higher +headlines above the match. +With \\[universal-argument] prefix, also show the DONE entries. +With a numeric prefix N, construct a sparse tree for the Nth element +of `org-todo-keywords'." + (interactive "P") + (let ((case-fold-search nil) + (kwd-re + (cond ((null arg) org-not-done-regexp) + ((equal arg '(4)) org-todo-regexp) + ((<= (prefix-numeric-value arg) (length org-todo-keywords)) + (regexp-quote (nth (1- (prefix-numeric-value arg)) + org-todo-keywords))) + (t (error "Invalid prefix argument: %s" arg))))) + (message "%d TODO entries found" + (org-occur (concat "^" outline-regexp " +" kwd-re ))))) + +(defun org-deadline () + "Insert the DEADLINE: string to make a deadline. +A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down] +to modify it to the correct date." + (interactive) + (insert + org-deadline-string " " + (format-time-string (car org-time-stamp-formats) + (org-read-date nil 'to-time))) + (message "%s" (substitute-command-keys + "Use \\[org-timestamp-up-day] and \\[org-timestamp-down-day] to change the date."))) + +(defun org-schedule () + "Insert the SCHEDULED: string to schedule a TODO item. +A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down] +to modify it to the correct date." + (interactive) + (insert + org-scheduled-string " " + (format-time-string (car org-time-stamp-formats) + (org-read-date nil 'to-time))) + (message "%s" (substitute-command-keys + "Use \\[org-timestamp-up-day] and \\[org-timestamp-down-day] to change the date."))) + + +(defun org-occur (regexp &optional callback) + "Make a compact tree which shows all matches of REGEXP. +The tree will show the lines where the regexp matches, and all higher +headlines above the match. It will also show the heading after the match, +to make sure editing the matching entry is easy. +If CALLBACK is non-nil, it is a function which is called to confirm +that the match should indeed be shown." + (interactive "sRegexp: ") + (org-remove-occur-highlights nil nil t) + (setq regexp (org-check-occur-regexp regexp)) + (let ((cnt 0)) + (save-excursion + (goto-char (point-min)) + (hide-sublevels 1) + (while (re-search-forward regexp nil t) + (when (or (not callback) + (save-match-data (funcall callback))) + (setq cnt (1+ cnt)) + (org-highlight-new-match (match-beginning 0) (match-end 0)) + (org-show-hierarchy-above)))) + (org-add-hook 'before-change-functions 'org-remove-occur-highlights + nil 'local) + (run-hooks 'org-occur-hook) + (if (interactive-p) + (message "%d match(es) for regexp %s" cnt regexp)) + cnt)) + +(defun org-show-hierarchy-above () + "Make sure point and the headings hierarchy above is visible." + (catch 'exit + (if (org-on-heading-p t) + (org-flag-heading nil) ; only show the heading + (and (or (org-invisible-p) (org-invisible-p2)) + (org-show-hidden-entry))) ; show entire entry + (save-excursion + (and org-show-following-heading + (outline-next-heading) + (org-flag-heading nil))) ; show the next heading + (when org-show-hierarchy-above + (save-excursion ; show all higher headings + (while (and (condition-case nil + (progn (org-up-heading-all 1) t) + (error nil)) + (not (bobp))) + (org-flag-heading nil)))))) + +;; Overlay compatibility functions +(defun org-make-overlay (beg end &optional buffer) + (if org-xemacs-p (make-extent beg end buffer) (make-overlay beg end buffer))) +(defun org-delete-overlay (ovl) + (if org-xemacs-p (delete-extent ovl) (delete-overlay ovl))) +(defun org-detatch-overlay (ovl) + (if org-xemacs-p (detach-extent ovl) (delete-overlay ovl))) +(defun org-move-overlay (ovl beg end &optional buffer) + (if org-xemacs-p + (set-extent-endpoints ovl beg end buffer) + (move-overlay ovl beg end buffer))) +(defun org-overlay-put (ovl prop value) + (if org-xemacs-p + (set-extent-property ovl prop value) + (overlay-put ovl prop value))) + +(defvar org-occur-highlights nil) +(defun org-highlight-new-match (beg end) + "Highlight from BEG to END and mark the highlight is an occur headline." + (let ((ov (org-make-overlay beg end))) + (org-overlay-put ov 'face 'secondary-selection) + (push ov org-occur-highlights))) + +(defun org-remove-occur-highlights (&optional beg end noremove) + "Remove the occur highlights from the buffer. +BEG and END are ignored. If NOREMOVE is nil, remove this function +from the `before-change-functions' in the current buffer." + (interactive) + (mapc 'org-delete-overlay org-occur-highlights) + (setq org-occur-highlights nil) + (unless noremove + (remove-hook 'before-change-functions + 'org-remove-occur-highlights 'local))) + +;;; Priorities + +(defvar org-priority-regexp ".*?\\(\\[#\\([A-Z]\\)\\] ?\\)" + "Regular expression matching the priority indicator.") + +(defvar org-remove-priority-next-time nil) + +(defun org-priority-up () + "Increase the priority of the current item." + (interactive) + (org-priority 'up)) + +(defun org-priority-down () + "Decrease the priority of the current item." + (interactive) + (org-priority 'down)) + +(defun org-priority (&optional action) + "Change the priority of an item by ARG. +ACTION can be set, up, or down." + (interactive) + (setq action (or action 'set)) + (let (current new news have remove) + (save-excursion + (org-back-to-heading) + (if (looking-at org-priority-regexp) + (setq current (string-to-char (match-string 2)) + have t) + (setq current org-default-priority)) + (cond + ((eq action 'set) + (message "Priority A-%c, SPC to remove: " org-lowest-priority) + (setq new (read-char-exclusive)) + (cond ((equal new ?\ ) (setq remove t)) + ((or (< (upcase new) ?A) (> (upcase new) org-lowest-priority)) + (error "Priority must be between `%c' and `%c'" + ?A org-lowest-priority)))) + ((eq action 'up) + (setq new (1- current))) + ((eq action 'down) + (setq new (1+ current))) + (t (error "Invalid action"))) + (setq new (min (max ?A (upcase new)) org-lowest-priority)) + (setq news (format "%c" new)) + (if have + (if remove + (replace-match "" t t nil 1) + (replace-match news t t nil 2)) + (if remove + (error "No priority cookie found in line") + (looking-at org-todo-line-regexp) + (if (match-end 2) + (progn + (goto-char (match-end 2)) + (insert " [#" news "]")) + (goto-char (match-beginning 3)) + (insert "[#" news "] "))))) + (if remove + (message "Priority removed") + (message "Priority of current item set to %s" news)))) + + +(defun org-get-priority (s) + "Find priority cookie and return priority." + (save-match-data + (if (not (string-match org-priority-regexp s)) + (* 1000 (- org-lowest-priority org-default-priority)) + (* 1000 (- org-lowest-priority + (string-to-char (match-string 2 s))))))) + +;;; Timestamps + +(defvar org-last-changed-timestamp nil) + +(defun org-time-stamp (arg) + "Prompt for a date/time and insert a time stamp. +If the user specifies a time like HH:MM, or if this command is called +with a prefix argument, the time stamp will contain date and time. +Otherwise, only the date will be included. All parts of a date not +specified by the user will be filled in from the current date/time. +So if you press just return without typing anything, the time stamp +will represent the current date/time. If there is already a timestamp +at the cursor, it will be modified." + (interactive "P") + (let ((fmt (if arg (cdr org-time-stamp-formats) + (car org-time-stamp-formats))) + (org-time-was-given nil) + time) + (cond + ((and (org-at-timestamp-p) + (eq last-command 'org-time-stamp) + (eq this-command 'org-time-stamp)) + (insert "--") + (setq time (let ((this-command this-command)) + (org-read-date arg 'totime))) + (if org-time-was-given (setq fmt (cdr org-time-stamp-formats))) + (insert (format-time-string fmt time))) + ((org-at-timestamp-p) + (setq time (let ((this-command this-command)) + (org-read-date arg 'totime))) + (and (org-at-timestamp-p) (replace-match + (setq org-last-changed-timestamp + (format-time-string fmt time)) + t t)) + (message "Timestamp updated")) + (t + (setq time (let ((this-command this-command)) + (org-read-date arg 'totime))) + (if org-time-was-given (setq fmt (cdr org-time-stamp-formats))) + (insert (format-time-string fmt time)))))) + +(defun org-time-stamp-inactive (&optional arg) + "Insert an inactive time stamp. +An inactive time stamp is enclosed in square brackets instead of angle +brackets. It is inactive in the sense that it does not trigger agenda entries, +does not link to the calendar and cannot be changed with the S-cursor keys. +So these are more for recording a certain time/date." + ;; FIXME: Would it be better not to ask for a date/time here? + (interactive "P") + (let ((fmt (if arg (cdr org-time-stamp-formats) + (car org-time-stamp-formats))) + (org-time-was-given nil) + time) + (setq time (org-read-date arg 'totime)) + (if org-time-was-given (setq fmt (cdr org-time-stamp-formats))) + (setq fmt (concat "[" (substring fmt 1 -1) "]")) + (insert (format-time-string fmt time)))) + +(defvar org-date-ovl (org-make-overlay 1 1)) +(org-overlay-put org-date-ovl 'face 'org-warning) +(org-detatch-overlay org-date-ovl) + +;;; FIXME: Make the function take "Fri" as "next friday" +;;; because these are mostly being used to record the current time. +(defun org-read-date (&optional with-time to-time) + "Read a date and make things smooth for the user. +The prompt will suggest to enter an ISO date, but you can also enter anything +which will at least partially be understood by `parse-time-string'. +Unrecognized parts of the date will default to the current day, month, year, +hour and minute. For example, + 3-2-5 --> 2003-02-05 + feb 15 --> currentyear-02-15 + sep 12 9 --> 2009-09-12 + 12:45 --> today 12:45 + 22 sept 0:34 --> currentyear-09-22 0:34 + 12 --> currentyear-currentmonth-12 + etc. +The function understands only English month and weekday abbreviations, +but this can be configured with the variables `parse-time-months' and +`parse-time-weekdays'. + +While prompting, a calendar is popped up - you can also select the +date with the mouse (button 1). The calendar shows a period of three +months. To scroll it to other months, use the keys `>' and `<'. +If you don't like the calendar, turn it off with + \(setq org-popup-calendar-for-date-prompt nil) + +With optional argument TO-TIME, the date will immediately be converted +to an internal time. +With an optional argument WITH-TIME, the prompt will suggest to also +insert a time. Note that when WITH-TIME is not set, you can still +enter a time, and this function will inform the calling routine about +this change. The calling routine may then choose to change the format +used to insert the time stamp into the buffer to include the time." + (require 'parse-time) + (let* ((org-time-stamp-rounding-minutes + (if (equal with-time '(16)) 0 org-time-stamp-rounding-minutes)) + (ct (org-current-time)) + (default-time + ;; Default time is either today, or, when entering a range, + ;; the range start. + (if (save-excursion + (re-search-backward + (concat org-ts-regexp "--\\=") + (- (point) 20) t)) + (apply + 'encode-time + (mapcar (lambda(x) (or x 0)) ;; FIXME: Problem with timezone? + (parse-time-string (match-string 1)))) + ct)) + (calendar-move-hook nil) + (view-diary-entries-initially nil) + (timestr (format-time-string + (if with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") default-time)) + (prompt (format "YYYY-MM-DD [%s]: " timestr)) + ans ans1 ans2 + second minute hour day month year tl) + + (if org-popup-calendar-for-date-prompt + ;; Also show a calendar for date selection + ;; Copied (with modifications) from planner.el by John Wiegley + (save-excursion + (save-window-excursion + (calendar) + (calendar-forward-day (- (time-to-days default-time) + (calendar-absolute-from-gregorian + (calendar-current-date)))) + (org-eval-in-calendar nil) + (let* ((old-map (current-local-map)) + (map (copy-keymap calendar-mode-map)) + (minibuffer-local-map (copy-keymap minibuffer-local-map))) + (define-key map (kbd "RET") 'org-calendar-select) + (define-key map (if org-xemacs-p [button1] [mouse-1]) + 'org-calendar-select-mouse) + (define-key map (if org-xemacs-p [button2] [mouse-2]) + 'org-calendar-select-mouse) + (define-key minibuffer-local-map [(meta shift left)] + (lambda () (interactive) + (org-eval-in-calendar '(calendar-backward-month 1)))) + (define-key minibuffer-local-map [(meta shift right)] + (lambda () (interactive) + (org-eval-in-calendar '(calendar-forward-month 1)))) + (define-key minibuffer-local-map [(shift up)] + (lambda () (interactive) + (org-eval-in-calendar '(calendar-backward-week 1)))) + (define-key minibuffer-local-map [(shift down)] + (lambda () (interactive) + (org-eval-in-calendar '(calendar-forward-week 1)))) + (define-key minibuffer-local-map [(shift left)] + (lambda () (interactive) + (org-eval-in-calendar '(calendar-backward-day 1)))) + (define-key minibuffer-local-map [(shift right)] + (lambda () (interactive) + (org-eval-in-calendar '(calendar-forward-day 1)))) + (define-key minibuffer-local-map ">" + (lambda () (interactive) + (org-eval-in-calendar '(scroll-calendar-left 1)))) + (define-key minibuffer-local-map "<" + (lambda () (interactive) + (org-eval-in-calendar '(scroll-calendar-right 1)))) + (unwind-protect + (progn + (use-local-map map) + (setq ans (read-string prompt "" nil nil)) + (if (not (string-match "\\S-" ans)) (setq ans nil)) + (setq ans (or ans1 ans ans2))) + (use-local-map old-map))))) + ;; Naked prompt only + (setq ans (read-string prompt "" nil timestr))) + (org-detatch-overlay org-date-ovl) + + (if (string-match + "^ *\\(\\([0-9]+\\)-\\)?\\([0-1]?[0-9]\\)-\\([0-3]?[0-9]\\)\\([^-0-9]\\|$\\)" ans) + (progn + (setq year (if (match-end 2) + (string-to-number (match-string 2 ans)) + (string-to-number (format-time-string "%Y"))) + month (string-to-number (match-string 3 ans)) + day (string-to-number (match-string 4 ans))) + (if (< year 100) (setq year (+ 2000 year))) + (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day) + t nil ans)))) + (setq tl (parse-time-string ans) + year (or (nth 5 tl) (string-to-number (format-time-string "%Y" ct))) + month (or (nth 4 tl) (string-to-number (format-time-string "%m" ct))) + day (or (nth 3 tl) (string-to-number (format-time-string "%d" ct))) + hour (or (nth 2 tl) (string-to-number (format-time-string "%H" ct))) + minute (or (nth 1 tl) (string-to-number (format-time-string "%M" ct))) + second (or (nth 0 tl) 0)) + (if (and (boundp 'org-time-was-given) + (nth 2 tl)) + (setq org-time-was-given t)) + (if (< year 100) (setq year (+ 2000 year))) + (if to-time + (encode-time second minute hour day month year) + (if (or (nth 1 tl) (nth 2 tl)) + (format "%04d-%02d-%02d %02d:%02d" year month day hour minute) + (format "%04d-%02d-%02d" year month day))))) + +(defun org-eval-in-calendar (form) + "Eval FORM in the calendar window and return to current window. +Also, store the cursor date in variable ans2." + (let ((sw (selected-window))) + (select-window (get-buffer-window "*Calendar*")) + (eval form) + (when (calendar-cursor-to-date) + (let* ((date (calendar-cursor-to-date)) + (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date)))) + (setq ans2 (format-time-string "%Y-%m-%d" time)))) + (org-move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer)) + (select-window sw))) + +(defun org-calendar-select () + "Return to `org-read-date' with the date currently selected. +This is used by `org-read-date' in a temporary keymap for the calendar buffer." + (interactive) + (when (calendar-cursor-to-date) + (let* ((date (calendar-cursor-to-date)) + (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date)))) + (setq ans1 (format-time-string "%Y-%m-%d" time))) + (if (active-minibuffer-window) (exit-minibuffer)))) + +(defun org-calendar-select-mouse (ev) + "Return to `org-read-date' with the date currently selected. +This is used by `org-read-date' in a temporary keymap for the calendar buffer." + (interactive "e") + (mouse-set-point ev) + (when (calendar-cursor-to-date) + (let* ((date (calendar-cursor-to-date)) + (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date)))) + (setq ans1 (format-time-string "%Y-%m-%d" time))) + (if (active-minibuffer-window) (exit-minibuffer)))) + +(defun org-check-deadlines (ndays) + "Check if there are any deadlines due or past due. +A deadline is considered due if it happens within `org-deadline-warning-days' +days from today's date. If the deadline appears in an entry marked DONE, +it is not shown. The prefix arg NDAYS can be used to test that many +days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are shown." + (interactive "P") + (let* ((org-warn-days + (cond + ((equal ndays '(4)) 100000) + (ndays (prefix-numeric-value ndays)) + (t org-deadline-warning-days))) + (case-fold-search nil) + (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")) + (callback + (lambda () + (and (let ((d1 (time-to-days (current-time))) + (d2 (time-to-days + (org-time-string-to-time (match-string 1))))) + (< (- d2 d1) org-warn-days)) + (not (org-entry-is-done-p)))))) + (message "%d deadlines past-due or due within %d days" + (org-occur regexp callback) + org-warn-days))) + +(defun org-evaluate-time-range (&optional to-buffer) + "Evaluate a time range by computing the difference between start and end. +Normally the result is just printed in the echo area, but with prefix arg +TO-BUFFER, the result is inserted just after the date stamp into the buffer. +If the time range is actually in a table, the result is inserted into the +next column. +For time difference computation, a year is assumed to be exactly 365 +days in order to avoid rounding problems." + (interactive "P") + (save-excursion + (unless (org-at-date-range-p) + (goto-char (point-at-bol)) + (re-search-forward org-tr-regexp (point-at-eol) t)) + (if (not (org-at-date-range-p)) + (error "Not at a time-stamp range, and none found in current line"))) + (let* ((ts1 (match-string 1)) + (ts2 (match-string 2)) + (havetime (or (> (length ts1) 15) (> (length ts2) 15))) + (match-end (match-end 0)) + (time1 (org-time-string-to-time ts1)) + (time2 (org-time-string-to-time ts2)) + (t1 (time-to-seconds time1)) + (t2 (time-to-seconds time2)) + (diff (abs (- t2 t1))) + (negative (< (- t2 t1) 0)) + ;; (ys (floor (* 365 24 60 60))) + (ds (* 24 60 60)) + (hs (* 60 60)) + (fy "%dy %dd %02d:%02d") + (fy1 "%dy %dd") + (fd "%dd %02d:%02d") + (fd1 "%dd") + (fh "%02d:%02d") + y d h m align) + ;; FIXME: Should I re-introduce years, make year refer to same date? + ;; This would be the only useful way to have years, actually. + (if havetime + (setq ; y (floor (/ diff ys)) diff (mod diff ys) + y 0 + d (floor (/ diff ds)) diff (mod diff ds) + h (floor (/ diff hs)) diff (mod diff hs) + m (floor (/ diff 60))) + (setq ; y (floor (/ diff ys)) diff (mod diff ys) + y 0 + d (floor (+ (/ diff ds) 0.5)) + h 0 m 0)) + (if (not to-buffer) + (message (org-make-tdiff-string y d h m)) + (when (org-at-table-p) + (goto-char match-end) + (setq align t) + (and (looking-at " *|") (goto-char (match-end 0)))) + (if (looking-at + "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]") + (replace-match "")) + (if negative (insert " -")) + (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m)) + (if (> d 0) (insert " " (format (if havetime fd fd1) d h m)) + (insert " " (format fh h m)))) + (if align (org-table-align)) + (message "Time difference inserted")))) + +(defun org-make-tdiff-string (y d h m) + (let ((fmt "") + (l nil)) + (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ") + l (push y l))) + (if (> d 0) (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ") + l (push d l))) + (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ") + l (push h l))) + (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ") + l (push m l))) + (apply 'format fmt (nreverse l)))) + +(defun org-time-string-to-time (s) + (apply 'encode-time (org-parse-time-string s))) + +(defun org-parse-time-string (s &optional nodefault) + "Parse the standard Org-mode time string. +This should be a lot faster than the normal `parse-time-string'. +If time is not given, defaults to 0:00. However, with optional NODEFAULT, +hour and minute fields will be nil if not given." + (if (string-match org-ts-regexp1 s) + (list 0 + (if (or (match-beginning 8) (not nodefault)) + (string-to-number (or (match-string 8 s) "0"))) + (if (or (match-beginning 7) (not nodefault)) + (string-to-number (or (match-string 7 s) "0"))) + (string-to-number (match-string 4 s)) + (string-to-number (match-string 3 s)) + (string-to-number (match-string 2 s)) + nil nil nil) + (make-list 9 0))) + +(defun org-timestamp-up (&optional arg) + "Increase the date item at the cursor by one. +If the cursor is on the year, change the year. If it is on the month or +the day, change that. +With prefix ARG, change by that many units." + (interactive "p") + (org-timestamp-change (prefix-numeric-value arg))) + +(defun org-timestamp-down (&optional arg) + "Decrease the date item at the cursor by one. +If the cursor is on the year, change the year. If it is on the month or +the day, change that. +With prefix ARG, change by that many units." + (interactive "p") + (org-timestamp-change (- (prefix-numeric-value arg)))) + +(defun org-timestamp-up-day (&optional arg) + "Increase the date in the time stamp by one day. +With prefix ARG, change that many days." + (interactive "p") + (if (and (not (org-at-timestamp-p)) + (org-on-heading-p)) + (org-todo 'up) + (org-timestamp-change (prefix-numeric-value arg) 'day))) + +(defun org-timestamp-down-day (&optional arg) + "Decrease the date in the time stamp by one day. +With prefix ARG, change that many days." + (interactive "p") + (if (and (not (org-at-timestamp-p)) + (org-on-heading-p)) + (org-todo 'down) + (org-timestamp-change (- (prefix-numeric-value arg)) 'day))) + +(defsubst org-pos-in-match-range (pos n) + (and (match-beginning n) + (<= (match-beginning n) pos) + (>= (match-end n) pos))) + +(defun org-at-timestamp-p () + "Determine if the cursor is in or at a timestamp." + (interactive) + (let* ((tsr org-ts-regexp2) + (pos (point)) + (ans (or (looking-at tsr) + (save-excursion + (skip-chars-backward "^<\n\r\t") + (if (> (point) 1) (backward-char 1)) + (and (looking-at tsr) + (> (- (match-end 0) pos) -1)))))) + (and (boundp 'org-ts-what) + (setq org-ts-what + (cond + ((org-pos-in-match-range pos 2) 'year) + ((org-pos-in-match-range pos 3) 'month) + ((org-pos-in-match-range pos 7) 'hour) + ((org-pos-in-match-range pos 8) 'minute) + ((or (org-pos-in-match-range pos 4) + (org-pos-in-match-range pos 5)) 'day) + (t 'day)))) + ans)) + +(defun org-timestamp-change (n &optional what) + "Change the date in the time stamp at point. +The date will be changed by N times WHAT. WHAT can be `day', `month', +`year', `minute', `second'. If WHAT is not given, the cursor position +in the timestamp determines what will be changed." + (let ((fmt (car org-time-stamp-formats)) + org-ts-what + (pos (point)) + ts time time0) + (if (not (org-at-timestamp-p)) + (error "Not at a timestamp")) + (setq org-ts-what (or what org-ts-what)) + (setq fmt (if (<= (abs (- (cdr org-ts-lengths) + (- (match-end 0) (match-beginning 0)))) + 1) + (cdr org-time-stamp-formats) + (car org-time-stamp-formats))) + (setq ts (match-string 0)) + (replace-match "") + (setq time0 (org-parse-time-string ts)) + (setq time + (apply 'encode-time + (append + (list (or (car time0) 0)) + (list (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0))) + (list (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0))) + (list (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0))) + (list (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0))) + (list (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0))) + (nthcdr 6 time0)))) + (if (eq what 'calendar) + (let ((cal-date + (save-excursion + (save-match-data + (set-buffer "*Calendar*") + (calendar-cursor-to-date))))) + (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month + (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day + (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year + (setcar time0 (or (car time0) 0)) + (setcar (nthcdr 1 time0) (or (nth 1 time0) 0)) + (setcar (nthcdr 2 time0) (or (nth 1 time0) 0)) + (setq time (apply 'encode-time time0)))) + (insert (setq org-last-changed-timestamp (format-time-string fmt time))) + (goto-char pos) + ;; Try to recenter the calendar window, if any + (if (and org-calendar-follow-timestamp-change + (get-buffer-window "*Calendar*" t) + (memq org-ts-what '(day month year))) + (org-recenter-calendar (time-to-days time))))) + +(defun org-recenter-calendar (date) + "If the calendar is visible, recenter it to DATE." + (let* ((win (selected-window)) + (cwin (get-buffer-window "*Calendar*" t)) + (calendar-move-hook nil)) + (when cwin + (select-window cwin) + (calendar-goto-date (if (listp date) date + (calendar-gregorian-from-absolute date))) + (select-window win)))) + +(defun org-goto-calendar (&optional arg) + "Go to the Emacs calendar at the current date. +If there is a time stamp in the current line, go to that date. +A prefix ARG can be used to force the current date." + (interactive "P") + (let ((tsr org-ts-regexp) diff + (calendar-move-hook nil) + (view-diary-entries-initially nil)) + (if (or (org-at-timestamp-p) + (save-excursion + (beginning-of-line 1) + (looking-at (concat ".*" tsr)))) + (let ((d1 (time-to-days (current-time))) + (d2 (time-to-days + (org-time-string-to-time (match-string 1))))) + (setq diff (- d2 d1)))) + (calendar) + (calendar-goto-today) + (if (and diff (not arg)) (calendar-forward-day diff)))) + +(defun org-date-from-calendar () + "Insert time stamp corresponding to cursor date in *Calendar* buffer. +If there is already a time stamp at the cursor position, update it." + (interactive) + (org-timestamp-change 0 'calendar)) + +;;; Agenda, and Diary Integration + +;;; Define the mode + +(defvar org-agenda-mode-map (make-sparse-keymap) + "Keymap for `org-agenda-mode'.") + +(defvar org-agenda-menu) ; defined later in this file. +(defvar org-agenda-follow-mode nil) +(defvar org-agenda-show-log nil) +(defvar org-agenda-buffer-name "*Org Agenda*") +(defvar org-agenda-redo-command nil) +(defvar org-agenda-mode-hook nil) +(defvar org-agenda-type nil) +(defvar org-agenda-force-single-file nil) + +;;;###autoload +(defun org-agenda-mode () + "Mode for time-sorted view on action items in Org-mode files. + +The following commands are available: + +\\{org-agenda-mode-map}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'org-agenda-mode) + (setq mode-name "Org-Agenda") + (use-local-map org-agenda-mode-map) + (easy-menu-add org-agenda-menu) + (if org-startup-truncated (setq truncate-lines t)) + (org-add-hook 'post-command-hook 'org-agenda-post-command-hook nil 'local) + (org-add-hook 'pre-command-hook 'org-unhighlight nil 'local) + (unless org-agenda-keep-modes + (setq org-agenda-follow-mode nil + org-agenda-show-log nil)) + (easy-menu-change + '("Agenda") "Agenda Files" + (append + (list + (vector + (if (get 'org-agenda-files 'org-restrict) + "Restricted to single file" + "Edit File List") + '(customize-variable 'org-agenda-files) + (not (get 'org-agenda-files 'org-restrict))) + "--") + (mapcar 'org-file-menu-entry (org-agenda-files)))) + (org-agenda-set-mode-name) + (apply + (if (fboundp 'run-mode-hooks) 'run-mode-hooks 'run-hooks) + (list 'org-agenda-mode-hook))) + +(define-key org-agenda-mode-map "\C-i" 'org-agenda-goto) +(define-key org-agenda-mode-map [(tab)] 'org-agenda-goto) +(define-key org-agenda-mode-map "\C-m" 'org-agenda-switch-to) +(define-key org-agenda-mode-map " " 'org-agenda-show) +(define-key org-agenda-mode-map "\C-c\C-t" 'org-agenda-todo) +(define-key org-agenda-mode-map "o" 'delete-other-windows) +(define-key org-agenda-mode-map "L" 'org-agenda-recenter) +(define-key org-agenda-mode-map "t" 'org-agenda-todo) +(define-key org-agenda-mode-map ":" 'org-agenda-set-tags) +(define-key org-agenda-mode-map "." 'org-agenda-goto-today) +(define-key org-agenda-mode-map "d" 'org-agenda-day-view) +(define-key org-agenda-mode-map "w" 'org-agenda-week-view) +(define-key org-agenda-mode-map (org-key 'S-right) 'org-agenda-date-later) +(define-key org-agenda-mode-map (org-key 'S-left) 'org-agenda-date-earlier) +(define-key org-agenda-mode-map [?\C-c ?\C-x (right)] 'org-agenda-date-later) +(define-key org-agenda-mode-map [?\C-c ?\C-x (left)] 'org-agenda-date-earlier) + +(define-key org-agenda-mode-map ">" 'org-agenda-date-prompt) +(let ((l '(1 2 3 4 5 6 7 8 9 0))) + (while l (define-key org-agenda-mode-map + (int-to-string (pop l)) 'digit-argument))) + +(define-key org-agenda-mode-map "f" 'org-agenda-follow-mode) +(define-key org-agenda-mode-map "l" 'org-agenda-log-mode) +(define-key org-agenda-mode-map "D" 'org-agenda-toggle-diary) +(define-key org-agenda-mode-map "g" 'org-agenda-toggle-time-grid) +(define-key org-agenda-mode-map "r" 'org-agenda-redo) +(define-key org-agenda-mode-map "q" 'org-agenda-quit) +(define-key org-agenda-mode-map "x" 'org-agenda-exit) +(define-key org-agenda-mode-map "P" 'org-agenda-show-priority) +(define-key org-agenda-mode-map "T" 'org-agenda-show-tags) +(define-key org-agenda-mode-map "n" 'next-line) +(define-key org-agenda-mode-map "p" 'previous-line) +(define-key org-agenda-mode-map "\C-n" 'org-agenda-next-date-line) +(define-key org-agenda-mode-map "\C-p" 'org-agenda-previous-date-line) +(define-key org-agenda-mode-map "," 'org-agenda-priority) +(define-key org-agenda-mode-map "\C-c," 'org-agenda-priority) +(define-key org-agenda-mode-map "i" 'org-agenda-diary-entry) +(define-key org-agenda-mode-map "c" 'org-agenda-goto-calendar) +(eval-after-load "calendar" + '(define-key calendar-mode-map org-calendar-to-agenda-key + 'org-calendar-goto-agenda)) +(define-key org-agenda-mode-map "C" 'org-agenda-convert-date) +(define-key org-agenda-mode-map "m" 'org-agenda-phases-of-moon) +(define-key org-agenda-mode-map "M" 'org-agenda-phases-of-moon) +(define-key org-agenda-mode-map "s" 'org-agenda-sunrise-sunset) +(define-key org-agenda-mode-map "S" 'org-agenda-sunrise-sunset) +(define-key org-agenda-mode-map "h" 'org-agenda-holidays) +(define-key org-agenda-mode-map "H" 'org-agenda-holidays) +(define-key org-agenda-mode-map "+" 'org-agenda-priority-up) +(define-key org-agenda-mode-map "-" 'org-agenda-priority-down) +(define-key org-agenda-mode-map (org-key 'S-up) 'org-agenda-priority-up) +(define-key org-agenda-mode-map (org-key 'S-down) 'org-agenda-priority-down) +(define-key org-agenda-mode-map [?\C-c ?\C-x (up)] 'org-agenda-priority-up) +(define-key org-agenda-mode-map [?\C-c ?\C-x (down)] 'org-agenda-priority-down) +(define-key org-agenda-mode-map [(right)] 'org-agenda-later) +(define-key org-agenda-mode-map [(left)] 'org-agenda-earlier) +(define-key org-agenda-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files) +(defvar org-agenda-keymap (copy-keymap org-agenda-mode-map) + "Local keymap for agenda entries from Org-mode.") + +(define-key org-agenda-keymap + (if org-xemacs-p [(button2)] [(mouse-2)]) 'org-agenda-goto-mouse) +(define-key org-agenda-keymap + (if org-xemacs-p [(button3)] [(mouse-3)]) 'org-agenda-show-mouse) +(define-key org-agenda-keymap [follow-link] 'mouse-face) +(easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu" + '("Agenda" + ("Agenda Files") + "--" + ["Show" org-agenda-show t] + ["Go To (other window)" org-agenda-goto t] + ["Go To (one window)" org-agenda-switch-to t] + ["Follow Mode" org-agenda-follow-mode + :style toggle :selected org-agenda-follow-mode :active t] + "--" + ["Cycle TODO" org-agenda-todo t] + ("Tags" + ["Show all Tags" org-agenda-show-tags t] + ["Set Tags" org-agenda-set-tags t]) + ("Reschedule" + ["Reschedule +1 day" org-agenda-date-later (org-agenda-check-type nil 'agenda 'timeline)] + ["Reschedule -1 day" org-agenda-date-earlier (org-agenda-check-type nil 'agenda 'timeline)] + "--" + ["Reschedule to ..." org-agenda-date-prompt (org-agenda-check-type nil 'agenda 'timeline)]) + ("Priority" + ["Set Priority" org-agenda-priority t] + ["Increase Priority" org-agenda-priority-up t] + ["Decrease Priority" org-agenda-priority-down t] + ["Show Priority" org-agenda-show-priority t]) + "--" + ;; ["New agenda command" org-agenda t] + ["Rebuild buffer" org-agenda-redo t] + "--" + ["Goto Today" org-agenda-goto-today (org-agenda-check-type nil 'agenda 'timeline)] + ["Next Dates" org-agenda-later (org-agenda-check-type nil 'agenda)] + ["Previous Dates" org-agenda-earlier (org-agenda-check-type nil 'agenda)] + "--" + ["Day View" org-agenda-day-view :active (org-agenda-check-type nil 'agenda) + :style radio :selected (equal org-agenda-ndays 1)] + ["Week View" org-agenda-week-view :active (org-agenda-check-type nil 'agenda) + :style radio :selected (equal org-agenda-ndays 7)] + "--" + ["Show Logbook entries" org-agenda-log-mode + :style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)] + ["Include Diary" org-agenda-toggle-diary + :style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)] + ["Use Time Grid" org-agenda-toggle-time-grid + :style toggle :selected org-agenda-use-time-grid :active (org-agenda-check-type nil 'agenda)] + "--" + ["New Diary Entry" org-agenda-diary-entry (org-agenda-check-type nil 'agenda 'timeline)] + ("Calendar Commands" + ["Goto Calendar" org-agenda-goto-calendar (org-agenda-check-type nil 'agenda 'timeline)] + ["Phases of the Moon" org-agenda-phases-of-moon (org-agenda-check-type nil 'agenda 'timeline)] + ["Sunrise/Sunset" org-agenda-sunrise-sunset (org-agenda-check-type nil 'agenda 'timeline)] + ["Holidays" org-agenda-holidays (org-agenda-check-type nil 'agenda 'timeline)] + ["Convert" org-agenda-convert-date (org-agenda-check-type nil 'agenda 'timeline)]) + ["Create iCalendar file" org-export-icalendar-combine-agenda-files t] + "--" + ["Quit" org-agenda-quit t] + ["Exit and Release Buffers" org-agenda-exit t] + )) + +;;;###autoload +(defun org-agenda (arg) + "Dispatch agenda commands to collect entries to the agenda buffer. +Prompts for a character to select a command. Any prefix arg will be passed +on to the selected command. The default selections are: + +a Call `org-agenda' to display the agenda for the current day or week. +t Call `org-todo-list' to display the global todo list. +T Call `org-todo-list' to display the global todo list, select only + entries with a specific TODO keyword (the user gets a prompt). +m Call `org-tags-view' to display headlines with tags matching + a condition (the user is prompted for the condition). +M Like `m', but select only TODO entries, no ordinary headlines. + +More commands can be added by configuring the variable +`org-agenda-custom-commands'. In particular, specific tags and TODO keyword +searches can be pre-defined in this way. + +If the current buffer is in Org-mode and visiting a file, you can also +first press `1' to indicate that the agenda should be temporarily (until the +next use of \\[org-agenda]) restricted to the current file." + (interactive "P") + (catch 'exit + (let ((restrict-ok (and buffer-file-name (eq major-mode 'org-mode))) + (custom org-agenda-custom-commands) + c entry key type string) + (put 'org-agenda-files 'org-restrict nil) + (save-window-excursion + (delete-other-windows) + (switch-to-buffer-other-window " *Agenda Commands*") + (erase-buffer) + (insert + "Press key for an agenda command: +-------------------------------- +a Agenda for current week or day +t List of all TODO entries T Entries with special TODO kwd +m Match a TAGS query M Like m, but only TODO entries +C Configure your own agenda commands") + (while (setq entry (pop custom)) + (setq key (car entry) type (nth 1 entry) string (nth 2 entry)) + (insert (format "\n%-4s%-14s: %s" + key + (cond + ((eq type 'tags) "Tags query") + ((eq type 'todo) "TODO keyword") + ((eq type 'tags-tree) "Tags tree") + ((eq type 'todo-tree) "TODO kwd tree") + ((eq type 'occur-tree) "Occur tree") + (t "???")) + (org-string-props string 'face 'org-link)))) + (goto-char (point-min)) + (if (fboundp 'fit-window-to-buffer) (fit-window-to-buffer)) + (message "Press key for agenda command%s" + (if restrict-ok ", or [1] to restrict to current file" "")) + (setq c (read-char-exclusive)) + (message "") + (when (equal c ?1) + (if restrict-ok + (put 'org-agenda-files 'org-restrict (list buffer-file-name)) + (error "Cannot restrict agenda to current buffer")) + (message "Press key for agenda command%s" + (if restrict-ok " (restricted to current file)" "")) + (setq c (read-char-exclusive)) + (message ""))) + (require 'calendar) ; FIXME: can we avoid this for some commands? + ;; For example the todo list should not need it (but does...) + (cond + ((equal c ?C) (customize-variable 'org-agenda-custom-commands)) + ((equal c ?a) (call-interactively 'org-agenda-list)) + ((equal c ?t) (call-interactively 'org-todo-list)) + ((equal c ?T) + (setq current-prefix-arg (or arg '(4))) + (call-interactively 'org-todo-list)) + ((equal c ?m) (call-interactively 'org-tags-view)) + ((equal c ?M) + (setq current-prefix-arg (or arg '(4))) + (call-interactively 'org-tags-view)) + ((setq entry (assoc (char-to-string c) org-agenda-custom-commands)) + (setq type (nth 1 entry) string (nth 2 entry)) + (cond + ((eq type 'tags) + (org-tags-view current-prefix-arg string)) + ((eq type 'todo) + (org-todo-list string)) + ((eq type 'tags-tree) + (org-check-for-org-mode) + (org-tags-sparse-tree current-prefix-arg string)) + ((eq type 'todo-tree) + (org-check-for-org-mode) + (org-occur (concat "^" outline-regexp "[ \t]*" + (regexp-quote string) "\\>"))) + ((eq type 'occur-tree) + (org-check-for-org-mode) + (org-occur string)) + (t (error "Invalid custom agenda command type %s" type)))) + (t (error "Invalid key")))))) + +(defun org-check-for-org-mode () + "Make sure current buffer is in org-mode. Error if not." + (or (eq major-mode 'org-mode) + (error "Cannot execute org-mode agenda command on buffer in %s." + major-mode))) + +(defun org-fit-agenda-window () + "Fit the window to the buffer size." + (and org-fit-agenda-window + (fboundp 'fit-window-to-buffer) + (fit-window-to-buffer nil (/ (* (frame-height) 3) 4) + (/ (frame-height) 2)))) + +(defun org-agenda-files () + "Get the list of agenda files." + (or (get 'org-agenda-files 'org-restrict) + org-agenda-files)) + +(defvar org-agenda-markers nil + "List of all currently active markers created by `org-agenda'.") +(defvar org-agenda-last-marker-time (time-to-seconds (current-time)) + "Creation time of the last agenda marker.") + +(defun org-agenda-new-marker (&optional pos) + "Return a new agenda marker. +Org-mode keeps a list of these markers and resets them when they are +no longer in use." + (let ((m (copy-marker (or pos (point))))) + (setq org-agenda-last-marker-time (time-to-seconds (current-time))) + (push m org-agenda-markers) + m)) + +(defun org-agenda-maybe-reset-markers (&optional force) + "Reset markers created by `org-agenda'. But only if they are old enough." + (if (or force + (> (- (time-to-seconds (current-time)) + org-agenda-last-marker-time) + 5)) + (while org-agenda-markers + (move-marker (pop org-agenda-markers) nil)))) + +(defvar org-agenda-new-buffers nil + "Buffers created to visit agenda files.") + +(defun org-get-agenda-file-buffer (file) + "Get a buffer visiting FILE. If the buffer needs to be created, add +it to the list of buffers which might be released later." + (let ((buf (find-buffer-visiting file))) + (if buf + buf ; just return it + ;; Make a new buffer and remember it + (setq buf (find-file-noselect file)) + (if buf (push buf org-agenda-new-buffers)) + buf))) + +(defun org-release-buffers (blist) + "Release all buffers in list, asking the user for confirmation when needed. +When a buffer is unmodified, it is just killed. When modified, it is saved +\(if the user agrees) and then killed." + (let (buf file) + (while (setq buf (pop blist)) + (setq file (buffer-file-name buf)) + (when (and (buffer-modified-p buf) + file + (y-or-n-p (format "Save file %s? " file))) + (with-current-buffer buf (save-buffer))) + (kill-buffer buf)))) + +(defvar org-respect-restriction nil) ; Dynamically-scoped param. + +(defun org-timeline (&optional include-all keep-modes) + "Show a time-sorted view of the entries in the current org file. +Only entries with a time stamp of today or later will be listed. With +\\[universal-argument] prefix, all unfinished TODO items will also be shown, +under the current date. +If the buffer contains an active region, only check the region for +dates." + (interactive "P") + (require 'calendar) + (org-agenda-maybe-reset-markers 'force) + (org-compile-prefix-format org-timeline-prefix-format) + (let* ((dopast t) + (dotodo include-all) + (doclosed org-agenda-show-log) + (org-agenda-keep-modes keep-modes) + (entry buffer-file-name) + (org-agenda-files (list buffer-file-name)) + (date (calendar-current-date)) + (win (selected-window)) + (pos1 (point)) + (beg (if (org-region-active-p) (region-beginning) (point-min))) + (end (if (org-region-active-p) (region-end) (point-max))) + (day-numbers (org-get-all-dates beg end 'no-ranges + t doclosed)) ; always include today + (today (time-to-days (current-time))) + (org-respect-restriction t) + (past t) + args + s e rtn d) + (setq org-agenda-redo-command + (list 'progn + (list 'switch-to-buffer-other-window (current-buffer)) + (list 'org-timeline (list 'quote include-all) t))) + (if (not dopast) + ;; Remove past dates from the list of dates. + (setq day-numbers (delq nil (mapcar (lambda(x) + (if (>= x today) x nil)) + day-numbers)))) + (switch-to-buffer-other-window + (get-buffer-create org-agenda-buffer-name)) + (setq buffer-read-only nil) + (erase-buffer) + (org-agenda-mode) (setq buffer-read-only nil) + (set (make-local-variable 'org-agenda-type) 'timeline) + (if doclosed (push :closed args)) + (push :timestamp args) + (if dotodo (push :todo args)) + (while (setq d (pop day-numbers)) + (if (and (>= d today) + dopast + past) + (progn + (setq past nil) + (insert (make-string 79 ?-) "\n"))) + (setq date (calendar-gregorian-from-absolute d)) + (setq s (point)) + (setq rtn (apply 'org-agenda-get-day-entries + entry date args)) + (if (or rtn (equal d today)) + (progn + (insert (calendar-day-name date) " " + (number-to-string (extract-calendar-day date)) " " + (calendar-month-name (extract-calendar-month date)) " " + (number-to-string (extract-calendar-year date)) "\n") + (put-text-property s (1- (point)) 'face + 'org-link) + (if (equal d today) + (put-text-property s (1- (point)) 'org-today t)) + (insert (org-finalize-agenda-entries rtn) "\n") + (put-text-property s (1- (point)) 'day d)))) + (goto-char (point-min)) + (setq buffer-read-only t) + (goto-char (or (text-property-any (point-min) (point-max) 'org-today t) + (point-min))) + (when (not org-select-timeline-window) + (select-window win) + (goto-char pos1)))) + +;;;###autoload +(defun org-agenda-list (&optional include-all start-day ndays keep-modes) + "Produce a weekly view from all files in variable `org-agenda-files'. +The view will be for the current week, but from the overview buffer you +will be able to go to other weeks. +With one \\[universal-argument] prefix argument INCLUDE-ALL, all unfinished TODO items will +also be shown, under the current date. +With two \\[universal-argument] prefix argument INCLUDE-ALL, all TODO entries marked DONE +on the days are also shown. See the variable `org-log-done' for how +to turn on logging. +START-DAY defaults to TODAY, or to the most recent match for the weekday +given in `org-agenda-start-on-weekday'. +NDAYS defaults to `org-agenda-ndays'." + (interactive "P") + (org-agenda-maybe-reset-markers 'force) + (org-compile-prefix-format org-agenda-prefix-format) + (require 'calendar) + (let* ((org-agenda-start-on-weekday + (if (or (equal ndays 1) + (and (null ndays) (equal 1 org-agenda-ndays))) + nil org-agenda-start-on-weekday)) + (org-agenda-keep-modes keep-modes) + (files (copy-sequence (org-agenda-files))) + (win (selected-window)) + (today (time-to-days (current-time))) + (sd (or start-day today)) + (start (if (or (null org-agenda-start-on-weekday) + (< org-agenda-ndays 7)) + sd + (let* ((nt (calendar-day-of-week + (calendar-gregorian-from-absolute sd))) + (n1 org-agenda-start-on-weekday) + (d (- nt n1))) + (- sd (+ (if (< d 0) 7 0) d))))) + (day-numbers (list start)) + (inhibit-redisplay t) + s e rtn rtnall file date d start-pos end-pos todayp nd) + (setq org-agenda-redo-command + (list 'org-agenda-list (list 'quote include-all) start-day ndays t)) + ;; Make the list of days + (setq ndays (or ndays org-agenda-ndays) + nd ndays) + (while (> ndays 1) + (push (1+ (car day-numbers)) day-numbers) + (setq ndays (1- ndays))) + (setq day-numbers (nreverse day-numbers)) + (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name))) + (progn + (delete-other-windows) + (switch-to-buffer-other-window + (get-buffer-create org-agenda-buffer-name)))) + (setq buffer-read-only nil) + (erase-buffer) + (org-agenda-mode) (setq buffer-read-only nil) + (set (make-local-variable 'org-agenda-type) 'agenda) + (set (make-local-variable 'starting-day) (car day-numbers)) + (set (make-local-variable 'include-all-loc) include-all) + (when (and (or include-all org-agenda-include-all-todo) + (member today day-numbers)) + (setq files (org-agenda-files) + rtnall nil) + (while (setq file (pop files)) + (catch 'nextfile + (org-check-agenda-file file) + (setq date (calendar-gregorian-from-absolute today) + rtn (org-agenda-get-day-entries + file date :todo)) + (setq rtnall (append rtnall rtn)))) + (when rtnall + (insert "ALL CURRENTLY OPEN TODO ITEMS:\n") + (add-text-properties (point-min) (1- (point)) + (list 'face 'org-link)) + (insert (org-finalize-agenda-entries rtnall) "\n"))) + (while (setq d (pop day-numbers)) + (setq date (calendar-gregorian-from-absolute d) + s (point)) + (if (or (setq todayp (= d today)) + (and (not start-pos) (= d sd))) + (setq start-pos (point)) + (if (and start-pos (not end-pos)) + (setq end-pos (point)))) + (setq files (org-agenda-files) + rtnall nil) + (while (setq file (pop files)) + (catch 'nextfile + (org-check-agenda-file file) + (if org-agenda-show-log + (setq rtn (org-agenda-get-day-entries + file date + :deadline :scheduled :timestamp :closed)) + (setq rtn (org-agenda-get-day-entries + file date + :deadline :scheduled :timestamp))) + (setq rtnall (append rtnall rtn)))) + (if org-agenda-include-diary + (progn + (require 'diary-lib) + (setq rtn (org-get-entries-from-diary date)) + (setq rtnall (append rtnall rtn)))) + (if (or rtnall org-agenda-show-all-dates) + (progn + (insert (format "%-9s %2d %s %4d\n" + (calendar-day-name date) + (extract-calendar-day date) + (calendar-month-name (extract-calendar-month date)) + (extract-calendar-year date))) + (put-text-property s (1- (point)) 'face + 'org-link) + (if rtnall (insert + (org-finalize-agenda-entries + (org-agenda-add-time-grid-maybe + rtnall nd todayp)) + "\n")) + (put-text-property s (1- (point)) 'day d)))) + (goto-char (point-min)) + (setq buffer-read-only t) + (org-fit-agenda-window) + (unless (and (pos-visible-in-window-p (point-min)) + (pos-visible-in-window-p (point-max))) + (goto-char (1- (point-max))) + (recenter -1) + (if (not (pos-visible-in-window-p (or start-pos 1))) + (progn + (goto-char (or start-pos 1)) + (recenter 1)))) + (goto-char (or start-pos 1)) + (if (not org-select-agenda-window) (select-window win)) + (message ""))) + +(defvar org-select-this-todo-keyword nil) + +;;;###autoload +(defun org-todo-list (arg &optional keep-modes) + "Show all TODO entries from all agenda file in a single list. +The prefix arg can be used to select a specific TODO keyword and limit +the list to these. When using \\[universal-argument], you will be prompted +for a keyword. A numeric prefix directly selects the Nth keyword in +`org-todo-keywords'." + (interactive "P") + (org-agenda-maybe-reset-markers 'force) + (org-compile-prefix-format org-agenda-prefix-format) + (let* ((org-agenda-keep-modes keep-modes) + (today (time-to-days (current-time))) + (date (calendar-gregorian-from-absolute today)) + (win (selected-window)) + (kwds org-todo-keywords) + (completion-ignore-case t) + (org-select-this-todo-keyword + (if (stringp arg) arg + (and arg (integerp arg) (nth (1- arg) org-todo-keywords)))) + rtn rtnall files file pos) + (when (equal arg '(4)) + (setq org-select-this-todo-keyword + (completing-read "Keyword: " (mapcar 'list org-todo-keywords) + nil t))) + (and (equal 0 arg) (setq org-select-this-todo-keyword nil)) + (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name))) + (progn + (delete-other-windows) + (switch-to-buffer-other-window + (get-buffer-create org-agenda-buffer-name)))) + (setq buffer-read-only nil) + (erase-buffer) + (org-agenda-mode) (setq buffer-read-only nil) + (set (make-local-variable 'org-agenda-type) 'todo) + (set (make-local-variable 'last-arg) arg) + (set (make-local-variable 'org-todo-keywords) kwds) + (set (make-local-variable 'org-agenda-redo-command) + '(org-todo-list (or current-prefix-arg last-arg) t)) + (setq files (org-agenda-files) + rtnall nil) + (while (setq file (pop files)) + (catch 'nextfile + (org-check-agenda-file file) + (setq rtn (org-agenda-get-day-entries file date :todo)) + (setq rtnall (append rtnall rtn)))) + (insert "Global list of TODO items of type: ") + (add-text-properties (point-min) (1- (point)) + (list 'face 'org-link)) + (setq pos (point)) + (insert (or org-select-this-todo-keyword "ALL") "\n") + (add-text-properties pos (1- (point)) (list 'face 'org-warning)) + (setq pos (point)) + (insert + "Available with `N r': (0)ALL " + (let ((n 0)) + (mapconcat (lambda (x) + (format "(%d)%s" (setq n (1+ n)) x)) + org-todo-keywords " ")) + "\n") + (add-text-properties pos (1- (point)) (list 'face 'org-link)) + (when rtnall + (insert (org-finalize-agenda-entries rtnall) "\n")) + (goto-char (point-min)) + (setq buffer-read-only t) + (org-fit-agenda-window) + (if (not org-select-agenda-window) (select-window win)))) + +(defun org-check-agenda-file (file) + "Make sure FILE exists. If not, ask user what to do." + ;; FIXME: this does not correctly change the menus + ;; Could probably be fixed by explicitly going to the buffer where + ;; the call originated. + (when (not (file-exists-p file)) + (message "non-existent file %s. [R]emove from agenda-files or [A]bort?" + file) + (let ((r (downcase (read-char-exclusive)))) + (cond + ((equal r ?r) + (org-remove-file file) + (throw 'nextfile t)) + (t (error "Abort")))))) + +(defun org-agenda-check-type (error &rest types) + "Check if agenda buffer is of allowed type. +If ERROR is non-nil, throw an error, otherwise just return nil." + (if (memq org-agenda-type types) + t + (if error + (error "Now allowed in %s-type agenda buffers" org-agenda-type) + nil))) + +(defun org-agenda-quit () + "Exit agenda by removing the window or the buffer." + (interactive) + (let ((buf (current-buffer))) + (if (not (one-window-p)) (delete-window)) + (kill-buffer buf) + (org-agenda-maybe-reset-markers 'force))) + +(defun org-agenda-exit () + "Exit agenda by removing the window or the buffer. +Also kill all Org-mode buffers which have been loaded by `org-agenda'. +Org-mode buffers visited directly by the user will not be touched." + (interactive) + (org-release-buffers org-agenda-new-buffers) + (setq org-agenda-new-buffers nil) + (org-agenda-quit)) + +(defun org-agenda-redo () + "Rebuild Agenda. +When this is the global TODO list, a prefix argument will be interpreted." + (interactive) + (message "Rebuilding agenda buffer...") + (eval org-agenda-redo-command) + (message "Rebuilding agenda buffer...done")) + +(defun org-agenda-goto-today () + "Go to today." + (interactive) + (org-agenda-check-type t 'timeline 'agenda) + (if (boundp 'starting-day) + (let ((cmd (car org-agenda-redo-command)) + (iall (nth 1 org-agenda-redo-command)) + (nday (nth 3 org-agenda-redo-command)) + (keep (nth 4 org-agenda-redo-command))) + (eval (list cmd iall nil nday keep))) + (goto-char (or (text-property-any (point-min) (point-max) 'org-today t) + (point-min))))) + +(defun org-agenda-later (arg) + "Go forward in time by `org-agenda-ndays' days. +With prefix ARG, go forward that many times `org-agenda-ndays'." + (interactive "p") + (org-agenda-check-type t 'agenda) + (org-agenda-list (if (boundp 'include-all-loc) include-all-loc nil) + (+ starting-day (* arg org-agenda-ndays)) nil t)) + +(defun org-agenda-earlier (arg) + "Go back in time by `org-agenda-ndays' days. +With prefix ARG, go back that many times `org-agenda-ndays'." + (interactive "p") + (org-agenda-check-type t 'agenda) + (org-agenda-list (if (boundp 'include-all-loc) include-all-loc nil) + (- starting-day (* arg org-agenda-ndays)) nil t)) + +(defun org-agenda-week-view () + "Switch to weekly view for agenda." + (interactive) + (org-agenda-check-type t 'agenda) + (setq org-agenda-ndays 7) + (org-agenda-list include-all-loc + (or (get-text-property (point) 'day) + starting-day) + nil t) + (org-agenda-set-mode-name) + (message "Switched to week view")) + +(defun org-agenda-day-view () + "Switch to daily view for agenda." + (interactive) + (org-agenda-check-type t 'agenda) + (setq org-agenda-ndays 1) + (org-agenda-list include-all-loc + (or (get-text-property (point) 'day) + starting-day) + nil t) + (org-agenda-set-mode-name) + (message "Switched to day view")) + +(defun org-agenda-next-date-line (&optional arg) + "Jump to the next line indicating a date in agenda buffer." + (interactive "p") + (org-agenda-check-type t 'agenda 'timeline) + (beginning-of-line 1) + (if (looking-at "^\\S-") (forward-char 1)) + (if (not (re-search-forward "^\\S-" nil t arg)) + (progn + (backward-char 1) + (error "No next date after this line in this buffer"))) + (goto-char (match-beginning 0))) + +(defun org-agenda-previous-date-line (&optional arg) + "Jump to the previous line indicating a date in agenda buffer." + (interactive "p") + (org-agenda-check-type t 'agenda 'timeline) + (beginning-of-line 1) + (if (not (re-search-backward "^\\S-" nil t arg)) + (error "No previous date before this line in this buffer"))) + +;; Initialize the highlight +(defvar org-hl (org-make-overlay 1 1)) +(org-overlay-put org-hl 'face 'highlight) + +(defun org-highlight (begin end &optional buffer) + "Highlight a region with overlay." + (funcall (if org-xemacs-p 'set-extent-endpoints 'move-overlay) + org-hl begin end (or buffer (current-buffer)))) + +(defun org-unhighlight () + "Detach overlay INDEX." + (funcall (if org-xemacs-p 'detach-extent 'delete-overlay) org-hl)) + + +(defun org-agenda-follow-mode () + "Toggle follow mode in an agenda buffer." + (interactive) + (setq org-agenda-follow-mode (not org-agenda-follow-mode)) + (org-agenda-set-mode-name) + (message "Follow mode is %s" + (if org-agenda-follow-mode "on" "off"))) + +(defun org-agenda-log-mode () + "Toggle log mode in an agenda buffer." + (interactive) + (org-agenda-check-type t 'agenda 'timeline) + (setq org-agenda-show-log (not org-agenda-show-log)) + (org-agenda-set-mode-name) + (org-agenda-redo) + (message "Log mode is %s" + (if org-agenda-show-log "on" "off"))) + +(defun org-agenda-toggle-diary () + "Toggle diary inclusion in an agenda buffer." + (interactive) + (org-agenda-check-type t 'agenda) + (setq org-agenda-include-diary (not org-agenda-include-diary)) + (org-agenda-redo) + (org-agenda-set-mode-name) + (message "Diary inclusion turned %s" + (if org-agenda-include-diary "on" "off"))) + +(defun org-agenda-toggle-time-grid () + "Toggle time grid in an agenda buffer." + (interactive) + (org-agenda-check-type t 'agenda) + (setq org-agenda-use-time-grid (not org-agenda-use-time-grid)) + (org-agenda-redo) + (org-agenda-set-mode-name) + (message "Time-grid turned %s" + (if org-agenda-use-time-grid "on" "off"))) + +(defun org-agenda-set-mode-name () + "Set the mode name to indicate all the small mode settings." + (setq mode-name + (concat "Org-Agenda" + (if (equal org-agenda-ndays 1) " Day" "") + (if (equal org-agenda-ndays 7) " Week" "") + (if org-agenda-follow-mode " Follow" "") + (if org-agenda-include-diary " Diary" "") + (if org-agenda-use-time-grid " Grid" "") + (if org-agenda-show-log " Log" ""))) + (force-mode-line-update)) + +(defun org-agenda-post-command-hook () + (and (eolp) (not (bolp)) (backward-char 1)) + (if (and org-agenda-follow-mode + (get-text-property (point) 'org-marker)) + (org-agenda-show))) + +(defvar org-disable-agenda-to-diary nil) ;Dynamically-scoped param. + +(defun org-get-entries-from-diary (date) + "Get the (Emacs Calendar) diary entries for DATE." + (let* ((fancy-diary-buffer "*temporary-fancy-diary-buffer*") + (diary-display-hook '(fancy-diary-display)) + (list-diary-entries-hook + (cons 'org-diary-default-entry list-diary-entries-hook)) + (diary-file-name-prefix-function nil) ; turn this feature off + (diary-modify-entry-list-string-function 'org-modify-diary-entry-string) + entries + (org-disable-agenda-to-diary t)) + (save-excursion + (save-window-excursion + (list-diary-entries date 1))) + (if (not (get-buffer fancy-diary-buffer)) + (setq entries nil) + (with-current-buffer fancy-diary-buffer + (setq buffer-read-only nil) + (if (= (point-max) 1) + ;; No entries + (setq entries nil) + ;; Omit the date and other unnecessary stuff + (org-agenda-cleanup-fancy-diary) + ;; Add prefix to each line and extend the text properties + (if (= (point-max) 1) + (setq entries nil) + (setq entries (buffer-substring (point-min) (- (point-max) 1))))) + (set-buffer-modified-p nil) + (kill-buffer fancy-diary-buffer))) + (when entries + (setq entries (org-split-string entries "\n")) + (setq entries + (mapcar + (lambda (x) + (setq x (org-format-agenda-item "" x "Diary" nil 'time)) + ;; Extend the text properties to the beginning of the line + (add-text-properties + 0 (length x) + (text-properties-at (1- (length x)) x) + x) + x) + entries))))) + +(defun org-agenda-cleanup-fancy-diary () + "Remove unwanted stuff in buffer created by `fancy-diary-display'. +This gets rid of the date, the underline under the date, and +the dummy entry installed by `org-mode' to ensure non-empty diary for each +date. It also removes lines that contain only whitespace." + (goto-char (point-min)) + (if (looking-at ".*?:[ \t]*") + (progn + (replace-match "") + (re-search-forward "\n=+$" nil t) + (replace-match "") + (while (re-search-backward "^ +\n?" nil t) (replace-match ""))) + (re-search-forward "\n=+$" nil t) + (delete-region (point-min) (min (point-max) (1+ (match-end 0))))) + (goto-char (point-min)) + (while (re-search-forward "^ +\n" nil t) + (replace-match "")) + (goto-char (point-min)) + (if (re-search-forward "^Org-mode dummy\n?" nil t) + (replace-match ""))) + +;; Make sure entries from the diary have the right text properties. +(eval-after-load "diary-lib" + '(if (boundp 'diary-modify-entry-list-string-function) + ;; We can rely on the hook, nothing to do + nil + ;; Hook not avaiable, must use advice to make this work + (defadvice add-to-diary-list (before org-mark-diary-entry activate) + "Make the position visible." + (if (and org-disable-agenda-to-diary ;; called from org-agenda + (stringp string) + buffer-file-name) + (setq string (org-modify-diary-entry-string string)))))) + +(defun org-modify-diary-entry-string (string) + "Add text properties to string, allowing org-mode to act on it." + (add-text-properties + 0 (length string) + (list 'mouse-face 'highlight + 'keymap org-agenda-keymap + 'help-echo + (format + "mouse-2 or RET jump to diary file %s" + (abbreviate-file-name buffer-file-name)) + 'org-agenda-diary-link t + 'org-marker (org-agenda-new-marker (point-at-bol))) + string) + string) + +(defun org-diary-default-entry () + "Add a dummy entry to the diary. +Needed to avoid empty dates which mess up holiday display." + ;; Catch the error if dealing with the new add-to-diary-alist + (when org-disable-agenda-to-diary + (condition-case nil + (add-to-diary-list original-date "Org-mode dummy" "") + (error + (add-to-diary-list original-date "Org-mode dummy" "" nil))))) + +(defun org-cycle-agenda-files () + "Cycle through the files in `org-agenda-files'. +If the current buffer visits an agenda file, find the next one in the list. +If the current buffer does not, find the first agenda file." + (interactive) + (let ((files (append org-agenda-files (list (car org-agenda-files)))) + (tcf (if buffer-file-name (file-truename buffer-file-name))) + file) + (unless files (error "No agenda files")) + (catch 'exit + (while (setq file (pop files)) + (if (equal (file-truename file) tcf) + (when (car files) + (find-file (car files)) + (throw 'exit t)))) + (find-file (car org-agenda-files))))) + +(defun org-agenda-file-to-end () + "Move/add the current file to the end of the agenda file list. +If the file is not present in the list, it is appended to the list. If it is +present, it is moved there." + (interactive) + (org-agenda-file-to-front 'to-end)) + +(defun org-agenda-file-to-front (&optional to-end) + "Move/add the current file to the top of the agenda file list. +If the file is not present in the list, it is added to the front. If it is +present, it is moved there. With optional argument TO-END, add/move to the +end of the list." + (interactive "P") + (let ((file-alist (mapcar (lambda (x) + (cons (file-truename x) x)) + org-agenda-files)) + (ctf (file-truename buffer-file-name)) + x had) + (setq x (assoc ctf file-alist) had x) + + (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name)))) + (if to-end + (setq file-alist (append (delq x file-alist) (list x))) + (setq file-alist (cons x (delq x file-alist)))) + (setq org-agenda-files (mapcar 'cdr file-alist)) + (let ((org-mode-hook nil) (default-major-mode 'fundamental-mode)) + (customize-save-variable 'org-agenda-files org-agenda-files)) + (org-install-agenda-files-menu) + (message "File %s to %s of agenda file list" + (if had "moved" "added") (if to-end "end" "front")))) + +(defun org-remove-file (&optional file) + "Remove current file from the list of files in variable `org-agenda-files'. +These are the files which are being checked for agenda entries. +Optional argument FILE means, use this file instead of the current." + (interactive) + (let* ((file (or file buffer-file-name)) + (true-file (file-truename file)) + (afile (abbreviate-file-name file)) + (files (delq nil (mapcar + (lambda (x) + (if (equal true-file + (file-truename x)) + nil x)) + org-agenda-files)))) + (if (not (= (length files) (length org-agenda-files))) + (progn + (setq org-agenda-files files) + (customize-save-variable 'org-agenda-files org-agenda-files) + (org-install-agenda-files-menu) + (message "Removed file: %s" afile)) + (message "File was not in list: %s" afile)))) + +(defun org-file-menu-entry (file) + (vector file (list 'find-file file) t)) +;; FIXME: Maybe we removed a buffer visited through the menu from +;; org-agenda-new-buffers, so that the buffer will not be removed +;; when exiting the agenda???? + +(defun org-get-all-dates (beg end &optional no-ranges force-today inactive) + "Return a list of all relevant day numbers from BEG to END buffer positions. +If NO-RANGES is non-nil, include only the start and end dates of a range, +not every single day in the range. If FORCE-TODAY is non-nil, make +sure that TODAY is included in the list. If INACTIVE is non-nil, also +inactive time stamps (those in square brackets) are included." + (let ((re (if inactive org-ts-regexp-both org-ts-regexp)) + dates date day day1 day2 ts1 ts2) + (if force-today + (setq dates (list (time-to-days (current-time))))) + (save-excursion + (goto-char beg) + (while (re-search-forward re end t) + (setq day (time-to-days (org-time-string-to-time + (substring (match-string 1) 0 10)))) + (or (memq day dates) (push day dates))) + (unless no-ranges + (goto-char beg) + (while (re-search-forward org-tr-regexp end t) + (setq ts1 (substring (match-string 1) 0 10) + ts2 (substring (match-string 2) 0 10) + day1 (time-to-days (org-time-string-to-time ts1)) + day2 (time-to-days (org-time-string-to-time ts2))) + (while (< (setq day1 (1+ day1)) day2) + (or (memq day1 dates) (push day1 dates))))) + (sort dates '<)))) + +;;;###autoload +(defun org-diary (&rest args) + "Return diary information from org-files. +This function can be used in a \"sexp\" diary entry in the Emacs calendar. +It accesses org files and extracts information from those files to be +listed in the diary. The function accepts arguments specifying what +items should be listed. The following arguments are allowed: + + :timestamp List the headlines of items containing a date stamp or + date range matching the selected date. Deadlines will + also be listed, on the expiration day. + + :deadline List any deadlines past due, or due within + `org-deadline-warning-days'. The listing occurs only + in the diary for *today*, not at any other date. If + an entry is marked DONE, it is no longer listed. + + :scheduled List all items which are scheduled for the given date. + The diary for *today* also contains items which were + scheduled earlier and are not yet marked DONE. + + :todo List all TODO items from the org-file. This may be a + long list - so this is not turned on by default. + Like deadlines, these entries only show up in the + diary for *today*, not at any other date. + +The call in the diary file should look like this: + + &%%(org-diary) ~/path/to/some/orgfile.org + +Use a separate line for each org file to check. Or, if you omit the file name, +all files listed in `org-agenda-files' will be checked automatically: + + &%%(org-diary) + +If you don't give any arguments (as in the example above), the default +arguments (:deadline :scheduled :timestamp) are used. So the example above may +also be written as + + &%%(org-diary :deadline :timestamp :scheduled) + +The function expects the lisp variables `entry' and `date' to be provided +by the caller, because this is how the calendar works. Don't use this +function from a program - use `org-agenda-get-day-entries' instead." + (org-agenda-maybe-reset-markers) + (org-compile-prefix-format org-agenda-prefix-format) + (setq args (or args '(:deadline :scheduled :timestamp))) + (let* ((files (if (and entry (stringp entry) (string-match "\\S-" entry)) + (list entry) + org-agenda-files)) + file rtn results) + ;; If this is called during org-agenda, don't return any entries to + ;; the calendar. Org Agenda will list these entries itself. + (if org-disable-agenda-to-diary (setq files nil)) + (while (setq file (pop files)) + (setq rtn (apply 'org-agenda-get-day-entries file date args)) + (setq results (append results rtn))) + (if results + (concat (org-finalize-agenda-entries results) "\n")))) +(defvar org-category-table nil) +(defun org-get-category-table () + "Get the table of categories and positions in current buffer." + (let (tbl) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\\(^\\|\r\\)#\\+CATEGORY:[ \t]*\\(.*\\)" nil t) + (push (cons (point) (org-trim (match-string 2))) tbl))) + tbl)) +(defun org-get-category (&optional pos) + "Get the category applying to position POS." + (if (not org-category-table) + (cond + ((null org-category) + (setq org-category + (if buffer-file-name + (file-name-sans-extension + (file-name-nondirectory buffer-file-name)) + "???"))) + ((symbolp org-category) (symbol-name org-category)) + (t org-category)) + (let ((tbl org-category-table) + (pos (or pos (point)))) + (while (and tbl (> (caar tbl) pos)) + (pop tbl)) + (or (cdar tbl) (cdr (nth (1- (length org-category-table)) + org-category-table)))))) + +(defun org-agenda-get-day-entries (file date &rest args) + "Does the work for `org-diary' and `org-agenda'. +FILE is the path to a file to be checked for entries. DATE is date like +the one returned by `calendar-current-date'. ARGS are symbols indicating +which kind of entries should be extracted. For details about these, see +the documentation of `org-diary'." + (setq args (or args '(:deadline :scheduled :timestamp))) + (let* ((org-startup-with-deadline-check nil) + (org-startup-folded nil) + (buffer (if (file-exists-p file) + (org-get-agenda-file-buffer file) + (error "No such file %s" file))) + arg results rtn) + (if (not buffer) + ;; If file does not exist, make sure an error message ends up in diary + (list (format "ORG-AGENDA-ERROR: No such org-file %s" file)) + (with-current-buffer buffer + (unless (eq major-mode 'org-mode) + (error "Agenda file %s is not in `org-mode'" file)) + (setq org-category-table (org-get-category-table)) + (let ((case-fold-search nil)) + (save-excursion + (save-restriction + (if org-respect-restriction + (if (org-region-active-p) + ;; Respect a region to restrict search + (narrow-to-region (region-beginning) (region-end))) + ;; If we work for the calendar or many files, + ;; get rid of any restriction + (widen)) + ;; The way we repeatedly append to `results' makes it O(n^2) :-( + (while (setq arg (pop args)) + (cond + ((and (eq arg :todo) + (equal date (calendar-current-date))) + (setq rtn (org-agenda-get-todos)) + (setq results (append results rtn))) + ((eq arg :timestamp) + (setq rtn (org-agenda-get-blocks)) + (setq results (append results rtn)) + (setq rtn (org-agenda-get-timestamps)) + (setq results (append results rtn))) + ((eq arg :scheduled) + (setq rtn (org-agenda-get-scheduled)) + (setq results (append results rtn))) + ((eq arg :closed) + (setq rtn (org-agenda-get-closed)) + (setq results (append results rtn))) + ((and (eq arg :deadline) + (equal date (calendar-current-date))) + (setq rtn (org-agenda-get-deadlines)) + (setq results (append results rtn)))))))) + results)))) + +(defun org-entry-is-done-p () + "Is the current entry marked DONE?" + (save-excursion + (and (re-search-backward "[\r\n]\\*" nil t) + (looking-at org-nl-done-regexp)))) + +(defun org-at-date-range-p () + "Is the cursor inside a date range?" + (interactive) + (save-excursion + (catch 'exit + (let ((pos (point))) + (skip-chars-backward "^<\r\n") + (skip-chars-backward "<") + (and (looking-at org-tr-regexp) + (>= (match-end 0) pos) + (throw 'exit t)) + (skip-chars-backward "^<\r\n") + (skip-chars-backward "<") + (and (looking-at org-tr-regexp) + (>= (match-end 0) pos) + (throw 'exit t))) + nil))) + +(defun org-agenda-get-todos () + "Return the TODO information for agenda display." + (let* ((props (list 'face nil + 'done-face 'org-done + 'mouse-face 'highlight + 'keymap org-agenda-keymap + 'help-echo + (format "mouse-2 or RET jump to org file %s" + (abbreviate-file-name buffer-file-name)))) + (regexp (concat "[\n\r]\\*+ *\\(" + (if org-select-this-todo-keyword + (concat "\\<\\(" org-select-this-todo-keyword + "\\)\\>") + org-not-done-regexp) + "[^\n\r]*\\)")) + marker priority category tags + ee txt) + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (goto-char (match-beginning 1)) + (setq marker (org-agenda-new-marker (1+ (match-beginning 0))) + category (org-get-category) + tags (org-get-tags-at (point)) + txt (org-format-agenda-item "" (match-string 1) category tags) + priority + (+ (org-get-priority txt) + (if org-todo-kwd-priority-p + (- org-todo-kwd-max-priority -2 + (length + (member (match-string 2) org-todo-keywords))) + 1))) + (add-text-properties + 0 (length txt) (append (list 'org-marker marker 'org-hd-marker marker + 'priority priority 'category category) + props) + txt) + (push txt ee) + (goto-char (match-end 1))) + (nreverse ee))) + +(defconst org-agenda-no-heading-message + "No heading for this item in buffer or region.") + +(defun org-agenda-get-timestamps () + "Return the date stamp information for agenda display." + (let* ((props (list 'face nil + 'mouse-face 'highlight + 'keymap org-agenda-keymap + 'help-echo + (format "mouse-2 or RET jump to org file %s" + (abbreviate-file-name buffer-file-name)))) + (regexp (regexp-quote + (substring + (format-time-string + (car org-time-stamp-formats) + (apply 'encode-time ; DATE bound by calendar + (list 0 0 0 (nth 1 date) (car date) (nth 2 date)))) + 0 11))) + marker hdmarker deadlinep scheduledp donep tmp priority category + ee txt timestr tags) + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (if (not (save-match-data (org-at-date-range-p))) + (progn + (setq marker (org-agenda-new-marker (match-beginning 0)) + category (org-get-category (match-beginning 0)) + tmp (buffer-substring (max (point-min) + (- (match-beginning 0) + org-ds-keyword-length)) + (match-beginning 0)) + timestr (buffer-substring (match-beginning 0) (point-at-eol)) + deadlinep (string-match org-deadline-regexp tmp) + scheduledp (string-match org-scheduled-regexp tmp) + donep (org-entry-is-done-p)) + (if (string-match ">" timestr) + ;; substring should only run to end of time stamp + (setq timestr (substring timestr 0 (match-end 0)))) + (save-excursion + (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t) + (progn + (goto-char (match-end 1)) + (setq hdmarker (org-agenda-new-marker) + tags (org-get-tags-at)) + (looking-at "\\*+[ \t]*\\([^\r\n]+\\)") + (setq txt (org-format-agenda-item + (format "%s%s" + (if deadlinep "Deadline: " "") + (if scheduledp "Scheduled: " "")) + (match-string 1) category tags timestr))) + (setq txt org-agenda-no-heading-message)) + (setq priority (org-get-priority txt)) + (add-text-properties + 0 (length txt) (append (list 'org-marker marker + 'org-hd-marker hdmarker) props) + txt) + (if deadlinep + (add-text-properties + 0 (length txt) + (list 'face + (if donep 'org-done 'org-warning) + 'undone-face 'org-warning + 'done-face 'org-done + 'category category + 'priority (+ 100 priority)) + txt) + (if scheduledp + (add-text-properties + 0 (length txt) + (list 'face 'org-scheduled-today + 'undone-face 'org-scheduled-today + 'done-face 'org-done + 'category category + priority (+ 99 priority)) + txt) + (add-text-properties + 0 (length txt) + (list 'priority priority 'category category) txt))) + (push txt ee)) + (outline-next-heading)))) + (nreverse ee))) + +(defun org-agenda-get-closed () + "Return the logged TODO entries for agenda display." + (let* ((props (list 'mouse-face 'highlight + 'keymap org-agenda-keymap + 'help-echo + (format "mouse-2 or RET jump to org file %s" + (abbreviate-file-name buffer-file-name)))) + (regexp (concat + "\\<" org-closed-string " *\\[" + (regexp-quote + (substring + (format-time-string + (car org-time-stamp-formats) + (apply 'encode-time ; DATE bound by calendar + (list 0 0 0 (nth 1 date) (car date) (nth 2 date)))) + 1 11)))) + marker hdmarker priority category tags + ee txt timestr) + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (if (not (save-match-data (org-at-date-range-p))) + (progn + (setq marker (org-agenda-new-marker (match-beginning 0)) + category (org-get-category (match-beginning 0)) + timestr (buffer-substring (match-beginning 0) (point-at-eol)) + ;; donep (org-entry-is-done-p) + ) + (if (string-match "\\]" timestr) + ;; substring should only run to end of time stamp + (setq timestr (substring timestr 0 (match-end 0)))) + (save-excursion + (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t) + (progn + (goto-char (match-end 1)) + (setq hdmarker (org-agenda-new-marker) + tags (org-get-tags-at)) + (looking-at "\\*+[ \t]*\\([^\r\n]+\\)") + (setq txt (org-format-agenda-item + "Closed: " + (match-string 1) category tags timestr))) + (setq txt org-agenda-no-heading-message)) + (setq priority 100000) + (add-text-properties + 0 (length txt) (append (list 'org-marker marker + 'org-hd-marker hdmarker + 'face 'org-done + 'priority priority + 'category category + 'undone-face 'org-warning + 'done-face 'org-done) props) + txt) + (push txt ee)) + (outline-next-heading)))) + (nreverse ee))) + +(defun org-agenda-get-deadlines () + "Return the deadline information for agenda display." + (let* ((wdays org-deadline-warning-days) + (props (list 'mouse-face 'highlight + 'keymap org-agenda-keymap + 'help-echo + (format "mouse-2 or RET jump to org file %s" + (abbreviate-file-name buffer-file-name)))) + (regexp org-deadline-time-regexp) + (todayp (equal date (calendar-current-date))) ; DATE bound by calendar + (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar + d2 diff pos pos1 category tags + ee txt head) + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (setq pos (1- (match-beginning 1)) + d2 (time-to-days + (org-time-string-to-time (match-string 1))) + diff (- d2 d1)) + ;; When to show a deadline in the calendar: + ;; If the expiration is within wdays warning time. + ;; Past-due deadlines are only shown on the current date + (if (and (< diff wdays) todayp (not (= diff 0))) + (save-excursion + (setq category (org-get-category)) + (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t) + (progn + (goto-char (match-end 0)) + (setq pos1 (match-end 1)) + (setq tags (org-get-tags-at pos1)) + (setq head (buffer-substring-no-properties + (point) + (progn (skip-chars-forward "^\r\n") + (point)))) + (if (string-match org-looking-at-done-regexp head) + (setq txt nil) + (setq txt (org-format-agenda-item + (format "In %3d d.: " diff) head category tags)))) + (setq txt org-agenda-no-heading-message)) + (when txt + (add-text-properties + 0 (length txt) + (append + (list 'org-marker (org-agenda-new-marker pos) + 'org-hd-marker (org-agenda-new-marker pos1) + 'priority (+ (- 10 diff) (org-get-priority txt)) + 'category category + 'face (cond ((<= diff 0) 'org-warning) + ((<= diff 5) 'org-scheduled-previously) + (t nil)) + 'undone-face (cond + ((<= diff 0) 'org-warning) + ((<= diff 5) 'org-scheduled-previously) + (t nil)) + 'done-face 'org-done) + props) + txt) + (push txt ee))))) + ee)) + +(defun org-agenda-get-scheduled () + "Return the scheduled information for agenda display." + (let* ((props (list 'face 'org-scheduled-previously + 'undone-face 'org-scheduled-previously + 'done-face 'org-done + 'mouse-face 'highlight + 'keymap org-agenda-keymap + 'help-echo + (format "mouse-2 or RET jump to org file %s" + (abbreviate-file-name buffer-file-name)))) + (regexp org-scheduled-time-regexp) + (todayp (equal date (calendar-current-date))) ; DATE bound by calendar + (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar + d2 diff pos pos1 category tags + ee txt head) + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (setq pos (1- (match-beginning 1)) + d2 (time-to-days + (org-time-string-to-time (match-string 1))) + diff (- d2 d1)) + ;; When to show a scheduled item in the calendar: + ;; If it is on or past the date. + (if (and (< diff 0) todayp) + (save-excursion + (setq category (org-get-category)) + (if (re-search-backward "\\(^\\|\r\\)\\*+[ \t]*" nil t) + (progn + (goto-char (match-end 0)) + (setq pos1 (match-end 1)) + (setq tags (org-get-tags-at)) + (setq head (buffer-substring-no-properties + (point) + (progn (skip-chars-forward "^\r\n") (point)))) + (if (string-match org-looking-at-done-regexp head) + (setq txt nil) + (setq txt (org-format-agenda-item + (format "Sched.%2dx: " (- 1 diff)) head + category tags)))) + (setq txt org-agenda-no-heading-message)) + (when txt + (add-text-properties + 0 (length txt) + (append (list 'org-marker (org-agenda-new-marker pos) + 'org-hd-marker (org-agenda-new-marker pos1) + 'priority (+ (- 5 diff) (org-get-priority txt)) + 'category category) + props) txt) + (push txt ee))))) + ee)) + +(defun org-agenda-get-blocks () + "Return the date-range information for agenda display." + (let* ((props (list 'face nil + 'mouse-face 'highlight + 'keymap org-agenda-keymap + 'help-echo + (format "mouse-2 or RET jump to org file %s" + (abbreviate-file-name buffer-file-name)))) + (regexp org-tr-regexp) + (d0 (calendar-absolute-from-gregorian date)) + marker hdmarker ee txt d1 d2 s1 s2 timestr category tags) + (goto-char (point-min)) + (while (re-search-forward regexp nil t) + (setq timestr (match-string 0) + s1 (match-string 1) + s2 (match-string 2) + d1 (time-to-days (org-time-string-to-time s1)) + d2 (time-to-days (org-time-string-to-time s2))) + (if (and (> (- d0 d1) -1) (> (- d2 d0) -1)) + ;; Only allow days between the limits, because the normal + ;; date stamps will catch the limits. + (save-excursion + (setq marker (org-agenda-new-marker (point))) + (setq category (org-get-category)) + (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t) + (progn + (setq hdmarker (org-agenda-new-marker (match-end 1))) + (goto-char (match-end 1)) + (setq tags (org-get-tags-at)) + (looking-at "\\*+[ \t]*\\([^\r\n]+\\)") + (setq txt (org-format-agenda-item + (format (if (= d1 d2) "" "(%d/%d): ") + (1+ (- d0 d1)) (1+ (- d2 d1))) + (match-string 1) category tags + (if (= d0 d1) timestr)))) + (setq txt org-agenda-no-heading-message)) + (add-text-properties + 0 (length txt) (append (list 'org-marker marker + 'org-hd-marker hdmarker + 'priority (org-get-priority txt) + 'category category) + props) + txt) + (push txt ee))) + (outline-next-heading)) + ;; Sort the entries by expiration date. + (nreverse ee))) + +(defconst org-plain-time-of-day-regexp + (concat + "\\(\\<[012]?[0-9]" + "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)" + "\\(--?" + "\\(\\<[012]?[0-9]" + "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)" + "\\)?") + "Regular expression to match a plain time or time range. +Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following +groups carry important information: +0 the full match +1 the first time, range or not +8 the second time, if it is a range.") + +(defconst org-stamp-time-of-day-regexp + (concat + "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +[a-zA-Z]+ +\\)" + "\\([012][0-9]:[0-5][0-9]\\)>" + "\\(--?" + "<\\1\\([012][0-9]:[0-5][0-9]\\)>\\)?") + "Regular expression to match a timestamp time or time range. +After a match, the following groups carry important information: +0 the full match +1 date plus weekday, for backreferencing to make sure both times on same day +2 the first time, range or not +4 the second time, if it is a range.") + +(defvar org-prefix-has-time nil + "A flag, set by `org-compile-prefix-format'. +The flag is set if the currently compiled format contains a `%t'.") +(defvar org-prefix-has-tag nil + "A flag, set by `org-compile-prefix-format'. +The flag is set if the currently compiled format contains a `%T'.") + +(defun org-format-agenda-item (extra txt &optional category tags dotime noprefix) + "Format TXT to be inserted into the agenda buffer. +In particular, it adds the prefix and corresponding text properties. EXTRA +must be a string and replaces the `%s' specifier in the prefix format. +CATEGORY (string, symbol or nil) may be used to overrule the default +category taken from local variable or file name. It will replace the `%c' +specifier in the format. DOTIME, when non-nil, indicates that a +time-of-day should be extracted from TXT for sorting of this entry, and for +the `%t' specifier in the format. When DOTIME is a string, this string is +searched for a time before TXT is. NOPREFIX is a flag and indicates that +only the correctly processes TXT should be returned - this is used by +`org-agenda-change-all-lines'. TAG can be the tag of the headline." + (save-match-data + ;; Diary entries sometimes have extra whitespace at the beginning + (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt))) + (let* ((category (or category + org-category + (if buffer-file-name + (file-name-sans-extension + (file-name-nondirectory buffer-file-name)) + ""))) + (tag (or (nth (1- (or (length tags) 0)) tags) "")) + time ;; needed for the eval of the prefix format + (ts (if dotime (concat (if (stringp dotime) dotime "") txt))) + (time-of-day (and dotime (org-get-time-of-day ts))) + stamp plain s0 s1 s2 rtn) + (when (and dotime time-of-day org-prefix-has-time) + ;; Extract starting and ending time and move them to prefix + (when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts)) + (setq plain (string-match org-plain-time-of-day-regexp ts))) + (setq s0 (match-string 0 ts) + s1 (match-string (if plain 1 2) ts) + s2 (match-string (if plain 8 4) ts)) + + ;; If the times are in TXT (not in DOTIMES), and the prefix will list + ;; them, we might want to remove them there to avoid duplication. + ;; The user can turn this off with a variable. + (if (and org-agenda-remove-times-when-in-prefix (or stamp plain) + (string-match (concat (regexp-quote s0) " *") txt) + (if (eq org-agenda-remove-times-when-in-prefix 'beg) + (= (match-beginning 0) 0) + t)) + (setq txt (replace-match "" nil nil txt)))) + ;; Normalize the time(s) to 24 hour + (if s1 (setq s1 (org-get-time-of-day s1 'string))) + (if s2 (setq s2 (org-get-time-of-day s2 'string)))) + + (when (and (or (eq org-agenda-remove-tags-when-in-prefix t) + (and org-agenda-remove-tags-when-in-prefix + org-prefix-has-tag)) + (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" txt)) + (setq txt (replace-match "" t t txt))) + + ;; Create the final string + (if noprefix + (setq rtn txt) + ;; Prepare the variables needed in the eval of the compiled format + (setq time (cond (s2 (concat s1 "-" s2)) + (s1 (concat s1 "......")) + (t "")) + extra (or extra "") + category (if (symbolp category) (symbol-name category) category)) + ;; Evaluate the compiled format + (setq rtn (concat (eval org-prefix-format-compiled) txt))) + + ;; And finally add the text properties + (add-text-properties + 0 (length rtn) (list 'category (downcase category) + 'tags tags + 'prefix-length (- (length rtn) (length txt)) + 'time-of-day time-of-day + 'dotime dotime) + rtn) + rtn))) + +(defun org-agenda-add-time-grid-maybe (list ndays todayp) + (catch 'exit + (cond ((not org-agenda-use-time-grid) (throw 'exit list)) + ((and todayp (member 'today (car org-agenda-time-grid)))) + ((and (= ndays 1) (member 'daily (car org-agenda-time-grid)))) + ((member 'weekly (car org-agenda-time-grid))) + (t (throw 'exit list))) + (let* ((have (delq nil (mapcar + (lambda (x) (get-text-property 1 'time-of-day x)) + list))) + (string (nth 1 org-agenda-time-grid)) + (gridtimes (nth 2 org-agenda-time-grid)) + (req (car org-agenda-time-grid)) + (remove (member 'remove-match req)) + new time) + (if (and (member 'require-timed req) (not have)) + ;; don't show empty grid + (throw 'exit list)) + (while (setq time (pop gridtimes)) + (unless (and remove (member time have)) + (setq time (int-to-string time)) + (push (org-format-agenda-item + nil string "" nil ;; FIXME: put a category for the grid? + (concat (substring time 0 -2) ":" (substring time -2))) + new) + (put-text-property + 1 (length (car new)) 'face 'org-time-grid (car new)))) + (if (member 'time-up org-agenda-sorting-strategy) + (append new list) + (append list new))))) + +(defun org-compile-prefix-format (format) + "Compile the prefix format into a Lisp form that can be evaluated. +The resulting form is returned and stored in the variable +`org-prefix-format-compiled'." + (setq org-prefix-has-time nil org-prefix-has-tag nil) + (let ((start 0) varform vars var (s format)e c f opt) + (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([cts]\\)" + s start) + (setq var (cdr (assoc (match-string 4 s) + '(("c" . category) ("t" . time) ("s" . extra) + ("T" . tag)))) + c (or (match-string 3 s) "") + opt (match-beginning 1) + start (1+ (match-beginning 0))) + (if (equal var 'time) (setq org-prefix-has-time t)) + (if (equal var 'tag) (setq org-prefix-has-tag t)) + (setq f (concat "%" (match-string 2 s) "s")) + (if opt + (setq varform + `(if (equal "" ,var) + "" + (format ,f (if (equal "" ,var) "" (concat ,var ,c))))) + (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c))))) + (setq s (replace-match "%s" t nil s)) + (push varform vars)) + (setq vars (nreverse vars)) + (setq org-prefix-format-compiled `(format ,s ,@vars)))) + +(defun org-get-time-of-day (s &optional string) + "Check string S for a time of day. +If found, return it as a military time number between 0 and 2400. +If not found, return nil. +The optional STRING argument forces conversion into a 5 character wide string +HH:MM." + (save-match-data + (when + (or + (string-match + "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)\\([AaPp][Mm]\\)?\\> *" s) + (string-match + "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\([AaPp][Mm]\\)\\> *" s)) + (let* ((t0 (+ (* 100 + (+ (string-to-number (match-string 1 s)) + (if (and (match-beginning 4) + (equal (downcase (match-string 4 s)) "pm")) + 12 0))) + (if (match-beginning 3) + (string-to-number (match-string 3 s)) + 0))) + (t1 (concat " " + (if (< t0 100) "0" "") (if (< t0 10) "0" "") + (int-to-string t0)))) + (if string (concat (substring t1 -4 -2) ":" (substring t1 -2)) t0))))) + +(defun org-finalize-agenda-entries (list) + "Sort and concatenate the agenda items." + (mapconcat 'identity (sort list 'org-entries-lessp) "\n")) + +(defsubst org-cmp-priority (a b) + "Compare the priorities of string A and B." + (let ((pa (or (get-text-property 1 'priority a) 0)) + (pb (or (get-text-property 1 'priority b) 0))) + (cond ((> pa pb) +1) + ((< pa pb) -1) + (t nil)))) + +(defsubst org-cmp-category (a b) + "Compare the string values of categories of strings A and B." + (let ((ca (or (get-text-property 1 'category a) "")) + (cb (or (get-text-property 1 'category b) ""))) + (cond ((string-lessp ca cb) -1) + ((string-lessp cb ca) +1) + (t nil)))) + +(defsubst org-cmp-time (a b) + "Compare the time-of-day values of strings A and B." + (let* ((def (if org-sort-agenda-notime-is-late 2401 -1)) + (ta (or (get-text-property 1 'time-of-day a) def)) + (tb (or (get-text-property 1 'time-of-day b) def))) + (cond ((< ta tb) -1) + ((< tb ta) +1) + (t nil)))) + +(defun org-entries-lessp (a b) + "Predicate for sorting agenda entries." + ;; The following variables will be used when the form is evaluated. + (let* ((time-up (org-cmp-time a b)) + (time-down (if time-up (- time-up) nil)) + (priority-up (org-cmp-priority a b)) + (priority-down (if priority-up (- priority-up) nil)) + (category-up (org-cmp-category a b)) + (category-down (if category-up (- category-up) nil)) + (category-keep (if category-up +1 nil))) ; FIXME +1 or -1? + (cdr (assoc + (eval (cons 'or org-agenda-sorting-strategy)) + '((-1 . t) (1 . nil) (nil . nil)))))) + +(defun org-agenda-show-priority () + "Show the priority of the current item. +This priority is composed of the main priority given with the [#A] cookies, +and by additional input from the age of a schedules or deadline entry." + (interactive) + (let* ((pri (get-text-property (point-at-bol) 'priority))) + (message "Priority is %d" (if pri pri -1000)))) + +(defun org-agenda-show-tags () + "Show the tags applicable to the current item." + (interactive) + (let* ((tags (get-text-property (point-at-bol) 'tags))) + (if tags + (message "Tags are :%s:" (mapconcat 'identity tags ":")) + (message "No tags associated with this line")))) + +(defun org-agenda-goto (&optional highlight) + "Go to the Org-mode file which contains the item at point." + (interactive) + (let* ((marker (or (get-text-property (point) 'org-marker) + (org-agenda-error))) + (buffer (marker-buffer marker)) + (pos (marker-position marker))) + (switch-to-buffer-other-window buffer) + (widen) + (goto-char pos) + (when (eq major-mode 'org-mode) + (org-show-hidden-entry) + (save-excursion + (and (outline-next-heading) + (org-flag-heading nil)))) ; show the next heading + (and highlight (org-highlight (point-at-bol) (point-at-eol))))) + +(defun org-agenda-switch-to () + "Go to the Org-mode file which contains the item at point." + (interactive) + (let* ((marker (or (get-text-property (point) 'org-marker) + (org-agenda-error))) + (buffer (marker-buffer marker)) + (pos (marker-position marker))) + (switch-to-buffer buffer) + (delete-other-windows) + (widen) + (goto-char pos) + (when (eq major-mode 'org-mode) + (org-show-hidden-entry) + (save-excursion + (and (outline-next-heading) + (org-flag-heading nil)))))) ; show the next heading + +(defun org-agenda-goto-mouse (ev) + "Go to the Org-mode file which contains the item at the mouse click." + (interactive "e") + (mouse-set-point ev) + (org-agenda-goto)) + +(defun org-agenda-show () + "Display the Org-mode file which contains the item at point." + (interactive) + (let ((win (selected-window))) + (org-agenda-goto t) + (select-window win))) + +(defun org-agenda-recenter (arg) + "Display the Org-mode file which contains the item at point and recenter." + (interactive "P") + (let ((win (selected-window))) + (org-agenda-goto t) + (recenter arg) + (select-window win))) + +(defun org-agenda-show-mouse (ev) + "Display the Org-mode file which contains the item at the mouse click." + (interactive "e") + (mouse-set-point ev) + (org-agenda-show)) + +(defun org-agenda-check-no-diary () + "Check if the entry is a diary link and abort if yes." + (if (get-text-property (point) 'org-agenda-diary-link) + (org-agenda-error))) + +(defun org-agenda-error () + (error "Command not allowed in this line")) + +(defvar org-last-heading-marker (make-marker) + "Marker pointing to the headline that last changed its TODO state +by a remote command from the agenda.") + +(defun org-agenda-todo (&optional arg) + "Cycle TODO state of line at point, also in Org-mode file. +This changes the line at point, all other lines in the agenda referring to +the same tree node, and the headline of the tree node in the Org-mode file." + (interactive "P") + (org-agenda-check-no-diary) + (let* ((col (current-column)) + (marker (or (get-text-property (point) 'org-marker) + (org-agenda-error))) + (buffer (marker-buffer marker)) + (pos (marker-position marker)) + (hdmarker (get-text-property (point) 'org-hd-marker)) + (buffer-read-only nil) + newhead) + (with-current-buffer buffer + (widen) + (goto-char pos) + (org-show-hidden-entry) + (save-excursion + (and (outline-next-heading) + (org-flag-heading nil))) ; show the next heading + (org-todo arg) + (forward-char 1) + (setq newhead (org-get-heading)) + (save-excursion + (org-back-to-heading) + (move-marker org-last-heading-marker (point)))) + (beginning-of-line 1) + (save-excursion + (org-agenda-change-all-lines newhead hdmarker 'fixface)) + (move-to-column col))) + +(defun org-agenda-change-all-lines (newhead hdmarker &optional fixface) + "Change all lines in the agenda buffer which match HDMARKER. +The new content of the line will be NEWHEAD (as modified by +`org-format-agenda-item'). HDMARKER is checked with +`equal' against all `org-hd-marker' text properties in the file. +If FIXFACE is non-nil, the face of each item is modified acording to +the new TODO state." + (let* (props m pl undone-face done-face finish new dotime cat tags) +; (setq newhead (org-format-agenda-item "x" newhead "x" nil 'noprefix)) + (save-excursion + (goto-char (point-max)) + (beginning-of-line 1) + (while (not finish) + (setq finish (bobp)) + (when (and (setq m (get-text-property (point) 'org-hd-marker)) + (equal m hdmarker)) + (setq props (text-properties-at (point)) + dotime (get-text-property (point) 'dotime) + cat (get-text-property (point) 'category) + tags (get-text-property (point) 'tags) + new (org-format-agenda-item "x" newhead cat tags dotime 'noprefix) + pl (get-text-property (point) 'prefix-length) + undone-face (get-text-property (point) 'undone-face) + done-face (get-text-property (point) 'done-face)) + (move-to-column pl) + (if (looking-at ".*") + (progn + (replace-match new t t) + (beginning-of-line 1) + (add-text-properties (point-at-bol) (point-at-eol) props) + (if fixface + (add-text-properties + (point-at-bol) (point-at-eol) + (list 'face + (if org-last-todo-state-is-todo + undone-face done-face)))) + (beginning-of-line 1)) + (error "Line update did not work"))) + (beginning-of-line 0))))) + +(defun org-agenda-priority-up () + "Increase the priority of line at point, also in Org-mode file." + (interactive) + (org-agenda-priority 'up)) + +(defun org-agenda-priority-down () + "Decrease the priority of line at point, also in Org-mode file." + (interactive) + (org-agenda-priority 'down)) + +(defun org-agenda-priority (&optional force-direction) + "Set the priority of line at point, also in Org-mode file. +This changes the line at point, all other lines in the agenda referring to +the same tree node, and the headline of the tree node in the Org-mode file." + (interactive) + (org-agenda-check-no-diary) + (let* ((marker (or (get-text-property (point) 'org-marker) + (org-agenda-error))) + (buffer (marker-buffer marker)) + (pos (marker-position marker)) + (hdmarker (get-text-property (point) 'org-hd-marker)) + (buffer-read-only nil) + newhead) + (with-current-buffer buffer + (widen) + (goto-char pos) + (org-show-hidden-entry) + (save-excursion + (and (outline-next-heading) + (org-flag-heading nil))) ; show the next heading + (funcall 'org-priority force-direction) + (end-of-line 1) + (setq newhead (org-get-heading))) + (org-agenda-change-all-lines newhead hdmarker) + (beginning-of-line 1))) + +(defun org-get-tags-at (&optional pos) + "Get a list of all headline targs applicable at POS. +POS defaults to point. If tags are inherited, the list contains +the targets in the same sequence as the headlines appear, i.e. +the tags of the current headline come last." + (interactive) + (let (tags) + (save-excursion + (goto-char (or pos (point))) + (save-match-data + (org-back-to-heading t) + (condition-case nil + (while t + (if (looking-at "[^\r\n]+?:\\([a-zA-Z_@0-9:]+\\):[ \t]*\\([\n\r]\\|\\'\\)") + (setq tags (append (org-split-string (match-string 1) ":") tags))) + (or org-use-tag-inheritance (error "")) + (org-up-heading-all 1)) + (error nil)))) + (message "%s" tags) + tags)) + +(defun org-agenda-set-tags () + "Set tags for the current headline." + (interactive) + (org-agenda-check-no-diary) + (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed + (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker) + (org-agenda-error))) + (buffer (marker-buffer hdmarker)) + (pos (marker-position hdmarker)) + (buffer-read-only nil) + newhead) + (with-current-buffer buffer + (widen) + (goto-char pos) + (org-show-hidden-entry) + (save-excursion + (and (outline-next-heading) + (org-flag-heading nil))) ; show the next heading + (call-interactively 'org-set-tags) + (end-of-line 1) + (setq newhead (org-get-heading))) + (org-agenda-change-all-lines newhead hdmarker) + (beginning-of-line 1))) + +(defun org-agenda-date-later (arg &optional what) + "Change the date of this item to one day later." + (interactive "p") + (org-agenda-check-type t 'agenda 'timeline) + (org-agenda-check-no-diary) + (let* ((marker (or (get-text-property (point) 'org-marker) + (org-agenda-error))) + (buffer (marker-buffer marker)) + (pos (marker-position marker))) + (with-current-buffer buffer + (widen) + (goto-char pos) + (if (not (org-at-timestamp-p)) + (error "Cannot find time stamp")) + (org-timestamp-change arg (or what 'day)) + (message "Time stamp changed to %s" org-last-changed-timestamp)))) + +(defun org-agenda-date-earlier (arg &optional what) + "Change the date of this item to one day earlier." + (interactive "p") + (org-agenda-date-later (- arg) what)) + +(defun org-agenda-date-prompt (arg) + "Change the date of this item. Date is prompted for, with default today. +The prefix ARG is passed to the `org-time-stamp' command and can therefore +be used to request time specification in the time stamp." + (interactive "P") + (org-agenda-check-type t 'agenda 'timeline) + (org-agenda-check-no-diary) + (let* ((marker (or (get-text-property (point) 'org-marker) + (org-agenda-error))) + (buffer (marker-buffer marker)) + (pos (marker-position marker))) + (with-current-buffer buffer + (widen) + (goto-char pos) + (if (not (org-at-timestamp-p)) + (error "Cannot find time stamp")) + (org-time-stamp arg) + (message "Time stamp changed to %s" org-last-changed-timestamp)))) + +(defun org-get-heading () + "Return the heading of the current entry, without the stars." + (save-excursion + (and (memq (char-before) '(?\n ?\r)) (skip-chars-forward "^\n\r")) +;;FIXME???????? (and (bolp) (end-of-line 1)) + (if (and (re-search-backward "[\r\n]\\*" nil t) + (looking-at "[\r\n]\\*+[ \t]+\\([^\r\n]*\\)")) + (match-string 1) + ""))) + +(defun org-agenda-diary-entry () + "Make a diary entry, like the `i' command from the calendar. +All the standard commands work: block, weekly etc." + (interactive) + (org-agenda-check-type t 'agenda 'timeline) + (require 'diary-lib) + (let* ((char (progn + (message "Diary entry: [d]ay [w]eekly [m]onthly [y]early [a]nniversary [b]lock [c]yclic") + (read-char-exclusive))) + (cmd (cdr (assoc char + '((?d . insert-diary-entry) + (?w . insert-weekly-diary-entry) + (?m . insert-monthly-diary-entry) + (?y . insert-yearly-diary-entry) + (?a . insert-anniversary-diary-entry) + (?b . insert-block-diary-entry) + (?c . insert-cyclic-diary-entry))))) + (oldf (symbol-function 'calendar-cursor-to-date)) + (point (point)) + (mark (or (mark t) (point)))) + (unless cmd + (error "No command associated with <%c>" char)) + (unless (and (get-text-property point 'day) + (or (not (equal ?b char)) + (get-text-property mark 'day))) + (error "Don't know which date to use for diary entry")) + ;; We implement this by hacking the `calendar-cursor-to-date' function + ;; and the `calendar-mark-ring' variable. Saves a lot of code. + (let ((calendar-mark-ring + (list (calendar-gregorian-from-absolute + (or (get-text-property mark 'day) + (get-text-property point 'day)))))) + (unwind-protect + (progn + (fset 'calendar-cursor-to-date + (lambda (&optional error) + (calendar-gregorian-from-absolute + (get-text-property point 'day)))) + (call-interactively cmd)) + (fset 'calendar-cursor-to-date oldf))))) + + +(defun org-agenda-execute-calendar-command (cmd) + "Execute a calendar command from the agenda, with the date associated to +the cursor position." + (org-agenda-check-type t 'agenda 'timeline) + (require 'diary-lib) + (unless (get-text-property (point) 'day) + (error "Don't know which date to use for calendar command")) + (let* ((oldf (symbol-function 'calendar-cursor-to-date)) + (point (point)) + (date (calendar-gregorian-from-absolute + (get-text-property point 'day))) + (displayed-day (extract-calendar-day date)) + (displayed-month (extract-calendar-month date)) + (displayed-year (extract-calendar-year date))) + (unwind-protect + (progn + (fset 'calendar-cursor-to-date + (lambda (&optional error) + (calendar-gregorian-from-absolute + (get-text-property point 'day)))) + (call-interactively cmd)) + (fset 'calendar-cursor-to-date oldf)))) + +(defun org-agenda-phases-of-moon () + "Display the phases of the moon for the 3 months around the cursor date." + (interactive) + (org-agenda-execute-calendar-command 'calendar-phases-of-moon)) + +(defun org-agenda-holidays () + "Display the holidays for the 3 months around the cursor date." + (interactive) + (org-agenda-execute-calendar-command 'list-calendar-holidays)) + +(defun org-agenda-sunrise-sunset (arg) + "Display sunrise and sunset for the cursor date. +Latitude and longitude can be specified with the variables +`calendar-latitude' and `calendar-longitude'. When called with prefix +argument, latitude and longitude will be prompted for." + (interactive "P") + (let ((calendar-longitude (if arg nil calendar-longitude)) + (calendar-latitude (if arg nil calendar-latitude)) + (calendar-location-name + (if arg "the given coordinates" calendar-location-name))) + (org-agenda-execute-calendar-command 'calendar-sunrise-sunset))) + +(defun org-agenda-goto-calendar () + "Open the Emacs calendar with the date at the cursor." + (interactive) + (org-agenda-check-type t 'agenda 'timeline) + (let* ((day (or (get-text-property (point) 'day) + (error "Don't know which date to open in calendar"))) + (date (calendar-gregorian-from-absolute day)) + (calendar-move-hook nil) + (view-diary-entries-initially nil)) + (calendar) + (calendar-goto-date date))) + +(defun org-calendar-goto-agenda () + "Compute the Org-mode agenda for the calendar date displayed at the cursor. +This is a command that has to be installed in `calendar-mode-map'." + (interactive) + (org-agenda-list nil (calendar-absolute-from-gregorian + (calendar-cursor-to-date)) + nil t)) + +(defun org-agenda-convert-date () + (interactive) + (org-agenda-check-type t 'agenda 'timeline) + (let ((day (get-text-property (point) 'day)) + date s) + (unless day + (error "Don't know which date to convert")) + (setq date (calendar-gregorian-from-absolute day)) + (setq s (concat + "Gregorian: " (calendar-date-string date) "\n" + "ISO: " (calendar-iso-date-string date) "\n" + "Day of Yr: " (calendar-day-of-year-string date) "\n" + "Julian: " (calendar-julian-date-string date) "\n" + "Astron. JD: " (calendar-astro-date-string date) + " (Julian date number at noon UTC)\n" + "Hebrew: " (calendar-hebrew-date-string date) " (until sunset)\n" + "Islamic: " (calendar-islamic-date-string date) " (until sunset)\n" + "French: " (calendar-french-date-string date) "\n" + "Mayan: " (calendar-mayan-date-string date) "\n" + "Coptic: " (calendar-coptic-date-string date) "\n" + "Ethiopic: " (calendar-ethiopic-date-string date) "\n" + "Persian: " (calendar-persian-date-string date) "\n" + "Chinese: " (calendar-chinese-date-string date) "\n")) + (with-output-to-temp-buffer "*Dates*" + (princ s)) + (if (fboundp 'fit-window-to-buffer) + (fit-window-to-buffer (get-buffer-window "*Dates*"))))) + +;;; Tags + +(defun org-scan-tags (action matcher &optional todo-only) + "Scan headline tags with inheritance and produce output ACTION. +ACTION can be `sparse-tree' or `agenda'. MATCHER is a Lisp form to be +evaluated, testing if a given set of tags qualifies a headline for +inclusion. When TODO-ONLY is non-nil, only lines with a TODO keyword +are included in the output." + (let* ((re (concat "[\n\r]" outline-regexp " *\\(\\<\\(" + (mapconcat 'regexp-quote + (nreverse (cdr (reverse org-todo-keywords))) + "\\|") + "\\>\\)\\)? *\\(.*?\\)\\(:[A-Za-z_@0-9:]+:\\)?[ \t]*[\n\r]")) + (props (list 'face nil + 'done-face 'org-done + 'undone-face nil + 'mouse-face 'highlight + 'keymap org-agenda-keymap + 'help-echo + (format "mouse-2 or RET jump to org file %s" + (abbreviate-file-name buffer-file-name)))) + lspos + tags tags-list tags-alist (llast 0) rtn level category i txt + todo marker) + + (save-excursion + (goto-char (point-min)) + (when (eq action 'sparse-tree) (hide-sublevels 1)) + (while (re-search-forward re nil t) + (setq todo (if (match-end 1) (match-string 2)) + tags (if (match-end 4) (match-string 4))) + (goto-char (setq lspos (1+ (match-beginning 0)))) + (setq level (funcall outline-level) + category (org-get-category)) + (setq i llast llast level) + ;; remove tag lists from same and sublevels + (while (>= i level) + (when (setq entry (assoc i tags-alist)) + (setq tags-alist (delete entry tags-alist))) + (setq i (1- i))) + ;; add the nex tags + (when tags + (setq tags (mapcar 'downcase (org-split-string tags ":")) + tags-alist + (cons (cons level tags) tags-alist))) + ;; compile tags for current headline + (setq tags-list + (if org-use-tag-inheritance + (apply 'append (mapcar 'cdr tags-alist)) + tags)) + (when (and (or (not todo-only) todo) + (eval matcher)) + ;; list this headline + (if (eq action 'sparse-tree) + (progn + (org-show-hierarchy-above)) + (setq txt (org-format-agenda-item + "" + (concat + (if org-tags-match-list-sublevels + (make-string (1- level) ?.) "") + (org-get-heading)) + category tags-list)) + (goto-char lspos) + (setq marker (org-agenda-new-marker)) + (add-text-properties + 0 (length txt) + (append (list 'org-marker marker 'org-hd-marker marker + 'category category) + props) + txt) + (push txt rtn)) + ;; if we are to skip sublevels, jump to end of subtree + (point) + (or org-tags-match-list-sublevels (org-end-of-subtree))))) + (nreverse rtn))) + +(defun org-tags-sparse-tree (&optional arg match) + "Create a sparse tree according to tags search string MATCH. +MATCH can contain positive and negative selection of tags, like +\"+WORK+URGENT-WITHBOSS\"." + (interactive "P") + (let ((org-show-following-heading nil) + (org-show-hierarchy-above nil)) + (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match))))) + +(defun org-make-tags-matcher (match) + "Create the TAGS matcher form for the tags-selecting string MATCH." + (unless match + ;; Get a new match request, with completion + (setq org-last-tags-completion-table + (or (org-get-buffer-tags) + org-last-tags-completion-table)) + (setq match (completing-read + "Tags: " 'org-tags-completion-function nil nil nil + 'org-tags-history))) + ;; parse the string and create a lisp form + (let ((match0 match) minus tag mm matcher orterms term orlist) + (setq orterms (org-split-string match "|")) + (while (setq term (pop orterms)) + (while (string-match "^&?\\([-+:]\\)?\\([A-Za-z_@0-9]+\\)" term) + (setq minus (and (match-end 1) + (equal (match-string 1 term) "-")) + tag (match-string 2 term) + term (substring term (match-end 0)) + mm (list 'member (downcase tag) 'tags-list) + mm (if minus (list 'not mm) mm)) + (push mm matcher)) + (push (if (> (length matcher) 1) (cons 'and matcher) (car matcher)) + orlist) + (setq matcher nil)) + (setq matcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist))) + ;; Return the string and lisp forms of the matcher + (cons match0 matcher))) + +;;;###autoload +(defun org-tags-view (&optional todo-only match keep-modes) + "Show all headlines for all `org-agenda-files' matching a TAGS criterion. +The prefix arg TODO-ONLY limits the search to TODO entries." + (interactive "P") + (org-agenda-maybe-reset-markers 'force) + (org-compile-prefix-format org-agenda-prefix-format) + (let* ((org-agenda-keep-modes keep-modes) + (org-tags-match-list-sublevels + (if todo-only t org-tags-match-list-sublevels)) + (win (selected-window)) + (completion-ignore-case t) + rtn rtnall files file pos matcher + buffer) + (setq matcher (org-make-tags-matcher match) + match (car matcher) matcher (cdr matcher)) + (if (not (equal (current-buffer) (get-buffer org-agenda-buffer-name))) + (progn + (delete-other-windows) + (switch-to-buffer-other-window + (get-buffer-create org-agenda-buffer-name)))) + (setq buffer-read-only nil) + (erase-buffer) + (org-agenda-mode) (setq buffer-read-only nil) + (set (make-local-variable 'org-agenda-type) 'tags) + (set (make-local-variable 'org-agenda-redo-command) + (list 'org-tags-view (list 'quote todo-only) + (list 'if 'current-prefix-arg nil match) t)) + (setq files (org-agenda-files) + rtnall nil) + (while (setq file (pop files)) + (catch 'nextfile + (org-check-agenda-file file) + (setq buffer (if (file-exists-p file) + (org-get-agenda-file-buffer file) + (error "No such file %s" file))) + (if (not buffer) + ;; If file does not exist, merror message to agenda + (setq rtn (list + (format "ORG-AGENDA-ERROR: No such org-file %s" file)) + rtnall (append rtnall rtn)) + (with-current-buffer buffer + (unless (eq major-mode 'org-mode) + (error "Agenda file %s is not in `org-mode'" file)) + (save-excursion + (save-restriction + (if org-respect-restriction + (if (org-region-active-p) + ;; Respect a region to restrict search + (narrow-to-region (region-beginning) (region-end))) + ;; If we work for the calendar or many files, + ;; get rid of any restriction + (widen)) + (setq rtn (org-scan-tags 'agenda matcher todo-only)) + (setq rtnall (append rtnall rtn)))))))) + (insert "Headlines with TAGS match: ") + (add-text-properties (point-min) (1- (point)) + (list 'face 'org-link)) + (setq pos (point)) + (insert match "\n") + (add-text-properties pos (1- (point)) (list 'face 'org-warning)) + (setq pos (point)) + (insert "Press `C-u r' to search again with new search string\n") + (add-text-properties pos (1- (point)) (list 'face 'org-link)) + (when rtnall + (insert (mapconcat 'identity rtnall "\n"))) + (goto-char (point-min)) + (setq buffer-read-only t) + (org-fit-agenda-window) + (if (not org-select-agenda-window) (select-window win)))) + +(defvar org-add-colon-after-tag-completion nil) ;; dynamically skoped param +(defun org-set-tags (&optional arg just-align) + "Set the tags for the current headline. +With prefix ARG, realign all tags in headings in the current buffer." + (interactive) + (let* (;(inherit (org-get-inherited-tags)) + (re (concat "^" outline-regexp)) + (col (current-column)) + (current (org-get-tags)) + tags hd empty invis) + (if arg + (save-excursion + (goto-char (point-min)) + (while (re-search-forward re nil t) + (org-set-tags nil t)) + (message "All tags realigned to column %d" org-tags-column)) + (if just-align + (setq tags current) + (setq org-last-tags-completion-table + (or (org-get-buffer-tags) + org-last-tags-completion-table)) + (setq tags + (let ((org-add-colon-after-tag-completion t)) + (completing-read "Tags: " 'org-tags-completion-function + nil nil current 'org-tags-history))) + (while (string-match "[-+&]+" tags) + (setq tags (replace-match ":" t t tags)))) + ;; FIXME: still optimize this by not checking when JUST-ALIGN? + (unless (setq empty (string-match "\\`[\t ]*\\'" tags)) + (unless (string-match ":$" tags) (setq tags (concat tags ":"))) + (unless (string-match "^:" tags) (setq tags (concat ":" tags)))) + (if (equal current "") + (progn + (end-of-line 1) + (or empty (insert-before-markers " "))) + (beginning-of-line 1) + (setq invis (org-invisible-p)) + (looking-at (concat "\\(.*\\)\\(" (regexp-quote current) "\\)[ \t]*")) + (setq hd (match-string 1)) + (delete-region (match-beginning 0) (match-end 0)) + (insert-before-markers (org-trim hd) (if empty "" " "))) + ;; FIXME: What happens when adding a new tag??? Seems OK!!! + (unless (equal tags "") + (move-to-column (max (current-column) + (if (> org-tags-column 0) + org-tags-column + (- (- org-tags-column) (length tags)))) + t) + (insert-before-markers tags) + (if (and (not invis) (org-invisible-p)) + (outline-flag-region (point-at-bol) (point) nil))) + (move-to-column col)))) + +(defun org-tags-completion-function (string predicate &optional flag) + (let (s1 s2 rtn (ctable org-last-tags-completion-table)) + (if (string-match "^\\(.*[-+:&|]\\)\\([^-+:&|]*\\)$" string) + (setq s1 (match-string 1 string) + s2 (match-string 2 string)) + (setq s1 "" s2 string)) + (cond + ((eq flag nil) + ;; try completion + (setq rtn (try-completion s2 ctable)) + (if (stringp rtn) + (concat s1 s2 (substring rtn (length s2)) + (if (and org-add-colon-after-tag-completion + (assoc rtn ctable)) + ":" ""))) + ) + ((eq flag t) + ;; all-completions + (all-completions s2 ctable) + ) + ((eq flag 'lambda) + ;; exact match? + (assoc s2 ctable))) + )) + +(defun org-get-tags () + "Get the TAGS string in the current headline." + (unless (org-on-heading-p) + (error "Not on a heading")) + (save-excursion + (beginning-of-line 1) + (if (looking-at ".*[ \t]\\(:[A-Za-z_@0-9:]+:\\)[ \t]*\\(\r\\|$\\)") + (match-string 1) + ""))) + +(defun org-get-buffer-tags () + "Get a table of all tags used in the buffer, for completion." + (let (tags) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "[ \t]:\\([A-Za-z_@0-9:]+\\):[ \t\r\n]" nil t) + (mapc (lambda (x) (add-to-list 'tags x)) + (org-split-string (match-string 1) ":")))) + (mapcar 'list tags))) + +;;; Link Stuff + +(defun org-find-file-at-mouse (ev) + "Open file link or URL at mouse." + (interactive "e") + (mouse-set-point ev) + (org-open-at-point 'in-emacs)) + +(defun org-open-at-mouse (ev) + "Open file link or URL at mouse." + (interactive "e") + (mouse-set-point ev) + (org-open-at-point)) + +(defun org-open-at-point (&optional in-emacs) + "Open link at or after point. +If there is no link at point, this function will search forward up to +the end of the current subtree. +Normally, files will be opened by an appropriate application. If the +optional argument IN-EMACS is non-nil, Emacs will visit the file." + (interactive "P") + (org-remove-occur-highlights nil nil t) + (if (org-at-timestamp-p) + (org-agenda-list nil (time-to-days (org-time-string-to-time + (substring (match-string 1) 0 10))) + 1) + (let (type path link line search (pos (point))) + (catch 'match + (save-excursion + (skip-chars-forward "^]\n\r") + (when (and (re-search-backward "\\[\\[" nil t) + (looking-at org-bracket-link-regexp) + (<= (match-beginning 0) pos) + (>= (match-end 0) pos)) + (setq link (match-string 1)) + (while (string-match " *\n *" link) + (setq link (replace-match " " t t link))) + (if (string-match org-link-regexp link) + (setq type (match-string 1 link) + path (match-string 2 link)) + (setq type "thisfile" + path link)) + (throw 'match t))) + + (when (get-text-property (point) 'org-linked-text) + (setq type "thisfile" + pos (if (get-text-property (1+ (point)) 'org-linked-text) + (1+ (point)) (point)) + path (buffer-substring + (previous-single-property-change pos 'org-linked-text) + (next-single-property-change pos 'org-linked-text))) + (throw 'match t)) + + (save-excursion + (skip-chars-backward + (concat (if org-allow-space-in-links "^" "^ ") + org-non-link-chars)) + (when (or (looking-at org-link-regexp) + (and (re-search-forward org-link-regexp (point-at-eol) t) + (<= (match-beginning 0) pos) + (>= (match-end 0) pos))) + (setq type (match-string 1) + path (match-string 2)) + (throw 'match t))) + (save-excursion + (skip-chars-backward "^ \t\n\r") + (when (looking-at "\\(:[A-Za-z_@0-9:]+\\):[ \t\r\n]") + (setq type "tags" + path (match-string 1)) + (while (string-match ":" path) + (setq path (replace-match "+" t t path))) + (throw 'match t))) + (save-excursion + (skip-chars-backward "a-zA-Z_") + (when (and org-activate-camels + (looking-at org-camel-regexp)) + (setq type "camel" path (match-string 0)) + (if (equal (char-before) ?*) + (setq path (concat "*" path)))) + (throw 'match t)) + (save-excursion + (when (re-search-forward + org-link-regexp + (save-excursion + (condition-case nil + (progn (outline-end-of-subtree) (max pos (point))) + (error (end-of-line 1) (point)))) + t) + (setq type (match-string 1) + path (match-string 2))))) + (unless path + (error "No link found")) + ;; Remove any trailing spaces in path + (if (string-match " +\\'" path) + (setq path (replace-match "" t t path))) + + (cond + + ((member type '("http" "https" "ftp" "mailto" "news")) + (browse-url (concat type ":" path))) + + ((string= type "tags") + (org-tags-view in-emacs path)) + ((or (string= type "camel") + (string= type "thisfile")) + (org-mark-ring-push) + (org-link-search + path + (cond ((equal in-emacs '(4)) 'occur) + ((equal in-emacs '(16)) 'org-occur) + (t nil)))) + + ((string= type "file") + (if (string-match "::?\\([0-9]+\\)\\'" path) ;; second : optional + (setq line (string-to-number (match-string 1 path)) + path (substring path 0 (match-beginning 0))) + (if (string-match "::\\(.+\\)\\'" path) + (setq search (match-string 1 path) + path (substring path 0 (match-beginning 0))))) + (org-open-file path in-emacs line search)) + + ((string= type "news") + (org-follow-gnus-link path)) + + ((string= type "bbdb") + (org-follow-bbdb-link path)) + + ((string= type "gnus") + (let (group article) + (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) + (error "Error in Gnus link")) + (setq group (match-string 1 path) + article (match-string 3 path)) + (org-follow-gnus-link group article))) + + ((string= type "vm") + (let (folder article) + (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) + (error "Error in VM link")) + (setq folder (match-string 1 path) + article (match-string 3 path)) + ;; in-emacs is the prefix arg, will be interpreted as read-only + (org-follow-vm-link folder article in-emacs))) + + ((string= type "wl") + (let (folder article) + (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) + (error "Error in Wanderlust link")) + (setq folder (match-string 1 path) + article (match-string 3 path)) + (org-follow-wl-link folder article))) + + ((string= type "mhe") + (let (folder article) + (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) + (error "Error in MHE link")) + (setq folder (match-string 1 path) + article (match-string 3 path)) + (org-follow-mhe-link folder article))) + + ((string= type "rmail") + (let (folder article) + (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) + (error "Error in RMAIL link")) + (setq folder (match-string 1 path) + article (match-string 3 path)) + (org-follow-rmail-link folder article))) + + ((string= type "shell") + (let ((cmd path)) + (while (string-match "@{" cmd) + (setq cmd (replace-match "<" t t cmd))) + (while (string-match "@}" cmd) + (setq cmd (replace-match ">" t t cmd))) + (if (or (not org-confirm-shell-links) + (yes-or-no-p (format "Execute \"%s\" in the shell? " cmd))) + (shell-command cmd) + (error "Abort")))) + + (t + (browse-url-at-point)))))) + +(defun org-link-search (s &optional type) + "Search for a link search option. +When S is a CamelCaseWord, search for a target, or for a sentence containing +the words. 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." + (let ((case-fold-search t) + (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " ")) + (pos (point)) + (pre "") (post "") + words re0 re1 re2 re3 re4 re5 re2a reall camel) + (cond ((save-excursion + (goto-char (point-min)) + (and + (re-search-forward + (concat "<<" (regexp-quote s0) ">>") nil t) + (setq pos (match-beginning 0)))) + ;; There is an exact target for this + (goto-char pos)) + ((string-match "^/\\(.*\\)/$" s) + ;; A regular expression + (cond + ((eq major-mode 'org-mode) + (org-occur (match-string 1 s))) + ;;((eq major-mode 'dired-mode) + ;; (grep (concat "grep -n -e '" (match-string 1 s) "' *"))) + (t (org-do-occur (match-string 1 s))))) + ((or (setq camel (string-match (concat "^" org-camel-regexp "$") s)) + t) + ;; A camel or a normal search string + (when (equal (string-to-char s) ?*) + ;; Anchor on headlines, post may include tags. + (setq pre "^\\*+[ \t]*\\(\\sw+\\)?[ \t]*" + post "[ \t]*\\([ \t]+:[a-zA-Z_@0-9:+]:[ \t]*\\)?$" + s (substring s 1))) + (remove-text-properties + 0 (length s) + '(face nil mouse-face nil keymap nil fontified nil) s) + ;; Make a series of regular expressions to find a match + (setq words + (if camel + (org-camel-to-words s) + (org-split-string s "[ \n\r\t]+")) + re0 (concat "<<" (regexp-quote s0) ">>") + re2 (concat "\\<" (mapconcat 'downcase words "[ \t]+") "\\>") + re2a (concat "\\<" (mapconcat 'downcase words "[ \t\r\n]+") "\\>") + re4 (concat "\\<" (mapconcat 'downcase words "[^a-zA-Z_\r\n]+") "\\>") + re1 (concat pre re2 post) + re3 (concat pre re4 post) + re5 (concat pre ".*" re4) + re2 (concat pre re2) + re2a (concat pre re2a) + re4 (concat pre re4) + reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2 + "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\(" + re5 "\\)" + )) + (cond + ((eq type 'org-occur) (org-occur reall)) + ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup)) + (t (goto-char (point-min)) + (if (or (org-search-not-link re0 nil t) + (org-search-not-link re1 nil t) + (org-search-not-link re2 nil t) + (org-search-not-link re2a nil t) ;; FIXME: Right place??? + (org-search-not-link re3 nil t) + (org-search-not-link re4 nil t) + (org-search-not-link re5 nil t) + ) + (goto-char (match-beginning 0)) + (goto-char pos) + (error "No match"))))) + (t + ;; Normal string-search + (goto-char (point-min)) + (if (search-forward s nil t) + (goto-char (match-beginning 0)) + (error "No match")))) + (and (eq major-mode 'org-mode) (org-show-hierarchy-above)))) + +(defun org-search-not-link (&rest args) + "Execute `re-search-forward', but only accept matches that are not a link." + (catch 'exit + (let ((pos (point)) p1) + (while (apply 're-search-forward args) + (setq p1 (point)) + (if (not (save-match-data + (and (re-search-backward "\\[\\[" nil t) + (looking-at org-bracket-link-regexp) + (<= (match-beginning 0) p1) + (>= (match-end 0) p1)))) + (progn (goto-char (match-end 0)) + (throw 'exit (point))) + (goto-char (match-end 0))))))) + +(defun org-do-occur (regexp &optional cleanup) + "Call the Emacs command `occur'. +If CLEANUP is non-nil, remove the printout of the regular expression +in the *Occur* buffer. This is useful if the regex is long and not useful +to read." + (occur regexp) + (when cleanup + (let ((cwin (selected-window)) win beg end) + (when (setq win (get-buffer-window "*Occur*")) + (select-window win)) + (goto-char (point-min)) + (when (re-search-forward "match[a-z]+" nil t) + (setq beg (match-end 0)) + (if (re-search-forward "^[ \t]*[0-9]+" nil t) + (setq end (1- (match-beginning 0))))) + (and beg end (let ((buffer-read-only)) (delete-region beg end))) + (goto-char (point-min)) + (select-window cwin)))) + +(defvar org-mark-ring nil + "Mark ring for positions before jumps in Org-mode.") +(defvar org-mark-ring-last-goto nil + "Last position in the mark ring used to go back.") +;; Fill and close the ring +(setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is reloaded +(loop for i from 1 to org-mark-ring-length do + (push (make-marker) org-mark-ring)) +(setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring) + org-mark-ring) + +(defun org-mark-ring-push (&optional pos buffer) + "Put the current position or POS into the mark ring and rotate it." + (interactive) + (setq pos (or pos (point))) + (setq org-mark-ring (nthcdr (1- org-mark-ring-length) org-mark-ring)) + (move-marker (car org-mark-ring) + (or pos (point)) + (or buffer (current-buffer))) + (message + (substitute-command-keys + "Position saved to mark ring, go back with \\[org-mark-ring-goto]."))) + +(defun org-mark-ring-goto (&optional n) + "Jump to the previous position in the mark ring. +With prefix arg N, jump back that many stored positions. When +called several times in succession, walk through the entire ring. +Org-mode commands jumping to a different position in the current file, +or to another Org-mode file, automatically push the old position +onto the ring." + (interactive "p") + (let (p m) + (if (eq last-command this-command) + (setq p (nthcdr n (or org-mark-ring-last-goto org-mark-ring))) + (setq p org-mark-ring)) + (setq org-mark-ring-last-goto p) + (setq m (car p)) + (switch-to-buffer (marker-buffer m)) + (goto-char m) + (if (or (org-invisible-p) (org-invisible-p2)) (org-show-hierarchy-above)))) + +(defun org-camel-to-words (s) + "Split \"CamelCaseWords\" to (\"Camel\" \"Case\" \"Words\")." + (let ((case-fold-search nil) + words) + (while (string-match "[a-z][A-Z]" s) + (push (substring s 0 (1+ (match-beginning 0))) words) + (setq s (substring s (1+ (match-beginning 0))))) + (nreverse (cons s words)))) + +(defun org-remove-angle-brackets (s) + (if (equal (substring s 0 1) "<") (setq s (substring s 1))) + (if (equal (substring s -1) ">") (setq s (substring s 0 -1))) + s) +(defun org-add-angle-brackets (s) + (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s))) + (if (equal (substring s -1) ">") nil (setq s (concat s ">"))) + s) + +(defun org-follow-bbdb-link (name) + "Follow a BBDB link to NAME." + (require 'bbdb) + (let ((inhibit-redisplay t) + (bbdb-electric-p nil)) + (catch 'exit + ;; Exact match on name + (bbdb-name (concat "\\`" name "\\'") nil) + (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil)) + ;; Exact match on name + (bbdb-company (concat "\\`" name "\\'") nil) + (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil)) + ;; Partial match on name + (bbdb-name name nil) + (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil)) + ;; Partial match on company + (bbdb-company name nil) + (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil)) + ;; General match including network address and notes + (bbdb name nil) + (when (= 0 (buffer-size (get-buffer "*BBDB*"))) + (delete-window (get-buffer-window "*BBDB*")) + (error "No matching BBDB record"))))) + +(defun org-follow-gnus-link (&optional group article) + "Follow a Gnus link to GROUP and ARTICLE." + (require 'gnus) + (funcall (cdr (assq 'gnus org-link-frame-setup))) + (if group (gnus-fetch-group group)) + (if article + (or (gnus-summary-goto-article article nil 'force) + (if (fboundp 'gnus-summary-insert-cached-articles) + (progn + (gnus-summary-insert-cached-articles) + (gnus-summary-goto-article article nil 'force)) + (message "Message could not be found."))))) + +(defun org-follow-vm-link (&optional folder article readonly) + "Follow a VM link to FOLDER and ARTICLE." + (require 'vm) + (setq article (org-add-angle-brackets article)) + (if (string-match "^//\\([a-zA-Z]+@\\)?\\([^:]+\\):\\(.*\\)" folder) + ;; ange-ftp or efs or tramp access + (let ((user (or (match-string 1 folder) (user-login-name))) + (host (match-string 2 folder)) + (file (match-string 3 folder))) + (cond + ((featurep 'tramp) + ;; use tramp to access the file + (if org-xemacs-p + (setq folder (format "[%s@%s]%s" user host file)) + (setq folder (format "/%s@%s:%s" user host file)))) + (t + ;; use ange-ftp or efs + (require (if org-xemacs-p 'efs 'ange-ftp)) + (setq folder (format "/%s@%s:%s" user host file)))))) + (when folder + (funcall (cdr (assq 'vm org-link-frame-setup)) folder readonly) + (sit-for 0.1) + (when article + (vm-select-folder-buffer) + (widen) + (let ((case-fold-search t)) + (goto-char (point-min)) + (if (not (re-search-forward + (concat "^" "message-id: *" (regexp-quote article)))) + (error "Could not find the specified message in this folder")) + (vm-isearch-update) + (vm-isearch-narrow) + (vm-beginning-of-message) + (vm-summarize))))) + +(defun org-follow-wl-link (folder article) + "Follow a Wanderlust link to FOLDER and ARTICLE." + (setq article (org-add-angle-brackets article)) + (wl-summary-goto-folder-subr folder 'no-sync t nil t) + (if article (wl-summary-jump-to-msg-by-message-id article ">")) + (wl-summary-redisplay)) + +(defun org-follow-rmail-link (folder article) + "Follow an RMAIL link to FOLDER and ARTICLE." + (setq article (org-add-angle-brackets article)) + (let (message-number) + (save-excursion + (save-window-excursion + (rmail (if (string= folder "RMAIL") rmail-file-name folder)) + (setq message-number + (save-restriction + (widen) + (goto-char (point-max)) + (if (re-search-backward + (concat "^Message-ID:\\s-+" (regexp-quote + (or article ""))) + nil t) + (rmail-what-message)))))) + (if message-number + (progn + (rmail (if (string= folder "RMAIL") rmail-file-name folder)) + (rmail-show-message message-number) + message-number) + (error "Message not found")))) + +;; mh-e integration based on planner-mode +(defun org-mhe-get-message-real-folder () + "Return the name of the current message real folder, so if you use +sequences, it will now work." + (save-excursion + (let* ((folder + (if (equal major-mode 'mh-folder-mode) + mh-current-folder + ;; Refer to the show buffer + mh-show-folder-buffer)) + (end-index + (if (boundp 'mh-index-folder) + (min (length mh-index-folder) (length folder)))) + ) + ;; a simple test on mh-index-data does not work, because + ;; mh-index-data is always nil in a show buffer. + (if (and (boundp 'mh-index-folder) + (string= mh-index-folder (substring folder 0 end-index))) + (if (equal major-mode 'mh-show-mode) + (save-window-excursion + (when (buffer-live-p (get-buffer folder)) + (progn + (pop-to-buffer folder) + (org-mhe-get-message-folder-from-index) + ) + )) + (org-mhe-get-message-folder-from-index) + ) + folder + ) + ))) + +(defun org-mhe-get-message-folder-from-index () + "Returns the name of the message folder in a index folder buffer." + (save-excursion + (mh-index-previous-folder) + (re-search-forward "^\\(+.*\\)$" nil t) + (message (match-string 1)))) + +(defun org-mhe-get-message-folder () + "Return the name of the current message folder. Be careful if you +use sequences." + (save-excursion + (if (equal major-mode 'mh-folder-mode) + mh-current-folder + ;; Refer to the show buffer + mh-show-folder-buffer))) + +(defun org-mhe-get-message-num () + "Return the number of the current message. Be careful if you +use sequences." + (save-excursion + (if (equal major-mode 'mh-folder-mode) + (mh-get-msg-num nil) + ;; Refer to the show buffer + (mh-show-buffer-message-number)))) + +(defun org-mhe-get-header (header) + "Return a header of the message in folder mode. This will create a +show buffer for the corresponding message. If you have a more clever +idea..." + (let* ((folder (org-mhe-get-message-folder)) + (num (org-mhe-get-message-num)) + (buffer (get-buffer-create (concat "show-" folder))) + (header-field)) + (with-current-buffer buffer + (mh-display-msg num folder) + (if (equal major-mode 'mh-folder-mode) + (mh-header-display) + (mh-show-header-display)) + (set-buffer buffer) + (setq header-field (mh-get-header-field header)) + (if (equal major-mode 'mh-folder-mode) + (mh-show) + (mh-show-show)) + header-field))) + +(defun org-follow-mhe-link (folder article) + "Follow an MHE link to FOLDER and ARTICLE. +If ARTICLE is nil FOLDER is shown. If the configuration variable +`org-mhe-search-all-folders' is t and `mh-searcher' is pick, +ARTICLE is searched in all folders. Indexed searches (swish++, +namazu, and others supported by MH-E) will always search in all +folders." + (require 'mh-e) + (require 'mh-search) + (require 'mh-utils) + (mh-find-path) + (if (not article) + (mh-visit-folder (mh-normalize-folder-name folder)) + (setq article (org-add-angle-brackets article)) + (mh-search-choose) + (if (equal mh-searcher 'pick) + (progn + (mh-search folder (list "--message-id" article)) + (when (and org-mhe-search-all-folders + (not (org-mhe-get-message-real-folder))) + (kill-this-buffer) + (mh-search "+" (list "--message-id" article)))) + (mh-search "+" article)) + (if (org-mhe-get-message-real-folder) + (mh-show-msg 1) + (kill-this-buffer) + (error "Message not found")))) + +(defun org-open-file (path &optional in-emacs line search) + "Open the file at PATH. +First, this expands any special file name abbreviations. Then the +configuration variable `org-file-apps' is checked if it contains an +entry for this file type, and if yes, the corresponding command is launched. +If no application is found, Emacs simply visits the file. +With optional argument IN-EMACS, Emacs will visit the file. +Optional LINE specifies a line to go to, optional SEARCH a string to +search for. If LINE or SEARCH is given, the file will always be +opened in Emacs. +If the file does not exist, an error is thrown." + (setq in-emacs (or in-emacs line search)) + (let* ((file (if (equal path "") + buffer-file-name + (convert-standard-filename (org-expand-file-name path)))) + (dirp (file-directory-p file)) + (dfile (downcase file)) + (old-buffer (current-buffer)) + (old-pos (point)) + (old-mode major-mode) + ext cmd apps) + (if (and (not (file-exists-p file)) + (not org-open-non-existing-files)) + (error "No such file: %s" file)) + (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile) + (setq ext (match-string 1 dfile)) + (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile) + (setq ext (match-string 1 dfile)))) + (setq apps (append org-file-apps (org-default-apps))) + (if in-emacs + (setq cmd 'emacs) + (setq cmd (or (and dirp (cdr (assoc 'directory apps))) + (cdr (assoc ext apps)) + (cdr (assoc t apps))))) + (when (eq cmd 'mailcap) + (require 'mailcap) + (mailcap-parse-mailcaps) + (let* ((mime-type (mailcap-extension-to-mime (or ext ""))) + (command (mailcap-mime-info mime-type))) + (if (stringp command) + (setq cmd command) + (setq cmd 'emacs)))) + (cond + ((and (stringp cmd) (not (string-match "^\\s-*$" cmd))) + (setq cmd (format cmd (concat "\"" file "\""))) + (save-window-excursion + (shell-command (concat cmd " &")))) + ((or (stringp cmd) + (eq cmd 'emacs)) + (unless (equal (file-truename file) (file-truename (or buffer-file-name ""))) + (funcall (cdr (assq 'file org-link-frame-setup)) file)) + (if line (goto-line line) + (if search (org-link-search search)))) + ((consp cmd) + (eval cmd)) + (t (funcall (cdr (assq 'file org-link-frame-setup)) file))) + (and (eq major-mode 'org-mode) (eq old-mode 'org-mode) + (or (not (equal old-buffer (current-buffer))) + (not (equal old-pos (point)))) + (org-mark-ring-push old-pos old-buffer)))) + +(defun org-default-apps () + "Return the default applications for this operating system." + (cond + ((eq system-type 'darwin) + org-file-apps-defaults-macosx) + ((eq system-type 'windows-nt) + org-file-apps-defaults-windowsnt) + (t org-file-apps-defaults-gnu))) + +(defun org-expand-file-name (path) + "Replace special path abbreviations and expand the file name." + (expand-file-name path)) + + +(defvar org-insert-link-history nil + "Minibuffer history for links inserted with `org-insert-link'.") + +(defvar org-stored-links nil + "Contains the links stored with `org-store-link'.") + +;;;###autoload +(defun org-store-link (arg) + "\\Store an org-link to the current location. +This link can later be inserted into an org-buffer with +\\[org-insert-link]. +For some link types, a prefix arg is interpreted: +For links to usenet articles, arg negates `org-usenet-links-prefer-google'. +For file links, arg negates `org-context-in-file-links'." + (interactive "P") + (let (link cpltxt txt (pos (point))) + (cond + + ((eq major-mode 'bbdb-mode) + (setq cpltxt (concat + "bbdb:" + (or (bbdb-record-name (bbdb-current-record)) + (bbdb-record-company (bbdb-current-record)))) + link (org-make-link cpltxt))) + + ((eq major-mode 'calendar-mode) + (let ((cd (calendar-cursor-to-date))) + (setq link + (format-time-string + (car org-time-stamp-formats) + (apply 'encode-time + (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd) + nil nil nil)))))) + + ((or (eq major-mode 'vm-summary-mode) + (eq major-mode 'vm-presentation-mode)) + (and (eq major-mode 'vm-presentation-mode) (vm-summarize)) + (vm-follow-summary-cursor) + (save-excursion + (vm-select-folder-buffer) + (let* ((message (car vm-message-pointer)) + (folder buffer-file-name) + (subject (vm-su-subject message)) + (author (vm-su-full-name message)) + (message-id (vm-su-message-id message))) + (setq message-id (org-remove-angle-brackets message-id)) + (setq folder (abbreviate-file-name folder)) + (if (string-match (concat "^" (regexp-quote vm-folder-directory)) + folder) + (setq folder (replace-match "" t t folder))) + (setq cpltxt (concat author " on: " subject)) + (setq link (concat cpltxt "\n " + (org-make-link + "vm:" folder "#" message-id)))))) + + ((eq major-mode 'wl-summary-mode) + (let* ((msgnum (wl-summary-message-number)) + (message-id (elmo-message-field wl-summary-buffer-elmo-folder + msgnum 'message-id)) + (wl-message-entity (elmo-msgdb-overview-get-entity + msgnum (wl-summary-buffer-msgdb))) + (author (wl-summary-line-from)) ; FIXME: how to get author name? + (subject "???")) ; FIXME: How to get subject of email? + (setq message-id (org-remove-angle-brackets message-id)) + (setq cpltxt (concat author " on: " subject)) + (setq link (concat cpltxt "\n " + (org-make-link + "wl:" wl-summary-buffer-folder-name + "#" message-id))))) + + ((or (equal major-mode 'mh-folder-mode) + (equal major-mode 'mh-show-mode)) + (let ((from-header (org-mhe-get-header "From:")) + (to-header (org-mhe-get-header "To:")) + (subject (org-mhe-get-header "Subject:"))) + (setq cpltxt (concat from-header " on: " subject)) + (setq link (concat cpltxt "\n " + (org-make-link + "mhe:" (org-mhe-get-message-real-folder) "#" + (org-remove-angle-brackets + (org-mhe-get-header "Message-Id:"))))))) + + ((eq major-mode 'rmail-mode) + (save-excursion + (save-restriction + (rmail-narrow-to-non-pruned-header) + (let ((folder buffer-file-name) + (message-id (mail-fetch-field "message-id")) + (author (mail-fetch-field "from")) + (subject (mail-fetch-field "subject"))) + (setq message-id (org-remove-angle-brackets message-id)) + (setq cpltxt (concat author " on: " subject)) + (setq link (concat cpltxt "\n " + (org-make-link + "rmail:" folder "#" message-id))))))) + + ((eq major-mode 'gnus-group-mode) + (let ((group (cond ((fboundp 'gnus-group-group-name) ; depending on Gnus + (gnus-group-group-name)) ; version + ((fboundp 'gnus-group-name) + (gnus-group-name)) + (t "???")))) + (setq cpltxt (concat + (if (org-xor arg org-usenet-links-prefer-google) + "http://groups.google.com/groups?group=" + "gnus:") + group) + link (org-make-link cpltxt)))) + + ((memq major-mode '(gnus-summary-mode gnus-article-mode)) + (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary)) + (gnus-summary-beginning-of-article) + (let* ((group (car gnus-article-current)) + (article (cdr gnus-article-current)) + (header (gnus-summary-article-header article)) + (author (mail-header-from header)) + (message-id (mail-header-id header)) + (date (mail-header-date header)) + (subject (gnus-summary-subject-string))) + (setq cpltxt (concat author " on: " subject)) + (if (org-xor arg org-usenet-links-prefer-google) + (setq link + (concat + cpltxt "\n " + (format "http://groups.google.com/groups?as_umsgid=%s" + (org-fixup-message-id-for-http message-id)))) + (setq link (concat cpltxt "\n" + (org-make-link + "gnus:" group + "#" (number-to-string article))))))) + + ((eq major-mode 'w3-mode) + (setq cpltxt (url-view-url t) + link (org-make-link cpltxt))) + ((eq major-mode 'w3m-mode) + (setq cpltxt w3m-current-url + link (org-make-link cpltxt))) + + ((eq major-mode 'org-mode) + ;; Just link to current headline + (setq cpltxt (concat "file:" + (abbreviate-file-name buffer-file-name))) + ;; Add a context search string + (when (org-xor org-context-in-file-links arg) + ;; Check if we are on a target + (if (save-excursion + (skip-chars-forward "^>\n\r") + (and (re-search-backward "<<" nil t) + (looking-at "<<\\(.*?\\)>>") + (<= (match-beginning 0) pos) + (>= (match-end 0) pos))) + (setq cpltxt (concat cpltxt "::" (match-string 1))) + (setq txt (cond + ((org-on-heading-p) nil) + ((org-region-active-p) + (buffer-substring (region-beginning) (region-end))) + (t (buffer-substring (point-at-bol) (point-at-eol))))) + (setq cpltxt + (concat cpltxt "::" + (if org-file-link-context-use-camel-case + (org-make-org-heading-camel txt) + (org-make-org-heading-search-string txt)))))) + (if (string-match "::\\'" cpltxt) + (setq cpltxt (substring cpltxt 0 -2))) + (setq link (org-make-link cpltxt))) + + (buffer-file-name + ;; Just link to this file here. + (setq cpltxt (concat "file:" + (abbreviate-file-name buffer-file-name))) + ;; Add a context string + (when (org-xor org-context-in-file-links arg) + (setq txt (if (org-region-active-p) + (buffer-substring (region-beginning) (region-end)) + (buffer-substring (point-at-bol) (point-at-eol)))) + (setq cpltxt + (concat cpltxt "::" + (if org-file-link-context-use-camel-case + (org-make-org-heading-camel txt) + (org-make-org-heading-search-string txt))))) + (setq link (org-make-link cpltxt))) + + ((interactive-p) + (error "Cannot link to a buffer which is not visiting a file")) + + (t (setq link nil))) + + (if (consp link) (setq cpltxt (car link) link (cdr link))) + + (if (and (interactive-p) link) + (progn + (setq org-stored-links + (cons (cons (or cpltxt link) link) org-stored-links)) + (message "Stored: %s" (or cpltxt link))) + link))) + +(defun org-make-org-heading-search-string (&optional string heading) + "Make search string for STRING or current headline." + (interactive) + (let ((s (or string (org-get-heading)))) + (unless (and string (not heading)) + ;; We are using a headline, clean up garbage in there. + (if (string-match org-todo-regexp s) + (setq s (replace-match "" t t s))) + (if (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" s) + (setq s (replace-match "" t t s))) + (setq s (org-trim s)) + (if (string-match (concat "^\\(" org-quote-string "\\|" + org-comment-string "\\)") s) + (setq s (replace-match "" t t s))) + (while (string-match org-ts-regexp s) + (setq s (replace-match "" t t s)))) + (while (string-match "[^a-zA-Z_0-9 \t]+" s) + (setq s (replace-match " " t t s))) + (or string (setq s (concat "*" s))) ; Add * for headlines + (mapconcat 'identity (org-split-string s "[ \t]+") " "))) + +(defun org-make-org-heading-camel (&optional string heading) + "Make a CamelCase string for STRING or the current headline." + (interactive) + (let ((s (or string (org-get-heading)))) + (unless (and string (not heading)) + ;; We are using a headline, clean up garbage in there. + (if (string-match org-todo-regexp s) + (setq s (replace-match "" t t s))) + (if (string-match ":[a-zA-Z_@0-9:]+:[ \t]*$" s) + (setq s (replace-match "" t t s))) + (setq s (org-trim s)) + (if (string-match (concat "^\\(" org-quote-string "\\|" + org-comment-string "\\)") s) + (setq s (replace-match "" t t s))) + (while (string-match org-ts-regexp s) + (setq s (replace-match "" t t s)))) + (while (string-match "[^a-zA-Z_ \t]+" s) + (setq s (replace-match " " t t s))) + (or string (setq s (concat "*" s))) ; Add * for headlines + (mapconcat 'capitalize (org-split-string s "[ \t]+") ""))) + +(defun org-make-link (&rest strings) + "Concatenate STRINGS, format resulting string with `org-link-format'." + (format org-link-format (apply 'concat strings))) + +(defun org-make-link2 (link &optional description) + "Make a link with brackets." + (concat "[[" link "]" + (if description (concat "[" description "]") "") + "]")) + +(defun org-xor (a b) + "Exclusive or." + (if a (not b) b)) + +(defun org-get-header (header) + "Find a header field in the current buffer." + (save-excursion + (goto-char (point-min)) + (let ((case-fold-search t) s) + (cond + ((eq header 'from) + (if (re-search-forward "^From:\\s-+\\(.*\\)" nil t) + (setq s (match-string 1))) + (while (string-match "\"" s) + (setq s (replace-match "" t t s))) + (if (string-match "[<(].*" s) + (setq s (replace-match "" t t s)))) + ((eq header 'message-id) + (if (re-search-forward "^message-id:\\s-+\\(.*\\)" nil t) + (setq s (match-string 1)))) + ((eq header 'subject) + (if (re-search-forward "^subject:\\s-+\\(.*\\)" nil t) + (setq s (match-string 1))))) + (if (string-match "\\`[ \t\]+" s) (setq s (replace-match "" t t s))) + (if (string-match "[ \t\]+\\'" s) (setq s (replace-match "" t t s))) + s))) + + +(defun org-fixup-message-id-for-http (s) + "Replace special characters in a message id, so it can be used in an http query." + (while (string-match "<" s) + (setq s (replace-match "%3C" t t s))) + (while (string-match ">" s) + (setq s (replace-match "%3E" t t s))) + (while (string-match "@" s) + (setq s (replace-match "%40" t t s))) + s) + +(defun org-insert-link (&optional complete-file) + "Insert a link. At the prompt, enter the link. + +Completion 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. + +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). + +With two \\[universal-argument] prefixes, enforce an absolute path even if the file +is in the current directory or below." + (interactive "P") + (let ((link (if complete-file + (read-file-name "File: ") + (completing-read + "Link: " org-stored-links nil nil nil + org-insert-link-history + (or (car (car org-stored-links)))))) + linktxt matched) + (if (or (not link) (equal link "")) + (error "No links available")) + (if complete-file + (let ((pwd (file-name-as-directory (expand-file-name ".")))) + (cond + ((equal complete-file '(16)) + (insert + (org-make-link + "file:" (abbreviate-file-name (expand-file-name link))))) + ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)") + (expand-file-name link)) + (insert + (org-make-link + "file:" (match-string 1 (expand-file-name link))))) + (t (insert (org-make-link "file:" link))))) + (setq linktxt (cdr (assoc link org-stored-links))) + (if (not org-keep-stored-link-after-insertion) + (setq org-stored-links (delq (assoc link org-stored-links) + org-stored-links))) + (if (not linktxt) (setq link (org-make-link link))) + (setq link (or linktxt link)) + (when (string-match "<\\]+\\)>" link) + (let* ((path (match-string 1 link)) + (case-fold-search nil) + (search (match-string 2 link))) + (when (save-match-data + (equal (file-truename buffer-file-name) + (file-truename path))) + ;; We are linking to this same file + (if (and org-file-link-context-use-camel-case + (save-match-data + (string-match (concat "^" org-camel-regexp "$") search))) + (setq link (replace-match search t t link) + matched t) + (setq link (replace-match (concat "[[" search "]]") + t t link) + matched t))))) + (let ((lines (org-split-string link "\n"))) + (insert (car lines)) + (setq matched (or matched (string-match org-link-regexp (car lines)))) + (setq lines (cdr lines)) + (while lines + (insert "\n") + (if (save-excursion + (beginning-of-line 0) + (looking-at "[ \t]+\\S-")) + (indent-relative)) + (setq matched (or matched + (string-match org-link-regexp (car lines)))) + (insert (car lines)) + (setq lines (cdr lines)))) + (unless matched + (error "Add link type: http(s),ftp,mailto,file,news,bbdb,vm,wl,rmail,gnus, or shell"))))) + +;;; Hooks for remember.el +;;;###autoload +(defun org-remember-annotation () + "Return a link to the current location as an annotation for remember.el. +If you are using Org-mode files as target for data storage with +remember.el, then the annotations should include a link compatible with the +conventions in Org-mode. This function returns such a link." + (org-store-link nil)) + +(defconst org-remember-help +"Select a destination location for the note. +UP/DOWN=headline TAB=cycle visibility [Q]uit RET//=Store +RET at beg-of-buf -> Append to file as level 2 headline +RET on headline -> Store as sublevel entry to current headline +/ -> before/after current headline, same headings level") + +;;;###autoload +(defun org-remember-apply-template () + "Initialize *remember* buffer with template, invode `org-mode'. +This function should be placed into `remember-mode-hook' and in fact requires +to be run from that hook to fucntion properly." + (when org-remember-templates + (let* ((entry (if (= (length org-remember-templates) 1) + (cdar org-remember-templates) + (message "Select template: %s" + (mapconcat + (lambda (x) (char-to-string (car x))) + org-remember-templates " ")) + (cdr (assoc (read-char-exclusive) org-remember-templates)))) + (tpl (if (consp (cdr entry)) (cadr entry) (cdr entry))) + (file (if (consp (cdr entry)) (nth 2 entry))) + (v-t (format-time-string (car org-time-stamp-formats) (org-current-time))) + (v-T (format-time-string (cdr org-time-stamp-formats) (org-current-time))) + (v-u (concat "[" (substring v-t 1 -1) "]")) + (v-U (concat "[" (substring v-T 1 -1) "]")) + (v-a annotation) ; defined in `remember-mode' + (v-i initial) ; defined in `remember-mode' + (v-n user-full-name) + ) + (unless tpl (setq tpl "") (message "No template") (ding)) + (insert tpl) (goto-char (point-min)) + (while (re-search-forward "%\\([tTuTai]\\)" nil t) + (when (and initial (equal (match-string 0) "%i")) + (save-match-data + (let* ((lead (buffer-substring + (point-at-bol) (match-beginning 0)))) + (setq v-i (mapconcat 'identity + (org-split-string initial "\n") + (concat "\n" lead)))))) + (replace-match + (or (eval (intern (concat "v-" (match-string 1)))) "") + t t)) + (let ((org-startup-folded nil) + (org-startup-with-deadline-check nil)) + (org-mode)) +; (use-local-map org-mode-map) +; (org-set-font-lock-defaults) + (if (and file (string-match "\\S-" file) (not (file-directory-p file))) + (set (make-local-variable 'org-default-notes-file) file)) + (goto-char (point-min)) + (if (re-search-forward "%\\?" nil t) (replace-match ""))))) + +;;;###autoload +(defun org-remember-handler () + "Store stuff from remember.el into an org file. +First prompts for an org file. If the user just presses return, the value +of `org-default-notes-file' is used. +Then the command offers the headings tree of the selected file in order to +file the text at a specific location. +You can either immediately press RET to get the note appended to the +file, or you can use vertical cursor motion and visibility cycling (TAB) to +find a better place. Then press RET or or in insert the note. + +Key Cursor position Note gets inserted +----------------------------------------------------------------------------- +RET buffer-start as level 2 heading at end of file +RET on headline as sublevel of the heading at cursor +RET no heading at cursor position, level taken from context. + Or use prefix arg to specify level manually. + on headline as same level, before current heading + on headline as same level, after current heading + +So the fastest way to store the note is to press RET RET to append it to +the default file. This way your current train of thought is not +interrupted, in accordance with the principles of remember.el. But with +little extra effort, you can push it directly to the correct location. + +Before being stored away, the function ensures that the text has a +headline, i.e. a first line that starts with a \"*\". If not, a headline +is constructed from the current date and some additional data. + +If the variable `org-adapt-indentation' is non-nil, the entire text is +also indented so that it starts in the same column as the headline +\(i.e. after the stars). + +See also the variable `org-reverse-note-order'." + (catch 'quit + (let* ((txt (buffer-substring (point-min) (point-max))) + (fastp current-prefix-arg) + (file (if fastp org-default-notes-file (org-get-org-file))) + (visiting (find-buffer-visiting file)) + (org-startup-with-deadline-check nil) + (org-startup-folded nil) + spos level indent reversed) + ;; Modify text so that it becomes a nice subtree which can be inserted + ;; into an org tree. + (let* ((lines (split-string txt "\n")) + first) + ;; remove empty lines at the beginning + (while (and lines (string-match "^[ \t]*\n" (car lines))) + (setq lines (cdr lines))) + (setq first (car lines) lines (cdr lines)) + (if (string-match "^\\*+" first) + ;; Is already a headline + (setq indent nil) + ;; We need to add a headline: Use time and first buffer line + (setq lines (cons first lines) + first (concat "* " (current-time-string) + " (" (remember-buffer-desc) ")") + indent " ")) + (if (and org-adapt-indentation indent) + (setq lines (mapcar (lambda (x) (concat indent x)) lines))) + (setq txt (concat first "\n" + (mapconcat 'identity lines "\n")))) + ;; Find the file + (if (not visiting) + (find-file-noselect file)) + (with-current-buffer (get-file-buffer file) + (setq reversed (org-notes-order-reversed-p)) + (save-excursion + (save-restriction + (widen) + ;; Ask the User for a location + (setq spos (if fastp 1 (org-get-location + (current-buffer) + org-remember-help))) + (if (not spos) (throw 'quit nil)) ; return nil to show we did + ; not handle this note + (goto-char spos) + (cond ((bobp) + ;; Put it at the start or end, as level 2 + (save-restriction + (widen) + (goto-char (if reversed (point-min) (point-max))) + (if (not (bolp)) (newline)) + (org-paste-subtree 2 txt))) + ((and (org-on-heading-p nil) (not current-prefix-arg)) + ;; Put it below this entry, at the beg/end of the subtree + (org-back-to-heading) + (setq level (funcall outline-level)) + (if reversed + (outline-end-of-heading) + (outline-end-of-subtree)) + (if (not (bolp)) (newline)) + (beginning-of-line 1) + (org-paste-subtree (1+ level) txt)) + (t + ;; Put it right there, with automatic level determined by + ;; org-paste-subtree or from prefix arg + (org-paste-subtree current-prefix-arg txt))) + (when remember-save-after-remembering + (save-buffer) + (if (not visiting) (kill-buffer (current-buffer))))))))) + t) ;; return t to indicate that we took care of this note. + +(defun org-get-org-file () + "Read a filename, with default directory `org-directory'." + (let ((default (or org-default-notes-file remember-data-file))) + (read-file-name (format "File name [%s]: " default) + (file-name-as-directory org-directory) + default))) + +(defun org-notes-order-reversed-p () + "Check if the current file should receive notes in reversed order." + (cond + ((not org-reverse-note-order) nil) + ((eq t org-reverse-note-order) t) + ((not (listp org-reverse-note-order)) nil) + (t (catch 'exit + (let ((all org-reverse-note-order) + entry) + (while (setq entry (pop all)) + (if (string-match (car entry) buffer-file-name) + (throw 'exit (cdr entry)))) + nil))))) + +;;; Tables + +;; Watch out: Here we are talking about two different kind of tables. +;; Most of the code is for the tables created with the Org-mode table editor. +;; Sometimes, we talk about tables created and edited with the table.el +;; Emacs package. We call the former org-type tables, and the latter +;; table.el-type tables. + + +(defun org-before-change-function (beg end) + "Every change indicates that a table might need an update." + (setq org-table-may-need-update t)) + +(defconst org-table-line-regexp "^[ \t]*|" + "Detects an org-type table line.") +(defconst org-table-dataline-regexp "^[ \t]*|[^-]" + "Detects an org-type table line.") +(defconst org-table-auto-recalculate-regexp "^[ \t]*| *# *\\(|\\|$\\)" + "Detects a table line marked for automatic recalculation.") +(defconst org-table-recalculate-regexp "^[ \t]*| *[#*] *\\(|\\|$\\)" + "Detects a table line marked for automatic recalculation.") +(defconst org-table-calculate-mark-regexp "^[ \t]*| *[!$^_#*] *\\(|\\|$\\)" + "Detects a table line marked for automatic recalculation.") +(defconst org-table-hline-regexp "^[ \t]*|-" + "Detects an org-type table hline.") +(defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]" + "Detects a table-type table hline.") +(defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)" + "Detects an org-type or table-type table.") +(defconst org-table-border-regexp "^[ \t]*[^| \t]" + "Searching from within a table (any type) this finds the first line +outside the table.") +(defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]" + "Searching from within a table (any type) this finds the first line +outside the table.") + +(defun org-table-create-with-table.el () + "Use the table.el package to insert a new table. +If there is already a table at point, convert between Org-mode tables +and table.el tables." + (interactive) + (require 'table) + (cond + ((org-at-table.el-p) + (if (y-or-n-p "Convert table to Org-mode table? ") + (org-table-convert))) + ((org-at-table-p) + (if (y-or-n-p "Convert table to table.el table? ") + (org-table-convert))) + (t (call-interactively 'table-insert)))) + +(defun org-table-create (&optional size) + "Query for a size and insert a table skeleton. +SIZE is a string Columns x Rows like for example \"3x2\"." + (interactive "P") + (unless size + (setq size (read-string + (concat "Table size Columns x Rows [e.g. " + org-table-default-size "]: ") + "" nil org-table-default-size))) + + (let* ((pos (point)) + (indent (make-string (current-column) ?\ )) + (split (org-split-string size " *x *")) + (rows (string-to-number (nth 1 split))) + (columns (string-to-number (car split))) + (line (concat (apply 'concat indent "|" (make-list columns " |")) + "\n"))) + (if (string-match "^[ \t]*$" (buffer-substring-no-properties + (point-at-bol) (point))) + (beginning-of-line 1) + (newline)) + ;; (mapcar (lambda (x) (insert line)) (make-list rows t)) + (dotimes (i rows) (insert line)) + (goto-char pos) + (if (> rows 1) + ;; Insert a hline after the first row. + (progn + (end-of-line 1) + (insert "\n|-") + (goto-char pos))) + (org-table-align))) + +(defun org-table-convert-region (beg0 end0 nspace) + "Convert region to a table. +The region goes from BEG0 to END0, but these borders will be moved +slightly, to make sure a beginning of line in the first line is included. +When NSPACE is non-nil, it indicates the minimum number of spaces that +separate columns (default: just one space)." + (let* ((beg (min beg0 end0)) + (end (max beg0 end0)) + (tabsep t) + re) + (goto-char beg) + (beginning-of-line 1) + (setq beg (move-marker (make-marker) (point))) + (goto-char end) + (if (bolp) (backward-char 1) (end-of-line 1)) + (setq end (move-marker (make-marker) (point))) + ;; Lets see if this is tab-separated material. If every nonempty line + ;; contains a tab, we will assume that it is tab-separated material + (if nspace + (setq tabsep nil) + (goto-char beg) + (and (re-search-forward "^[^\n\t]+$" end t) (setq tabsep nil))) + (if nspace (setq tabsep nil)) + (if tabsep + (setq re "^\\|\t") + (setq re (format "^ *\\| *\t *\\| \\{%d,\\}" + (max 1 (prefix-numeric-value nspace))))) + (goto-char beg) + (while (re-search-forward re end t) + (replace-match "|" t t)) + (goto-char beg) + (insert " ") + (org-table-align))) + +(defun org-table-import (file arg) + "Import FILE as a table. +The file is assumed to be tab-separated. Such files can be produced by most +spreadsheet and database applications. If no tabs (at least one per line) +are found, lines will be split on whitespace into fields." + (interactive "f\nP") + (or (bolp) (newline)) + (let ((beg (point)) + (pm (point-max))) + (insert-file-contents file) + (org-table-convert-region beg (+ (point) (- (point-max) pm)) arg))) + +(defun org-table-export () + "Export table as a tab-separated file. +Such a file can be imported into a spreadsheet program like Excel." + (interactive) + (let* ((beg (org-table-begin)) + (end (org-table-end)) + (table (buffer-substring beg end)) + (file (read-file-name "Export table to: ")) + buf) + (unless (or (not (file-exists-p file)) + (y-or-n-p (format "Overwrite file %s? " file))) + (error "Abort")) + (with-current-buffer (find-file-noselect file) + (setq buf (current-buffer)) + (erase-buffer) + (fundamental-mode) + (insert table) + (goto-char (point-min)) + (while (re-search-forward "^[ \t]*|[ \t]*" nil t) + (replace-match "" t t) + (end-of-line 1)) + (goto-char (point-min)) + (while (re-search-forward "[ \t]*|[ \t]*$" nil t) + (replace-match "" t t) + (goto-char (min (1+ (point)) (point-max)))) + (goto-char (point-min)) + (while (re-search-forward "^-[-+]*$" nil t) + (replace-match "") + (if (looking-at "\n") + (delete-char 1))) + (goto-char (point-min)) + (while (re-search-forward "[ \t]*|[ \t]*" nil t) + (replace-match "\t" t t)) + (save-buffer)) + (kill-buffer buf))) + +(defvar org-table-aligned-begin-marker (make-marker) + "Marker at the beginning of the table last aligned. +Used to check if cursor still is in that table, to minimize realignment.") +(defvar org-table-aligned-end-marker (make-marker) + "Marker at the end of the table last aligned. +Used to check if cursor still is in that table, to minimize realignment.") +(defvar org-table-last-alignment nil + "List of flags for flushright alignment, from the last re-alignment. +This is being used to correctly align a single field after TAB or RET.") +(defvar org-table-last-column-widths nil + "List of max width of fields in each column. +This is being used to correctly align a single field after TAB or RET.") + +(defvar org-last-recalc-line nil) + +(defun org-table-align () + "Align the table at point by aligning all vertical bars." + (interactive) + ;; (message "align") (sit-for 2) + (let* ( + ;; Limits of table + (beg (org-table-begin)) + (end (org-table-end)) + ;; Current cursor position + (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point)))) + (colpos (org-table-current-column)) + (winstart (window-start)) + text lines (new "") lengths l typenums ty fields maxfields i + column + (indent "") cnt frac + rfmt hfmt + (spaces (if (org-in-invisibility-spec-p '(org-table)) + org-table-spaces-around-invisible-separators + org-table-spaces-around-separators)) + (sp1 (car spaces)) + (sp2 (cdr spaces)) + (rfmt1 (concat + (make-string sp2 ?\ ) "%%%s%ds" (make-string sp1 ?\ ) "|")) + (hfmt1 (concat + (make-string sp2 ?-) "%s" (make-string sp1 ?-) "+")) + emptystrings) + (untabify beg end) + ;; (message "Aligning table...") + ;; Get the rows + (setq lines (org-split-string + (buffer-substring-no-properties beg end) "\n")) + ;; Store the indentation of the first line + (if (string-match "^ *" (car lines)) + (setq indent (make-string (- (match-end 0) (match-beginning 0)) ?\ ))) + ;; Mark the hlines + (setq lines (mapcar (lambda (l) + (if (string-match "^ *|-" l) + nil + (if (string-match "[ \t]+$" l) + (substring l 0 (match-beginning 0)) + l))) + lines)) + ;; Get the data fields + (setq fields (mapcar + (lambda (l) + (org-split-string l " *| *")) + (delq nil (copy-sequence lines)))) + ;; How many fields in the longest line? + (condition-case nil + (setq maxfields (apply 'max (mapcar 'length fields))) + (error + (kill-region beg end) + (org-table-create org-table-default-size) + (error "Empty table - created default table"))) + ;; A list of empty string to fill any short rows on output + (setq emptystrings (make-list maxfields "")) + ;; Get the maximum length of a field and the most common datatype + ;; for each column + (setq i -1) + (while (< (setq i (1+ i)) maxfields) ;; Loop over all columns + (setq column (mapcar (lambda (x) (or (nth i x) "")) fields)) + ;; maximum length + (push (apply 'max 1 (mapcar 'string-width column)) lengths) + ;; compute the fraction stepwise, ignoring empty fields + (setq cnt 0 frac 0.0) + (mapcar + (lambda (x) + (if (equal x "") + nil + (setq frac ( / (+ (* frac cnt) + (if (string-match org-table-number-regexp x) 1 0)) + (setq cnt (1+ cnt)))))) + column) + (push (>= frac org-table-number-fraction) typenums)) + (setq lengths (nreverse lengths) + typenums (nreverse typenums)) + (setq org-table-last-alignment typenums + org-table-last-column-widths lengths) + ;; Compute the formats needed for output of the table + (setq rfmt (concat indent "|") hfmt (concat indent "|")) + (while (setq l (pop lengths)) + (setq ty (if (pop typenums) "" "-")) ; number types flushright + (setq rfmt (concat rfmt (format rfmt1 ty l)) + hfmt (concat hfmt (format hfmt1 (make-string l ?-))))) + (setq rfmt (concat rfmt "\n") + hfmt (concat (substring hfmt 0 -1) "|\n")) + ;; Produce the new table + ;;(while lines + ;; (setq l (pop lines)) + ;; (if l + ;; (setq new (concat new (apply 'format rfmt + ;; (append (pop fields) emptystrings)))) + ;; (setq new (concat new hfmt)))) + (setq new (mapconcat + (lambda (l) + (if l (apply 'format rfmt + (append (pop fields) emptystrings)) + hfmt)) + lines "")) + ;; Replace the old one + (delete-region beg end) + (move-marker end nil) + (move-marker org-table-aligned-begin-marker (point)) + (insert new) + (move-marker org-table-aligned-end-marker (point)) + ;; Try to move to the old location (approximately) + (goto-line linepos) + (set-window-start (selected-window) winstart 'noforce) + (org-table-goto-column colpos) + (setq org-table-may-need-update nil) + (if (org-in-invisibility-spec-p '(org-table)) + (org-table-add-invisible-to-vertical-lines)) + )) + +(defun org-table-begin (&optional table-type) + "Find the beginning of the table and return its position. +With argument TABLE-TYPE, go to the beginning of a table.el-type table." + (save-excursion + (if (not (re-search-backward + (if table-type org-table-any-border-regexp + org-table-border-regexp) + nil t)) + (error "Can't find beginning of table") + (goto-char (match-beginning 0)) + (beginning-of-line 2) + (point)))) + +(defun org-table-end (&optional table-type) + "Find the end of the table and return its position. +With argument TABLE-TYPE, go to the end of a table.el-type table." + (save-excursion + (if (not (re-search-forward + (if table-type org-table-any-border-regexp + org-table-border-regexp) + nil t)) + (goto-char (point-max)) + (goto-char (match-beginning 0))) + (point-marker))) + +(defun org-table-justify-field-maybe (&optional new) + "Justify the current field, text to left, number to right. +Optional argument NEW may specify text to replace the current field content." + (cond + ((and (not new) org-table-may-need-update)) ; Realignment will happen anyway + ((org-at-table-hline-p) + ;; FIXME: I used to enforce realign here, but I think this is not needed. + ;; (setq org-table-may-need-update t) + ) + ((and (not new) + (or (not (equal (marker-buffer org-table-aligned-begin-marker) + (current-buffer))) + (< (point) org-table-aligned-begin-marker) + (>= (point) org-table-aligned-end-marker))) + ;; This is not the same table, force a full re-align + (setq org-table-may-need-update t)) + (t ;; realign the current field, based on previous full realign + (let* ((pos (point)) s + (col (org-table-current-column)) + (num (nth (1- col) org-table-last-alignment)) + l f n o e) + (when (> col 0) + (skip-chars-backward "^|\n") + (if (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)") + (progn + (setq s (match-string 1) + o (match-string 0) + l (max 1 (- (match-end 0) (match-beginning 0) 3)) + e (not (= (match-beginning 2) (match-end 2)))) + (setq f (format (if num " %%%ds %s" " %%-%ds %s") + l (if e "|" (setq org-table-may-need-update t) "")) + n (format f s t t)) + (if new + (if (<= (length new) l) + (setq n (format f new t t)) ;; FIXME: why t t????? + (setq n (concat new "|") org-table-may-need-update t))) + (or (equal n o) + (let (org-table-may-need-update) + (replace-match n)))) + (setq org-table-may-need-update t)) + (goto-char pos)))))) + +(defun org-table-next-field () + "Go to the next field in the current table, creating new lines as needed. +Before doing so, re-align the table if necessary." + (interactive) + (org-table-maybe-eval-formula) + (org-table-maybe-recalculate-line) + (if (and org-table-automatic-realign + org-table-may-need-update) + (org-table-align)) + (let ((end (org-table-end))) + (if (org-at-table-hline-p) + (end-of-line 1)) + (condition-case nil + (progn + (re-search-forward "|" end) + (if (looking-at "[ \t]*$") + (re-search-forward "|" end)) + (if (and (looking-at "-") + org-table-tab-jumps-over-hlines + (re-search-forward "^[ \t]*|\\([^-]\\)" end t)) + (goto-char (match-beginning 1))) + (if (looking-at "-") + (progn + (beginning-of-line 0) + (org-table-insert-row 'below)) + (if (looking-at " ") (forward-char 1)))) + (error + (org-table-insert-row 'below))))) + +(defun org-table-previous-field () + "Go to the previous field in the table. +Before doing so, re-align the table if necessary." + (interactive) + (org-table-justify-field-maybe) + (org-table-maybe-recalculate-line) + (if (and org-table-automatic-realign + org-table-may-need-update) + (org-table-align)) + (if (org-at-table-hline-p) + (end-of-line 1)) + (re-search-backward "|" (org-table-begin)) + (re-search-backward "|" (org-table-begin)) + (while (looking-at "|\\(-\\|[ \t]*$\\)") + (re-search-backward "|" (org-table-begin))) + (if (looking-at "| ?") + (goto-char (match-end 0)))) + +(defun org-table-next-row () + "Go to the next row (same column) in the current table. +Before doing so, re-align the table if necessary." + (interactive) + (org-table-maybe-eval-formula) + (org-table-maybe-recalculate-line) + (if (or (looking-at "[ \t]*$") + (save-excursion (skip-chars-backward " \t") (bolp))) + (newline) + (if (and org-table-automatic-realign + org-table-may-need-update) + (org-table-align)) + (let ((col (org-table-current-column))) + (beginning-of-line 2) + (if (or (not (org-at-table-p)) + (org-at-table-hline-p)) + (progn + (beginning-of-line 0) + (org-table-insert-row 'below))) + (org-table-goto-column col) + (skip-chars-backward "^|\n\r") + (if (looking-at " ") (forward-char 1))))) + +(defun org-table-copy-down (n) + "Copy a field down in the current column. +If the field at the cursor is empty, copy into it the content of the nearest +non-empty field above. With argument N, use the Nth non-empty field. +If the current field is not empty, it is copied down to the next row, and +the cursor is moved with it. Therefore, repeating this command causes the +column to be filled row-by-row. +If the variable `org-table-copy-increment' is non-nil and the field is an +integer, it will be incremented while copying." + (interactive "p") + (let* ((colpos (org-table-current-column)) + (field (org-table-get-field)) + (non-empty (string-match "[^ \t]" field)) + (beg (org-table-begin)) + txt) + (org-table-check-inside-data-field) + (if non-empty + (progn + (setq txt (org-trim field)) + (org-table-next-row) + (org-table-blank-field)) + (save-excursion + (setq txt + (catch 'exit + (while (progn (beginning-of-line 1) + (re-search-backward org-table-dataline-regexp + beg t)) + (org-table-goto-column colpos t) + (if (and (looking-at + "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|") + (= (setq n (1- n)) 0)) + (throw 'exit (match-string 1)))))))) + (if txt + (progn + (if (and org-table-copy-increment + (string-match "^[0-9]+$" txt)) + (setq txt (format "%d" (+ (string-to-number txt) 1)))) + (insert txt) + (org-table-maybe-recalculate-line) + (org-table-align)) + (error "No non-empty field found")))) + +(defun org-table-check-inside-data-field () + "Is point inside a table data field? +I.e. not on a hline or before the first or after the last column? +This actually throws an error, so it aborts the current command." + (if (or (not (org-at-table-p)) + (= (org-table-current-column) 0) + (org-at-table-hline-p) + (looking-at "[ \t]*$")) + (error "Not in table data field"))) + +(defvar org-table-clip nil + "Clipboard for table regions.") + +(defun org-table-blank-field () + "Blank the current table field or active region." + (interactive) + (org-table-check-inside-data-field) + (if (and (interactive-p) (org-region-active-p)) + (let (org-table-clip) + (org-table-cut-region (region-beginning) (region-end))) + (skip-chars-backward "^|") + (backward-char 1) + (if (looking-at "|[^|\n]+") + (let* ((pos (match-beginning 0)) + (match (match-string 0)) + (len (string-width match))) + (replace-match (concat "|" (make-string (1- len) ?\ ))) + (goto-char (+ 2 pos)) + (substring match 1))))) + +(defun org-table-get-field (&optional n replace) + "Return the value of the field in column N of current row. +N defaults to current field. +If REPLACE is a string, replace field with this value. The return value +is always the old value." + (and n (org-table-goto-column n)) + (skip-chars-backward "^|\n") + (backward-char 1) + (if (looking-at "|[^|\r\n]*") + (let* ((pos (match-beginning 0)) + (val (buffer-substring (1+ pos) (match-end 0)))) + (if replace + (replace-match (concat "|" replace))) + (goto-char (min (point-at-eol) (+ 2 pos))) + val) + (forward-char 1) "")) + +(defun org-table-current-column () + "Find out which column we are in. +When called interactively, column is also displayed in echo area." + (interactive) + (if (interactive-p) (org-table-check-inside-data-field)) + (save-excursion + (let ((cnt 0) (pos (point))) + (beginning-of-line 1) + (while (search-forward "|" pos t) + (setq cnt (1+ cnt))) + (if (interactive-p) (message "This is table column %d" cnt)) + cnt))) + +(defun org-table-goto-column (n &optional on-delim force) + "Move the cursor to the Nth column in the current table line. +With optional argument ON-DELIM, stop with point before the left delimiter +of the field. +If there are less than N fields, just go to after the last delimiter. +However, when FORCE is non-nil, create new columns if necessary." + (interactive "p") + (let ((pos (point-at-eol))) + (beginning-of-line 1) + (when (> n 0) + (while (and (> (setq n (1- n)) -1) + (or (search-forward "|" pos t) + (and force + (progn (end-of-line 1) + (skip-chars-backward "^|") + (insert " | ")))))) +; (backward-char 2) t))))) + (when (and force (not (looking-at ".*|"))) + (save-excursion (end-of-line 1) (insert " | "))) + (if on-delim + (backward-char 1) + (if (looking-at " ") (forward-char 1)))))) + +(defun org-at-table-p (&optional table-type) + "Return t if the cursor is inside an org-type table. +If TABLE-TYPE is non-nil, also check for table.el-type tables." + (if org-enable-table-editor + (save-excursion + (beginning-of-line 1) + (looking-at (if table-type org-table-any-line-regexp + org-table-line-regexp))) + nil)) + +(defun org-at-table.el-p () + "Return t if and only if we are at a table.el table." + (and (org-at-table-p 'any) + (save-excursion + (goto-char (org-table-begin 'any)) + (looking-at org-table1-hline-regexp)))) + +(defun org-table-recognize-table.el () + "If there is a table.el table nearby, recognize it and move into it." + (if org-table-tab-recognizes-table.el + (if (org-at-table.el-p) + (progn + (beginning-of-line 1) + (if (looking-at org-table-dataline-regexp) + nil + (if (looking-at org-table1-hline-regexp) + (progn + (beginning-of-line 2) + (if (looking-at org-table-any-border-regexp) + (beginning-of-line -1))))) + (if (re-search-forward "|" (org-table-end t) t) + (progn + (require 'table) + (if (table--at-cell-p (point)) + t + (message "recognizing table.el table...") + (table-recognize-table) + (message "recognizing table.el table...done"))) + (error "This should not happen...")) + t) + nil) + nil)) + +(defun org-at-table-hline-p () + "Return t if the cursor is inside a hline in a table." + (if org-enable-table-editor + (save-excursion + (beginning-of-line 1) + (looking-at org-table-hline-regexp)) + nil)) + +(defun org-table-insert-column () + "Insert a new column into the table." + (interactive) + (if (not (org-at-table-p)) + (error "Not at a table")) + (org-table-find-dataline) + (let* ((col (max 1 (org-table-current-column))) + (beg (org-table-begin)) + (end (org-table-end)) + ;; Current cursor position + (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point)))) + (colpos col)) + (goto-char beg) + (while (< (point) end) + (if (org-at-table-hline-p) + nil + (org-table-goto-column col t) + (insert "| ")) + (beginning-of-line 2)) + (move-marker end nil) + (goto-line linepos) + (org-table-goto-column colpos) + (org-table-align) + (org-table-modify-formulas 'insert col))) + +(defun org-table-find-dataline () + "Find a dataline in the current table, which is needed for column commands." + (if (and (org-at-table-p) + (not (org-at-table-hline-p))) + t + (let ((col (current-column)) + (end (org-table-end))) + (move-to-column col) + (while (and (< (point) end) + (or (not (= (current-column) col)) + (org-at-table-hline-p))) + (beginning-of-line 2) + (move-to-column col)) + (if (and (org-at-table-p) + (not (org-at-table-hline-p))) + t + (error + "Please position cursor in a data line for column operations"))))) + +(defun org-table-delete-column () + "Delete a column into the table." + (interactive) + (if (not (org-at-table-p)) + (error "Not at a table")) + (org-table-find-dataline) + (org-table-check-inside-data-field) + (let* ((col (org-table-current-column)) + (beg (org-table-begin)) + (end (org-table-end)) + ;; Current cursor position + (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point)))) + (colpos col)) + (goto-char beg) + (while (< (point) end) + (if (org-at-table-hline-p) + nil + (org-table-goto-column col t) + (and (looking-at "|[^|\n]+|") + (replace-match "|"))) + (beginning-of-line 2)) + (move-marker end nil) + (goto-line linepos) + (org-table-goto-column colpos) + (org-table-align) + (org-table-modify-formulas 'remove col))) + +(defun org-table-move-column-right () + "Move column to the right." + (interactive) + (org-table-move-column nil)) +(defun org-table-move-column-left () + "Move column to the left." + (interactive) + (org-table-move-column 'left)) + +(defun org-table-move-column (&optional left) + "Move the current column to the right. With arg LEFT, move to the left." + (interactive "P") + (if (not (org-at-table-p)) + (error "Not at a table")) + (org-table-find-dataline) + (org-table-check-inside-data-field) + (let* ((col (org-table-current-column)) + (col1 (if left (1- col) col)) + (beg (org-table-begin)) + (end (org-table-end)) + ;; Current cursor position + (linepos (+ (if (bolp) 1 0) (count-lines (point-min) (point)))) + (colpos (if left (1- col) (1+ col)))) + (if (and left (= col 1)) + (error "Cannot move column further left")) + (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$")) + (error "Cannot move column further right")) + (goto-char beg) + (while (< (point) end) + (if (org-at-table-hline-p) + nil + (org-table-goto-column col1 t) + (and (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|") + (replace-match "|\\2|\\1|"))) + (beginning-of-line 2)) + (move-marker end nil) + (goto-line linepos) + (org-table-goto-column colpos) + (org-table-align) + (org-table-modify-formulas 'swap col (if left (1- col) (1+ col))))) + +(defun org-table-move-row-down () + "Move table row down." + (interactive) + (org-table-move-row nil)) +(defun org-table-move-row-up () + "Move table row up." + (interactive) + (org-table-move-row 'up)) + +(defun org-table-move-row (&optional up) + "Move the current table line down. With arg UP, move it up." + (interactive "P") + (let ((col (current-column)) + (pos (point)) + (tonew (if up 0 2)) + txt) + (beginning-of-line tonew) + (if (not (org-at-table-p)) + (progn + (goto-char pos) + (error "Cannot move row further"))) + (goto-char pos) + (beginning-of-line 1) + (setq pos (point)) + (setq txt (buffer-substring (point) (1+ (point-at-eol)))) + (delete-region (point) (1+ (point-at-eol))) + (beginning-of-line tonew) + (insert txt) + (beginning-of-line 0) + (move-to-column col))) + +(defun org-table-insert-row (&optional arg) + "Insert a new row above the current line into the table. +With prefix ARG, insert below the current line." + (interactive "P") + (if (not (org-at-table-p)) + (error "Not at a table")) + (let* ((line + (org-expand-wide-chars + (buffer-substring-no-properties (point-at-bol) (point-at-eol)))) + new) + (if (string-match "^[ \t]*|-" line) + (setq new (mapcar (lambda (x) (if (member x '(?| ?+)) ?| ?\ )) line)) + (setq new (mapcar (lambda (x) (if (equal x ?|) ?| ?\ )) line))) + ;; Fix the first field if necessary + (setq new (concat new)) + (if (string-match "^[ \t]*| *[#$] *|" line) + (setq new (replace-match (match-string 0 line) t t new))) + (beginning-of-line (if arg 2 1)) + (let (org-table-may-need-update) + (insert-before-markers new) + (insert-before-markers "\n")) + (beginning-of-line 0) + (re-search-forward "| ?" (point-at-eol) t) + (and org-table-may-need-update (org-table-align)))) + +(defun org-table-insert-hline (&optional arg) + "Insert a horizontal-line below the current line into the table. +With prefix ARG, insert above the current line." + (interactive "P") + (if (not (org-at-table-p)) + (error "Not at a table")) + (let ((line + (org-expand-wide-chars + (buffer-substring-no-properties (point-at-bol) (point-at-eol)))) + (col (current-column)) + start) + (if (string-match "^[ \t]*|-" line) + (setq line + (mapcar (lambda (x) (if (member x '(?| ?+)) + (prog1 (if start ?+ ?|) (setq start t)) + (if start ?- ?\ ))) + line)) + (setq line + (mapcar (lambda (x) (if (equal x ?|) + (prog1 (if start ?+ ?|) (setq start t)) + (if start ?- ?\ ))) + line))) + (beginning-of-line (if arg 1 2)) + (apply 'insert line) + (if (equal (char-before (point)) ?+) + (progn (backward-delete-char 1) (insert "|"))) + (insert "\n") + (beginning-of-line (if arg 1 -1)) + (move-to-column col))) + +(defun org-expand-wide-chars (s) + "Expand wide characters to spaces." + (let (w a) + (mapconcat + (lambda (x) + (if (> (setq w (string-width (setq a (char-to-string x)))) 1) + (make-string w ?\ ) + a)) + s ""))) + +(defun org-table-kill-row () + "Delete the current row or horizontal line from the table." + (interactive) + (if (not (org-at-table-p)) + (error "Not at a table")) + (let ((col (current-column))) + (kill-region (point-at-bol) (min (1+ (point-at-eol)) (point-max))) + (if (not (org-at-table-p)) (beginning-of-line 0)) + (move-to-column col))) + +(defun org-table-sort-lines (beg end numericp) + "Sort table lines in region. +Point and mark define the first and last line to include. Both point and +mark should be in the column that is used for sorting. For example, to +sort according to column 3, put the mark in the first line to sort, in +table column 3. Put point into the last line to be included in the sorting, +also in table column 3. The command will prompt for the sorting method +\(n for numerical, a for alphanumeric)." + (interactive "r\nsSorting method: [n]=numeric [a]=alpha: ") + (setq numericp (string-match "[nN]" numericp)) + (org-table-align) ;; Just to be safe + (let* (bcol ecol cmp column lns) + (goto-char beg) + (org-table-check-inside-data-field) + (setq column (org-table-current-column) + beg (move-marker (make-marker) (point-at-bol))) + (goto-char end) + (org-table-check-inside-data-field) + (setq end (move-marker (make-marker) (1+ (point-at-eol)))) + (untabify beg end) + (goto-char beg) + (org-table-goto-column column) + (skip-chars-backward "^|") + (setq bcol (current-column)) + (org-table-goto-column (1+ column)) + (skip-chars-backward "^|") + (setq ecol (1- (current-column))) + (setq cmp (if numericp + (lambda (a b) (< (car a) (car b))) + (lambda (a b) (string< (car a) (car b))))) + (setq lns (mapcar (lambda(x) (cons (org-trim (substring x bcol ecol)) x)) + (split-string (buffer-substring beg end) "\n"))) + (if numericp + (setq lns (mapcar (lambda(x) + (cons (string-to-number (car x)) (cdr x))) + lns))) + (delete-region beg end) + (move-marker beg nil) + (move-marker end nil) + (insert (mapconcat 'cdr (setq lns (sort lns cmp)) "\n") "\n") + (message "%d lines sorted %s based on column %d" + (length lns) + (if numericp "numerically" "alphabetically") column))) + +(defun org-table-cut-region (beg end) + "Copy region in table to the clipboard and blank all relevant fields." + (interactive "r") + (org-table-copy-region beg end 'cut)) + +(defun org-table-copy-region (beg end &optional cut) + "Copy rectangular region in table to clipboard. +A special clipboard is used which can only be accessed +with `org-table-paste-rectangle'." + (interactive "rP") + (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2 + region cols + (rpl (if cut " " nil))) + (goto-char beg) + (org-table-check-inside-data-field) + (setq l01 (count-lines (point-min) (point)) + c01 (org-table-current-column)) + (goto-char end) + (org-table-check-inside-data-field) + (setq l02 (count-lines (point-min) (point)) + c02 (org-table-current-column)) + (setq l1 (min l01 l02) l2 (max l01 l02) + c1 (min c01 c02) c2 (max c01 c02)) + (catch 'exit + (while t + (catch 'nextline + (if (> l1 l2) (throw 'exit t)) + (goto-line l1) + (if (org-at-table-hline-p) (throw 'nextline (setq l1 (1+ l1)))) + (setq cols nil ic1 c1 ic2 c2) + (while (< ic1 (1+ ic2)) + (push (org-table-get-field ic1 rpl) cols) + (setq ic1 (1+ ic1))) + (push (nreverse cols) region) + (setq l1 (1+ l1))))) + (setq org-table-clip (nreverse region)) + (if cut (org-table-align)) + org-table-clip)) + +(defun org-table-paste-rectangle () + "Paste a rectangular region into a table. +The upper right corner ends up in the current field. All involved fields +will be overwritten. If the rectangle does not fit into the present table, +the table is enlarged as needed. The process ignores horizontal separator +lines." + (interactive) + (unless (and org-table-clip (listp org-table-clip)) + (error "First cut/copy a region to paste!")) + (org-table-check-inside-data-field) + (let* ((clip org-table-clip) + (line (count-lines (point-min) (point))) + (col (org-table-current-column)) + (org-enable-table-editor t) + (org-table-automatic-realign nil) + c cols field) + (while (setq cols (pop clip)) + (while (org-at-table-hline-p) (beginning-of-line 2)) + (if (not (org-at-table-p)) + (progn (end-of-line 0) (org-table-next-field))) + (setq c col) + (while (setq field (pop cols)) + (org-table-goto-column c nil 'force) + (org-table-get-field nil field) + (setq c (1+ c))) + (beginning-of-line 2)) + (goto-line line) + (org-table-goto-column col) + (org-table-align))) + +(defun org-table-convert () + "Convert from `org-mode' table to table.el and back. +Obviously, this only works within limits. When an Org-mode table is +converted to table.el, all horizontal separator lines get lost, because +table.el uses these as cell boundaries and has no notion of horizontal lines. +A table.el table can be converted to an Org-mode table only if it does not +do row or column spanning. Multiline cells will become multiple cells. +Beware, Org-mode does not test if the table can be successfully converted - it +blindly applies a recipe that works for simple tables." + (interactive) + (require 'table) + (if (org-at-table.el-p) + ;; convert to Org-mode table + (let ((beg (move-marker (make-marker) (org-table-begin t))) + (end (move-marker (make-marker) (org-table-end t)))) + (table-unrecognize-region beg end) + (goto-char beg) + (while (re-search-forward "^\\([ \t]*\\)\\+-.*\n" end t) + (replace-match "")) + (goto-char beg)) + (if (org-at-table-p) + ;; convert to table.el table + (let ((beg (move-marker (make-marker) (org-table-begin))) + (end (move-marker (make-marker) (org-table-end)))) + ;; first, get rid of all horizontal lines + (goto-char beg) + (while (re-search-forward "^\\([ \t]*\\)|-.*\n" end t) + (replace-match "")) + ;; insert a hline before first + (goto-char beg) + (org-table-insert-hline 'above) + (beginning-of-line -1) + ;; insert a hline after each line + (while (progn (beginning-of-line 3) (< (point) end)) + (org-table-insert-hline)) + (goto-char beg) + (setq end (move-marker end (org-table-end))) + ;; replace "+" at beginning and ending of hlines + (while (re-search-forward "^\\([ \t]*\\)|-" end t) + (replace-match "\\1+-")) + (goto-char beg) + (while (re-search-forward "-|[ \t]*$" end t) + (replace-match "-+")) + (goto-char beg))))) + +(defun org-table-wrap-region (arg) + "Wrap several fields in a column like a paragraph. +This is useful if you'd like to spread the contents of a field over several +lines, in order to keep the table compact. + +If there is an active region, and both point and mark are in the same column, +the text in the column is wrapped to minimum width for the given number of +lines. Generally, this makes the table more compact. A prefix ARG may be +used to change the number of desired lines. For example, `C-2 \\[org-table-wrap]' +formats the selected text to two lines. If the region was longer than two +lines, the remaining lines remain empty. A negative prefix argument reduces +the current number of lines by that amount. The wrapped text is pasted back +into the table. If you formatted it to more lines than it was before, fields +further down in the table get overwritten - so you might need to make space in +the table first. + +If there is no region, the current field is split at the cursor position and +the text fragment to the right of the cursor is prepended to the field one +line down. + +If there is no region, but you specify a prefix ARG, the current field gets +blank, and the content is appended to the field above." + (interactive "P") + (org-table-check-inside-data-field) + (if (org-region-active-p) + ;; There is a region: fill as a paragraph + (let ((beg (region-beginning)) + nlines) + (org-table-cut-region (region-beginning) (region-end)) + (if (> (length (car org-table-clip)) 1) + (error "Region must be limited to single column")) + (setq nlines (if arg + (if (< arg 1) + (+ (length org-table-clip) arg) + arg) + (length org-table-clip))) + (setq org-table-clip + (mapcar 'list (org-wrap (mapconcat 'car org-table-clip " ") + nil nlines))) + (goto-char beg) + (org-table-paste-rectangle)) + ;; No region, split the current field at point + (if arg + ;; combine with field above + (let ((s (org-table-blank-field)) + (col (org-table-current-column))) + (beginning-of-line 0) + (while (org-at-table-hline-p) (beginning-of-line 0)) + (org-table-goto-column col) + (skip-chars-forward "^|") + (skip-chars-backward " ") + (insert " " (org-trim s)) + (org-table-align)) + ;; split field + (when (looking-at "\\([^|]+\\)+|") + (let ((s (match-string 1))) + (replace-match " |") + (goto-char (match-beginning 0)) + (org-table-next-row) + (insert (org-trim s) " ") + (org-table-align)))))) + +(defun org-trim (s) + "Remove whitespace at beginning and end of string." + (if (string-match "^[ \t]+" s) (setq s (replace-match "" t t s))) + (if (string-match "[ \t]+$" s) (setq s (replace-match "" t t s))) + s) + +(defun org-wrap (string &optional width lines) + "Wrap string to either a number of lines, or a width in characters. +If WIDTH is non-nil, the string is wrapped to that width, however many lines +that costs. If there is a word longer than WIDTH, the text is actually +wrapped to the length of that word. +IF WIDTH is nil and LINES is non-nil, the string is forced into at most that +many lines, whatever width that takes. +The return value is a list of lines, without newlines at the end." + (let* ((words (org-split-string string "[ \t\n]+")) + (maxword (apply 'max (mapcar 'string-width words))) + w ll) + (cond (width + (org-do-wrap words (max maxword width))) + (lines + (setq w maxword) + (setq ll (org-do-wrap words maxword)) + (if (<= (length ll) lines) + ll + (setq ll words) + (while (> (length ll) lines) + (setq w (1+ w)) + (setq ll (org-do-wrap words w))) + ll)) + (t (error "Cannot wrap this"))))) + + +(defun org-do-wrap (words width) + "Create lines of maximum width WIDTH (in characters) from word list WORDS." + (let (lines line) + (while words + (setq line (pop words)) + (while (and words (< (+ (length line) (length (car words))) width)) + (setq line (concat line " " (pop words)))) + (setq lines (push line lines))) + (nreverse lines))) + +;; FIXME: I think I can make this more efficient +(defun org-split-string (string &optional separators) + "Splits STRING into substrings at SEPARATORS. +No empty strings are returned if there are matches at the beginning +and end of string." + (let ((rexp (or separators "[ \f\t\n\r\v]+")) + (start 0) + notfirst + (list nil)) + (while (and (string-match rexp string + (if (and notfirst + (= start (match-beginning 0)) + (< start (length string))) + (1+ start) start)) + (< (match-beginning 0) (length string))) + (setq notfirst t) + (or (eq (match-beginning 0) 0) + (and (eq (match-beginning 0) (match-end 0)) + (eq (match-beginning 0) start)) + (setq list + (cons (substring string start (match-beginning 0)) + list))) + (setq start (match-end 0))) + (or (eq start (length string)) + (setq list + (cons (substring string start) + list))) + (nreverse list))) + +(defun org-table-add-invisible-to-vertical-lines () + "Add an `invisible' property to vertical lines of current table." + (interactive) + (let* ((beg (org-table-begin)) + (end (org-table-end)) + (end1)) + (save-excursion + (goto-char beg) + (while (< (point) end) + (setq end1 (point-at-eol)) + (if (looking-at org-table-dataline-regexp) + (while (re-search-forward "|" end1 t) + (add-text-properties (1- (point)) (point) + '(invisible org-table))) + (while (re-search-forward "[+|]" end1 t) + (add-text-properties (1- (point)) (point) + '(invisible org-table)))) + (beginning-of-line 2))))) + +(defun org-table-toggle-vline-visibility (&optional arg) + "Toggle the visibility of table vertical lines. +The effect is immediate and on all tables in the file. +With prefix ARG, make lines invisible when ARG is positive, make lines +visible when ARG is not positive." + (interactive "P") + (let ((action (cond + ((and arg (> (prefix-numeric-value arg) 0)) 'on) + ((and arg (< (prefix-numeric-value arg) 1)) 'off) + (t (if (org-in-invisibility-spec-p '(org-table)) + 'off + 'on))))) + (if (eq action 'off) + (progn + (org-remove-from-invisibility-spec '(org-table)) + (org-table-map-tables 'org-table-align) + (message "Vertical table lines visible") + (if (org-at-table-p) + (org-table-align))) + (org-add-to-invisibility-spec '(org-table)) + (org-table-map-tables 'org-table-align) + (message "Vertical table lines invisible")) + (redraw-frame (selected-frame)))) + +(defun org-table-map-tables (function) + "Apply FUNCTION to the start of all tables in the buffer." + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (while (re-search-forward org-table-any-line-regexp nil t) + (message "Mapping tables: %d%%" (/ (* 100.0 (point)) (buffer-size))) + (beginning-of-line 1) + (if (looking-at org-table-line-regexp) + (save-excursion (funcall function))) + (re-search-forward org-table-any-border-regexp nil 1))))) + +(defun org-table-sum (&optional beg end nlast) + "Sum numbers in region of current table column. +The result will be displayed in the echo area, and will be available +as kill to be inserted with \\[yank]. + +If there is an active region, it is interpreted as a rectangle and all +numbers in that rectangle will be summed. If there is no active +region and point is located in a table column, sum all numbers in that +column. + +If at least one number looks like a time HH:MM or HH:MM:SS, all other +numbers are assumed to be times as well (in decimal hours) and the +numbers are added as such. + +If NLAST is a number, only the NLAST fields will actually be summed." + (interactive) + (save-excursion + (let (col (timecnt 0) diff h m s org-table-clip) + (cond + ((and beg end)) ; beg and end given explicitly + ((org-region-active-p) + (setq beg (region-beginning) end (region-end))) + (t + (setq col (org-table-current-column)) + (goto-char (org-table-begin)) + (unless (re-search-forward "^[ \t]*|[^-]" nil t) + (error "No table data")) + (org-table-goto-column col) +;not needed? (skip-chars-backward "^|") + (setq beg (point)) + (goto-char (org-table-end)) + (unless (re-search-backward "^[ \t]*|[^-]" nil t) + (error "No table data")) + (org-table-goto-column col) +;not needed? (skip-chars-forward "^|") + (setq end (point)))) + (let* ((items (apply 'append (org-table-copy-region beg end))) + (items1 (cond ((not nlast) items) + ((>= nlast (length items)) items) + (t (setq items (reverse items)) + (setcdr (nthcdr (1- nlast) items) nil) + (nreverse items)))) + (numbers (delq nil (mapcar 'org-table-get-number-for-summing + items1))) + (res (apply '+ numbers)) + (sres (if (= timecnt 0) + (format "%g" res) + (setq diff (* 3600 res) + h (floor (/ diff 3600)) diff (mod diff 3600) + m (floor (/ diff 60)) diff (mod diff 60) + s diff) + (format "%d:%02d:%02d" h m s)))) + (kill-new sres) + (if (interactive-p) + (message "%s" + (substitute-command-keys + (format "Sum of %d items: %-20s (\\[yank] will insert result into buffer)" + (length numbers) sres)))) + sres)))) + +(defun org-table-get-number-for-summing (s) + (let (n) + (if (string-match "^ *|? *" s) + (setq s (replace-match "" nil nil s))) + (if (string-match " *|? *$" s) + (setq s (replace-match "" nil nil s))) + (setq n (string-to-number s)) + (cond + ((and (string-match "0" s) + (string-match "\\`[-+ \t0.edED]+\\'" s)) 0) + ((string-match "\\`[ \t]+\\'" s) nil) + ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?\\'" s) + (let ((h (string-to-number (or (match-string 1 s) "0"))) + (m (string-to-number (or (match-string 2 s) "0"))) + (s (string-to-number (or (match-string 4 s) "0")))) + (if (boundp 'timecnt) (setq timecnt (1+ timecnt))) + (* 1.0 (+ h (/ m 60.0) (/ s 3600.0))))) + ((equal n 0) nil) + (t n)))) + +(defun org-table-get-vertical-vector (desc &optional tbeg col) + "Get a calc vector from a column, accorting to descriptor DESC. +Optional arguments TBEG and COL can give the beginning of the table and +the current column, to avoid unnecessary parsing." + (save-excursion + (or tbeg (setq tbeg (org-table-begin))) + (or col (setq col (org-table-current-column))) + (let (beg end nn n n1 n2 l (thisline (org-current-line)) hline-list) + (cond + ((string-match "\\(I+\\)\\(-\\(I+\\)\\)?" desc) + (setq n1 (- (match-end 1) (match-beginning 1))) + (if (match-beginning 3) + (setq n2 (- (match-end 2) (match-beginning 3)))) + (setq n (if n2 (max n1 n2) n1)) + (setq n1 (if n2 (min n1 n2))) + (setq nn n) + (while (and (> nn 0) + (re-search-backward org-table-hline-regexp tbeg t)) + (push (org-current-line) hline-list) + (setq nn (1- nn))) + (setq hline-list (nreverse hline-list)) + (goto-line (nth (1- n) hline-list)) + (when (re-search-forward org-table-dataline-regexp) + (org-table-goto-column col) + (setq beg (point))) + (goto-line (if n1 (nth (1- n1) hline-list) thisline)) + (when (re-search-backward org-table-dataline-regexp) + (org-table-goto-column col) + (setq end (point))) + (setq l (apply 'append (org-table-copy-region beg end))) + (concat "[" (mapconcat (lambda (x) (setq x (org-trim x)) + (if (equal x "") "0" x)) + l ",") "]")) + ((string-match "\\([0-9]+\\)-\\([0-9]+\\)" desc) + (setq n1 (string-to-number (match-string 1 desc)) + n2 (string-to-number (match-string 2 desc))) + (beginning-of-line 1) + (save-excursion + (when (re-search-backward org-table-dataline-regexp tbeg t n1) + (org-table-goto-column col) + (setq beg (point)))) + (when (re-search-backward org-table-dataline-regexp tbeg t n2) + (org-table-goto-column col) + (setq end (point))) + (setq l (apply 'append (org-table-copy-region beg end))) + (concat "[" (mapconcat + (lambda (x) (setq x (org-trim x)) + (if (equal x "") "0" x)) + l ",") "]")) + ((string-match "\\([0-9]+\\)" desc) + (beginning-of-line 1) + (when (re-search-backward org-table-dataline-regexp tbeg t + (string-to-number (match-string 0 desc))) + (org-table-goto-column col) + (org-trim (org-table-get-field)))))))) + +(defvar org-table-formula-history nil) + +(defvar org-table-column-names nil + "Alist with column names, derived from the `!' line.") +(defvar org-table-column-name-regexp nil + "Regular expression matching the current column names.") +(defvar org-table-local-parameters nil + "Alist with parameter names, derived from the `$' line.") +(defvar org-table-named-field-locations nil + "Alist with locations of named fields.") + +(defun org-table-get-formula (&optional equation named) + "Read a formula from the minibuffer, offer stored formula as default." + (let* ((name (car (rassoc (list (org-current-line) + (org-table-current-column)) + org-table-named-field-locations))) + (scol (if named + (if name name + (error "Not in a named field")) + (int-to-string (org-table-current-column)))) + (dummy (and name (not named) + (not (y-or-n-p "Replace named-field formula with column equation? " )) + (error "Abort"))) + (org-table-may-need-update nil) + (stored-list (org-table-get-stored-formulas)) + (stored (cdr (assoc scol stored-list))) + (eq (cond + ((and stored equation (string-match "^ *=? *$" equation)) + stored) + ((stringp equation) + equation) + (t (read-string + (format "%s formula $%s=" (if named "Field" "Column") scol) + (or stored "") 'org-table-formula-history + ;stored + )))) + mustsave) + (when (not (string-match "\\S-" eq)) + ;; remove formula + (setq stored-list (delq (assoc scol stored-list) stored-list)) + (org-table-store-formulas stored-list) + (error "Formula removed")) + (if (string-match "^ *=?" eq) (setq eq (replace-match "" t t eq))) + (if (string-match " *$" eq) (setq eq (replace-match "" t t eq))) + (if (and name (not named)) + ;; We set the column equation, delete the named one. + (setq stored-list (delq (assoc name stored-list) stored-list) + mustsave t)) + (if stored + (setcdr (assoc scol stored-list) eq) + (setq stored-list (cons (cons scol eq) stored-list))) + (if (or mustsave (not (equal stored eq))) + (org-table-store-formulas stored-list)) + eq)) + +(defun org-table-store-formulas (alist) + "Store the list of formulas below the current table." + (setq alist (sort alist (lambda (a b) (string< (car a) (car b))))) + (save-excursion + (goto-char (org-table-end)) + (if (looking-at "\\([ \t]*\n\\)*#\\+TBLFM:.*\n?") + (delete-region (point) (match-end 0))) + (insert "#+TBLFM: " + (mapconcat (lambda (x) + (concat "$" (car x) "=" (cdr x))) + alist "::") + "\n"))) + +(defun org-table-get-stored-formulas () + "Return an alist with the t=stored formulas directly after current table." + (interactive) + (let (scol eq eq-alist strings string seen) + (save-excursion + (goto-char (org-table-end)) + (when (looking-at "\\([ \t]*\n\\)*#\\+TBLFM: *\\(.*\\)") + (setq strings (org-split-string (match-string 2) " *:: *")) + (while (setq string (pop strings)) + (when (string-match "\\$\\([a-zA-Z0-9]+\\) *= *\\(.*[^ \t]\\)" string) + (setq scol (match-string 1 string) + eq (match-string 2 string) + eq-alist (cons (cons scol eq) eq-alist)) + (if (member scol seen) + (error "Double definition `$%s=' in TBLFM line, please fix by hand" scol) + (push scol seen)))))) + (nreverse eq-alist))) + +(defun org-table-modify-formulas (action &rest columns) + "Modify the formulas stored below the current table. +ACTION can be `remove', `insert', `swap'. For `swap', two column numbers are +expected, for the other actions only a single column number is needed." + (let ((list (org-table-get-stored-formulas)) + (nmax (length (org-split-string + (buffer-substring (point-at-bol) (point-at-eol)) + "|"))) + col col1 col2 scol si sc1 sc2) + (cond + ((null list)) ; No action needed if there are no stored formulas + ((eq action 'remove) + (setq col (car columns) + scol (int-to-string col)) + (org-table-replace-in-formulas list scol "INVALID") + (if (assoc scol list) (setq list (delq (assoc scol list) list))) + (loop for i from (1+ col) upto nmax by 1 do + (setq si (int-to-string i)) + (org-table-replace-in-formulas list si (int-to-string (1- i))) + (if (assoc si list) (setcar (assoc si list) + (int-to-string (1- i)))))) + ((eq action 'insert) + (setq col (car columns)) + (loop for i from nmax downto col by 1 do + (setq si (int-to-string i)) + (org-table-replace-in-formulas list si (int-to-string (1+ i))) + (if (assoc si list) (setcar (assoc si list) + (int-to-string (1+ i)))))) + ((eq action 'swap) + (setq col1 (car columns) col2 (nth 1 columns) + sc1 (int-to-string col1) sc2 (int-to-string col2)) + ;; Hopefully, ZqZ will never be a name in a table... FIXME: + (org-table-replace-in-formulas list sc1 "ZqZ") + (org-table-replace-in-formulas list sc2 sc1) + (org-table-replace-in-formulas list "ZqZ" sc2) + (if (assoc sc1 list) (setcar (assoc sc1 list) "ZqZ")) + (if (assoc sc2 list) (setcar (assoc sc2 list) sc1)) + (if (assoc "ZqZ" list) (setcar (assoc "ZqZ" list) sc2))) + (t (error "Invalid action in `org-table-modify-formulas'"))) + (if list (org-table-store-formulas list)))) + +(defun org-table-replace-in-formulas (list s1 s2) + (let (elt re s) + (setq s1 (concat "$" (if (integerp s1) (int-to-string s1) s1)) + s2 (concat "$" (if (integerp s2) (int-to-string s2) s2)) + re (concat (regexp-quote s1) "\\>")) + (while (setq elt (pop list)) + (setq s (cdr elt)) + (while (string-match re s) + (setq s (replace-match s2 t t s))) + (setcdr elt s)))) + +(defun org-table-get-specials () + "Get the column names and local parameters for this table." + (save-excursion + (let ((beg (org-table-begin)) (end (org-table-end)) + names name fields fields1 field cnt c v line col) + (setq org-table-column-names nil + org-table-local-parameters nil + org-table-named-field-locations nil) + (goto-char beg) + (when (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t) + (setq names (org-split-string (match-string 1) " *| *") + cnt 1) + (while (setq name (pop names)) + (setq cnt (1+ cnt)) + (if (string-match "^[a-zA-Z][a-zA-Z0-9]*$" name) + (push (cons name (int-to-string cnt)) org-table-column-names)))) + (setq org-table-column-names (nreverse org-table-column-names)) + (setq org-table-column-name-regexp + (concat "\\$\\(" (mapconcat 'car org-table-column-names "\\|") "\\)\\>")) + (goto-char beg) + (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t) + (setq fields (org-split-string (match-string 1) " *| *")) + (while (setq field (pop fields)) + (if (string-match "^\\([a-zA-Z][a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field) + (push (cons (match-string 1 field) (match-string 2 field)) + org-table-local-parameters)))) + (goto-char beg) + (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t) + (setq c (match-string 1) + fields (org-split-string (match-string 2) " *| *")) + (save-excursion + (beginning-of-line (if (equal c "_") 2 0)) + (setq line (org-current-line) col 1) + (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)") + (setq fields1 (org-split-string (match-string 1) " *| *")))) + (while (and fields1 (setq field (pop fields))) + (setq v (pop fields1) col (1+ col)) + (when (and (stringp field) (stringp v) + (string-match "^[a-zA-Z][a-zA-Z0-9]*$" field)) + (push (cons field v) org-table-local-parameters) + (push (list field line col) org-table-named-field-locations))))))) + +(defun org-this-word () + ;; Get the current word + (save-excursion + (let ((beg (progn (skip-chars-backward "^ \t\n") (point))) + (end (progn (skip-chars-forward "^ \t\n") (point)))) + (buffer-substring-no-properties beg end)))) + +(defun org-table-maybe-eval-formula () + "Check if the current field starts with \"=\" or \":=\". +If yes, store the formula and apply it." + ;; We already know we are in a table. Get field will only return a formula + ;; when appropriate. It might return a separator line, but no problem. + (when org-table-formula-evaluate-inline + (let* ((field (org-trim (or (org-table-get-field) ""))) + named eq) + (when (string-match "^:?=\\(.*\\)" field) + (setq named (equal (string-to-char field) ?:) + eq (match-string 1 field)) + (if (fboundp 'calc-eval) + (org-table-eval-formula (if named '(4) nil) eq)))))) + +(defvar org-recalc-commands nil + "List of commands triggering the recalculation of a line. +Will be filled automatically during use.") + +(defvar org-recalc-marks + '((" " . "Unmarked: no special line, no automatic recalculation") + ("#" . "Automatically recalculate this line upon TAB, RET, and C-c C-c in the line") + ("*" . "Recalculate only when entire table is recalculated with `C-u C-c *'") + ("!" . "Column name definition line. Reference in formula as $name.") + ("$" . "Parameter definition line name=value. Reference in formula as $name.") + ("_" . "Names for values in row below this one.") + ("^" . "Names for values in row above this one."))) + +(defun org-table-rotate-recalc-marks (&optional newchar) + "Rotate the recalculation mark in the first column. +If in any row, the first field is not consistent with a mark, +insert a new column for the markers. +When there is an active region, change all the lines in the region, +after prompting for the marking character. +After each change, a message will be displayed indicating the meaning +of the new mark." + (interactive) + (unless (org-at-table-p) (error "Not at a table")) + (let* ((marks (append (mapcar 'car org-recalc-marks) '(" "))) + (beg (org-table-begin)) + (end (org-table-end)) + (l (org-current-line)) + (l1 (if (org-region-active-p) (org-current-line (region-beginning)))) + (l2 (if (org-region-active-p) (org-current-line (region-end)))) + (have-col + (save-excursion + (goto-char beg) + (not (re-search-forward "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" end t)))) + (col (org-table-current-column)) + (forcenew (car (assoc newchar org-recalc-marks))) + epos new) + (when l1 + (message "Change region to what mark? Type # * ! $ or SPC: ") + (setq newchar (char-to-string (read-char-exclusive)) + forcenew (car (assoc newchar org-recalc-marks)))) + (if (and newchar (not forcenew)) + (error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'" + newchar)) + (if l1 (goto-line l1)) + (save-excursion + (beginning-of-line 1) + (unless (looking-at org-table-dataline-regexp) + (error "Not at a table data line"))) + (unless have-col + (org-table-goto-column 1) + (org-table-insert-column) + (org-table-goto-column (1+ col))) + (setq epos (point-at-eol)) + (save-excursion + (beginning-of-line 1) + (org-table-get-field + 1 (if (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|") + (concat " " + (setq new (or forcenew + (cadr (member (match-string 1) marks)))) + " ") + " # "))) + (if (and l1 l2) + (progn + (goto-line l1) + (while (progn (beginning-of-line 2) (not (= (org-current-line) l2))) + (and (looking-at org-table-dataline-regexp) + (org-table-get-field 1 (concat " " new " ")))) + (goto-line l1))) + (if (not (= epos (point-at-eol))) (org-table-align)) + (goto-line l) + (and (interactive-p) (message (cdr (assoc new org-recalc-marks)))))) + +(defun org-table-maybe-recalculate-line () + "Recompute the current line if marked for it, and if we haven't just done it." + (interactive) + (and org-table-allow-automatic-line-recalculation + (not (and (memq last-command org-recalc-commands) + (equal org-last-recalc-line (org-current-line)))) + (save-excursion (beginning-of-line 1) + (looking-at org-table-auto-recalculate-regexp)) + (fboundp 'calc-eval) + (org-table-recalculate) t)) + +(defvar org-table-formula-debug nil + "Non-nil means, debug table formulas. +When nil, simply write \"#ERROR\" in corrupted fields.") + +(defvar modes) +(defsubst org-set-calc-mode (var &optional value) + (if (stringp var) + (setq var (assoc var '(("D" calc-angle-mode deg) + ("R" calc-angle-mode rad) + ("F" calc-prefer-frac t) + ("S" calc-symbolic-mode t))) + value (nth 2 var) var (nth 1 var))) + (if (memq var modes) + (setcar (cdr (memq var modes)) value) + (cons var (cons value modes))) + modes) + +(defun org-table-eval-formula (&optional arg equation + suppress-align suppress-const + suppress-store) + "Replace the table field value at the cursor by the result of a calculation. + +This function makes use of Dave Gillespie's Calc package, in my view the +most exciting program ever written for GNU Emacs. So you need to have Calc +installed in order to use this function. + +In a table, this command replaces the value in the current field with the +result of a formula. It also installs the formula as the \"current\" column +formula, by storing it in a special line below the table. When called +with a `C-u' prefix, the current field must ba a named field, and the +formula is installed as valid in only this specific field. + +When called, the command first prompts for a formula, which is read in +the minibuffer. Previously entered formulas are available through the +history list, and the last used formula is offered as a default. +These stored formulas are adapted correctly when moving, inserting, or +deleting columns with the corresponding commands. + +The formula can be any algebraic expression understood by the Calc package. +For details, see the Org-mode manual. + +This function can also be called from Lisp programs and offers +additional arguments: EQUATION can be the formula to apply. If this +argument is given, the user will not be prompted. SUPPRESS-ALIGN is +used to speed-up recursive calls by by-passing unnecessary aligns. +SUPPRESS-CONST suppresses the interpretation of constants in the +formula, assuming that this has been done already outside the function. +SUPPRESS-STORE means the formula should not be stored, either because +it is already stored, or because it is a modified equation that should +not overwrite the stored one." + (interactive "P") + (require 'calc) + (org-table-check-inside-data-field) + (org-table-get-specials) + (let* (fields + (ndown (if (integerp arg) arg 1)) + (org-table-automatic-realign nil) + (case-fold-search nil) + (down (> ndown 1)) + (formula (if (and equation suppress-store) + equation + (org-table-get-formula equation (equal arg '(4))))) + (n0 (org-table-current-column)) + (modes (copy-sequence org-calc-default-modes)) + n form fmt x ev orig c) + ;; Parse the format string. Since we have a lot of modes, this is + ;; a lot of work. However, I think calc still uses most of the time. + (if (string-match ";" formula) + (let ((tmp (org-split-string formula ";"))) + (setq formula (car tmp) + fmt (concat (cdr (assoc "%" org-table-local-parameters)) + (nth 1 tmp))) + (while (string-match "[pnfse]\\(-?[0-9]+\\)" fmt) + (setq c (string-to-char (match-string 1 fmt)) + n (string-to-number (or (match-string 1 fmt) ""))) + (if (= c ?p) (setq modes (org-set-calc-mode 'calc-internal-prec n)) + (setq modes (org-set-calc-mode + 'calc-float-format + (list (cdr (assoc c '((?n . float) (?f . fix) + (?s . sci) (?e . eng)))) + n)))) + (setq fmt (replace-match "" t t fmt))) + (while (string-match "[DRFS]" fmt) + (setq modes (org-set-calc-mode (match-string 0 fmt))) + (setq fmt (replace-match "" t t fmt))) + (unless (string-match "\\S-" fmt) + (setq fmt nil)))) + (if (and (not suppress-const) org-table-formula-use-constants) + (setq formula (org-table-formula-substitute-names formula))) + (setq orig (or (get-text-property 1 :orig-formula formula) "?")) + (while (> ndown 0) + (setq fields (org-split-string + (buffer-substring + (point-at-bol) (point-at-eol)) " *| *")) + (if org-table-formula-numbers-only + (setq fields (mapcar + (lambda (x) (number-to-string (string-to-number x))) + fields))) + (setq ndown (1- ndown)) + (setq form (copy-sequence formula)) + ;; Insert the references to fields in same row + (while (string-match "\\$\\([0-9]+\\)?" form) + (setq n (if (match-beginning 1) + (string-to-number (match-string 1 form)) + n0) + x (nth (1- n) fields)) + (unless x (error "Invalid field specifier \"%s\"" + (match-string 0 form))) + (if (equal x "") (setq x "0")) + (setq form (replace-match (concat "(" x ")") t t form))) + ;; Insert ranges in current column + (while (string-match "\\&[-I0-9]+" form) + (setq form (replace-match + (save-match-data + (org-table-get-vertical-vector (match-string 0 form) + nil n0)) + t t form))) + (setq ev (calc-eval (cons form modes) + (if org-table-formula-numbers-only 'num))) + + (when org-table-formula-debug + (with-output-to-temp-buffer "*Help*" + (princ (format "Substitution history of formula +Orig: %s +$xyz-> %s +$1-> %s\n" orig formula form)) + (if (listp ev) + (princ (format " %s^\nError: %s" + (make-string (car ev) ?\-) (nth 1 ev))) + (princ (format "Result: %s\nFormat: %s\nFinal: %s" + ev (or fmt "NONE") + (if fmt (format fmt (string-to-number ev)) ev))))) + (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*")) + (unless (and (interactive-p) (not ndown)) + (unless (let (inhibit-redisplay) + (y-or-n-p "Debugging Formula. Continue to next? ")) + (org-table-align) + (error "Abort")) + (delete-window (get-buffer-window "*Help*")) + (message ""))) + (if (listp ev) (setq fmt nil ev "#ERROR")) + (org-table-justify-field-maybe + (if fmt (format fmt (string-to-number ev)) ev)) + (if (and down (> ndown 0) (looking-at ".*\n[ \t]*|[^-]")) + (call-interactively 'org-return) + (setq ndown 0))) + (and down (org-table-maybe-recalculate-line)) + (or suppress-align (and org-table-may-need-update + (org-table-align))))) + +(defun org-table-recalculate (&optional all noalign) + "Recalculate the current table line by applying all stored formulas." + (interactive "P") + (or (memq this-command org-recalc-commands) + (setq org-recalc-commands (cons this-command org-recalc-commands))) + (unless (org-at-table-p) (error "Not at a table")) + (org-table-get-specials) + (let* ((eqlist (sort (org-table-get-stored-formulas) + (lambda (a b) (string< (car a) (car b))))) + (inhibit-redisplay t) + (line-re org-table-dataline-regexp) + (thisline (+ (if (bolp) 1 0) (count-lines (point-min) (point)))) + (thiscol (org-table-current-column)) + beg end entry eqlnum eqlname eql (cnt 0) eq a name) + ;; Insert constants in all formulas + (setq eqlist + (mapcar (lambda (x) + (setcdr x (org-table-formula-substitute-names (cdr x))) + x) + eqlist)) + ;; Split the equation list + (while (setq eq (pop eqlist)) + (if (<= (string-to-char (car eq)) ?9) + (push eq eqlnum) + (push eq eqlname))) + (setq eqlnum (nreverse eqlnum) eqlname (nreverse eqlname)) + (if all + (progn + (setq end (move-marker (make-marker) (1+ (org-table-end)))) + (goto-char (setq beg (org-table-begin))) + (if (re-search-forward org-table-calculate-mark-regexp end t) + ;; This is a table with marked lines, only compute selected lines + (setq line-re org-table-recalculate-regexp) + ;; Move forward to the first non-header line + (if (and (re-search-forward org-table-dataline-regexp end t) + (re-search-forward org-table-hline-regexp end t) + (re-search-forward org-table-dataline-regexp end t)) + (setq beg (match-beginning 0)) + nil))) ;; just leave beg where it is + (setq beg (point-at-bol) + end (move-marker (make-marker) (1+ (point-at-eol))))) + (goto-char beg) + (and all (message "Re-applying formulas to full table...")) + (while (re-search-forward line-re end t) + (unless (string-match "^ *[_^!$] *$" (org-table-get-field 1)) + ;; Unprotected line, recalculate + (and all (message "Re-applying formulas to full table...(line %d)" + (setq cnt (1+ cnt)))) + (setq org-last-recalc-line (org-current-line)) + (setq eql eqlnum) + (while (setq entry (pop eql)) + (goto-line org-last-recalc-line) + (org-table-goto-column (string-to-number (car entry)) nil 'force) + (org-table-eval-formula nil (cdr entry) 'noalign 'nocst 'nostore)))) + (goto-line thisline) + (org-table-goto-column thiscol) + (or noalign (and org-table-may-need-update (org-table-align)) + (and all (message "Re-applying formulas to %d lines...done" cnt))) + ;; Now do the names fields + (while (setq eq (pop eqlname)) + (setq name (car eq) + a (assoc name org-table-named-field-locations)) + (when a + (message "Re-applying formula to named field: %s" name) + (goto-line (nth 1 a)) + (org-table-goto-column (nth 2 a)) + (org-table-eval-formula nil (cdr eq) 'noalign 'nocst 'nostore))) + ;; back to initial position + (goto-line thisline) + (org-table-goto-column thiscol) + (or noalign (and org-table-may-need-update (org-table-align)) + (and all (message "Re-applying formulas...done"))))) + +(defun org-table-formula-substitute-names (f) + "Replace $const with values in string F." + (let ((start 0) a n1 n2 nn1 nn2 s (f1 f)) + ;; First, check for column names + (while (setq start (string-match org-table-column-name-regexp f start)) + (setq start (1+ start)) + (setq a (assoc (match-string 1 f) org-table-column-names)) + (setq f (replace-match (concat "$" (cdr a)) t t f))) + ;; Expand ranges to vectors + (while (string-match "\\$\\([0-9]+\\)\\.\\.\\.?\\$\\([0-9]+\\)" f) + (setq n1 (string-to-number (match-string 1 f)) + n2 (string-to-number (match-string 2 f)) + nn1 (1+ (min n1 n2)) nn2 (max n1 n2) + s (concat "[($" (number-to-string (1- nn1)) ")")) + (loop for i from nn1 upto nn2 do + (setq s (concat s ",($" (int-to-string i) ")"))) + (setq s (concat s "]")) + (if (< n2 n1) (setq s (concat "rev(" s ")"))) + (setq f (replace-match s t t f))) + ;; Parameters and constants + (setq start 0) + (while (setq start (string-match "\\$\\([a-zA-Z][a-zA-Z0-9]*\\)" f start)) + (setq start (1+ start)) + (if (setq a (save-match-data + (org-table-get-constant (match-string 1 f)))) + (setq f (replace-match (concat "(" a ")") t t f)))) + (if org-table-formula-debug + (put-text-property 0 (length f) :orig-formula f1 f)) + f)) + +(defun org-table-get-constant (const) + "Find the value for a parameter or constant in a formula. +Parameters get priority." + (or (cdr (assoc const org-table-local-parameters)) + (cdr (assoc const org-table-formula-constants)) + (and (fboundp 'constants-get) (constants-get const)) + "#UNDEFINED_NAME")) + +(defvar org-edit-formulas-map (make-sparse-keymap)) +(define-key org-edit-formulas-map "\C-c\C-c" 'org-finish-edit-formulas) +(define-key org-edit-formulas-map "\C-c\C-q" 'org-abort-edit-formulas) +(define-key org-edit-formulas-map "\C-c?" 'org-show-variable) + +(defvar org-pos) +(defvar org-window-configuration) + +(defun org-table-edit-formulas () + "Edit the formulas of the current table in a separate buffer." + (interactive) + (unless (org-at-table-p) + (error "Not at a table")) + (org-table-get-specials) + (let ((eql (org-table-get-stored-formulas)) + (pos (move-marker (make-marker) (point))) + (wc (current-window-configuration)) + entry loc s) + (switch-to-buffer-other-window "*Edit Formulas*") + (erase-buffer) + (fundamental-mode) + (set (make-local-variable 'org-pos) pos) + (set (make-local-variable 'org-window-configuration) wc) + (use-local-map org-edit-formulas-map) + (setq s "# Edit formulas and finish with `C-c C-c'. +# Use `C-u C-c C-c' to also appy them immediately to the entire table. +# Use `C-c ?' to get information about $name at point. +# To cancel editing, press `C-c C-q'.\n") + (put-text-property 0 (length s) 'face 'font-lock-comment-face s) + (insert s) + (while (setq entry (pop eql)) + (when (setq loc (assoc (car entry) org-table-named-field-locations)) + (setq s (format "# Named formula, referring to column %d in line %d\n" + (nth 2 loc) (nth 1 loc))) + (put-text-property 0 (length s) 'face 'font-lock-comment-face s) + (insert s)) + (setq s (concat "$" (car entry) "=" (cdr entry) "\n")) + (remove-text-properties 0 (length s) '(face nil) s) + (insert s)) + (goto-char (point-min)) + (message "Edit formulas and finish with `C-c C-c'."))) + +(defun org-show-variable () + "Show the location/value of the $ expression at point." + (interactive) + (let (var (pos org-pos) (win (selected-window)) e) + (save-excursion + (or (looking-at "\\$") (skip-chars-backward "$a-zA-Z0-9")) + (if (looking-at "\\$\\([a-zA-Z0-9]+\\)") + (setq var (match-string 1)) + (error "No variable at point"))) + (cond + ((setq e (assoc var org-table-named-field-locations)) + (switch-to-buffer-other-window (marker-buffer pos)) + (goto-line (nth 1 e)) + (org-table-goto-column (nth 2 e)) + (select-window win) + (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e))) + ((setq e (assoc var org-table-column-names)) + (switch-to-buffer-other-window (marker-buffer pos)) + (goto-char pos) + (goto-char (org-table-begin)) + (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|") + (org-table-end) t) + (progn + (goto-char (match-beginning 1)) + (message "Named column (column %s)" (cdr e))) + (error "Column name not found")) + (select-window win)) + ((string-match "^[0-9]$" var) + ;; column number + (switch-to-buffer-other-window (marker-buffer pos)) + (goto-char pos) + (goto-char (org-table-begin)) + (recenter 1) + (if (re-search-forward org-table-dataline-regexp + (org-table-end) t) + (progn + (goto-char (match-beginning 0)) + (org-table-goto-column (string-to-number var)) + (message "Column %s" var)) + (error "Column name not found")) + (select-window win)) + ((setq e (assoc var org-table-local-parameters)) + (switch-to-buffer-other-window (marker-buffer pos)) + (goto-char pos) + (goto-char (org-table-begin)) + (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") nil t) + (progn + (goto-char (match-beginning 1)) + (message "Local parameter.")) + (error "Parameter not found")) + (select-window win)) + (t + (cond + ((setq e (assoc var org-table-formula-constants)) + (message "Constant: $%s=%s in `org-table-formula-constants'." var (cdr e))) + ((setq e (and (fboundp 'constants-get) (constants-get var))) + (message "Constant: $%s=%s, retrieved from `constants.el'." var e)) + (t (error "Undefined name $%s" var))))))) + +(defun org-finish-edit-formulas (&optional arg) + "Parse the buffer for formula definitions and install them. +With prefix ARG, apply the new formulas to the table." + (interactive "P") + (let ((pos org-pos) eql) + (goto-char (point-min)) + (while (re-search-forward "^\\$\\([a-zA-Z0-9]+\\) *= *\\(.*?\\) *$" nil t) + (push (cons (match-string 1) (match-string 2)) eql)) + (set-window-configuration org-window-configuration) + (select-window (get-buffer-window (marker-buffer pos))) + (goto-char pos) + (unless (org-at-table-p) + (error "Lost table position - cannot install formulae")) + (org-table-store-formulas eql) + (move-marker pos nil) + (kill-buffer "*Edit Formulas*") + (if arg + (org-table-recalculate 'all) + (message "New formulas installed - press C-u C-c C-c to apply.")))) + +(defun org-abort-edit-formulas () + "Abort editing formulas, without installing the changes." + (interactive) + (let ((pos org-pos)) + (set-window-configuration org-window-configuration) + (select-window (get-buffer-window (marker-buffer pos))) + (goto-char pos) + (message "Formula editing aborted without installing changes"))) + +;;; The orgtbl minor mode + +;; Define a minor mode which can be used in other modes in order to +;; integrate the org-mode table editor. + +;; This is really a hack, because the org-mode table editor uses several +;; keys which normally belong to the major mode, for example the TAB and +;; RET keys. Here is how it works: The minor mode defines all the keys +;; necessary to operate the table editor, but wraps the commands into a +;; function which tests if the cursor is currently inside a table. If that +;; is the case, the table editor command is executed. However, when any of +;; those keys is used outside a table, the function uses `key-binding' to +;; look up if the key has an associated command in another currently active +;; keymap (minor modes, major mode, global), and executes that command. +;; There might be problems if any of the keys used by the table editor is +;; otherwise used as a prefix key. + +;; Another challenge is that the key binding for TAB can be tab or \C-i, +;; likewise the binding for RET can be return or \C-m. Orgtbl-mode +;; addresses this by checking explicitly for both bindings. + +;; The optimized version (see variable `orgtbl-optimized') takes over +;; all keys which are bound to `self-insert-command' in the *global map*. +;; Some modes bind other commands to simple characters, for example +;; AUCTeX binds the double quote to `Tex-insert-quote'. With orgtbl-mode +;; active, this binding is ignored inside tables and replaced with a +;; modified self-insert. + +(defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized) + "Non-nil means, use the optimized table editor version for `orgtbl-mode'. +In the optimized version, the table editor takes over all simple keys that +normally just insert a character. In tables, the characters are inserted +in a way to minimize disturbing the table structure (i.e. in overwrite mode +for empty fields). Outside tables, the correct binding of the keys is +restored. + +The default for this option is t if the optimized version is also used in +Org-mode. See the variable `org-enable-table-editor' for details. Changing +this variable requires a restart of Emacs to become effective." + :group 'org-table + :type 'boolean) + +(defvar orgtbl-mode nil + "Variable controlling `orgtbl-mode', a minor mode enabling the `org-mode' +table editor in arbitrary modes.") +(make-variable-buffer-local 'orgtbl-mode) + +(defvar orgtbl-mode-map (make-keymap) + "Keymap for `orgtbl-mode'.") + +;;;###autoload +(defun turn-on-orgtbl () + "Unconditionally turn on `orgtbl-mode'." + (orgtbl-mode 1)) + +;;;###autoload +(defun orgtbl-mode (&optional arg) + "The `org-mode' table editor as a minor mode for use in other modes." + (interactive) + (if (eq major-mode 'org-mode) + ;; Exit without error, in case some hook functions calls this + ;; by accident in org-mode. + (message "Orgtbl-mode is not useful in org-mode, command ignored") + (setq orgtbl-mode + (if arg (> (prefix-numeric-value arg) 0) (not orgtbl-mode))) + (if orgtbl-mode + (progn + (and (orgtbl-setup) (defun orgtbl-setup () nil)) + ;; Make sure we are first in minor-mode-map-alist + (let ((c (assq 'orgtbl-mode minor-mode-map-alist))) + (and c (setq minor-mode-map-alist + (cons c (delq c minor-mode-map-alist))))) + (set (make-local-variable (quote org-table-may-need-update)) t) + (org-add-hook 'before-change-functions 'org-before-change-function + nil 'local) + (set (make-local-variable 'org-old-auto-fill-inhibit-regexp) + auto-fill-inhibit-regexp) + (set (make-local-variable 'auto-fill-inhibit-regexp) + (if auto-fill-inhibit-regexp + (concat "\\([ \t]*|\\|" auto-fill-inhibit-regexp) + "[ \t]*|")) + (easy-menu-add orgtbl-mode-menu) + (run-hooks 'orgtbl-mode-hook)) + (setq auto-fill-inhibit-regexp org-old-auto-fill-inhibit-regexp) + (remove-hook 'before-change-functions 'org-before-change-function t) + (easy-menu-remove orgtbl-mode-menu) + (force-mode-line-update 'all)))) + +;; Install it as a minor mode. +(put 'orgtbl-mode :included t) +(put 'orgtbl-mode :menu-tag "Org Table Mode") +(add-minor-mode 'orgtbl-mode " OrgTbl" orgtbl-mode-map) + +(defun orgtbl-make-binding (fun n &rest keys) + "Create a function for binding in the table minor mode. +FUN is the command to call inside a table. N is used to create a unique +command name. KEYS are keys that should be checked in for a command +to execute outside of tables." + (eval + (list 'defun + (intern (concat "orgtbl-hijacker-command-" (int-to-string n))) + '(arg) + (concat "In tables, run `" (symbol-name fun) "'.\n" + "Outside of tables, run the binding of `" + (mapconcat (lambda (x) (format "%s" x)) keys "' or `") + "'.") + '(interactive "p") + (list 'if + '(org-at-table-p) + (list 'call-interactively (list 'quote fun)) + (list 'let '(orgtbl-mode) + (list 'call-interactively + (append '(or) + (mapcar (lambda (k) + (list 'key-binding k)) + keys) + '('orgtbl-error)))))))) + +(defun orgtbl-error () + "Error when there is no default binding for a table key." + (interactive) + (error "This key is has no function outside tables")) + +(defun orgtbl-setup () + "Setup orgtbl keymaps." + (let ((nfunc 0) + (bindings + (list + '([(meta shift left)] org-table-delete-column) + '([(meta left)] org-table-move-column-left) + '([(meta right)] org-table-move-column-right) + '([(meta shift right)] org-table-insert-column) + '([(meta shift up)] org-table-kill-row) + '([(meta shift down)] org-table-insert-row) + '([(meta up)] org-table-move-row-up) + '([(meta down)] org-table-move-row-down) + '("\C-c\C-w" org-table-cut-region) + '("\C-c\M-w" org-table-copy-region) + '("\C-c\C-y" org-table-paste-rectangle) + '("\C-c-" org-table-insert-hline) +; '([(shift tab)] org-table-previous-field) + '("\C-m" org-table-next-row) + (list (org-key 'S-return) 'org-table-copy-down) + '([(meta return)] org-table-wrap-region) + '("\C-c\C-q" org-table-wrap-region) + '("\C-c?" org-table-current-column) + '("\C-c " org-table-blank-field) + '("\C-c+" org-table-sum) + '("\C-c|" org-table-toggle-vline-visibility) + '("\C-c=" org-table-eval-formula) + '("\C-c'" org-table-edit-formulas) + '("\C-c*" org-table-recalculate) + '("\C-c^" org-table-sort-lines) + '([(control ?#)] org-table-rotate-recalc-marks))) + elt key fun cmd) + (while (setq elt (pop bindings)) + (setq nfunc (1+ nfunc)) + (setq key (car elt) + fun (nth 1 elt) + cmd (orgtbl-make-binding fun nfunc key)) + (define-key orgtbl-mode-map key cmd)) + ;; Special treatment needed for TAB and RET + (define-key orgtbl-mode-map [(return)] + (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m")) + (define-key orgtbl-mode-map "\C-m" + (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)])) + (define-key orgtbl-mode-map [(tab)] + (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i")) + (define-key orgtbl-mode-map "\C-i" + (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)]))) + (define-key orgtbl-mode-map "\C-i" + (orgtbl-make-binding 'orgtbl-tab 104 [(shift tab)])) + (define-key orgtbl-mode-map "\C-c\C-c" + (orgtbl-make-binding 'org-ctrl-c-ctrl-c 105 "\C-c\C-c")) + (when orgtbl-optimized + ;; If the user wants maximum table support, we need to hijack + ;; some standard editing functions + (org-remap orgtbl-mode-map + 'self-insert-command 'orgtbl-self-insert-command + 'delete-char 'orgtbl-delete-char + 'delete-backward-char 'orgtbl-delete-backward-char) + (define-key orgtbl-mode-map "|" 'org-force-self-insert)) + (easy-menu-define orgtbl-mode-menu orgtbl-mode-map "OrgTbl menu" + '("OrgTbl" + ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p) :keys "C-c C-c"] + ["Next Field" org-cycle :active (org-at-table-p) :keys "TAB"] + ["Previous Field" org-shifttab :active (org-at-table-p) :keys "S-TAB"] + ["Next Row" org-return :active (org-at-table-p) :keys "RET"] + "--" + ["Blank Field" org-table-blank-field :active (org-at-table-p) :keys "C-c SPC"] + ["Copy Field from Above" + org-table-copy-down :active (org-at-table-p) :keys "S-RET"] + "--" + ("Column" + ["Move Column Left" org-metaleft :active (org-at-table-p) :keys "M-"] + ["Move Column Right" org-metaright :active (org-at-table-p) :keys "M-"] + ["Delete Column" org-shiftmetaleft :active (org-at-table-p) :keys "M-S-"] + ["Insert Column" org-shiftmetaright :active (org-at-table-p) :keys "M-S-"]) + ("Row" + ["Move Row Up" org-metaup :active (org-at-table-p) :keys "M-"] + ["Move Row Down" org-metadown :active (org-at-table-p) :keys "M-"] + ["Delete Row" org-shiftmetaup :active (org-at-table-p) :keys "M-S-"] + ["Insert Row" org-shiftmetadown :active (org-at-table-p) :keys "M-S-"] + ["Sort lines in region" org-table-sort-lines (org-at-table-p) :keys "C-c ^"] + "--" + ["Insert Hline" org-table-insert-hline :active (org-at-table-p) :keys "C-c -"]) + ("Rectangle" + ["Copy Rectangle" org-copy-special :active (org-at-table-p)] + ["Cut Rectangle" org-cut-special :active (org-at-table-p)] + ["Paste Rectangle" org-paste-special :active (org-at-table-p)] + ["Fill Rectangle" org-table-wrap-region :active (org-at-table-p)]) + "--" + ["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="] + ["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="] + ["Edit Formulas" org-table-edit-formulas :active (org-at-table-p) :keys "C-c '"] + ["Recalculate line" org-table-recalculate :active (org-at-table-p) :keys "C-c *"] + ["Recalculate all" (org-table-recalculate '(4)) :active (org-at-table-p) :keys "C-u C-c *"] + ["Toggle Recalculate Mark" org-table-rotate-recalc-marks :active (org-at-table-p) :keys "C-c #"] + ["Sum Column/Rectangle" org-table-sum + :active (or (org-at-table-p) (org-region-active-p)) :keys "C-c +"] + ["Which Column?" org-table-current-column :active (org-at-table-p) :keys "C-c ?"] + ["Debug Formulas" + (setq org-table-formula-debug (not org-table-formula-debug)) + :style toggle :selected org-table-formula-debug] + )) + t) + +(defun orgtbl-tab () + "Justification and field motion for `orgtbl-mode'." + (interactive) + (org-table-justify-field-maybe) + (org-table-next-field)) + +(defun orgtbl-ret () + "Justification and field motion for `orgtbl-mode'." + (interactive) + (org-table-justify-field-maybe) + (org-table-next-row)) + +(defun orgtbl-self-insert-command (N) + "Like `self-insert-command', use overwrite-mode for whitespace in tables. +If the cursor is in a table looking at whitespace, the whitespace is +overwritten, and the table is not marked as requiring realignment." + (interactive "p") + (if (and (org-at-table-p) + (or + (and org-table-auto-blank-field + (member last-command + '(orgtbl-hijacker-command-100 + orgtbl-hijacker-command-101 + orgtbl-hijacker-command-102 + orgtbl-hijacker-command-103 + orgtbl-hijacker-command-104 + orgtbl-hijacker-command-105)) + (org-table-blank-field)) + t) + (eq N 1) + (looking-at "[^|\n]* +|")) + (let (org-table-may-need-update) + (goto-char (1- (match-end 0))) + (delete-backward-char 1) + (goto-char (match-beginning 0)) + (self-insert-command N)) + (setq org-table-may-need-update t) + (let (orgtbl-mode) + (call-interactively (key-binding (vector last-input-event)))))) + +(defun org-force-self-insert (N) + "Needed to enforce self-insert under remapping." + (interactive "p") + (self-insert-command N)) + +(defun orgtbl-delete-backward-char (N) + "Like `delete-backward-char', insert whitespace at field end in tables. +When deleting backwards, in tables this function will insert whitespace in +front of the next \"|\" separator, to keep the table aligned. The table will +still be marked for re-alignment, because a narrow field may lead to a +reduced column width." + (interactive "p") + (if (and (org-at-table-p) + (eq N 1) + (string-match "|" (buffer-substring (point-at-bol) (point))) + (looking-at ".*?|")) + (let ((pos (point))) + (backward-delete-char N) + (skip-chars-forward "^|") + (insert " ") + (goto-char (1- pos))) + (delete-backward-char N))) + +(defun orgtbl-delete-char (N) + "Like `delete-char', but insert whitespace at field end in tables. +When deleting characters, in tables this function will insert whitespace in +front of the next \"|\" separator, to keep the table aligned. The table +will still be marked for re-alignment, because a narrow field may lead to +a reduced column width." + (interactive "p") + (if (and (org-at-table-p) + (not (bolp)) + (not (= (char-after) ?|)) + (eq N 1)) + (if (looking-at ".*?|") + (let ((pos (point))) + (replace-match (concat + (substring (match-string 0) 1 -1) + " |")) + (goto-char pos))) + (delete-char N))) + +;;; Exporting + +(defconst org-level-max 20) + +(defun org-export-find-first-heading-line (list) + "Remove all lines from LIST which are before the first headline." + (let ((orig-list list) + (re (concat "^" outline-regexp))) + (while (and list + (not (string-match re (car list)))) + (pop list)) + (or list orig-list))) + +(defun org-skip-comments (lines) + "Skip lines starting with \"#\" and subtrees starting with COMMENT." + (let ((re1 (concat "^\\(\\*+\\)[ \t]+" org-comment-string)) + (re2 "^\\(\\*+\\)[ \t\n\r]") + rtn line level) + (while (setq line (pop lines)) + (cond + ((and (string-match re1 line) + (setq level (- (match-end 1) (match-beginning 1)))) + ;; Beginning of a COMMENT subtree. Skip it. + (while (and (setq line (pop lines)) + (or (not (string-match re2 line)) + (> (- (match-end 1) (match-beginning 1)) level)))) + (setq lines (cons line lines))) + ((string-match "^#" line) + ;; an ordinary comment line + ) + ((and org-export-table-remove-special-lines + (string-match "^[ \t]*| *[!_^] *|" line)) + ;; a special table line that should be removed + ) + (t (setq rtn (cons line rtn))))) + (nreverse rtn))) + +;; ASCII + +(defconst org-ascii-underline '(?\$ ?\# ?^ ?\~ ?\= ?\-) + "Characters for underlining headings in ASCII export.") + +(defconst org-html-entities + '(("nbsp") + ("iexcl") + ("cent") + ("pound") + ("curren") + ("yen") + ("brvbar") + ("sect") + ("uml") + ("copy") + ("ordf") + ("laquo") + ("not") + ("shy") + ("reg") + ("macr") + ("deg") + ("plusmn") + ("sup2") + ("sup3") + ("acute") + ("micro") + ("para") + ("middot") + ("odot"."o") + ("star"."*") + ("cedil") + ("sup1") + ("ordm") + ("raquo") + ("frac14") + ("frac12") + ("frac34") + ("iquest") + ("Agrave") + ("Aacute") + ("Acirc") + ("Atilde") + ("Auml") + ("Aring") ("AA"."Å") + ("AElig") + ("Ccedil") + ("Egrave") + ("Eacute") + ("Ecirc") + ("Euml") + ("Igrave") + ("Iacute") + ("Icirc") + ("Iuml") + ("ETH") + ("Ntilde") + ("Ograve") + ("Oacute") + ("Ocirc") + ("Otilde") + ("Ouml") + ("times") + ("Oslash") + ("Ugrave") + ("Uacute") + ("Ucirc") + ("Uuml") + ("Yacute") + ("THORN") + ("szlig") + ("agrave") + ("aacute") + ("acirc") + ("atilde") + ("auml") + ("aring") + ("aelig") + ("ccedil") + ("egrave") + ("eacute") + ("ecirc") + ("euml") + ("igrave") + ("iacute") + ("icirc") + ("iuml") + ("eth") + ("ntilde") + ("ograve") + ("oacute") + ("ocirc") + ("otilde") + ("ouml") + ("divide") + ("oslash") + ("ugrave") + ("uacute") + ("ucirc") + ("uuml") + ("yacute") + ("thorn") + ("yuml") + ("fnof") + ("Alpha") + ("Beta") + ("Gamma") + ("Delta") + ("Epsilon") + ("Zeta") + ("Eta") + ("Theta") + ("Iota") + ("Kappa") + ("Lambda") + ("Mu") + ("Nu") + ("Xi") + ("Omicron") + ("Pi") + ("Rho") + ("Sigma") + ("Tau") + ("Upsilon") + ("Phi") + ("Chi") + ("Psi") + ("Omega") + ("alpha") + ("beta") + ("gamma") + ("delta") + ("epsilon") + ("varepsilon"."ε") + ("zeta") + ("eta") + ("theta") + ("iota") + ("kappa") + ("lambda") + ("mu") + ("nu") + ("xi") + ("omicron") + ("pi") + ("rho") + ("sigmaf") ("varsigma"."ς") + ("sigma") + ("tau") + ("upsilon") + ("phi") + ("chi") + ("psi") + ("omega") + ("thetasym") ("vartheta"."ϑ") + ("upsih") + ("piv") + ("bull") ("bullet"."•") + ("hellip") ("dots"."…") + ("prime") + ("Prime") + ("oline") + ("frasl") + ("weierp") + ("image") + ("real") + ("trade") + ("alefsym") + ("larr") ("leftarrow"."←") ("gets"."←") + ("uarr") ("uparrow"."↑") + ("rarr") ("to"."→") ("rightarrow"."→") + ("darr")("downarrow"."↓") + ("harr") ("leftrightarrow"."↔") + ("crarr") ("hookleftarrow"."↵") ; has round hook, not quite CR + ("lArr") ("Leftarrow"."⇐") + ("uArr") ("Uparrow"."⇑") + ("rArr") ("Rightarrow"."⇒") + ("dArr") ("Downarrow"."⇓") + ("hArr") ("Leftrightarrow"."⇔") + ("forall") + ("part") ("partial"."∂") + ("exist") ("exists"."∃") + ("empty") ("emptyset"."∅") + ("nabla") + ("isin") ("in"."∈") + ("notin") + ("ni") + ("prod") + ("sum") + ("minus") + ("lowast") ("ast"."∗") + ("radic") + ("prop") ("proptp"."∝") + ("infin") ("infty"."∞") + ("ang") ("angle"."∠") + ("and") ("vee"."∧") + ("or") ("wedge"."∨") + ("cap") + ("cup") + ("int") + ("there4") + ("sim") + ("cong") ("simeq"."≅") + ("asymp")("approx"."≈") + ("ne") ("neq"."≠") + ("equiv") + ("le") + ("ge") + ("sub") ("subset"."⊂") + ("sup") ("supset"."⊃") + ("nsub") + ("sube") + ("supe") + ("oplus") + ("otimes") + ("perp") + ("sdot") ("cdot"."⋅") + ("lceil") + ("rceil") + ("lfloor") + ("rfloor") + ("lang") + ("rang") + ("loz") ("Diamond"."◊") + ("spades") ("spadesuit"."♠") + ("clubs") ("clubsuit"."♣") + ("hearts") ("diamondsuit"."♥") + ("diams") ("diamondsuit"."♦") + ("quot") + ("amp") + ("lt") + ("gt") + ("OElig") + ("oelig") + ("Scaron") + ("scaron") + ("Yuml") + ("circ") + ("tilde") + ("ensp") + ("emsp") + ("thinsp") + ("zwnj") + ("zwj") + ("lrm") + ("rlm") + ("ndash") + ("mdash") + ("lsquo") + ("rsquo") + ("sbquo") + ("ldquo") + ("rdquo") + ("bdquo") + ("dagger") + ("Dagger") + ("permil") + ("lsaquo") + ("rsaquo") + ("euro") + + ("arccos"."arccos") + ("arcsin"."arcsin") + ("arctan"."arctan") + ("arg"."arg") + ("cos"."cos") + ("cosh"."cosh") + ("cot"."cot") + ("coth"."coth") + ("csc"."csc") + ("deg"."deg") + ("det"."det") + ("dim"."dim") + ("exp"."exp") + ("gcd"."gcd") + ("hom"."hom") + ("inf"."inf") + ("ker"."ker") + ("lg"."lg") + ("lim"."lim") + ("liminf"."liminf") + ("limsup"."limsup") + ("ln"."ln") + ("log"."log") + ("max"."max") + ("min"."min") + ("Pr"."Pr") + ("sec"."sec") + ("sin"."sin") + ("sinh"."sinh") + ("sup"."sup") + ("tan"."tan") + ("tanh"."tanh") + ) + "Entities for TeX->HTML translation. +Entries can be like (\"ent\"), in which case \"\\ent\" will be translated to +\"&ent;\". An entry can also be a dotted pair like (\"ent\".\"&other;\"). +In that case, \"\\ent\" will be translated to \"&other;\". +The list contains HTML entities for Latin-1, Greek and other symbols. +It is supplemented by a number of commonly used TeX macros with appropriate +translations. There is currently no way for users to extend this.") + +(defun org-cleaned-string-for-export (string) + "Cleanup a buffer substring so that links can be created safely." + (interactive) + (let* ((cb (current-buffer)) + (re-radio (and org-target-link-regexp + (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)"))) + rtn) + (save-excursion + (set-buffer (get-buffer-create " org-mode-tmp")) + (erase-buffer) + (insert string) + (org-mode) + ;; Find targets in comments and move them out of comments, + ;; but mark them as targets that should be invisible + (goto-char (point-min)) + (while (re-search-forward "^#.*?\\(<<\r\n]+>>>?\\).*" nil t) + (replace-match "\\1(INVISIBLE)")) + ;; Find matches for radio targets and turn them into links + (goto-char (point-min)) + (when re-radio + (while (re-search-forward re-radio nil t) + (replace-match "\\1[[\\2]]"))) + ;; Find all links that contain a newline and put them into a single line + (goto-char (point-min)) + (while (re-search-forward "\\(\\[\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\]\\)" nil t) + (replace-match "\\1 \\2") + (goto-char (match-beginning 0))) + ;; Remove comments + (goto-char (point-min)) + (while (re-search-forward "^#.*\n?" nil t) + (replace-match "")) + (setq rtn (buffer-string))) + (kill-buffer " org-mode-tmp") + rtn)) + +(defun org-solidify-link-text (s &optional alist) + "Take link text and make a safe target out of it." + (save-match-data + (let* ((rtn + (mapconcat + 'identity + (org-split-string s "[ \t\r\n]+") "--")) + (a (assoc rtn alist))) + (or (cdr a) rtn)))) + +(defun org-convert-to-odd-levels () + "Convert an org-mode file with all levels allowed to one with odd levels. +This will leave level 1 alone, convert level 2 to level 3, level 3 to +level 5 etc." + (interactive) + (when (yes-or-no-p "Are you sure you want to globally change levels to odd? ") + (let ((org-odd-levels-only nil) n) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "^\\*\\*+" nil t) + (setq n (1- (length (match-string 0)))) + (while (>= (setq n (1- n)) 0) + (org-demote)) + (end-of-line 1)))))) + + +(defun org-convert-to-oddeven-levels () + "Convert an org-mode file with only odd levels to one with odd and even levels. +This promotes level 3 to level 2, level 5 to level 3 etc. If the file contains a +section with an even level, conversion would destroy the structure of the file. An error +is signaled in this case." + (interactive) + (goto-char (point-min)) + ;; First check if there are no even levels + (when (re-search-forward "^\\(\\*\\*\\)+[^*]" nil t) + (org-show-hierarchy-above) + (error "Not all levels are odd in this file. Conversion not possible.")) + (when (yes-or-no-p "Are you sure you want to globally change levels to odd-even? ") + (let ((org-odd-levels-only nil) n) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "^\\*\\*+" nil t) + (setq n (/ (length (match-string 0)) 2)) + (while (>= (setq n (1- n)) 0) + (org-promote)) + (end-of-line 1)))))) + +(defun org-tr-level (n) + "Make N odd if required." + (if org-odd-levels-only (1+ (/ n 2)) n)) + +(defvar org-last-level nil) ; dynamically scoped variable + +(defun org-export-as-ascii (arg) + "Export the outline as a pretty ASCII file. +If there is an active region, export only the region. +The prefix ARG specifies how many levels of the outline should become +underlined headlines. The default is 3." + (interactive "P") + (setq-default org-todo-line-regexp org-todo-line-regexp) + (let* ((region + (buffer-substring + (if (org-region-active-p) (region-beginning) (point-min)) + (if (org-region-active-p) (region-end) (point-max)))) + (lines (org-export-find-first-heading-line + (org-skip-comments + (org-split-string + (org-cleaned-string-for-export region) + "[\r\n]")))) + (org-startup-with-deadline-check nil) + (level 0) line txt + (umax nil) + (case-fold-search nil) + (filename (concat (file-name-sans-extension buffer-file-name) + ".txt")) + (buffer (find-file-noselect filename)) + (levels-open (make-vector org-level-max nil)) + (date (format-time-string "%Y/%m/%d" (current-time))) + (time (format-time-string "%X" (org-current-time))) + (author user-full-name) + (title (buffer-name)) + (options nil) + (email user-mail-address) + (language org-export-default-language) + (text nil) + (todo nil) + (lang-words nil)) + + (setq org-last-level 1) + (org-init-section-numbers) + + (find-file-noselect filename) + + ;; Search for the export key lines + (org-parse-key-lines) + + (setq lang-words (or (assoc language org-export-language-setup) + (assoc "en" org-export-language-setup))) + (if org-export-ascii-show-new-buffer + (switch-to-buffer-other-window buffer) + (set-buffer buffer)) + (erase-buffer) + (fundamental-mode) + (if options (org-parse-export-options options)) + (setq umax (if arg (prefix-numeric-value arg) + org-export-headline-levels)) + + ;; File header + (if title (org-insert-centered title ?=)) + (insert "\n") + (if (or author email) + (insert (concat (nth 1 lang-words) ": " (or author "") + (if email (concat " <" email ">") "") + "\n"))) + (if (and date time) + (insert (concat (nth 2 lang-words) ": " date " " time "\n"))) + (if text (insert (concat (org-html-expand-for-ascii text) "\n\n"))) + + (insert "\n\n") + + (if org-export-with-toc + (progn + (insert (nth 3 lang-words) "\n" + (make-string (length (nth 3 lang-words)) ?=) "\n") + (mapcar '(lambda (line) + (if (string-match org-todo-line-regexp + line) + ;; This is a headline + (progn + (setq level (- (match-end 1) (match-beginning 1)) + level (org-tr-level level) + txt (match-string 3 line) + todo + (or (and (match-beginning 2) + (not (equal (match-string 2 line) + org-done-string))) + ; TODO, not DONE + (and (= level umax) + (org-search-todo-below + line lines level)))) + (setq txt (org-html-expand-for-ascii txt)) + + (if org-export-with-section-numbers + (setq txt (concat (org-section-number level) + " " txt))) + (if (<= level umax) + (progn + (insert + (make-string (* (1- level) 4) ?\ ) + (format (if todo "%s (*)\n" "%s\n") txt)) + (setq org-last-level level)) + )))) + lines))) + + (org-init-section-numbers) + (while (setq line (pop lines)) + ;; Remove the quoted HTML tags. + (setq line (org-html-expand-for-ascii line)) + ;; Remove targets + (while (string-match "<<]*>>>?[ \t]*\n?" line) + (setq line (replace-match "" t t line))) + ;; Replace internal links + (while (string-match org-bracket-link-regexp line) + (setq line (replace-match + (if (match-end 3) "[\\3]" "[\\1]") + t nil line))) + (cond + ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line) + ;; a Headline + (setq level (org-tr-level (- (match-end 1) (match-beginning 1))) + txt (match-string 2 line)) + (org-ascii-level-start level txt umax)) + (t (insert line "\n")))) + (normal-mode) + (save-buffer) + (goto-char (point-min)))) + +(defun org-search-todo-below (line lines level) + "Search the subtree below LINE for any TODO entries." + (let ((rest (cdr (memq line lines))) + (re org-todo-line-regexp) + line lv todo) + (catch 'exit + (while (setq line (pop rest)) + (if (string-match re line) + (progn + (setq lv (- (match-end 1) (match-beginning 1)) + todo (and (match-beginning 2) + (not (equal (match-string 2 line) + org-done-string)))) + ; TODO, not DONE + (if (<= lv level) (throw 'exit nil)) + (if todo (throw 'exit t)))))))) + +;; FIXME: Try to handle and as faces via text properties. +;; FIXME: Can I implement *bold*,/italic/ and _underline_ for ASCII export? +(defun org-html-expand-for-ascii (line) + "Handle quoted HTML for ASCII export." + (if org-export-html-expand + (while (string-match "@<[^<>\n]*>" line) + ;; We just remove the tags for now. + (setq line (replace-match "" nil nil line)))) + line) + +(defun org-insert-centered (s &optional underline) + "Insert the string S centered and underline it with character UNDERLINE." + (let ((ind (max (/ (- 80 (string-width s)) 2) 0))) + (insert (make-string ind ?\ ) s "\n") + (if underline + (insert (make-string ind ?\ ) + (make-string (string-width s) underline) + "\n")))) + +(defun org-ascii-level-start (level title umax) + "Insert a new level in ASCII export." + (let (char) + (if (> level umax) + (insert (make-string (* 2 (- level umax 1)) ?\ ) "* " title "\n") + (if (or (not (equal (char-before) ?\n)) + (not (equal (char-before (1- (point))) ?\n))) + (insert "\n")) + (setq char (nth (- umax level) (reverse org-ascii-underline))) + (if org-export-with-section-numbers + (setq title (concat (org-section-number level) " " title))) + (insert title "\n" (make-string (string-width title) char) "\n")))) + +(defun org-export-copy-visible () + "Copy the visible part of the buffer to another buffer, for printing. +Also removes the first line of the buffer if it specifies a mode, +and all options lines." + (interactive) + (let* ((filename (concat (file-name-sans-extension buffer-file-name) + ".txt")) + (buffer (find-file-noselect filename)) + (ore (concat + (org-make-options-regexp + '("CATEGORY" "SEQ_TODO" "PRI_TODO" "TYP_TODO" + "STARTUP" "ARCHIVE" + "TITLE" "AUTHOR" "EMAIL" "TEXT" "OPTIONS" "LANGUAGE")) + (if org-noutline-p "\\(\n\\|$\\)" ""))) + s e) + (with-current-buffer buffer + (erase-buffer) + (text-mode)) + (save-excursion + (setq s (goto-char (point-min))) + (while (not (= (point) (point-max))) + (goto-char (org-find-invisible)) + (append-to-buffer buffer s (point)) + (setq s (goto-char (org-find-visible))))) + (switch-to-buffer-other-window buffer) + (newline) + (goto-char (point-min)) + (if (looking-at ".*-\\*- mode:.*\n") + (replace-match "")) + (while (re-search-forward ore nil t) + (replace-match "")) + (goto-char (point-min)))) + +(defun org-find-visible () + (if (featurep 'noutline) + (let ((s (point))) + (while (and (not (= (point-max) (setq s (next-overlay-change s)))) + (get-char-property s 'invisible))) + s) + (skip-chars-forward "^\n") + (point))) +(defun org-find-invisible () + (if (featurep 'noutline) + (let ((s (point))) + (while (and (not (= (point-max) (setq s (next-overlay-change s)))) + (not (get-char-property s 'invisible)))) + s) + (skip-chars-forward "^\r") + (point))) + +;; HTML + +(defun org-get-current-options () + "Return a string with current options as keyword options. +Does include HTML export options as well as TODO and CATEGORY stuff." + (format + "#+TITLE: %s +#+AUTHOR: %s +#+EMAIL: %s +#+LANGUAGE: %s +#+TEXT: Some descriptive text to be emitted. Several lines OK. +#+OPTIONS: H:%d num:%s toc:%s \\n:%s @:%s ::%s |:%s ^:%s *:%s TeX:%s +#+CATEGORY: %s +#+SEQ_TODO: %s +#+TYP_TODO: %s +#+STARTUP: %s %s %s %s +#+ARCHIVE: %s +" + (buffer-name) (user-full-name) user-mail-address org-export-default-language + org-export-headline-levels + org-export-with-section-numbers + org-export-with-toc + org-export-preserve-breaks + org-export-html-expand + org-export-with-fixed-width + org-export-with-tables + org-export-with-sub-superscripts + org-export-with-emphasize + org-export-with-TeX-macros + (file-name-nondirectory buffer-file-name) + (if (equal org-todo-interpretation 'sequence) + (mapconcat 'identity org-todo-keywords " ") + "TODO FEEDBACK VERIFY DONE") + (if (equal org-todo-interpretation 'type) + (mapconcat 'identity org-todo-keywords " ") + "Me Jason Marie DONE") + (cdr (assoc org-startup-folded + '((nil . "nofold")(t . "fold")(content . "content")))) + (if org-startup-with-deadline-check "dlcheck" "nodlcheck") + (if org-odd-levels-only "odd" "oddeven") + (if org-hide-leading-stars "hidestars" "showstars") + org-archive-location + )) + +(defun org-insert-export-options-template () + "Insert into the buffer a template with information for exporting." + (interactive) + (if (not (bolp)) (newline)) + (let ((s (org-get-current-options))) + (and (string-match "#\\+CATEGORY" s) + (setq s (substring s 0 (match-beginning 0)))) + (insert s))) + +(defun org-toggle-fixed-width-section (arg) + "Toggle the fixed-width export. +If there is no active region, the QUOTE keyword at the current headline is +inserted or removed. When present, it causes the text between this headline +and the next to be exported as fixed-width text, and unmodified. +If there is an active region, this command adds or removes a colon as the +first character of this line. If the first character of a line is a colon, +this line is also exported in fixed-width font." + (interactive "P") + (let* ((cc 0) + (regionp (org-region-active-p)) + (beg (if regionp (region-beginning) (point))) + (end (if regionp (region-end))) + (nlines (or arg (if (and beg end) (count-lines beg end) 1))) + (re "[ \t]*\\(:\\)") + off) + (if regionp + (save-excursion + (goto-char beg) + (setq cc (current-column)) + (beginning-of-line 1) + (setq off (looking-at re)) + (while (> nlines 0) + (setq nlines (1- nlines)) + (beginning-of-line 1) + (cond + (arg + (move-to-column cc t) + (insert ":\n") + (forward-line -1)) + ((and off (looking-at re)) + (replace-match "" t t nil 1)) + ((not off) (move-to-column cc t) (insert ":"))) + (forward-line 1))) + (save-excursion + (org-back-to-heading) + (if (looking-at (concat outline-regexp + "\\( +\\<" org-quote-string "\\>\\)")) + (replace-match "" t t nil 1) + (if (looking-at outline-regexp) + (progn + (goto-char (match-end 0)) + (insert " " org-quote-string)))))))) + +(defun org-export-as-html-and-open (arg) + "Export the outline as HTML and immediately open it with a browser. +If there is an active region, export only the region. +The prefix ARG specifies how many levels of the outline should become +headlines. The default is 3. Lower levels will become bulleted lists." + (interactive "P") + (org-export-as-html arg 'hidden) + (org-open-file buffer-file-name)) + +(defun org-export-as-html-batch () + "Call `org-export-as-html', may be used in batch processing as +emacs --batch + --load=$HOME/lib/emacs/org.el + --eval \"(setq org-export-headline-levels 2)\" + --visit=MyFile --funcall org-export-as-html-batch" + (org-export-as-html org-export-headline-levels 'hidden)) + +(defun org-export-as-html (arg &optional hidden) + "Export the outline as a pretty HTML file. +If there is an active region, export only the region. +The prefix ARG specifies how many levels of the outline should become +headlines. The default is 3. Lower levels will become bulleted lists." + (interactive "P") + (setq-default org-todo-line-regexp org-todo-line-regexp) + (setq-default org-deadline-line-regexp org-deadline-line-regexp) + (setq-default org-done-string org-done-string) + (let* ((style org-export-html-style) + (odd org-odd-levels-only) + (region-p (org-region-active-p)) + (region + (buffer-substring + (if region-p (region-beginning) (point-min)) + (if region-p (region-end) (point-max)))) + (all_lines + (org-skip-comments (org-split-string + (org-cleaned-string-for-export region) + "[\r\n]"))) + (lines (org-export-find-first-heading-line all_lines)) + (level 0) (line "") (origline "") txt todo + (umax nil) + (filename (concat (file-name-sans-extension buffer-file-name) + ".html")) + (buffer (find-file-noselect filename)) + (levels-open (make-vector org-level-max nil)) + (date (format-time-string "%Y/%m/%d" (current-time))) + (time (format-time-string "%X" (org-current-time))) + (author user-full-name) + (title (buffer-name)) + (options nil) + (quote-re (concat "^\\*+[ \t]*" org-quote-string "\\>")) + (inquote nil) + (infixed nil) + (in-local-list nil) + (local-list-num nil) + (local-list-indent nil) + (llt org-plain-list-ordered-item-terminator) + (email user-mail-address) + (language org-export-default-language) + (text nil) + (lang-words nil) + (target-alist nil) tg + (head-count 0) cnt + (start 0) + ;; FIXME: The following returns always nil under XEmacs + (coding-system (and (fboundp 'coding-system-get) + (boundp 'buffer-file-coding-system) + buffer-file-coding-system)) + (coding-system-for-write (or coding-system coding-system-for-write)) + (save-buffer-coding-system (or coding-system save-buffer-coding-system)) + (charset (and coding-system + (coding-system-get coding-system 'mime-charset))) + table-open type + table-buffer table-orig-buffer + ind start-is-num starter + ) + (message "Exporting...") + + (setq org-last-level 1) + (org-init-section-numbers) + + ;; Search for the export key lines + (org-parse-key-lines) + (setq lang-words (or (assoc language org-export-language-setup) + (assoc "en" org-export-language-setup))) + + ;; Switch to the output buffer + (if (or hidden (not org-export-html-show-new-buffer)) + (set-buffer buffer) + (switch-to-buffer-other-window buffer)) + (erase-buffer) + (fundamental-mode) + (let ((case-fold-search nil) + (org-odd-levels-only odd)) + (if options (org-parse-export-options options)) + (setq umax (if arg (prefix-numeric-value arg) + org-export-headline-levels)) + + ;; File header + (insert (format + " + +%s + + + + +%s + +" + language (org-html-expand title) (or charset "iso-8859-1") + date time author style)) + (if title (insert (concat "

" + (org-html-expand title) "

\n"))) + (if author (insert (concat (nth 1 lang-words) ": " author "\n"))) + (if email (insert (concat "<" + email ">\n"))) + (if (or author email) (insert "
\n")) + (if (and date time) (insert (concat (nth 2 lang-words) ": " + date " " time "
\n"))) + (if text (insert (concat "

\n" (org-html-expand text)))) + (if org-export-with-toc + (progn + (insert (format "

%s

\n" (nth 3 lang-words))) + (insert "
    \n") + (setq lines + (mapcar '(lambda (line) + (if (string-match org-todo-line-regexp line) + ;; This is a headline + (progn + (setq level (- (match-end 1) (match-beginning 1)) + level (org-tr-level level) + txt (save-match-data + (org-html-expand + (match-string 3 line))) + todo + (or (and (match-beginning 2) + (not (equal (match-string 2 line) + org-done-string))) + ; TODO, not DONE + (and (= level umax) + (org-search-todo-below + line lines level)))) + (if org-export-with-section-numbers + (setq txt (concat (org-section-number level) + " " txt))) + (if (<= level umax) + (progn + (setq head-count (+ head-count 1)) + (if (> level org-last-level) + (progn + (setq cnt (- level org-last-level)) + (while (>= (setq cnt (1- cnt)) 0) + (insert "
      ")) + (insert "\n"))) + (if (< level org-last-level) + (progn + (setq cnt (- org-last-level level)) + (while (>= (setq cnt (1- cnt)) 0) + (insert "
    ")) + (insert "\n"))) + ;; Check for targets + (while (string-match org-target-regexp line) + (setq tg (match-string 1 line) + line (replace-match + (concat "@" tg "@ ") + t t line)) + (push (cons (org-solidify-link-text tg) + (format "sec-%d" head-count)) + target-alist)) + (while (string-match "<\\(<\\)+\\|>\\(>\\)+" txt) + (setq txt (replace-match "" t t txt))) + (insert + (format + (if todo + "
  • %s\n" + "
  • %s\n") + head-count txt)) + + (setq org-last-level level)) + ))) + line) + lines)) + (while (> org-last-level 0) + (setq org-last-level (1- org-last-level)) + (insert "
\n")) + )) + (setq head-count 0) + (org-init-section-numbers) + + (while (setq line (pop lines) origline line) + (catch 'nextline + + ;; end of quote section? + (when (and inquote (string-match "^\\*+" line)) + (insert "\n") + (setq inquote nil)) + ;; inside a quote section? + (when inquote + (insert (org-html-protect line) "\n") + (throw 'nextline nil)) + + ;; verbatim lines + (when (and org-export-with-fixed-width + (string-match "^[ \t]*:\\(.*\\)" line)) + (when (not infixed) + (setq infixed t) + (insert "
\n"))
+	    (insert (org-html-protect (match-string 1 line)) "\n")
+	    (when (and lines
+		       (not (string-match "^[ \t]*\\(:.*\\)"
+					  (car lines))))
+	      (setq infixed nil)
+	      (insert "
\n")) + (throw 'nextline nil)) + + + ;; make targets to anchors + (while (string-match "<<]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line) + (cond + ((match-end 2) + (setq line (replace-match + (concat "@\\nbsp@") + t t line))) + ((and org-export-with-toc (equal (string-to-char line) ?*)) + (setq line (replace-match + (concat "@" (match-string 1 line) "@ ") +; (concat "@" (match-string 1 line) "@ ") + t t line))) + (t + (setq line (replace-match + (concat "@" (match-string 1 line) "@ ") + t t line))))) + ;; Replace internal links + (while (string-match org-bracket-link-regexp line) + (setq line (replace-match + (concat + "@" + (match-string (if (match-end 3) 3 1) line) + "@") + t t line))) + + ;; Protect the external links + (setq start 0) + (while (string-match org-link-maybe-angles-regexp line start) + (setq start (match-end 0)) + (setq line (replace-match + (concat "\000" (match-string 1 line) "\000") + t t line))) + + ;; replace "&" by "&", "<" and ">" by "<" and ">" + ;; handle @<..> HTML tags (replace "@>..<" by "<..>") + (setq line (org-html-expand line)) + + ;; Format the links + (setq start 0) + (while (string-match org-protected-link-regexp line start) + (setq start (- (match-end 0) 2)) + (setq type (match-string 1 line)) + (cond + ((member type '("http" "https" "ftp" "mailto" "news")) + ;; standard URL + (setq line (replace-match + ; "<\\1:\\2>" + "\\1:\\2" + nil nil line))) + ((string= type "file") + ;; FILE link + (let* ((filename (match-string 2 line)) + (abs-p (file-name-absolute-p filename)) + (thefile (if abs-p (expand-file-name filename) filename)) + (thefile (save-match-data + (if (string-match ":[0-9]+$" thefile) + (replace-match "" t t thefile) + thefile))) + (file-is-image-p + (save-match-data + (string-match (org-image-file-name-regexp) thefile)))) + (setq line (replace-match + (if (and org-export-html-inline-images + file-is-image-p) + (concat "") + (concat "\\1:\\2")) + nil nil line)))) + + ((member type '("bbdb" "vm" "wl" "mhe" "rmail" "gnus" "shell")) + (setq line (replace-match + "<\\1:\\2>" nil nil line))))) + + ;; TODO items + (if (and (string-match org-todo-line-regexp line) + (match-beginning 2)) + (if (equal (match-string 2 line) org-done-string) + (setq line (replace-match + "\\2" + nil nil line 2)) + (setq line (replace-match "\\2" + nil nil line 2)))) + + ;; DEADLINES + (if (string-match org-deadline-line-regexp line) + (progn + (if (save-match-data + (string-match "\\&" + nil nil line 1))))) + (cond + ((string-match "^\\(\\*+\\)[ \t]*\\(.*\\)" line) + ;; This is a headline + (setq level (org-tr-level (- (match-end 1) (match-beginning 1))) + txt (match-string 2 line)) + (if (<= level umax) (setq head-count (+ head-count 1))) + (when in-local-list + ;; Close any local lists before inserting a new header line + (while local-list-num + (insert (if (car local-list-num) "\n" "")) + (pop local-list-num)) + (setq local-list-indent nil + in-local-list nil)) + (org-html-level-start level txt umax + (and org-export-with-toc (<= level umax)) + head-count) + ;; QUOTES + (when (string-match quote-re line) + (insert "
")
+	      (setq inquote t)))
+
+	   ((and org-export-with-tables
+		 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
+	    (if (not table-open)
+		;; New table starts
+		(setq table-open t table-buffer nil table-orig-buffer nil))
+	    ;; Accumulate lines
+	    (setq table-buffer (cons line table-buffer)
+		  table-orig-buffer (cons origline table-orig-buffer))
+	    (when (or (not lines)
+		      (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
+					 (car lines))))
+	      (setq table-open nil
+		    table-buffer (nreverse table-buffer)
+		    table-orig-buffer (nreverse table-orig-buffer))
+	      (insert (org-format-table-html table-buffer table-orig-buffer))))
+	   (t
+	    ;; Normal lines
+	    (when (and (> org-export-plain-list-max-depth 0)
+		       (string-match
+			(cond
+			 ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*]\\)\\|\\([0-9]+[.)]\\)\\)?\\( +[^ \t\n\r]\\|[ \t]*$\\)")
+			 ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*]\\)\\|\\([0-9]+\\.\\)\\)?\\( +[^ \t\n\r]\\|[ \t]*$\\)")
+			 ((= llt ?\)) "^\\( \t]*\\)\\(\\([-+*]\\)\\|\\([0-9]+)\\)\\)?\\( +[^ \t\n\r]\\|[ \t]*$\\)")
+			 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
+			line))
+	      (setq ind (org-get-string-indentation line)
+		    start-is-num (match-beginning 4)
+		    starter (if (match-beginning 2) (match-string 2 line))
+		    line (substring line (match-beginning 5)))
+	      (unless (string-match "[^ \t]" line)
+		;; empty line.  Pretend indentation is large.
+		(setq ind (1+ (or (car local-list-indent) 1))))
+	      (while (and in-local-list
+			  (or (and (= ind (car local-list-indent))
+				   (not starter))
+			      (< ind (car local-list-indent))))
+		(insert (if (car local-list-num) "\n" ""))
+		(pop local-list-num) (pop local-list-indent)
+		(setq in-local-list local-list-indent))
+	      (cond
+	       ((and starter
+		     (or (not in-local-list)
+			 (> ind (car local-list-indent)))
+		     (< (length local-list-indent)
+			org-export-plain-list-max-depth))
+		;; Start new (level of ) list
+		(insert (if start-is-num "
    \n
  1. \n" "
      \n
    • \n")) + (push start-is-num local-list-num) + (push ind local-list-indent) + (setq in-local-list t)) + (starter + ;; continue current list + (insert "
    • \n")))) + ;; Empty lines start a new paragraph. If hand-formatted lists + ;; are not fully interpreted, lines starting with "-", "+", "*" + ;; also start a new paragraph. + (if (string-match "^ [-+*]-\\|^[ \t]*$" line) (insert "

      ")) + (insert line (if org-export-preserve-breaks "
      \n" "\n")))) + )) + (if org-export-html-with-timestamp + (insert org-export-html-html-helper-timestamp)) + (insert "\n\n") + (normal-mode) + (save-buffer) + (goto-char (point-min))))) + +(defun org-format-table-html (lines olines) + "Find out which HTML converter to use and return the HTML code." + (if (string-match "^[ \t]*|" (car lines)) + ;; A normal org table + (org-format-org-table-html lines) + ;; Table made by table.el - test for spanning + (let* ((hlines (delq nil (mapcar + (lambda (x) + (if (string-match "^[ \t]*\\+-" x) x + nil)) + lines))) + (first (car hlines)) + (ll (and (string-match "\\S-+" first) + (match-string 0 first))) + (re (concat "^[ \t]*" (regexp-quote ll))) + (spanning (delq nil (mapcar (lambda (x) (not (string-match re x))) + hlines)))) + (if (and (not spanning) + (not org-export-prefer-native-exporter-for-tables)) + ;; We can use my own converter with HTML conversions + (org-format-table-table-html lines) + ;; Need to use the code generator in table.el, with the original text. + (org-format-table-table-html-using-table-generate-source olines))))) + +(defun org-format-org-table-html (lines) + "Format a table into HTML." + (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines))) + (setq lines (nreverse lines)) + (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines))) + (setq lines (nreverse lines)) + (when org-export-table-remove-special-lines + ;; Check if the table has a marking column. If yes remove the + ;; column and the special lines + (let* ((special + (not + (memq nil + (mapcar + (lambda (x) + (or (string-match "^[ \t]*|-" x) + (string-match "^[ \t]*| *\\([#!$*_^ ]\\) *|" x))) + lines))))) + (if special + (setq lines + (delq nil + (mapcar + (lambda (x) + (if (string-match "^[ \t]*| *[!_^] *|" x) + nil ; ignore this line + (and (or (string-match "^[ \t]*|-+\\+" x) + (string-match "^[ \t]*|[^|]*|" x)) + (replace-match "|" t t x)))) + lines)))))) + + (let ((head (and org-export-highlight-first-table-line + (delq nil (mapcar + (lambda (x) (string-match "^[ \t]*|-" x)) + (cdr lines))))) + line fields html) + (setq html (concat org-export-html-table-tag "\n")) + (while (setq line (pop lines)) + (catch 'next-line + (if (string-match "^[ \t]*|-" line) + (progn + (setq head nil) ;; head ends here, first time around + ;; ignore this line + (throw 'next-line t))) + ;; Break the line into fields + (setq fields (org-split-string line "[ \t]*|[ \t]*")) + (setq html (concat + html + "

" + (mapconcat (lambda (x) + (if head + (concat "") + (concat ""))) + fields "") + "\n")))) + (setq html (concat html "
" x "" x "
\n")) + html)) + +(defun org-fake-empty-table-line (line) + "Replace everything except \"|\" with spaces." + (let ((i (length line)) + (newstr (copy-sequence line))) + (while (> i 0) + (setq i (1- i)) + (if (not (eq (aref newstr i) ?|)) + (aset newstr i ?\ ))) + newstr)) + +(defun org-format-table-table-html (lines) + "Format a table generated by table.el into HTML. +This conversion does *not* use `table-generate-source' from table.el. +This has the advantage that Org-mode's HTML conversions can be used. +But it has the disadvantage, that no cell- or row-spanning is allowed." + (let (line field-buffer + (head org-export-highlight-first-table-line) + fields html empty) + (setq html (concat org-export-html-table-tag "\n")) + (while (setq line (pop lines)) + (setq empty " ") + (catch 'next-line + (if (string-match "^[ \t]*\\+-" line) + (progn + (if field-buffer + (progn + (setq html (concat + html + "" + (mapconcat + (lambda (x) + (if (equal x "") (setq x empty)) + (if head + (concat "" x "\n") + (concat "" x "\n"))) + field-buffer "\n") + "\n")) + (setq head nil) + (setq field-buffer nil))) + ;; Ignore this line + (throw 'next-line t))) + ;; Break the line into fields and store the fields + (setq fields (org-split-string line "[ \t]*|[ \t]*")) + (if field-buffer + (setq field-buffer (mapcar + (lambda (x) + (concat x "
" (pop fields))) + field-buffer)) + (setq field-buffer fields)))) + (setq html (concat html "\n")) + html)) + +(defun org-format-table-table-html-using-table-generate-source (lines) + "Format a table into html, using `table-generate-source' from table.el. +This has the advantage that cell- or row-spanning is allowed. +But it has the disadvantage, that Org-mode's HTML conversions cannot be used." + (require 'table) + (with-current-buffer (get-buffer-create " org-tmp1 ") + (erase-buffer) + (insert (mapconcat 'identity lines "\n")) + (goto-char (point-min)) + (if (not (re-search-forward "|[^+]" nil t)) + (error "Error processing table")) + (table-recognize-table) + (with-current-buffer (get-buffer-create " org-tmp2 ") (erase-buffer)) + (table-generate-source 'html " org-tmp2 ") + (set-buffer " org-tmp2 ") + (buffer-substring (point-min) (point-max)))) + +(defun org-html-protect (s) + ;; convert & to &, < to < and > to > + (let ((start 0)) + (while (string-match "&" s start) + (setq s (replace-match "&" t t s) + start (1+ (match-beginning 0)))) + (while (string-match "<" s) + (setq s (replace-match "<" t t s))) + (while (string-match ">" s) + (setq s (replace-match ">" t t s)))) + s) + +(defun org-html-expand (string) + "Prepare STRING for HTML export. Applies all active conversions." + ;; First check if there is a link in the line - if yes, apply conversions + ;; only before the start of the link. + ;; FIXME: This is no longer correct, because links now have an end. + (let* ((m (string-match org-link-regexp string)) + (s (if m (substring string 0 m) string)) + (r (if m (substring string m) ""))) + ;; convert & to &, < to < and > to > + (setq s (org-html-protect s)) + (if org-export-html-expand + (while (string-match "@<\\([^&]*\\)>" s) + (setq s (replace-match "<\\1>" nil nil s)))) + (if org-export-with-emphasize + (setq s (org-export-html-convert-emphasize s))) + (if org-export-with-sub-superscripts + (setq s (org-export-html-convert-sub-super s))) + (if org-export-with-TeX-macros + (let ((start 0) wd ass) + (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)" s start)) + (setq wd (match-string 1 s)) + (if (setq ass (assoc wd org-html-entities)) + (setq s (replace-match (or (cdr ass) + (concat "&" (car ass) ";")) + t t s)) + (setq start (+ start (length wd))))))) + (concat s r))) + +(defun org-create-multibrace-regexp (left right n) + "Create a regular expression which will match a balanced sexp. +Opening delimiter is LEFT, and closing delimiter is RIGHT, both given +as single character strings. +The regexp returned will match the entire expression including the +delimiters. It will also define a single group which contains the +match except for the outermost delimiters. The maximum depth of +stacked delimiters is N. Escaping delimiters is not possible." + (let* ((nothing (concat "[^" "\\" left "\\" right "]*?")) + (or "\\|") + (re nothing) + (next (concat "\\(?:" nothing left nothing right "\\)+" nothing))) + (while (> n 1) + (setq n (1- n) + re (concat re or next) + next (concat "\\(?:" nothing left next right "\\)+" nothing))) + (concat left "\\(" re "\\)" right))) + +(defvar org-match-substring-regexp + (concat + "\\([^\\]\\)\\([_^]\\)\\(" + "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)" + "\\|" + "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)" + "\\|" + "\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)") + "The regular expression matching a sub- or superscript.") + +(defun org-export-html-convert-sub-super (string) + "Convert sub- and superscripts in STRING to HTML." + (let (key c) + (while (string-match org-match-substring-regexp string) + (setq key (if (string= (match-string 2 string) "_") "sub" "sup")) + (setq c (or (match-string 8 string) + (match-string 6 string) + (match-string 5 string))) + (setq string (replace-match + (concat (match-string 1 string) + "<" key ">" c "") + t t string))) + (while (string-match "\\\\\\([_^]\\)" string) + (setq string (replace-match (match-string 1 string) t t string)))) + string) + +(defun org-export-html-convert-emphasize (string) + (let (c (s 0)) + (while (string-match "\\(\\W\\|^\\)\\([*/_]\\)\\(\\w+\\)\\2\\(\\W\\|$\\)" string s) + (setq c (cdr (assoc (match-string 2 string) + '(("*" . "b") ("/" . "i") ("_" . "u")))) + s (+ (match-end 0) 3) + string (replace-match + (concat "\\1<" c ">\\3\\4") t nil string))) + string)) + +(defun org-parse-key-lines () + "Find the special key lines with the information for exporters." + (save-excursion + (goto-char 0) + (let ((re (org-make-options-regexp + '("TITLE" "AUTHOR" "EMAIL" "TEXT" "OPTIONS" "LANGUAGE"))) + key) + (while (re-search-forward re nil t) + (setq key (match-string 1)) + (cond ((string-equal key "TITLE") + (setq title (match-string 2))) + ((string-equal key "AUTHOR") + (setq author (match-string 2))) + ((string-equal key "EMAIL") + (setq email (match-string 2))) + ((string-equal key "LANGUAGE") + (setq language (match-string 2))) + ((string-equal key "TEXT") + (setq text (concat text "\n" (match-string 2)))) + ((string-equal key "OPTIONS") + (setq options (match-string 2)))))))) + +(defun org-parse-export-options (s) + "Parse the export options line." + (let ((op '(("H" . org-export-headline-levels) + ("num" . org-export-with-section-numbers) + ("toc" . org-export-with-toc) + ("\\n" . org-export-preserve-breaks) + ("@" . org-export-html-expand) + (":" . org-export-with-fixed-width) + ("|" . org-export-with-tables) + ("^" . org-export-with-sub-superscripts) + ("*" . org-export-with-emphasize) + ("TeX" . org-export-with-TeX-macros))) + o) + (while (setq o (pop op)) + (if (string-match (concat (regexp-quote (car o)) ":\\([^ \t\n\r;,.]*\\)") + s) + (set (make-local-variable (cdr o)) + (car (read-from-string (match-string 1 s)))))))) + +(defun org-html-level-start (level title umax with-toc head-count) + "Insert a new level in HTML export." + (let ((l (1+ (max level umax)))) + (while (<= l org-level-max) + (if (aref levels-open (1- l)) + (progn + (org-html-level-close l) + (aset levels-open (1- l) nil))) + (setq l (1+ l))) + (if (> level umax) + (progn + (if (aref levels-open (1- level)) + (insert "
  • " title "

    \n") + (aset levels-open (1- level) t) + (insert "

    ")) + +;; Variable holding the vector with section numbers +(defvar org-section-numbers (make-vector org-level-max 0)) + +(defun org-init-section-numbers () + "Initialize the vector for the section numbers." + (let* ((level -1) + (numbers (nreverse (org-split-string "" "\\."))) + (depth (1- (length org-section-numbers))) + (i depth) number-string) + (while (>= i 0) + (if (> i level) + (aset org-section-numbers i 0) + (setq number-string (or (car numbers) "0")) + (if (string-match "\\`[A-Z]\\'" number-string) + (aset org-section-numbers i + (- (string-to-char number-string) ?A -1)) + (aset org-section-numbers i (string-to-number number-string))) + (pop numbers)) + (setq i (1- i))))) + +(defun org-section-number (&optional level) + "Return a string with the current section number. +When LEVEL is non-nil, increase section numbers on that level." + (let* ((depth (1- (length org-section-numbers))) idx n (string "")) + (when level + (when (> level -1) + (aset org-section-numbers + level (1+ (aref org-section-numbers level)))) + (setq idx (1+ level)) + (while (<= idx depth) + (if (not (= idx 1)) + (aset org-section-numbers idx 0)) + (setq idx (1+ idx)))) + (setq idx 0) + (while (<= idx depth) + (setq n (aref org-section-numbers idx)) + (setq string (concat string (if (not (string= string "")) "." "") + (int-to-string n))) + (setq idx (1+ idx))) + (save-match-data + (if (string-match "\\`\\([@0]\\.\\)+" string) + (setq string (replace-match "" nil nil string))) + (if (string-match "\\(\\.0\\)+\\'" string) + (setq string (replace-match "" nil nil string)))) + string)) + + +(defun org-export-icalendar-this-file () + "Export current file as an iCalendar file. +The iCalendar file will be located in the same directory as the Org-mode +file, but with extension `.ics'." + (interactive) + (org-export-icalendar nil buffer-file-name)) + +;;;###autoload +(defun org-export-icalendar-all-agenda-files () + "Export all files in `org-agenda-files' to iCalendar .ics files. +Each iCalendar file will be located in the same directory as the Org-mode +file, but with extension `.ics'." + (interactive) + (apply 'org-export-icalendar nil org-agenda-files)) + +;;;###autoload +(defun org-export-icalendar-combine-agenda-files () + "Export all files in `org-agenda-files' to a single combined iCalendar file. +The file is stored under the name `org-combined-agenda-icalendar-file'." + (interactive) + (apply 'org-export-icalendar t org-agenda-files)) + +(defun org-export-icalendar (combine &rest files) + "Create iCalendar files for all elements of FILES. +If COMBINE is non-nil, combine all calendar entries into a single large +file and store it under the name `org-combined-agenda-icalendar-file'." + (save-excursion + (let* (file ical-file ical-buffer category started org-agenda-new-buffers) + (when combine + (setq ical-file org-combined-agenda-icalendar-file + ical-buffer (org-get-agenda-file-buffer ical-file)) + (set-buffer ical-buffer) (erase-buffer)) + (while (setq file (pop files)) + (catch 'nextfile + (org-check-agenda-file file) + (unless combine + (setq ical-file (concat (file-name-sans-extension file) ".ics")) + (setq ical-buffer (org-get-agenda-file-buffer ical-file)) + (set-buffer ical-buffer) (erase-buffer)) + (set-buffer (org-get-agenda-file-buffer file)) + (setq category (or org-category + (file-name-sans-extension + (file-name-nondirectory buffer-file-name)))) + (if (symbolp category) (setq category (symbol-name category))) + (let ((standard-output ical-buffer)) + (if combine + (and (not started) (setq started t) + (org-start-icalendar-file org-icalendar-combined-name)) + (org-start-icalendar-file category)) + (org-print-icalendar-entries combine category) + (when (or (and combine (not files)) (not combine)) + (org-finish-icalendar-file) + (set-buffer ical-buffer) + (save-buffer) + (run-hooks 'org-after-save-iCalendar-file-hook))))) + (org-release-buffers org-agenda-new-buffers)))) + +(defvar org-after-save-iCalendar-file-hook nil + "Hook run after an iCalendar file has been saved. +The iCalendar buffer is still current when this hook is run. +A good way to use this is to tell a desktop calenndar application to re-read +the iCalendar file.") + +(defun org-print-icalendar-entries (&optional combine category) + "Print iCalendar entries for the current Org-mode file to `standard-output'. +When COMBINE is non nil, add the category to each line." + (let ((re2 (concat "--?-?\\(" org-ts-regexp "\\)")) + (dts (org-ical-ts-to-string + (format-time-string (cdr org-time-stamp-formats) (current-time)) + "DTSTART")) + hd ts ts2 state (inc t) pos scheduledp deadlinep tmp pri) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward org-ts-regexp nil t) + (setq pos (match-beginning 0) + ts (match-string 0) + inc t + hd (org-get-heading)) + (if (looking-at re2) + (progn + (goto-char (match-end 0)) + (setq ts2 (match-string 1) inc nil)) + (setq ts2 ts + tmp (buffer-substring (max (point-min) + (- pos org-ds-keyword-length)) + pos) + deadlinep (string-match org-deadline-regexp tmp) + scheduledp (string-match org-scheduled-regexp tmp) + ;; donep (org-entry-is-done-p) + )) + (if (or (string-match org-tr-regexp hd) + (string-match org-ts-regexp hd)) + (setq hd (replace-match "" t t hd))) + (if combine + (setq hd (concat hd " (category " category ")"))) + (if deadlinep (setq hd (concat "DL: " hd " This is a deadline"))) + (if scheduledp (setq hd (concat "S: " hd " Scheduled for this date"))) + (princ (format "BEGIN:VEVENT +%s +%s +SUMMARY:%s +END:VEVENT\n" + (org-ical-ts-to-string ts "DTSTART") + (org-ical-ts-to-string ts2 "DTEND" inc) + hd))) + (when org-icalendar-include-todo + (goto-char (point-min)) + (while (re-search-forward org-todo-line-regexp nil t) + (setq state (match-string 1)) + (unless (equal state org-done-string) + (setq hd (match-string 3)) + (if (string-match org-priority-regexp hd) + (setq pri (string-to-char (match-string 2 hd)) + hd (concat (substring hd 0 (match-beginning 1)) + (substring hd (- (match-end 1))))) + (setq pri org-default-priority)) + (setq pri (floor (1+ (* 8. (/ (float (- org-lowest-priority pri)) + (- org-lowest-priority ?A)))))) + + (princ (format "BEGIN:VTODO +%s +SUMMARY:%s +SEQUENCE:1 +PRIORITY:%d +END:VTODO\n" + dts hd pri)))))))) + +(defun org-start-icalendar-file (name) + "Start an iCalendar file by inserting the header." + (let ((user user-full-name) + (name (or name "unknown")) + (timezone (cadr (current-time-zone)))) + (princ + (format "BEGIN:VCALENDAR +VERSION:2.0 +X-WR-CALNAME:%s +PRODID:-//%s//Emacs with Org-mode//EN +X-WR-TIMEZONE:%s +CALSCALE:GREGORIAN\n" name user timezone)))) + +(defun org-finish-icalendar-file () + "Finish an iCalendar file by inserting the END statement." + (princ "END:VCALENDAR\n")) + +(defun org-ical-ts-to-string (s keyword &optional inc) + "Take a time string S and convert it to iCalendar format. +KEYWORD is added in front, to make a complete line like DTSTART.... +When INC is non-nil, increase the hour by two (if time string contains +a time), or the day by one (if it does not contain a time)." + (let ((t1 (org-parse-time-string s 'nodefault)) + t2 fmt have-time time) + (if (and (car t1) (nth 1 t1) (nth 2 t1)) + (setq t2 t1 have-time t) + (setq t2 (org-parse-time-string s))) + (let ((s (car t2)) (mi (nth 1 t2)) (h (nth 2 t2)) + (d (nth 3 t2)) (m (nth 4 t2)) (y (nth 5 t2))) + (when inc + (if have-time (setq h (+ 2 h)) (setq d (1+ d)))) + (setq time (encode-time s mi h d m y))) + (setq fmt (if have-time ":%Y%m%dT%H%M%S" ";VALUE=DATE:%Y%m%d")) + (concat keyword (format-time-string fmt time)))) + + +;;; Key bindings + +;; - Bindings in Org-mode map are currently +;; 0123456789abcdefghijklmnopqrstuvwxyz!?@#$%^&-+*/=()_{}[]:;"|,.<>~`'\t the alphabet +;; abcd fgh j lmnopqrstuvwxyz!? #$ ^ -+*/= [] ; |,.<>~ '\t necessary bindings +;; e (?) useful from outline-mode +;; i k @ expendable from outline-mode +;; 0123456789 % & ()_{} " ` free + +;; Make `C-c C-x' a prefix key +(define-key org-mode-map "\C-c\C-x" (make-sparse-keymap)) + +;; TAB key with modifiers +(define-key org-mode-map "\C-i" 'org-cycle) +(define-key org-mode-map [(tab)] 'org-cycle) +(define-key org-mode-map [(meta tab)] 'org-complete) +(define-key org-mode-map "\M-\C-i" 'org-complete) ; for tty emacs +;; The following line is necessary under Suse GNU/Linux +(unless org-xemacs-p + (define-key org-mode-map [S-iso-lefttab] 'org-shifttab)) +(define-key org-mode-map [(shift tab)] 'org-shifttab) + +(define-key org-mode-map (org-key 'S-return) 'org-table-copy-down) +(define-key org-mode-map "\C-c\C-xc" 'org-table-copy-down) ; tty +(define-key org-mode-map [(meta shift return)] 'org-insert-todo-heading) +(define-key org-mode-map "\C-c\C-xM" 'org-insert-todo-heading) ; tty +(define-key org-mode-map [(meta return)] 'org-meta-return) +(define-key org-mode-map "\C-c\C-xm" 'org-meta-return) ; tty emacs +(define-key org-mode-map [?\e (return)] 'org-meta-return) ; tty emacs + +;; Cursor keys with modifiers +(define-key org-mode-map [(meta left)] 'org-metaleft) +(define-key org-mode-map [?\e (left)] 'org-metaleft) ; for tty emacs +(define-key org-mode-map "\C-c\C-xl" 'org-metaleft) ; for tty emacs +(define-key org-mode-map [(meta right)] 'org-metaright) +(define-key org-mode-map [?\e (right)] 'org-metaright) ; for tty emacs +(define-key org-mode-map "\C-c\C-xr" 'org-metaright) ; for tty emacs +(define-key org-mode-map [(meta up)] 'org-metaup) +(define-key org-mode-map [?\e (up)] 'org-metaup) ; for tty emacs +(define-key org-mode-map "\C-c\C-xu" 'org-metaup) ; for tty emacs +(define-key org-mode-map [(meta down)] 'org-metadown) +(define-key org-mode-map [?\e (down)] 'org-metadown) ; for tty emacs +(define-key org-mode-map "\C-c\C-xd" 'org-metadown) ; for tty emacs + +(define-key org-mode-map [(meta shift left)] 'org-shiftmetaleft) +(define-key org-mode-map "\C-c\C-xL" 'org-shiftmetaleft) ; tty +(define-key org-mode-map [(meta shift right)] 'org-shiftmetaright) +(define-key org-mode-map "\C-c\C-xR" 'org-shiftmetaright) ; tty +(define-key org-mode-map [(meta shift up)] 'org-shiftmetaup) +(define-key org-mode-map "\C-c\C-xU" 'org-shiftmetaup) ; tty +(define-key org-mode-map [(meta shift down)] 'org-shiftmetadown) +(define-key org-mode-map "\C-c\C-xD" 'org-shiftmetadown) ; tty +(define-key org-mode-map (org-key 'S-up) 'org-shiftup) +(define-key org-mode-map [?\C-c ?\C-x (up)] 'org-shiftup) +(define-key org-mode-map (org-key 'S-down) 'org-shiftdown) +(define-key org-mode-map [?\C-c ?\C-x (down)] 'org-shiftdown) +(define-key org-mode-map (org-key 'S-left) 'org-shiftleft) +(define-key org-mode-map [?\C-c ?\C-x (left)] 'org-shiftleft) +(define-key org-mode-map (org-key 'S-right) 'org-shiftright) +(define-key org-mode-map [?\C-c ?\C-x (right)] 'org-shiftright) + +;; All the other keys +(define-key org-mode-map "\C-c$" 'org-archive-subtree) +(define-key org-mode-map "\C-c\C-j" 'org-goto) +(define-key org-mode-map "\C-c\C-t" 'org-todo) +(define-key org-mode-map "\C-c\C-s" 'org-schedule) +(define-key org-mode-map "\C-c\C-d" 'org-deadline) +(define-key org-mode-map "\C-c;" 'org-toggle-comment) +(define-key org-mode-map "\C-c\C-v" 'org-show-todo-tree) +(define-key org-mode-map "\C-c\C-w" 'org-check-deadlines) +(define-key org-mode-map "\C-c/" 'org-occur) ; Minor-mode reserved +(define-key org-mode-map "\C-c\\" 'org-tags-sparse-tree) ; Minor-mode res. +(define-key org-mode-map "\C-c\C-m" 'org-insert-heading) +(define-key org-mode-map "\M-\C-m" 'org-insert-heading) +(define-key org-mode-map "\C-c\C-l" 'org-insert-link) +(define-key org-mode-map "\C-c\C-o" 'org-open-at-point) +(define-key org-mode-map "\C-c%" 'org-mark-ring-push) +(define-key org-mode-map "\C-c&" 'org-mark-ring-goto) +(define-key org-mode-map "\C-c\C-z" 'org-time-stamp) ; Alternative binding +(define-key org-mode-map "\C-c." 'org-time-stamp) ; Minor-mode reserved +(define-key org-mode-map "\C-c!" 'org-time-stamp-inactive) ; Minor-mode r. +(define-key org-mode-map "\C-c," 'org-priority) ; Minor-mode reserved +(define-key org-mode-map "\C-c\C-y" 'org-evaluate-time-range) +(define-key org-mode-map "\C-c>" 'org-goto-calendar) +(define-key org-mode-map "\C-c<" 'org-date-from-calendar) +(define-key org-mode-map [(control ?,)] 'org-cycle-agenda-files) +(define-key org-mode-map "\C-c[" 'org-agenda-file-to-front) +(define-key org-mode-map "\C-c]" 'org-remove-file) +(define-key org-mode-map "\C-c\C-r" 'org-timeline) +(define-key org-mode-map "\C-c-" 'org-table-insert-hline) +(define-key org-mode-map "\C-c^" 'org-table-sort-lines) +(define-key org-mode-map "\C-c\C-c" 'org-ctrl-c-ctrl-c) +(define-key org-mode-map "\C-m" 'org-return) +(define-key org-mode-map "\C-c?" 'org-table-current-column) +(define-key org-mode-map "\C-c " 'org-table-blank-field) +(define-key org-mode-map "\C-c+" 'org-table-sum) +(define-key org-mode-map "\C-c|" 'org-table-toggle-vline-visibility) +(define-key org-mode-map "\C-c=" 'org-table-eval-formula) +(define-key org-mode-map "\C-c'" 'org-table-edit-formulas) +(define-key org-mode-map "\C-c*" 'org-table-recalculate) +(define-key org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks) +(define-key org-mode-map "\C-c~" 'org-table-create-with-table.el) +(define-key org-mode-map "\C-c\C-q" 'org-table-wrap-region) +(define-key org-mode-map "\C-c\C-xa" 'org-export-as-ascii) +(define-key org-mode-map "\C-c\C-x\C-a" 'org-export-as-ascii) +(define-key org-mode-map "\C-c\C-xv" 'org-export-copy-visible) +(define-key org-mode-map "\C-c\C-x\C-v" 'org-export-copy-visible) +;; OPML support is only an option for the future +;(define-key org-mode-map "\C-c\C-xo" 'org-export-as-opml) +;(define-key org-mode-map "\C-c\C-x\C-o" 'org-export-as-opml) +(define-key org-mode-map "\C-c\C-xi" 'org-export-icalendar-this-file) +(define-key org-mode-map "\C-c\C-x\C-i" 'org-export-icalendar-all-agenda-files) +(define-key org-mode-map "\C-c\C-xc" 'org-export-icalendar-combine-agenda-files) +(define-key org-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files) +(define-key org-mode-map "\C-c\C-xt" 'org-insert-export-options-template) +(define-key org-mode-map "\C-c:" 'org-toggle-fixed-width-section) +(define-key org-mode-map "\C-c\C-xh" 'org-export-as-html) +(define-key org-mode-map "\C-c\C-xb" 'org-export-as-html-and-open) +(define-key org-mode-map "\C-c\C-x\C-b" 'org-export-as-html-and-open) + +(define-key org-mode-map "\C-c\C-x\C-k" 'org-cut-special) +(define-key org-mode-map "\C-c\C-x\C-w" 'org-cut-special) +(define-key org-mode-map "\C-c\C-x\M-w" 'org-copy-special) +(define-key org-mode-map "\C-c\C-x\C-y" 'org-paste-special) + +(defsubst org-table-p () (org-at-table-p)) + +(defun org-self-insert-command (N) + "Like `self-insert-command', use overwrite-mode for whitespace in tables. +If the cursor is in a table looking at whitespace, the whitespace is +overwritten, and the table is not marked as requiring realignment." + (interactive "p") + (if (and (org-table-p) + (or + (and org-table-auto-blank-field + (member last-command + '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c)) + (org-table-blank-field)) + t) + (eq N 1) + (looking-at "[^|\n]* +|")) + (let (org-table-may-need-update) + (goto-char (1- (match-end 0))) + (delete-backward-char 1) + (goto-char (match-beginning 0)) + (self-insert-command N)) + (setq org-table-may-need-update t) + (self-insert-command N))) + +;; FIXME: +;; The following two functions might still be optimized to trigger +;; re-alignment less frequently. + +(defun org-delete-backward-char (N) + "Like `delete-backward-char', insert whitespace at field end in tables. +When deleting backwards, in tables this function will insert whitespace in +front of the next \"|\" separator, to keep the table aligned. The table will +still be marked for re-alignment, because a narrow field may lead to a +reduced column width." + (interactive "p") + (if (and (org-table-p) + (eq N 1) + (string-match "|" (buffer-substring (point-at-bol) (point))) + (looking-at ".*?|")) + (let ((pos (point))) + (backward-delete-char N) + (skip-chars-forward "^|") + (insert " ") + (goto-char (1- pos))) + (backward-delete-char N))) + +(defun org-delete-char (N) + "Like `delete-char', but insert whitespace at field end in tables. +When deleting characters, in tables this function will insert whitespace in +front of the next \"|\" separator, to keep the table aligned. The table +will still be marked for re-alignment, because a narrow field may lead to +a reduced column width." + (interactive "p") + (if (and (org-table-p) + (not (bolp)) + (not (= (char-after) ?|)) + (eq N 1)) + (if (looking-at ".*?|") + (let ((pos (point))) + (replace-match (concat + (substring (match-string 0) 1 -1) + " |")) + (goto-char pos))) + (delete-char N))) + +;; How to do this: Measure non-white length of current string +;; If equal to column width, we should realign. + +(defun org-remap (map &rest commands) + "In MAP, remap the functions given in COMMANDS. +COMMANDS is a list of alternating OLDDEF NEWDEF command names." + (let (new old) + (while commands + (setq old (pop commands) new (pop commands)) + (if (fboundp 'command-remapping) + (define-key map (vector 'remap old) new) + (substitute-key-definition old new map global-map))))) + +(when (eq org-enable-table-editor 'optimized) + ;; If the user wants maximum table support, we need to hijack + ;; some standard editing functions + (org-remap org-mode-map + 'self-insert-command 'org-self-insert-command + 'delete-char 'org-delete-char + 'delete-backward-char 'org-delete-backward-char) + (define-key org-mode-map "|" 'org-force-self-insert)) + +(defun org-shiftcursor-error () + "Throw an error because Shift-Cursor command was applied in wrong context." + (error "This command is active in special context like tables, headlines or timestamps")) + +(defun org-shifttab () + "Global visibility cycling or move to previous table field. +Calls `(org-cycle t)' or `org-table-previous-field', depending on context. +See the individual commands for more information." + (interactive) + (cond + ((org-at-table-p) (org-table-previous-field)) + (t (org-cycle '(4))))) + +(defun org-shiftmetaleft () + "Promote subtree or delete table column. +Calls `org-promote-subtree' or `org-table-delete-column', depending on context. +See the individual commands for more information." + (interactive) + (cond + ((org-at-table-p) (org-table-delete-column)) + ((org-on-heading-p) (org-promote-subtree)) + ((org-at-item-p) (call-interactively 'org-outdent-item)) + (t (org-shiftcursor-error)))) + +(defun org-shiftmetaright () + "Demote subtree or insert table column. +Calls `org-demote-subtree' or `org-table-insert-column', depending on context. +See the individual commands for more information." + (interactive) + (cond + ((org-at-table-p) (org-table-insert-column)) + ((org-on-heading-p) (org-demote-subtree)) + ((org-at-item-p) (call-interactively 'org-indent-item)) + (t (org-shiftcursor-error)))) + +(defun org-shiftmetaup (&optional arg) + "Move subtree up or kill table row. +Calls `org-move-subtree-up' or `org-table-kill-row' or +`org-move-item-up' depending on context. See the individual commands +for more information." + (interactive "P") + (cond + ((org-at-table-p) (org-table-kill-row)) + ((org-on-heading-p) (org-move-subtree-up arg)) + ((org-at-item-p) (org-move-item-up arg)) + (t (org-shiftcursor-error)))) +(defun org-shiftmetadown (&optional arg) + "Move subtree down or insert table row. +Calls `org-move-subtree-down' or `org-table-insert-row' or +`org-move-item-down', depending on context. See the individual +commands for more information." + (interactive "P") + (cond + ((org-at-table-p) (org-table-insert-row arg)) + ((org-on-heading-p) (org-move-subtree-down arg)) + ((org-at-item-p) (org-move-item-down arg)) + (t (org-shiftcursor-error)))) + +(defun org-metaleft (&optional arg) + "Promote heading or move table column to left. +Calls `org-do-promote' or `org-table-move-column', depending on context. +With no specific context, calls the Emacs default `backward-word'. +See the individual commands for more information." + (interactive "P") + (cond + ((org-at-table-p) (org-table-move-column 'left)) + ((or (org-on-heading-p) (org-region-active-p)) (org-do-promote)) + (t (backward-word (prefix-numeric-value arg))))) + +(defun org-metaright (&optional arg) + "Demote subtree or move table column to right. +Calls `org-do-demote' or `org-table-move-column', depending on context. +With no specific context, calls the Emacs default `forward-word'. +See the individual commands for more information." + (interactive "P") + (cond + ((org-at-table-p) (org-table-move-column nil)) + ((or (org-on-heading-p) (org-region-active-p)) (org-do-demote)) + (t (forward-word (prefix-numeric-value arg))))) + +(defun org-metaup (&optional arg) + "Move subtree up or move table row up. +Calls `org-move-subtree-up' or `org-table-move-row' or +`org-move-item-up', depending on context. See the individual commands +for more information." + (interactive "P") + (cond + ((org-at-table-p) (org-table-move-row 'up)) + ((org-on-heading-p) (org-move-subtree-up arg)) + ((org-at-item-p) (org-move-item-up arg)) + (t (org-shiftcursor-error)))) + +(defun org-metadown (&optional arg) + "Move subtree down or move table row down. +Calls `org-move-subtree-down' or `org-table-move-row' or +`org-move-item-down', depending on context. See the individual +commands for more information." + (interactive "P") + (cond + ((org-at-table-p) (org-table-move-row nil)) + ((org-on-heading-p) (org-move-subtree-down arg)) + ((org-at-item-p) (org-move-item-down arg)) + (t (org-shiftcursor-error)))) + +(defun org-shiftup (&optional arg) + "Increase item in timestamp or increase priority of current item. +Calls `org-timestamp-up' or `org-priority-up', depending on context. +See the individual commands for more information." + (interactive "P") + (cond + ((org-at-timestamp-p) (org-timestamp-up arg)) + (t (org-priority-up)))) + +(defun org-shiftdown (&optional arg) + "Decrease item in timestamp or decrease priority of current item. +Calls `org-timestamp-down' or `org-priority-down', depending on context. +See the individual commands for more information." + (interactive "P") + (cond + ((org-at-timestamp-p) (org-timestamp-down arg)) + (t (org-priority-down)))) + +(defun org-shiftright () + "Next TODO keyword or timestamp one day later, depending on context." + (interactive) + (cond + ((org-at-timestamp-p) (org-timestamp-up-day)) + ((org-on-heading-p) (org-todo 'right)) + (t (org-shiftcursor-error)))) + +(defun org-shiftleft () + "Previous TODO keyword or timestamp one day earlier, depending on context." + (interactive) + (cond + ((org-at-timestamp-p) (org-timestamp-down-day)) + ((org-on-heading-p) (org-todo 'left)) + (t (org-shiftcursor-error)))) + +(defun org-copy-special () + "Copy region in table or copy current subtree. +Calls `org-table-copy' or `org-copy-subtree', depending on context. +See the individual commands for more information." + (interactive) + (call-interactively + (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree))) + +(defun org-cut-special () + "Cut region in table or cut current subtree. +Calls `org-table-copy' or `org-cut-subtree', depending on context. +See the individual commands for more information." + (interactive) + (call-interactively + (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree))) + +(defun org-paste-special (arg) + "Paste rectangular region into table, or past subtree relative to level. +Calls `org-table-paste-rectangle' or `org-paste-subtree', depending on context. +See the individual commands for more information." + (interactive "P") + (if (org-at-table-p) + (org-table-paste-rectangle) + (org-paste-subtree arg))) + +(defun org-ctrl-c-ctrl-c (&optional arg) + "Call realign table, or recognize a table.el table, or update keywords. +When the cursor is inside a table created by the table.el package, +activate that table. Otherwise, if the cursor is at a normal table +created with org.el, re-align that table. This command works even if +the automatic table editor has been turned off. + +If the cursor is in a headline, prompt for tags and insert them into +the current line, aligned to `org-tags-column'. When in a headline and +called with prefix arg, realign all tags in the current buffer. + +If the cursor is in one of the special #+KEYWORD lines, this triggers +scanning the buffer for these lines and updating the information. +If the cursor is on a #+TBLFM line, re-apply the formulae to the table." + (interactive "P") + (let ((org-enable-table-editor t)) + (cond + ((and (boundp 'remember-buffer) (equal (buffer-name) remember-buffer)) + (remember-buffer)) + ((org-on-target-p) (org-update-radio-target-regexp)) + ((org-on-heading-p) (org-set-tags arg)) + ((org-at-table.el-p) + (require 'table) + (beginning-of-line 1) + (re-search-forward "|" (save-excursion (end-of-line 2) (point))) + (table-recognize-table)) + ((org-at-table-p) + (org-table-maybe-eval-formula) + (if arg + (org-table-recalculate t) + (org-table-maybe-recalculate-line)) + (org-table-align)) + ((org-at-item-p) + (org-renumber-ordered-list (prefix-numeric-value arg))) + ((save-excursion (beginning-of-line 1) (looking-at "#\\+\\([A-Z]+\\)")) + (cond + ((equal (match-string 1) "TBLFM") + ;; Recalculate the table before this line + (save-excursion + (beginning-of-line 1) + (skip-chars-backward " \r\n\t") + (if (org-at-table-p) (org-table-recalculate t)))) + (t + (org-mode-restart)))) + ((org-region-active-p) + (org-table-convert-region (region-beginning) (region-end) arg)) + ((condition-case nil + (and (region-beginning) (region-end)) + (error nil)) + (if (y-or-n-p "Convert inactive region to table? ") + (org-table-convert-region (region-beginning) (region-end) arg) + (error "Abort"))) + (t (error "C-c C-c can do nothing useful at this location."))))) + +(defun org-mode-restart () + "Restart Org-mode, to scan again for special lines. +Also updates the keyword regular expressions." + (interactive) + (let ((org-inhibit-startup t)) (org-mode)) + (message "Org-mode restarted to refresh keyword and special line setup")) + +(defun org-return () + "Goto next table row or insert a newline. +Calls `org-table-next-row' or `newline', depending on context. +See the individual commands for more information." + (interactive) + (cond + ((org-at-table-p) + (org-table-justify-field-maybe) + (org-table-next-row)) + (t (newline)))) + +(defun org-meta-return (&optional arg) + "Insert a new heading or wrap a region in a table. +Calls `org-insert-heading' or `org-table-wrap-region', depending on context. +See the individual commands for more information." + (interactive "P") + (cond + ((org-at-table-p) + (org-table-wrap-region arg)) + (t (org-insert-heading arg)))) + +;;; Menu entries + +;; Define the Org-mode menus +(easy-menu-define org-tbl-menu org-mode-map "Tbl menu" + '("Tbl" + ["Align" org-ctrl-c-ctrl-c (org-at-table-p)] + ["Next Field" org-cycle (org-at-table-p)] + ["Previous Field" org-shifttab (org-at-table-p)] + ["Next Row" org-return (org-at-table-p)] + "--" + ["Blank Field" org-table-blank-field (org-at-table-p)] + ["Copy Field from Above" org-table-copy-down (org-at-table-p)] + "--" + ("Column" + ["Move Column Left" org-metaleft (org-at-table-p)] + ["Move Column Right" org-metaright (org-at-table-p)] + ["Delete Column" org-shiftmetaleft (org-at-table-p)] + ["Insert Column" org-shiftmetaright (org-at-table-p)]) + ("Row" + ["Move Row Up" org-metaup (org-at-table-p)] + ["Move Row Down" org-metadown (org-at-table-p)] + ["Delete Row" org-shiftmetaup (org-at-table-p)] + ["Insert Row" org-shiftmetadown (org-at-table-p)] + ["Sort lines in region" org-table-sort-lines (org-at-table-p)] + "--" + ["Insert Hline" org-table-insert-hline (org-at-table-p)]) + ("Rectangle" + ["Copy Rectangle" org-copy-special (org-at-table-p)] + ["Cut Rectangle" org-cut-special (org-at-table-p)] + ["Paste Rectangle" org-paste-special (org-at-table-p)] + ["Fill Rectangle" org-table-wrap-region (org-at-table-p)]) + "--" + ("Calculate" + ["Set Column Formula" org-table-eval-formula (org-at-table-p)] + ["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="] + ["Edit Formulas" org-table-edit-formulas (org-at-table-p)] + "--" + ["Recalculate line" org-table-recalculate (org-at-table-p)] + ["Recalculate all" (lambda () (interactive) (org-table-recalculate '(4))) :active (org-at-table-p) :keys "C-u C-c *"] + ["Toggle Recalculate Mark" org-table-rotate-recalc-marks (org-at-table-p)] + "--" + ["Sum Column/Rectangle" org-table-sum + (or (org-at-table-p) (org-region-active-p))] + ["Which Column?" org-table-current-column (org-at-table-p)]) + ["Debug Formulas" + (setq org-table-formula-debug (not org-table-formula-debug)) + :style toggle :selected org-table-formula-debug] + "--" + ["Invisible Vlines" org-table-toggle-vline-visibility + :style toggle :selected (org-in-invisibility-spec-p '(org-table))] + "--" + ["Create" org-table-create (and (not (org-at-table-p)) + org-enable-table-editor)] + ["Convert Region" org-ctrl-c-ctrl-c (not (org-at-table-p 'any))] + ["Import from File" org-table-import (not (org-at-table-p))] + ["Export to File" org-table-export (org-at-table-p)] + "--" + ["Create/Convert from/to table.el" org-table-create-with-table.el t])) + +(easy-menu-define org-org-menu org-mode-map "Org menu" + '("Org" + ["Cycle Visibility" org-cycle (or (bobp) (outline-on-heading-p))] + ["Cycle Global Visibility" org-shifttab (not (org-at-table-p))] + ["Sparse Tree" org-occur t] + ["Show All" show-all t] + "--" + ["New Heading" org-insert-heading t] + ("Navigate Headings" + ["Up" outline-up-heading t] + ["Next" outline-next-visible-heading t] + ["Previous" outline-previous-visible-heading t] + ["Next Same Level" outline-forward-same-level t] + ["Previous Same Level" outline-backward-same-level t] + "--" + ["Jump" org-goto t]) + ("Edit Structure" + ["Move Subtree Up" org-shiftmetaup (not (org-at-table-p))] + ["Move Subtree Down" org-shiftmetadown (not (org-at-table-p))] + "--" + ["Copy Subtree" org-copy-special (not (org-at-table-p))] + ["Cut Subtree" org-cut-special (not (org-at-table-p))] + ["Paste Subtree" org-paste-special (not (org-at-table-p))] + "--" + ["Promote Heading" org-metaleft (not (org-at-table-p))] + ["Promote Subtree" org-shiftmetaleft (not (org-at-table-p))] + ["Demote Heading" org-metaright (not (org-at-table-p))] + ["Demote Subtree" org-shiftmetaright (not (org-at-table-p))] + "--" + ["Archive Subtree" org-archive-subtree t] + "--" + ["Convert to odd levels" org-convert-to-odd-levels t] + ["Convert to odd/even levels" org-convert-to-oddeven-levels t]) + "--" + ("TODO Lists" + ["TODO/DONE/-" org-todo t] + ["Show TODO Tree" org-show-todo-tree t] + ["Global TODO list" org-todo-list t] + "--" + ["Set Priority" org-priority t] + ["Priority Up" org-shiftup t] + ["Priority Down" org-shiftdown t]) + ("Dates and Scheduling" + ["Timestamp" org-time-stamp t] + ["Timestamp (inactive)" org-time-stamp-inactive t] + ("Change Date" + ["1 Day Later" org-timestamp-up-day t] + ["1 Day Earlier" org-timestamp-down-day t] + ["1 ... Later" org-shiftup t] + ["1 ... Earlier" org-shiftdown t]) + ["Compute Time Range" org-evaluate-time-range t] + ["Schedule Item" org-schedule t] + ["Deadline" org-deadline t] + "--" + ["Goto Calendar" org-goto-calendar t] + ["Date from Calendar" org-date-from-calendar t]) + "--" + ["Agenda Command" org-agenda t] + ("File List for Agenda") + ("Special views current file" + ["TODO Tree" org-show-todo-tree t] + ["Check Deadlines" org-check-deadlines t] + ["Timeline" org-timeline t] + ["Tags Tree" org-tags-sparse-tree t]) + "--" + ("Hyperlinks" + ["Store Link (Global)" org-store-link t] + ["Insert Link" org-insert-link t] + ["Follow Link" org-open-at-point t]) + "--" + ("Export" + ["ASCII" org-export-as-ascii t] + ["Extract Visible Text" org-export-copy-visible t] + ["HTML" org-export-as-html t] + ["HTML and Open" org-export-as-html-and-open t] +; ["OPML" org-export-as-opml nil] + "--" + ["iCalendar this file" org-export-icalendar-this-file t] + ["iCalendar all agenda files" org-export-icalendar-all-agenda-files + :active t :keys "C-c C-x C-i"] + ["iCalendar combined" org-export-icalendar-combine-agenda-files t] + "--" + ["Option Template" org-insert-export-options-template t] + ["Toggle Fixed Width" org-toggle-fixed-width-section t]) + "--" + ("Documentation" + ["Show Version" org-version t] + ["Info Documentation" org-info t]) + ("Customize" + ["Browse Org Group" org-customize t] + "--" + ["Build Full Customize Menu" org-create-customize-menu + (fboundp 'customize-menu-create)]) + "--" + ["Refresh setup" org-mode-restart t] + )) + +(defun org-info (&optional node) + "Read documentation for Org-mode in the info system. +With optional NODE, go directly to that node." + (interactive) + (require 'info) + (Info-goto-node (format "(org)%s" (or node "")))) + +(defun org-install-agenda-files-menu () + (easy-menu-change + '("Org") "File List for Agenda" + (append + (list + ["Edit File List" (customize-variable 'org-agenda-files) t] + ["Add/Move Current File to Front of List" org-agenda-file-to-front t] + ["Remove Current File from List" org-remove-file t] + ["Cycle through agenda files" org-cycle-agenda-files t] + "--") + (mapcar 'org-file-menu-entry org-agenda-files)))) + +;;; Documentation + +(defun org-customize () + "Call the customize function with org as argument." + (interactive) + (customize-browse 'org)) + +(defun org-create-customize-menu () + "Create a full customization menu for Org-mode, insert it into the menu." + (interactive) + (if (fboundp 'customize-menu-create) + (progn + (easy-menu-change + '("Org") "Customize" + `(["Browse Org group" org-customize t] + "--" + ,(customize-menu-create 'org) + ["Set" Custom-set t] + ["Save" Custom-save t] + ["Reset to Current" Custom-reset-current t] + ["Reset to Saved" Custom-reset-saved t] + ["Reset to Standard Settings" Custom-reset-standard t])) + (message "\"Org\"-menu now contains full customization menu")) + (error "Cannot expand menu (outdated version of cus-edit.el)"))) + +;;; Miscellaneous stuff + +(defun org-move-line-down (arg) + "Move the current line down. With prefix argument, move it past ARG lines." + (interactive "p") + (let ((col (current-column)) + beg end pos) + (beginning-of-line 1) (setq beg (point)) + (beginning-of-line 2) (setq end (point)) + (beginning-of-line (+ 1 arg)) + (setq pos (move-marker (make-marker) (point))) + (insert (delete-and-extract-region beg end)) + (goto-char pos) + (move-to-column col))) + +(defun org-move-line-up (arg) + "Move the current line up. With prefix argument, move it past ARG lines." + (interactive "p") + (let ((col (current-column)) + beg end pos) + (beginning-of-line 1) (setq beg (point)) + (beginning-of-line 2) (setq end (point)) + (beginning-of-line (- arg)) + (setq pos (move-marker (make-marker) (point))) + (insert (delete-and-extract-region beg end)) + (goto-char pos) + (move-to-column col))) + +;; Paragraph filling stuff. +;; We want this to be just right, so use the full arsenal. +;; FIXME: This very likely does not work correctly for XEmacs, because the +;; filladapt package works slightly differently. + +(defun org-set-autofill-regexps () + (interactive) + ;; In the paragraph separator we include headlines, because filling + ;; text in a line directly attached to a headline would otherwise + ;; fill the headline as well. + (set (make-local-variable 'paragraph-separate) "\f\\|\\*\\|[ ]*$\\|[ \t]*[:|]") + ;; The paragraph starter includes hand-formatted lists. + (set (make-local-variable 'paragraph-start) + "\f\\|[ ]*$\\|\\([*\f]+\\)\\|[ \t]*\\([-+*]\\|[0-9]+[.)][ \t]+\\)\\|[ \t]*[:|]") + ;; Inhibit auto-fill for headers, tables and fixed-width lines. + ;; But only if the user has not turned off tables or fixed-width regions + (set (make-local-variable 'auto-fill-inhibit-regexp) + (concat "\\*\\|#" + (if (or org-enable-table-editor org-enable-fixed-width-editor) + (concat + "\\|[ \t]*[" + (if org-enable-table-editor "|" "") + (if org-enable-fixed-width-editor ":" "") + "]")))) + ;; We use our own fill-paragraph function, to make sure that tables + ;; and fixed-width regions are not wrapped. That function will pass + ;; through to `fill-paragraph' when appropriate. + (set (make-local-variable 'fill-paragraph-function) 'org-fill-paragraph) + ;; Adaptive filling: To get full control, first make sure that + ;; `adaptive-fill-regexp' never matches. Then install our won matcher. + (setq adaptive-fill-regexp "\000") + (setq adaptive-fill-function 'org-adaptive-fill-function)) + +(defun org-fill-paragraph (&optional justify) + "Re-align a table, pass through to fill-paragraph if no table." + (let ((table-p (org-at-table-p)) + (table.el-p (org-at-table.el-p))) + (cond ((equal (char-after (point-at-bol)) ?*) t) ; skip headlines + (table.el-p t) ; skip table.el tables + (table-p (org-table-align) t) ; align org-mode tables + (t nil)))) ; call paragraph-fill + +;; For reference, this is the default value of adaptive-fill-regexp +;; "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*" + +(defun org-adaptive-fill-function () + "Return a fill prefix for org-mode files. +In particular, this makes sure hanging paragraphs for hand-formatted lists +work correctly." + (if (looking-at " *\\([-*+] \\|[0-9]+[.)] \\)?") + (make-string (- (match-end 0) (match-beginning 0)) ?\ ))) + +;; Functions needed for Emacs/XEmacs region compatibility + +(defun org-add-hook (hook function &optional append local) + "Add-hook, compatible with both Emacsen." + (if (and local org-xemacs-p) + (add-local-hook hook function append) + (add-hook hook function append local))) + +(defun org-region-active-p () + "Is `transient-mark-mode' on and the region active? +Works on both Emacs and XEmacs." + (if org-ignore-region + nil + (if org-xemacs-p + (and zmacs-regions (region-active-p)) + (and transient-mark-mode mark-active)))) + +(defun org-add-to-invisibility-spec (arg) + "Add elements to `buffer-invisibility-spec'. +See documentation for `buffer-invisibility-spec' for the kind of elements +that can be added." + (cond + ((fboundp 'add-to-invisibility-spec) + (add-to-invisibility-spec arg)) + ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t)) + (setq buffer-invisibility-spec (list arg))) + (t + (setq buffer-invisibility-spec + (cons arg buffer-invisibility-spec))))) + +(defun org-remove-from-invisibility-spec (arg) + "Remove elements from `buffer-invisibility-spec'." + (if (fboundp 'remove-from-invisibility-spec) + (remove-from-invisibility-spec arg) + (if (consp buffer-invisibility-spec) + (setq buffer-invisibility-spec + (delete arg buffer-invisibility-spec))))) + +(defun org-in-invisibility-spec-p (arg) + "Is ARG a member of `buffer-invisibility-spec'?" + (if (consp buffer-invisibility-spec) + (member arg buffer-invisibility-spec) + nil)) + +(defun org-image-file-name-regexp () + "Return regexp matching the file names of images." + (if (fboundp 'image-file-name-regexp) + (image-file-name-regexp) + (let ((image-file-name-extensions + '("png" "jpeg" "jpg" "gif" "tiff" "tif" + "xbm" "xpm" "pbm" "pgm" "ppm"))) + (concat "\\." + (regexp-opt (nconc (mapcar 'upcase + image-file-name-extensions) + image-file-name-extensions) + t) + "\\'")))) + +;; Functions needed for compatibility with old outline.el. + +;; Programming for the old outline.el (that uses selective display +;; instead of `invisible' text properties) is a nightmare, mostly +;; because regular expressions can no longer be anchored at +;; beginning/end of line. Therefore a number of function need special +;; treatment when the old outline.el is being used. + +;; The following functions capture almost the entire compatibility code +;; between the different versions of outline-mode. The only other +;; places where this is important are the font-lock-keywords, and in +;; `org-export-copy-visible'. Search for `org-noutline-p' to find them. + +;; C-a should go to the beginning of a *visible* line, also in the +;; new outline.el. I guess this should be patched into Emacs? +(defun org-beginning-of-line () + "Go to the beginning of the current line. If that is invisible, continue +to a visible line beginning. This makes the function of C-a more intuitive." + (interactive) + (beginning-of-line 1) + (if (bobp) + nil + (backward-char 1) + (if (org-invisible-p) + (while (and (not (bobp)) (org-invisible-p)) + (backward-char 1) + (beginning-of-line 1)) + (forward-char 1)))) + +(when org-noutline-p + (define-key org-mode-map "\C-a" 'org-beginning-of-line)) +;; FIXME: should I use substitute-key-definition to reach other bindings +;; of beginning-of-line? + +(defun org-invisible-p () + "Check if point is at a character currently not visible." + (if org-noutline-p + ;; Early versions of noutline don't have `outline-invisible-p'. + (if (fboundp 'outline-invisible-p) + (outline-invisible-p) + (get-char-property (point) 'invisible)) + (save-excursion + (skip-chars-backward "^\r\n") + (equal (char-before) ?\r)))) + +(defun org-invisible-p2 () + "Check if point is at a character currently not visible." + (save-excursion + (if org-noutline-p + (progn + (if (and (eolp) (not (bobp))) (backward-char 1)) + ;; Early versions of noutline don't have `outline-invisible-p'. + (if (fboundp 'outline-invisible-p) + (outline-invisible-p) + (get-char-property (point) 'invisible))) + (skip-chars-backward "^\r\n") + (equal (char-before) ?\r)))) + +(defun org-back-to-heading (&optional invisible-ok) + "Move to previous heading line, or beg of this line if it's a heading. +Only visible heading lines are considered, unless INVISIBLE-OK is non-nil." + (if org-noutline-p + (outline-back-to-heading invisible-ok) + (if (and (memq (char-before) '(?\n ?\r)) + (looking-at outline-regexp)) + t + (if (re-search-backward (concat (if invisible-ok "\\([\r\n]\\|^\\)" "^") + outline-regexp) + nil t) + (if invisible-ok + (progn (goto-char (match-end 1)) + (looking-at outline-regexp))) + (error "Before first heading"))))) + +(defun org-on-heading-p (&optional invisible-ok) + "Return t if point is on a (visible) heading line. +If INVISIBLE-OK is non-nil, an invisible heading line is ok too." + (if org-noutline-p + (outline-on-heading-p 'invisible-ok) + (save-excursion + (skip-chars-backward "^\n\r") + (and (looking-at outline-regexp) + (or invisible-ok + (bobp) + (equal (char-before) ?\n)))))) + +(defun org-on-target-p () + (let ((pos (point))) + (save-excursion + (skip-chars-forward "<") + (and (re-search-backward "<<" nil t) + (or (looking-at org-target-regexp) + (looking-at org-radio-target-regexp)) + (<= (match-beginning 0) pos) + (>= (match-end 0) pos))))) + +(defun org-up-heading-all (arg) + "Move to the heading line of which the present line is a subheading. +This function considers both visible and invisible heading lines. +With argument, move up ARG levels." + (if org-noutline-p + (if (fboundp 'outline-up-heading-all) + (outline-up-heading-all arg) ; emacs 21 version of outline.el + (outline-up-heading arg t)) ; emacs 22 version of outline.el + (org-back-to-heading t) + (looking-at outline-regexp) + (if (<= (- (match-end 0) (match-beginning 0)) arg) + (error "Cannot move up %d levels" arg) + (re-search-backward + (concat "[\n\r]" (regexp-quote + (make-string (- (match-end 0) (match-beginning 0) arg) + ?*)) + "[^*]")) + (forward-char 1)))) + +(defun org-show-hidden-entry () + "Show an entry where even the heading is hidden." + (save-excursion + (if (not org-noutline-p) + (progn + (org-back-to-heading t) + (org-flag-heading nil))) + (org-show-entry))) + +(defun org-check-occur-regexp (regexp) + "If REGEXP starts with \"^\", modify it to check for \\r as well. +Of course, only for the old outline mode." + (if org-noutline-p + regexp + (if (string-match "^\\^" regexp) + (concat "[\n\r]" (substring regexp 1)) + regexp))) + +(defun org-flag-heading (flag &optional entry) + "Flag the current heading. FLAG non-nil means make invisible. +When ENTRY is non-nil, show the entire entry." + (save-excursion + (org-back-to-heading t) + (if (not org-noutline-p) + ;; Make the current headline visible + (outline-flag-region (max 1 (1- (point))) (point) (if flag ?\r ?\n))) + ;; Check if we should show the entire entry + (if entry + (progn + (org-show-entry) + (save-excursion ;; FIXME: Is this the fix for points in the -| + ;; middle of text? | + (and (outline-next-heading) ;; | + (org-flag-heading nil)))) ; show the next heading _| + (outline-flag-region (max 1 (1- (point))) + (save-excursion (outline-end-of-heading) (point)) + (if org-noutline-p + flag + (if flag ?\r ?\n)))))) + +(defun org-end-of-subtree (&optional invisible-OK) + ;; This is an exact copy of the original function, but it uses + ;; `org-back-to-heading', to make it work also in invisible + ;; trees. And is uses an invisible-OK argument. + ;; Under Emacs this is not needed, but the old outline.el needs this fix. + (org-back-to-heading invisible-OK) + (let ((first t) + (level (funcall outline-level))) + (while (and (not (eobp)) + (or first (> (funcall outline-level) level))) + (setq first nil) + (outline-next-heading)) + (if (memq (preceding-char) '(?\n ?\^M)) + (progn + ;; Go to end of line before heading + (forward-char -1) + (if (memq (preceding-char) '(?\n ?\^M)) + ;; leave blank line before heading + (forward-char -1)))))) + +(defun org-show-subtree () + "Show everything after this heading at deeper levels." + (outline-flag-region + (point) + (save-excursion + (outline-end-of-subtree) (outline-next-heading) (point)) + (if org-noutline-p nil ?\n))) + +(defun org-show-entry () + "Show the body directly following this heading. +Show the heading too, if it is currently invisible." + (interactive) + (save-excursion + (org-back-to-heading t) + (outline-flag-region + (1- (point)) + (save-excursion + (re-search-forward (concat "[\r\n]\\(" outline-regexp "\\)") nil 'move) + (or (match-beginning 1) (point-max))) + (if org-noutline-p nil ?\n)))) + + +(defun org-make-options-regexp (kwds) + "Make a regular expression for keyword lines." + (concat + (if org-noutline-p "^" "[\n\r]") + "#?[ \t]*\\+\\(" + (mapconcat 'regexp-quote kwds "\\|") + "\\):[ \t]*" + (if org-noutline-p "\\(.+\\)" "\\([^\n\r]+\\)"))) + +;; Make `bookmark-jump' show the jump location if it was hidden. +(eval-after-load "bookmark" + '(if (boundp 'bookmark-after-jump-hook) + ;; We can use the hook + (add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide) + ;; Hook not available, use advice + (defadvice bookmark-jump (after org-make-visible activate) + "Make the position visible." + (org-bookmark-jump-unhide)))) + +(defun org-bookmark-jump-unhide () + "Unhide the current position, to show the bookmark location." + (and (eq major-mode 'org-mode) + (or (org-invisible-p) + (save-excursion (goto-char (max (point-min) (1- (point)))) + (org-invisible-p))) + (org-show-hierarchy-above))) + +;;; Finish up + +(provide 'org) + +(run-hooks 'org-load-hook) + +;; Experimental code + + + +;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd +;;; org.el ends here + diff --git a/org.pdf b/org.pdf new file mode 100644 index 000000000..7ed4b20c8 Binary files /dev/null and b/org.pdf differ diff --git a/org.texi b/org.texi new file mode 100644 index 000000000..5eb4f1484 --- /dev/null +++ b/org.texi @@ -0,0 +1,3542 @@ +\input texinfo +@c %**start of header +@setfilename org +@c @setfilename ../info/org +@settitle Org Mode Manual + +@set VERSION 4.12 +@set DATE March 2006 + +@dircategory Emacs +@direntry +* Org Mode: (org). outline-based notes management and organizer +@end direntry + +@c Version and Contact Info +@set MAINTAINERSITE @uref{http://www.astro.uva.nl/~dominik/Tools/org/,maintainers webpage} +@set MAINTAINER Carsten Dominik +@set MAINTAINEREMAIL @email{dominik@@science.uva.nl} +@set MAINTAINERCONTACT @uref{mailto:dominik@@science.uva.nl,contact the maintainer} +@c %**end of header +@finalout + +@c Macro definitions + +@c FIXME: does not look good in html +@c Subheadings inside a table. Need a difference between info and the rest. +@macro tsubheading{text} +@ifinfo +@subsubheading \text\ +@end ifinfo +@ifnotinfo +@item @b{\text\} +@end ifnotinfo +@end macro + +@copying +This manual is for Org-mode (version @value{VERSION}). + +Copyright @copyright{} 2004, 2005, 2006 Free Software Foundation + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with the Front-Cover texts being ``A GNU Manual,'' +and with the Back-Cover Texts as in (a) below. A copy of the +license is included in the section entitled ``GNU Free Documentation +License.'' + +(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify +this GNU Manual, like GNU software. Copies published by the Free +Software Foundation raise funds for GNU development.'' +@end quotation +@end copying + +@titlepage +@title Org Mode Manual + +@subtitle Release @value{VERSION} +@author by Carsten Dominik + +@c The following two commands start the copyright page. +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@c Output the table of contents at the beginning. +@contents + +@ifnottex +@node Top, Introduction, (dir), (dir) +@top Org Mode Manual + +@insertcopying +@end ifnottex + +@menu +* Introduction:: Getting started +* Document Structure:: A tree works like your brain +* Tables:: Pure magic for quick formatting +* Hyperlinks:: Notes in context +* TODO items:: Every tree branch can be a TODO item +* Timestamps:: Assign date and time to items +* Agenda Views:: Collecting information into views +* Exporting:: Sharing and publishing of notes +* Miscellaneous:: All the rest which did not fit elsewhere +* Index:: The fast road to specific information +* Key Index:: Key bindings and where they are described + +@detailmenu + --- The Detailed Node Listing --- + +Introduction + +* Summary:: Brief summary of what Org-mode does +* Installation and Activation:: How to install Org-mode +* Feedback:: Bug reports, ideas, patches etc. + +Document Structure + +* Outlines:: Org-mode is based on outline-mode +* Headlines:: How to typeset org-tree headlines +* Visibility cycling:: Show and hide, much simplified +* Motion:: Jumping to other headlines +* Structure editing:: Changing sequence and level of headlines +* Archiving:: Move done task trees to a different place +* Sparse trees:: Matches embedded in context +* Tags:: Tagging headlines and matching sets of tags +* Plain Lists:: Editing hand-formatted lists + +Tables + +* Built-in table editor:: Simple tables +* Table calculations:: Compute a field from other fields +* orgtbl-mode:: The table editor as minor mode +* table.el:: Complex tables + +Calculations in tables + +* Formula syntax:: How to write a formula +* Column formulas:: Formulas valid for all fields in a column +* Advanced features:: Field names, parameters and automatic recalc +* Named-field formulas:: Formulas valid in single fields +* Editing/debugging formulas:: Changing a stored formula +* Appetizer:: Taste the power of calc + +Hyperlinks + +* Internal Links:: Links to other places in the current file +* External Links:: URL-like links to the world +* Managing links:: Creating, inserting and following +* Search Options:: Linking to a specific location +* Remember:: Org-trees store quick notes + +Internal Links + +* Radio targets:: Make targets trigger links in plain text. +* CamelCase links:: Activating CamelCase words as links + +TODO items + +* TODO basics:: Marking and displaying TODO entries +* Progress Logging:: Document your productivity +* TODO extensions:: Workflow and assignments +* Priorities:: Some things are more important than others + +Extended use of TODO keywords + +* Workflow states:: From TODO to DONE in steps +* TODO types:: I do this, Fred the rest +* Per file keywords:: Different files, different requirements + +Timestamps + +* Time stamps:: Assigning a time to a tree entry +* Creating timestamps:: Commands which insert timestamps + +Agenda Views + +* Agenda files:: Files being searched for agenda information +* Agenda dispatcher:: Keyboard access to agenda views +* Weekly/Daily Agenda:: The calendar page with current tasks +* Global TODO list:: All unfinished action items +* Matching headline tags:: Structured information with fine-tuned search +* Timeline:: Time-sorted view for single file +* Agenda commands:: Remote editing of org trees + +The weekly/daily agenda + +* Categories:: Not all tasks are equal +* Time-of-day specifications:: How the agenda knows the time +* Calendar/Diary integration:: Integrating Anniversaries and more +* Sorting of agenda items:: The order of things + +Exporting + +* ASCII export:: Export as a structured ASCII file +* HTML export:: Export as an HTML file +* iCalendar export:: Create calendar entries. + +HTML export + +* HTML formatting:: Interpretation of the buffer content +* Export options:: How to influence exports +* Comment lines:: Lines which will not be exported + +Miscellaneous + +* Completion:: M-TAB knows what you need +* Customization:: Adapting Org-mode to your taste +* Clean view:: Getting rid of leading stars in the outline +* TTY keys:: Using Org-mode on a tty +* FAQ:: Frequently asked questions +* Interaction:: Other Emacs packages +* Bugs:: Things which do not work perfectly +* Acknowledgments:: These people provided feedback and more + +@end detailmenu +@end menu + +@node Introduction, Document Structure, Top, Top +@chapter Introduction +@cindex introduction + +@menu +* Summary:: Brief summary of what Org-mode does +* Installation and Activation:: How to install Org-mode +* Feedback:: Bug reports, ideas, patches etc. +@end menu + +@node Summary, Installation and Activation, Introduction, Introduction +@section Summary +@cindex summary + +Org-mode is a mode for keeping notes, maintaining ToDo lists, and doing +project planning with a fast and effective plain-text system. + +Org-mode develops organizational tasks around NOTES files that contain +information about projects as plain text. Org-mode is implemented on +top of outline-mode, which makes it possible to keep the content of +large files well structured. Visibility cycling and structure editing +help to work with the tree. Tables are easily created with a built-in +table editor. Org-mode supports ToDo items, deadlines, time stamps, +and scheduling. It dynamically compiles entries into an agenda that +utilizes and smoothly integrates much of the Emacs calendar and diary. +Plain text URL-like links connect to websites, emails, Usenet +messages, BBDB entries, and any files related to the projects. For +printing and sharing of notes, an Org-mode file can be exported as a +structured ASCII file, as HTML, or (todo and agenda items only) as an +iCalendar file. + +Org-mode keeps simple things simple. When first fired up, it should +feel like a simple but easy to use outliner. Complexity is not +imposed, but a large amount of functionality is available when you +need it. Org-mode can be used on different levels and in different +ways, for example + +@example +@r{@bullet{} as an outline extension with visibility cycling and structure editing} +@r{@bullet{} as an ASCII system and table editor for taking structured notes} +@r{@bullet{} as an ASCII table editor with spreadsheet-like capabilities} +@r{@bullet{} as a simple hypertext system, with HTML export} +@r{@bullet{} as a TODO list editor} +@r{@bullet{} as a full agenda and planner with deadlines and work scheduling} +@end example + +The Org-mode table editor can be integrated into any major mode by +activating the minor Orgtbl-mode. + +There is a website for Org-mode which provides links to the newest +version of Org-mode, as well as additional information, screen shots +and example files. This page is located at +@uref{http://www.astro.uva.nl/~dominik/Tools/org/}. + +@page + +@node Installation and Activation, Feedback, Summary, Introduction +@section Installation and Activation +@cindex installation +@cindex autoload +@cindex global keybindings +@cindex keybindings, global + +If Org-mode is part of the Emacs distribution or an XEmacs package, +you only need to copy the following lines to your @file{.emacs} file. +The last two lines define @emph{global} keys for the commands +@command{org-store-link} and @command{org-agenda} - please +choose suitable keys yourself. + +@lisp +;; The following lines are always needed. Choose your own keys. +(add-to-list 'auto-mode-alist '("\\.org$" . org-mode)) +(define-key global-map "\C-cl" 'org-store-link) +(define-key global-map "\C-ca" 'org-agenda) +@end lisp + +If you have downloaded Org-mode from the Web, you must byte-compile +@file{org.el} and put it on your load path. In addition to the Emacs +Lisp lines above, you also need to add the following lines to +@file{.emacs}: + +@lisp +;; These lines only if org-mode is not part of the X/Emacs distribution. +(autoload 'org-mode "org" "Org mode" t) +(autoload 'org-diary "org" "Diary entries from Org mode") +(autoload 'org-agenda "org" "Multi-file agenda from Org mode" t) +(autoload 'org-store-link "org" "Store a link to the current location" t) +(autoload 'orgtbl-mode "org" "Org tables as a minor mode" t) +(autoload 'turn-on-orgtbl "org" "Org tables as a minor mode") +@end lisp + +@cindex org-mode, turning on +With this setup, all files with extension @samp{.org} will be put into +Org-mode. As an alternative, make the first line of a file look like +this: + +@example +MY PROJECTS -*- mode: org; -*- +@end example + +@noindent which will select Org-mode for this buffer no matter what +the file's name is. See also the variable +@code{org-insert-mode-line-in-empty-file'}. + +@node Feedback, , Installation and Activation, Introduction +@section Feedback +@cindex feedback +@cindex bug reports +@cindex maintainer +@cindex author + +If you find problems with Org-mode, or if you have questions, remarks, +or ideas about it, please contact the maintainer Carsten Dominik at +@value{MAINTAINEREMAIL}. + +For bug reports, please provide as much information as possible, +including the version information of Emacs (@kbd{C-h v emacs-version +@key{RET}}) and Org-mode (@kbd{M-x org-version}), as well as the +Org-mode related setup in @file{.emacs}. If an error occurs, a +traceback can be very useful. Often a small example file helps, along +with clear information about: +@enumerate +@item What exactly did you do? +@item What did you expect to happen? +@item What happened instead? +@end enumerate +@noindent Thanks for helping to improve this mode. + +@node Document Structure, Tables, Introduction, Top +@chapter Document Structure +@cindex document structure +@cindex structure of document + +Org-mode is based on outline mode and provides flexible commands to +edit the structure of the document. + +@menu +* Outlines:: Org-mode is based on outline-mode +* Headlines:: How to typeset org-tree headlines +* Visibility cycling:: Show and hide, much simplified +* Motion:: Jumping to other headlines +* Structure editing:: Changing sequence and level of headlines +* Archiving:: Move done task trees to a different place +* Sparse trees:: Matches embedded in context +* Tags:: Tagging headlines and matching sets of tags +* Plain Lists:: Editing hand-formatted lists +@end menu + +@node Outlines, Headlines, Document Structure, Document Structure +@section Outlines +@cindex outlines +@cindex outline-mode + +Org-mode is implemented on top of outline-mode. Outlines allow to +organize a document in a hierarchical structure, which (at least for +me) is the best representation of notes and thoughts. Overview over +this structure is achieved by folding (hiding) large parts of the +document to show only the general document structure and the parts +currently being worked on. Org-mode greatly simplifies the use of +outlines by compressing the entire show/hide functionality into a +single command @command{org-cycle}, which is bound to the @key{TAB} +key. + +@node Headlines, Visibility cycling, Outlines, Document Structure +@section Headlines +@cindex headlines +@cindex outline tree + +Headlines define the structure of an outline tree. The Headlines in +Org-mode start with one or more stars, on the left margin. For +example + +@example +* Top level headline +** Second level +*** 3rd level + some text +*** 3rd level + more text +* Another top level headline +@end example +@noindent Some people find the many stars too noisy and would prefer an +outline that has whitespace followed by a single star as headline +starters. @ref{Clean view} describes a setup to realize this. + +@node Visibility cycling, Motion, Headlines, Document Structure +@section Visibility cycling +@cindex cycling, visibility +@cindex visibility cycling +@cindex trees, visibility +@cindex show hidden text +@cindex hide text + +Outlines make it possible to hide parts of the text in the buffer. +Org-mode uses a single command bound to the @key{TAB} key to change +the visibility in the buffer. + +@cindex subtree visibility states +@cindex folded, subtree visibility state +@cindex children, subtree visibility state +@cindex subtree, subtree visibility state +@table @kbd +@kindex @key{TAB} +@item @key{TAB} +Rotate current subtree between the states +@example +,-> FOLDED -> CHILDREN -> SUBTREE --. +'-----------------------------------' +@end example +At the beginning of the buffer (or when called with @kbd{C-u}), this does +the same as the command @kbd{S-@key{TAB}} below. + +@cindex global visibility states +@cindex overview, global visibility state +@cindex contents, global visibility state +@cindex show all, global visibility state +@kindex S-@key{TAB} +@item S-@key{TAB} +Rotate the entire buffer between the states +@example +,-> OVERVIEW -> CONTENTS -> SHOW ALL --. +'--------------------------------------' +@end example +Note that inside tables, @kbd{S-@key{TAB}} jumps to the previous field. + +@cindex show all, command +@kindex C-c C-a +@item C-c C-a +Show all. +@end table + +When Emacs first visits an Org-mode file, the global state is set to +OVERVIEW, i.e. only the top level headlines are visible. This can be +configured through the variable @code{org-startup-folded}, or on a +per-file basis by adding one of the following lines anywhere in the +buffer: + +@example +#+STARTUP: fold +#+STARTUP: nofold +#+STARTUP: content +@end example + +@node Motion, Structure editing, Visibility cycling, Document Structure +@section Motion +@cindex motion, between headlines +@cindex jumping, to headlines +@cindex headline navigation +The following commands jump to other headlines in the buffer. + +@table @kbd +@kindex C-c C-n +@item C-c C-n +Next heading. +@kindex C-c C-p +@item C-c C-p +Previous heading. +@kindex C-c C-f +@item C-c C-f +Next heading same level. +@kindex C-c C-b +@item C-c C-b +Previous heading same level. +@kindex C-c C-u +@item C-c C-u +Backward to higher level heading. +@kindex C-c C-j +@item C-c C-j +Jump to a different place without changing the current outline +visibility. Shows the document structure in a temporary buffer, where +you can use visibility cycling (@key{TAB}) to find your destination. +After pressing @key{RET}, the cursor moves to the selected location in +the original buffer, and the headings hierarchy above it is made +visible. +@end table + +@node Structure editing, Archiving, Motion, Document Structure +@section Structure editing +@cindex structure editing +@cindex headline, promotion and demotion +@cindex promotion, of subtrees +@cindex demotion, of subtrees +@cindex subtree, cut and paste +@cindex pasting, of subtrees +@cindex cutting, of subtrees +@cindex copying, of subtrees +@cindex subtrees, cut and paste + +@table @kbd +@kindex M-@key{RET} +@item M-@key{RET} +Insert new heading with same level as current. If the cursor is in a +plain list item, a new item is created. To force creation of a new +headline, use a prefix arg, or first press @key{RET} to get to the +beginning of the next line. +@kindex M-S-@key{RET} +@item M-S-@key{RET} +Insert new TODO entry with same level as current heading. +@kindex M-@key{left} +@item M-@key{left} +Promote current heading by one level +@kindex M-@key{right} +@item M-@key{right} +Demote current heading by one level +@kindex M-S-@key{left} +@item M-S-@key{left} +Promote the current subtree by one level +@kindex M-S-@key{right} +@item M-S-@key{right} +Demote the current subtree by one level +@kindex M-S-@key{up} +@item M-S-@key{up} +Move subtree up (swap with previous subtree of same +level) +@kindex M-S-@key{down} +@item M-S-@key{down} +Move subtree down (swap with next subtree of same level) +@kindex C-c C-x C-w +@kindex C-c C-x C-k +@item C-c C-x C-w +@itemx C-c C-x C-k +Kill subtree, i.e. remove it from buffer but save in kill ring. +@kindex C-c C-x M-w +@item C-c C-x M-w +Copy subtree to kill ring. +@kindex C-c C-x C-y +@item C-c C-x C-y +Yank subtree from kill ring. This does modify the level of the subtree to +make sure the tree fits in nicely at the yank position. The yank +level can also be specified with a prefix arg, or by yanking after a +headline marker like @samp{****}. +@end table + +@cindex region, active +@cindex active region +@cindex transient-mark-mode +When there is an active region (transient-mark-mode), promotion and +demotion work on all headlines in the region. To select a region of +headlines, it is best to place both point and mark at the beginning of a +line, mark at the beginning of the first headline, and point at the line +just after the last headline to change. Note that when the cursor is +inside a table (@pxref{Tables}), the Meta-Cursor keys have different +functionality. + +@node Archiving, Sparse trees, Structure editing, Document Structure +@section Archiving +@cindex archiving +@cindex filing subtrees + +When a project represented by a (sub)tree is finished, you may want +to move the tree to an archive place, either in the same file under a +special top-level heading, or even to a different file. +@table @kbd +@kindex C-c $ +@item @kbd{C-c $} +Archive the subtree starting at the cursor position to the location +given by @code{org-archive-location}. +@end table + +@cindex archive locations +The default archive is a file in the same directory as the current +file, with the name derived by appending @file{_archive} to the +current file name. For information and examples on how to change +this, see the documentation string of the variable +@code{org-archive-location}. If you are also using the Org-mode +agenda, archiving to a different file is a good way to keep archived +trees from contributing agenda items. + +@node Sparse trees, Tags, Archiving, Document Structure +@section Sparse trees +@cindex sparse trees +@cindex trees, sparse +@cindex folding, sparse trees +@cindex occur, command + +An important feature of Org-mode is the ability to construct +@emph{sparse trees} for selected information in an outline tree. A +sparse tree means that the entire document is folded as much as +possible, but the selected information is made visible along with the +headline structure above it@footnote{See also the variables +@code{org-show-hierarchy-above} and +@code{org-show-following-heading}.}. Just try it out and you will see +immediately how it works. + +Org-mode contains several commands creating such trees. The most +basic one is @command{org-occur}: + +@table @kbd +@kindex C-c / +@item C-c / +Occur. Prompts for a regexp and shows a sparse tree with all matches. +If the match is in a headline, the headline is made visible. If the +match is in the body of an entry, headline and body are made visible. +In order to provide minimal context, also the full hierarchy of +headlines above the match is shown, as well as the headline following +the match. Each match is also highlighted, the highlights disappear +when the buffer is changed with an editing command. +@end table +@noindent +For frequently used sparse trees of specific search strings, you can +use the variable @code{org-agenda-custom-commands} to define fast +keyboard access to specific sparse trees. These commands will then be +accessible through the agenda dispatcher (@pxref{Agenda dispatcher}). +For example +@lisp +(setq org-agenda-custom-commands + '(("f" occur-tree "FIXME"))) +@end lisp +@noindent will define the key @kbd{C-c a f} as a shortcut for creating +a sparse tree matching the string @samp{FIXME}. + +Other commands are using sparse trees as well. For example @kbd{C-c +C-v} creates a sparse TODO tree (@pxref{TODO basics}). + +@kindex C-c C-x v +@cindex printing sparse trees +@cindex visible text, printing +To print a sparse tree, you can use the Emacs command +@code{ps-print-buffer-with-faces} which does not print invisible parts +of the document @footnote{This does not work under XEmacs, because +XEmacs uses selective display for outlining, not text properties}. +Or you can use the command @kbd{C-c C-x v} to copy the visible part of +the document to another file (extension @file{.txt}) which then can be +printed in any desired way. + +@node Tags, Plain Lists, Sparse trees, Document Structure +@section Tags +@cindex tags +@cindex headline tagging +@cindex matching, tags +@cindex sparse tree, tag based + +If you wish to implement a tag system to cross-correlate information, +this can be done as well in Org-mode. Every headline can contain a +list of tags, at the end of the headline. Tags are normal words +containing letters, numbers, @samp{_}, and @samp{@@}. Tags must be +preceded and followed by a single colon; like @samp{:WORK:}. Several +tags can be specified like @samp{:WORK:URGENT:}. + +@cindex inheritance, of tags +Tags make use of the hierarchical structure of outline trees. If a +heading has a certain tag, all subheadings will inherit the tag as +well. For example, in the list + +@example +* Meeting with the French group :WORK: +** Summary by Frank :BOSS:NOTES: +*** TODO Prepare slides for him :ACTION: +@end example +@noindent +the final heading will have the tags @samp{:WORK:}, @samp{:BOSS:}, +@samp{:NOTES:}, and @samp{:ACTION:}. When executing tag searches and +Org-mode finds that a certain headline matches the search criterion, +it will not check any sublevel headline, assuming that these likely +also match, and that the list of matches can become very long. You +can influence inheritance and searching using the variables +@code{org-use-tag-inheritance} and +@code{org-tags-match-list-sublevels}. + +@kindex M-@key{TAB} +Tags can simply be typed into the buffer. After a colon, +@kbd{M-@key{TAB}} offers completion on all tags being used in the +current buffer. There are also special commands for inserting tags, +and for executing searches based on tags. + +@table @kbd +@kindex C-c C-c +@item C-c C-c +@cindex completion, of tags +Enter new tags for the current headline. The minibuffer will prompt +for a list of tags and offer completion with respect to all other tags +used in the current buffer. Several tags, separated by colons, may be +specified at the prompt. After pressing @key{RET}, the tags will +be inserted and aligned to @code{org-tags-column}. When called with a +@kbd{C-u} prefix, align all tags in the current buffer to that column, +just to make things look nice. TAGS are automatically realigned after +promotion, demotion, and TODO state changes (@pxref{TODO basics}). +@kindex C-c \ +@item C-c \ +Create a sparse tree with all headlines matching a tags search. +@kindex C-c a m +@item C-c a m +Create a global list of tag matches from all agenda files. +@xref{Matching headline tags}. +@kindex C-c a M +@item C-c a M +Create a global list of tag matches from all agenda files, but check +only TODO items and force checking subitems (see variable +@code{org-tags-match-list-sublevels}). +@end table + +A tags search string can use Boolean operators @samp{&} for AND and +@samp{|} for OR. @samp{&} binds more strongly than +@samp{|}. Parenthesis are currently no implemented. A tag may also be +preceded by @samp{-}, to select against it, and @samp{+} is syntactic +sugar for positive selection. The AND operator @samp{&} is optional +when @samp{+} or @samp{-} is present. For example, @samp{+WORK-BOSS} +would select all headlines that are tagged @samp{:WORK:}, but discard +those also tagged @samp{:BOSS:}. The search string @samp{WORK|LAPTOP} +selects all lines tagged @samp{:WORK:} or @samp{:LAPTOP:}. The string +@samp{WORK|LAPTOP&NIGHT} requires that the @samp{:LAPTOP:} lines are +also tagged @samp{NIGHT}. + +@node Plain Lists, , Tags, Document Structure +@section Plain Lists +@cindex plain lists +@cindex lists, plain +@cindex lists, ordered +@cindex ordered lists + +Headlines define the structure of the Org-mode file, and also lists +(for example TODO items (@pxref{TODO items}) should be created using +headline levels. However, when taking notes, the plain text is +sometimes easier to read with hand-formatted lists. Org-mode supports +editing such lists, and the HTML exporter (@pxref{Exporting}) does +parse and format them. + +Org-mode knows ordered and unordered lists. Unordered list items start +with @samp{-}, @samp{+}, or @samp{*}@footnote{When using @samp{*} as a +bullet, lines must be indented or they will be seen as top-level +headlines. Also, when you are hiding leading stars to get a clean +outline view, plain list items starting with a star are visually +indistinguishable from true headlines. In short: Even though @samp{*} +is supported, it may be better to not use it for plain list items} as +bullets. Ordered list items start with @samp{1.} or @samp{1)}. Items +belonging to the same list must have the same indentation on the first +line. In particular, if an ordered list reaches number @samp{10.}, also +the 2--digit numbers must be written left-aligned with the other numbers +in the list. Indentation also determines the end of a list item. It +ends before the next line that is indented like the bullet/number, or +less. For example: + +@example +** Lord of the Rings +My favorite scenes are (in this order) +1. Eowyns fight with the witch king + + this was already my favorite scene in the book + + I really like Miranda Otto. +2. The attack of the Rohirrim +3. Peter Jackson being shot by Legolas + - on DVD only + He makes a really funny face when it happens. +@end example + +Org-mode supports these lists by tuning filling and wrapping commands +to correctly deal with them. Furthermore, the following commands act +on items when the cursor is in the first line of an item (the line +with the bullet or number). + +@table @kbd +@kindex @key{TAB} +@item @key{TAB} +Items can be folded just like headline levels if you set the variable +@code{org-cycle-include-plain-lists}. The level of an item is then +given by the indentation of the bullet/number. However, items are +always subordinate to real headlines, the hierarchies remain +completely separated. +@kindex M-@key{RET} +@item M-@key{RET} +Insert new item at current level. With prefix arg, for a new heading. +@kindex M-S-@key{up} +@kindex M-S-@key{down} +@item M-S-@key{up} +@itemx M-S-@key{down} +Move the item including subitems up/down (swap with previous/next item +of same indentation). If the list is ordered, renumbering is +automatic. +@kindex M-S-@key{left} +@kindex M-S-@key{right} +@item M-S-@key{left} +@itemx M-S-@key{right} +Decrease/increase the indentation of the item, including subitems. +Initially, the item tree is selected based on current indentation. +When these commands are executed several times in direct succession, +the initially selected region is used, even if the new indentation +would imply a different hierarchy. To use the new hierarchy, break +the command chain with a cursor motion or so. +@kindex C-c C-c +@item C-c C-c +Renumber the ordered list at the cursor. +@end table + +@node Tables, Hyperlinks, Document Structure, Top +@chapter Tables +@cindex tables +@cindex editing tables + +Org-mode has a very fast and intuitive table editor built-in. +Spreadsheet-like calculations are supported in connection with the +Emacs @file{calc} package. + +@menu +* Built-in table editor:: Simple tables +* Table calculations:: Compute a field from other fields +* orgtbl-mode:: The table editor as minor mode +* table.el:: Complex tables +@end menu + +@node Built-in table editor, Table calculations, Tables, Tables +@section The built-in table editor +@cindex table editor, builtin + +Org-mode makes it easy to format tables in plain ASCII. Any line with +@samp{|} as the first non-white character is considered part of a +table. @samp{|} is also the column separator. A table might look +like this: + +@example +| Name | Phone | Age | +|-------+-------+-----| +| Peter | 1234 | 17 | +| Anna | 4321 | 25 | +@end example + +A table is re-aligned automatically each time you press @key{TAB} or +@key{RET} or @kbd{C-c C-c} inside the table. @key{TAB} also moves to +the next field (@key{RET} to the next row) and creates new table rows +at the end of the table or before horizontal lines. The indentation +of the table is set by the first line. Any line starting with +@samp{|-} is considered as a horizontal separator line and will be +expanded on the next re-align to span the whole table width. So, to +create the above table, you would only type + +@example +|Name|Phone|Age +|- +@end example +@noindent and then press @key{TAB} to align the table and start filling in +fields. + +When typing text into a field, Org-mode treats @key{DEL}, +@key{Backspace}, and all character keys in a special way, so that +inserting and deleting avoids shifting other fields. Also, when +typing @emph{immediately after the cursor was moved into a new field +with @kbd{@key{TAB}}, @kbd{S-@key{TAB}} or @kbd{@key{RET}}}, the +field is automatically made blank. If this behavior is too +unpredictable for you, configure the variables +@code{org-enable-table-editor} and @code{org-table-auto-blank-field}. + +@table @kbd +@tsubheading{Creation and conversion} +@item M-x org-table-create +Creates an empty Org-mode table. However, it is much easier to just +start typing, like @kbd{|Name|Phone|Age @key{RET} |- @key{TAB}} + +@kindex C-c C-c +@item C-c C-c +Convert region to table. Works when the cursor is not in an existing +table, and when there is a region defined. If every line contains at +least one TAB character, the function assumes that the material is tab +separated. If not, lines are split at whitespace into fields. You +can use a prefix argument to indicate how many consecutive spaces are +at least required to indicate a field separator (default: just one). + +@tsubheading{Re-aligning and field motion} +@kindex C-c C-c +@item C-c C-c +Re-align the table without moving the cursor. + +@kindex @key{TAB} +@item @key{TAB} +Re-align the table, move to the next field. Creates a new row if +necessary. + +@kindex S-@key{TAB} +@item S-@key{TAB} +Re-align, move to previous field. + +@kindex @key{RET} +@item @key{RET} +Re-align the table and move down to next row. Creates a new row if +necessary. At the beginning or end of a line, @key{RET} still does +NEWLINE, so it can be used to split a table. + +@tsubheading{Column and row editing} +@kindex M-@key{left} +@kindex M-@key{right} +@item M-@key{left} +@itemx M-@key{right} +Move the current column left/right + +@kindex M-S-@key{left} +@item M-S-@key{left} +Kill the current column. + +@kindex M-S-@key{right} +@item M-S-@key{right} +Insert a new column to the left of the cursor position. + +@kindex M-@key{up} +@kindex M-@key{down} +@item M-@key{up} +@itemx M-@key{down} +Move the current row up/down + +@kindex M-S-@key{up} +@item M-S-@key{up} +Kill the current row or horizontal line. + +@kindex M-S-@key{down} +@item M-S-@key{down} +Insert a new row above (with arg: below) the current row. + +@kindex C-c - +@item C-c - +Insert a horizontal line below current row. With prefix arg, the line +is created above the current line. + +@kindex C-c ^ +@item C-c ^ +Sort the table lines in the region. Point and mark must be in the first +and last line to be included, and must be in the column that should be +used for sorting. The command prompts for numerical versus +alphanumerical sorting. + +@tsubheading{Regions} +@kindex C-c C-x M-w +@item C-c C-x M-w +Copy a rectangular region from a table to a special clipboard. Point +and mark determine edge fields of the rectangle. The process ignores +horizontal separator lines. +@kindex C-c C-x C-w +@item C-c C-x C-w +Copy a rectangular region from a table to a special clipboard, and +blank all fields in the rectangle. So this is the ``cut'' operation. +@kindex C-c C-x C-y +@item C-c C-x C-y +Paste a rectangular region into a table. +The upper right corner ends up in the current field. All involved fields +will be overwritten. If the rectangle does not fit into the present table, +the table is enlarged as needed. The process ignores horizontal separator +lines. +@kindex C-c C-q +@item C-c C-q +Wrap several fields in a column like a paragraph. If there is an active +region, and both point and mark are in the same column, the text in the +column is wrapped to minimum width for the given number of lines. A +prefix ARG may be used to change the number of desired lines. If there +is no region, the current field is split at the cursor position and the +text fragment to the right of the cursor is prepended to the field one +line down. If there is no region, but you specify a prefix ARG, the +current field gets blank, and the content is appended to the field +above. + +@tsubheading{Calculations} +@cindex formula, in tables +@cindex calculations, in tables +@kindex C-c = +@item C-c = +Install a new formula for the current column and replace current field +with the result of the formula. + +@kindex C-u C-c = +@item C-u C-c = +Install a new formula for the current field, which must be a named +field. Evaluate the formula and replace the field content with the +result. + +@kindex C-c ' +@item C-c ' +Edit all formulas associated with the current table in a separate +buffer. + +@kindex C-c * +@item C-c * +Recalculate the current row by applying the stored formulas from left +to right. When called with a @kbd{C-u} prefix, recalculate the +entire table, starting with the first non-header line (i.e. below the +first horizontal separator line). For details, see @ref{Table calculations}. + +@kindex C-# +@item C-# +Rotate the calculation mark in first column through the states +@samp{}, @samp{#}, @samp{*}, @samp{!}, @samp{$}. For the meaning of +these marks see @ref{Advanced features}. When there is an active +region, change all marks in the region. + +@kindex C-c ? +@item C-c ? +Which table column is the cursor in? Displays number >0 in echo +area. + +@cindex region, active +@cindex active region +@cindex transient-mark-mode +@kindex C-c + +@item C-c + +Sum the numbers in the current column, or in the rectangle defined by +the active region. The result is shown in the echo area and can +be inserted with @kbd{C-y}. + +@kindex S-@key{RET} +@item S-@key{RET} +When current field is empty, copy from first non-empty field above. +When not empty, copy current field down to next row and move cursor +along with it. Depending on the variable +@code{org-table-copy-increment}, integer field values will be +incremented during copy. This key is also used by CUA-mode +(@pxref{Interaction}). + +@tsubheading{Miscellaneous} +@kindex C-c | +@item C-c | +Toggle the visibility of vertical lines in tables. The lines are +still there, only made invisible with a text property. Any @samp{|} +added by hand will become invisible on the next align. + +@item M-x org-table-import +Import a file as a table. The table should be TAB- or whitespace +separated. Useful for example to import an Excel table or data from a +database, because these programs generally can write TAB-separated text +files. This command works by inserting the file into the buffer and +then converting the region to a table. Any prefix argument is passed on +to the converter, which uses it to determine the separator. + +@item M-x org-table-export +Export the table as a TAB-separated file. Useful for data exchange with +for example Excel or database programs. + +@end table + +If you don't like the automatic table editor because it gets into your +way in lines which you would like to start with @samp{|}, you can turn +it off with +@lisp +(setq org-enable-table-editor nil) +@end lisp +@noindent The only table command which then still works is +@kbd{C-c C-c} to do a manual re-align. + +@node Table calculations, orgtbl-mode, Built-in table editor, Tables +@section Calculations in tables +@cindex calculations, in tables +@cindex spreadsheet capabilities +@cindex @file{calc} package + +The table editor makes use of the Emacs @file{calc} package to +implement spreadsheet-like capabilities. Org-mode has two levels of +complexity for table calculations. On the basic level, tables do only +horizontal computations, so a field can be computed from other fields +@emph{in the same row}, and Org-mode assumes that there is only one +formula for each column. This is very efficient to work with and +enough for many tasks. On the complex level, columns and individual +fields can be named for easier referencing in formulas, individual +named fields can have their own formula associated with them, and +recalculation can be automated. + +@menu +* Formula syntax:: How to write a formula +* Column formulas:: Formulas valid for all fields in a column +* Advanced features:: Field names, parameters and automatic recalc +* Named-field formulas:: Formulas valid in single fields +* Editing/debugging formulas:: Changing a stored formula +* Appetizer:: Taste the power of calc +@end menu + +@node Formula syntax, Column formulas, Table calculations, Table calculations +@subsection Formula syntax +@cindex formula syntax +@cindex syntax, of formulas + +A formula can be any algebraic expression understood by the Emacs +@file{calc} package. Note that @file{calc} has the slightly +non-standard conversion that @samp{/} has lower precedence than +@samp{*}, so that @samp{a/b*c} is interpreted as @samp{a/(b*c)}. Before +evaluation by @code{calc-eval} (@pxref{Calling Calc from Your Lisp +Programs,calc-eval,Calling calc from Your Lisp Programs,calc,GNU Emacs +Calc Manual}), variable substitution takes place: + +@example + $ @r{refers to the current field} + $3 @r{refers to the field in column 3 of the current row} + $3..$7 @r{a vector of the fields in columns 3-7 of current row} + $P1..$P3 @r{vector of column range, using column names} + &2 @r{second data field above the current, in same column} + &5-2 @r{vector from fifth to second field above current} + &III-II @r{vector of fields between 2nd and 3rd hline above} + &III @r{vector of fields between third hline above and current field} + $name @r{a named field, parameter or constant} +@end example + +@cindex vectors, in table calculations +The range vectors can be directly fed into the calc vector functions +like @samp{vmean} and @samp{vsum}. + +@cindex name, of column or field +@cindex constants, in calculations +@samp{$name} is interpreted as the name of a column, parameter or +constant. Constants are defined globally through the variable +@code{org-table-formula-constants}. If you have the +@file{constants.el} package, it will also be used to resolve +constants, including natural constants like @samp{$h} for Planck's +constant, units like @samp{$km} for kilometers. Column names and +parameters can be specified in special table lines. These are +described below, see @ref{Advanced features}. + +@cindex format specifier +@cindex mode, for @file{calc} +A formula can contain an optional mode string after a semicolon. This +string consists of flags to influence calc's modes@footnote{By +default, Org-mode uses the standard calc modes (precision 12, angular +units degrees, fraction and symbolic modes off). However, the display +format has been changed to @code{(float 5)} to keep tables compact. +The default settings can be configured using the variable +@code{org-calc-default-modes}.} during execution, e.g. @samp{p20} to +switch the internal precision to 20 digits, @samp{n3}, @samp{s3}, +@samp{e2} or @samp{f4} to switch to normal, scientific, engineering, +or fix display format, respectively, and @samp{D}, @samp{R}, @samp{F}, +and @samp{S} to turn on degrees, radians, fraction and symbolic modes, +respectively. In addition, you may provide a @code{printf} format +specifier to reformat the final result. A few examples: +@example + $1+$2 @r{Sum of first and second field} + $1+$2;%.2f @r{Same, format result to two decimals} + exp($2)+exp($1) @r{Math functions can be used} + $;%.1f @r{Reformat current cell to 1 decimal} + ($3-32)*5/9 @r{Degrees F -> C conversion} + $c/$1/$cm @r{Hz -> cm conversion, using @file{constants.el}} + tan($1);Dp3s1 @r{Compute in degrees, precision 3, display SCI 1} + sin($1);Dp3%.1e @r{Same, but use printf specifier for display} + vmean($2..$7) @r{Compute column range mean, using vector function} + vsum(&III) @r{Sum numbers from 3rd hline above to here} + taylor($3,x=7,2) @r{taylor series of $3, at x=7, second degree} +@end example + +@node Column formulas, Advanced features, Formula syntax, Table calculations +@subsection Column formulas +@cindex column formula +@cindex formula, for table column + +To apply a formula to a field, type it directly into the field, +preceded by an equal sign, like @samp{=$1+$2}. When you press +@key{TAB} or @key{RET} or @kbd{C-c C-c} with the cursor still in the +field, the formula will be stored as the formula for the current +column, evaluated and the current field replaced with the result. If +the field contains only @samp{=}, the previously stored formula for +this column is used. + +For each column, Org-mode will remember the most recently used +formula. The information is stored in a special line starting with +@samp{#+TBLFM} directly below the table. When adding/deleting/moving +columns with the appropriate commands, the stored equations will be +modified accordingly. When a column used in a calculation is removed, +references to this column become invalid and will cause an error upon +applying the equation. + +Instead of typing an equation into the field, you may also use the +command @kbd{C-c =}. It prompts for a formula (with default taken +from the @samp{#+TBLFM:} line) and applies it to the current field. A +numerical prefix (e.g. @kbd{C-5 C-c =}) will apply it to that many +subsequent fields in the current column. + +@cindex recomputing table fields +To recompute all the fields in a line, use the command @kbd{C-c *}. +It re-applies all stored equations to the current row, from left to +right. With a @kbd{C-u} prefix, this will be done to every line in +the table, so use this command it you want to make sure the entire +table is up-to-date. @kbd{C-u C-c C-c} is another way to update the +entire table. Global updating does not touch the line(s) above the +first horizontal separator line, assuming that this is the table +header. + +@node Advanced features, Named-field formulas, Column formulas, Table calculations +@subsection Advanced features + +If you want want the recalculation of fields to happen automatically, +or if you want to be able to assign a formula to an individual field +(instead of an entire column) you need to reserve the first column of +the table for special marking characters. Here is an example of a +table that collects exam results of students and makes use of these +features: +@example +@group +|---+---------+--------+--------+--------+-------+------| +| | Student | Prob 1 | Prob 2 | Prob 3 | Total | Note | +|---+---------+--------+--------+--------+-------+------| +| ! | | P1 | P2 | P3 | Tot | | +| # | Maximum | 10 | 15 | 25 | 50 | 10.0 | +| ^ | | m1 | m2 | m3 | mt | | +|---+---------+--------+--------+--------+-------+------| +| # | Peter | 10 | 8 | 23 | 41 | 8.2 | +| # | Sara | 6 | 14 | 19 | 39 | 7.8 | +| # | Sam | 2 | 4 | 3 | 9 | 1.8 | +|---+---------+--------+--------+--------+-------+------| +| | Average | | | | 29.7 | | +| ^ | | | | | at | | +| $ | max=50 | | | | | | +|---+---------+--------+--------+--------+-------+------| +#+TBLFM: $6=vsum($P1..$P3)::$7=10*$Tot/$max;%.1f::$at=vmean(&II);%.1f +@end group +@end example + +@noindent @b{Important}: Please note that for these special tables, +recalculating the table with @kbd{C-u C-c *} does only affect rows +which are marked @samp{#} or @samp{*}, and named fields. The column +formulas are not applied in rows with empty first field. + +@cindex marking characters, tables +The marking characters have the following meaning: +@table @samp +@item ! +The fields in this line define names for the columns, so that you may +refer to a column as @samp{$Tot} instead of @samp{$6}. +@item ^ +This row defines names for the fields @emph{above} the row. With such +a definition, any formula in the table may use @samp{$m1} to refer to +the value @samp{10}. Also, named fields can have their own formula +associated with them. +@item _ +Similar to @samp{^}, but defines names for the fields in the row +@emph{below}. +@item $ +Fields in this row can define @emph{parameters} for formulas. For +example, if a field in a @samp{$} row contains @samp{max=50}, then +formulas in this table can refer to the value 50 using @samp{$max}. +Parameters work exactly like constants, only that they can be defined on +a per-table basis. Changing a parameter and then recalculating the +table can be useful. +@item # +Fields in this row are automatically recalculated when pressing +@key{TAB} or @key{RET} or @kbd{S-@key{TAB}} in this row. Also, this row +is selected for a global recalculation with @kbd{C-u C-c *}. Unmarked +lines will be left alone by this command. +@item * +Selects this line for global recalculation with @kbd{C-u C-c *}, but +not for automatic recalculation. Use this when automatic +recalculation slows down editing too much. +@item +Unmarked lines are exempted from recalculation with @kbd{C-u C-c *}. +All lines that should be recalculated should be marked with @samp{#} +or @samp{*}. +@end table + +@node Named-field formulas, Editing/debugging formulas, Advanced features, Table calculations +@subsection Named-field formulas +@cindex named field formula +@cindex formula, for named table field + +A named field can have its own formula associated with it. In the +example above, this is used for the @samp{at} field that contains +the average result of the students. To enter a formula for a named +field, just type it onto the buffer, preceded by @samp{:=}. Or use +@kbd{C-u C-c =}. This equation will be stored below the table like +@samp{$name=...}. Any recalculation in the table (even if only +requested for the current line) will also update all named field +formulas. + +@node Editing/debugging formulas, Appetizer, Named-field formulas, Table calculations +@subsection Editing and debugging formulas +@cindex formula editing +@cindex editing, of table formulas + +To edit a column or field formula, you can use the commands @kbd{C-c +=} and @kbd{C-u C-c =}, respectively. The currently active expression +is then presented as default in the minibuffer, were it may be edited. + +Note that making a table field blank does not remove the formula +associated with the field - during the next recalculation the field +will be filled again. To remove a formula from a field, you have to +give an empty reply when prompted for the formula, or to edit the +@samp{#+TBLFM} line. + +@kindex C-c C-c +You may edit the @samp{#+TBLFM} directly and re-apply +the changed equations with @kbd{C-c C-c} in that line, or with the +normal recalculation commands in the table. + +@kindex C-c ' +@kindex C-c C-c +@kindex C-c C-q +@kindex C-c ? +In particular for large tables with many formulas, it is convenient to +use the command @kbd{C-c '} to edit the formulas of the current table +in a separate buffer. That buffer will show the formulas one per +line, and you are free to edit, add and remove formulas. Press +@kbd{C-c ?} on a @samp{$...} expression to get information about its +interpretation. Exiting the buffer with @kbd{C-c C-c} only stores the +modified formulas below the table. Exiting with @kbd{C-u C-c C-c} +also applies them to the entire table. @kbd{C-c C-q} exits without +installing the changes. + +When the evaluation of a formula leads to an error, the field content +becomes the string @samp{#ERROR}. If you would like see what is going +on during variable substitution and calculation in order to find a +bug, turn on formula debugging in the menu and repeat the calculation +by pressing, for example by pressing @kbd{C-c = @key{RET}} in a field. +Detailed information will be displayed. + +@node Appetizer, , Editing/debugging formulas, Table calculations +@subsection Appetizer + +Finally, just to wet your appetite on what can be done with the fantastic +@file{calc} package, here is a table that computes the Taylor series +for a couple of functions (homework: try that with Excel :-) + +@example +@group +|---+-------------+---+-----+--------------------------------------| +| | Func | n | x | Result | +|---+-------------+---+-----+--------------------------------------| +| # | exp(x) | 1 | x | 1 + x | +| # | exp(x) | 2 | x | 1 + x + x^2 / 2 | +| # | exp(x) | 3 | x | 1 + x + x^2 / 2 + x^3 / 6 | +| # | x^2+sqrt(x) | 2 | x=0 | x*(0.5 / 0) + x^2 (2 - 0.25 / 0) / 2 | +| # | x^2+sqrt(x) | 2 | x=1 | 2 + 2.5 x - 2.5 + 0.875 (x - 1)^2 | +| * | tan(x) | 3 | x | 0.0175 x + 1.77e-6 x^3 | +|---+-------------+---+-----+--------------------------------------| +#+TBLFM: $5=taylor($2,$4,$3);n3 +@end group +@end example + +@node orgtbl-mode, table.el, Table calculations, Tables +@section The Orgtbl minor mode +@cindex orgtbl-mode +@cindex minor mode for tables + +If you like the intuitive way the Org-mode table editor works, you +might want to use it also in other modes like text-mode or mail-mode. +The minor mode Orgtbl-mode makes this possible. You can always toggle +the mode with @kbd{M-x orgtbl-mode}. To turn it on by default, for +example in mail mode, use +@lisp +(add-hook 'mail-mode-hook 'turn-on-orgtbl) +@end lisp + +@node table.el, , orgtbl-mode, Tables +@section The @file{table.el} package +@kindex C-c C-c +@cindex table editor, @file{table.el} +@cindex @file{table.el} + +Complex ASCII tables with automatic line wrapping, column- and +row-spanning, and alignment can be created using the Emacs table +package by Takaaki Ota (@uref{http://sourceforge.net/projects/table}, +and also part of Emacs 22). +When @key{TAB} or @kbd{C-c C-c} is pressed in such a table, Org-mode +will call @command{table-recognize-table} and move the cursor into the +table. Inside a table, the keymap of Org-mode is inactive. In order +to execute Org-mode-related commands, leave the table. + +@table @kbd +@kindex C-c C-c +@item C-c C-c +Recognize @file{table.el} table. Works when the cursor is in a +table.el table. + +@kindex C-c ~ +@item C-c ~ +Insert a table.el table. If there is already a table at point, this +command converts it between the table.el format and the Org-mode +format. See the documentation string of the command +@code{org-convert-table} for the restrictions under which this is +possible. +@end table + +@node Hyperlinks, TODO items, Tables, Top +@chapter Hyperlinks +@cindex hyperlinks + +Just like HMTL, Org-mode provides links inside a file, and external +links to other files, Usenet articles, emails and much more. + +@menu +* Internal Links:: Links to other places in the current file +* External Links:: URL-like links to the world +* Managing links:: Creating, inserting and following +* Search Options:: Linking to a specific location +* Remember:: Org-trees store quick notes +@end menu + +@node Internal Links, External Links, Hyperlinks, Hyperlinks +@section Internal Links +@cindex internal links +@cindex links, internal +@cindex CamelCase links + +Strings inside double brackets like @samp{[[My Target]]} are links +that lead to a text search in the current file. The link can be +followed with @kbd{C-c C-o} or with a mouse click (@pxref{Managing +links}). The preferred match for such a link is a dedicated target: +The same string in double angular brackets. Targets may be located +anywhere, often it is convenient to put them into a comment line, for +example +@example +# <> +@end example + +If no dedicated target exists, Org-mode will search for the words in +the link, in the above example for @samp{my target}. Links starting +with a star like @samp{*My Target} restrict the search to headlines. +When searching, Org-mode will first try an exact match, but then move +on to more and more lenient searches. For example, the link +@samp{[[*My Targets]]} will find any of the following +@example +** My targets +** TODO my targets are bright +** my 20 targets are +@end example +It is therefore often not necessary to set a dedicated target. To +insert a link targeting a headline, in-buffer completion can be used. +Just type a star followed by a few optional letters into the buffer +and press @kbd{M-@key{TAB}}. All headlines in the current buffer will +be offered as completions. @xref{Managing links}, for more commands +creating links. + +Following a link pushes a mark onto Org-mode's own mark ring. You can +return to the previous position with @kbd{C-c &}. Using this command +several times in direct succession goes back to positions recorded +earlier. + +@menu +* Radio targets:: Make targets trigger links in plain text. +* CamelCase links:: Activating CamelCase words as links +@end menu + +@node Radio targets, CamelCase links, Internal Links, Internal Links +@subsection Radio targets + +You can configure Org-mode to link any occurrences of certain target +names in normal text. So without explicitly creating a link, the text +connects to the target radioing its position. Radio targets are +enclosed by triple angular brackets. For example, a target +@samp{<<>>} causes each occurrence of @samp{my target} in +normal text to become activated as a link. The Org-mode file is +scanned automatically for radio targets only when the file is first +loaded into Emacs. To update the target list during editing, press +@kbd{C-c C-c} with the cursor on or at a target. + +@node CamelCase links, , Radio targets, Internal Links +@subsection CamelCase words as links +@cindex completion, of CamelCase links +@cindex CamelCase links, completion of + +As an alternative to @samp{[[...]]} links, Org-mode also supports +CamelCase words as links. This feature is not turned on by default +because of the occasional inconsistencies this system suffers from. +To activate CamelCase words as links, and to make headline completion +offer CamelCase version of headlines, the following customization is +needed: +@lisp +(setq org-activate-camels t + org-file-link-context-use-camel-case t) +@end lisp + +@node External Links, Managing links, Internal Links, Hyperlinks +@section External Links +@cindex links, external +@cindex external links +@cindex links, external +@cindex GNUS links +@cindex BBDB links +@cindex URL links +@cindex file links +@cindex VM links +@cindex RMAIL links +@cindex WANDERLUST links +@cindex MH-E links +@cindex USENET links +@cindex SHELL links + +Org-mode supports links to files, websites, Usenet and email messages; +and BBDB database entries. Links are just plain-text URL-like +locators, optionally enclosed by angular brackets. The following list +shows examples for each link type. + +@example + @r{on the web} + @r{file, absolute path} + @r{file, relative path} + @r{Usenet link} + @r{Mail link} + @r{VM folder link} + @r{VM message link} + @r{VM on remote machine} + @r{WANDERLUST folder link} + @r{WANDERLUST message link} + @r{MH-E folder link} + @r{MH-E message link} + @r{RMAIL folder link} + @r{RMAIL message link} + @r{GNUS group link} + @r{GNUS article link} + @r{BBDB link} +@footnote{Note that @samp{<} and @samp{>} cannot be part of a link, and therefore of a shell command. If you need redirection, use @@@{ and @@@} instead.} @r{A shell command} +@end example + +A link may contain space characters and is terminated by @samp{>} or by +the end of a line. In tables, the end of a table field also terminates +a link. Angle brackets around a link are not required, but are +recommended to avoid problems with punctuation and other text following +the link. See also the variable @code{org-allow-space-in-links}. + + +@node Managing links, Search Options, External Links, Hyperlinks +@section Managing links + +Org-mode provides methods to create a link in the correct syntax, to +insert it into an org-mode file, and to follow the link. + +@table @kbd +@kindex C-c l +@cindex storing links +@item C-c l +Store a link to the current location. This is a @emph{global} command +which can be used in any buffer to create a link. The link will be +stored for later insertion into an Org-mode buffer (see below). For +VM, RMAIL, WANDERLUST, GNUS and BBDB buffers, the link will point to +the current article/entry. For W3 and W3M buffer, the link goes to +the current URL. For Org-mode files, the current headline is +targeted. For any other files, the link will point to the file, with +a search string (@pxref{Search Options}) pointing to the +contents of the current line. If there is an active region, the +selected words will form the basis of the search string. The key +binding @kbd{C-c l} is only a suggestion - see @ref{Installation and +Activation}. + +@kindex C-c C-l +@cindex link completion +@cindex file name completion +@cindex completion, of links +@cindex completion, of file names +@cindex inserting links +@item C-c C-l +Insert a link. This prompts for a link to be inserted into the +buffer. You can just type a link, using one of the link type prefixes +mentioned in the examples above. Through completion, all links stored +during the current session can be accessed. When called with prefix +arg, you can use file name completion to enter a file link. The link +will be formatted as given in the variable @code{org-link-format} and +inserted into the buffer. Note that you don't have to use this +command to insert a link. Links in Org-mode are plain text, and you +can type or paste them straight into the buffer. + +@cindex following links +@kindex C-c C-o +@item C-c C-o +Open link at point. This will launch a web browser for URLs (using +@command{browse-url-at-point}), run vm/gnus/bbdb for the corresponding +links, and execute the command in a shell link. When the cursor is on +a CamelCase link, this commands runs the corresponding search. When +the cursor is on a TAGS list in a headline, it creates the +corresponding TAGS view. Furthermore, it will visit text files in +@samp{file:} links with Emacs and select a suitable application for +non-text files. Classification of files is based on file extension +only. See option @code{org-file-apps}. If there is no link at point, +the current subtree will be searched for one. If you want to override +the default application and visit the file with Emacs, use a @kbd{C-u} +prefix. If the cursor is on a time stamp, compiles the agenda for +that date. + +@strong{IMPORTANT}: Be careful not to use any dangerous commands in a +shell link. + +@kindex mouse-2 +@kindex mouse-1 +@item mouse-2 +@itemx mouse-1 +On links, @kbd{mouse-2} will open the link just like @kbd{C-c C-o} +would. Under Emacs 22, also @kbd{mouse-1} will follow a link. + +@kindex mouse-3 +@item mouse-3 +Like @kbd{mouse-2}, but force file links to be opened with Emacs. + +@cindex mark ring +@kindex C-c % +@item C-c % +Push the current position onto the mark ring, to be able to return +easily. Commands following an internal link do this automatically. + +@cindex links, returning to +@kindex C-c & +@item C-c & +Jump back to a recorded position. A position is recorded by the +commands following internal links, and by @kbd{C-c %}. Using this +command several times in direct succession moves through a ring of +previously recorded positions. +@end table + + +@node Search Options, Remember, Managing links, Hyperlinks +@section Search options in file links +@cindex search option in file links +@cindex file links, searching + +File links can contain additional information to make Emacs jump to a +particular location in the file when following a link. This can be a +line number or a search option after a double@footnote{For backward +compatibility, line numbers can also follow a single colon.} colon. +For example: +@example + + + + +@end example +@noindent Here is what these options do. + +@table @code +@item 255 +Jump to line 255. +@item My Target +Search for a link target @samp{<>}, or do a text search for +@samp{my target}, similar to the search in internal links, see +@ref{Internal Links}. +@item *My Target +In an Org-mode file, restrict search to headlines. +@item /regexp/ +Do a regular expression search for @code{regexp}. This uses the Emacs +command @code{occur} to list all matches in a separate window. If the +target file is in Org-mode, @code{org-occur} is used to create a +sparse tree with the matches. +@c If the target file is a directory, +@c @code{grep} will be used to search all files in the directory. +@end table + +As a degenerate case, a file link with an empty file name can be used +to search the current file. For example, @code{} does +a search for @samp{find me} in the current file, just like +@samp{[[find me]]} would. + +@node Remember, , Search Options, Hyperlinks +@section Remember +@cindex @file{remember.el} + +Another way to create org entries with links to other files is through +the @emph{Remember} package by John Wiegley. @emph{Remember} lets you +store quick notes with little interruption of your work flow. See +@uref{http://www.emacswiki.org/cgi-bin/wiki/RememberMode} for more +information. The notes produced by @emph{Remember} can be stored in +different ways, and Org-mode files are a good target. Org-mode allows +to file away notes either to a default file, or directly to the +correct location in your Org-mode outline tree. The following +customization@footnote{The three autoload forms are only necessary if +@file{org.el} is not part of the Emacs distribution or an XEmacs +package.} will tell @emph{Remember} to use org files as target, and to +create annotations compatible with Org-mode links. + +@example +(autoload 'org-remember-annotation "org") +(autoload 'org-remember-apply-template "org") +(autoload 'org-remember-handler "org") +(setq org-directory "~/path/to/my/orgfiles/") +(setq org-default-notes-file "~/.notes") +(setq remember-annotation-functions '(org-remember-annotation)) +(setq remember-handler-functions '(org-remember-handler)) +(add-hook 'remember-mode-hook 'org-remember-apply-template) +@end example + +@cindex templates, for remember +In combination with Org-mode, you can use templates to generate +different types of remember notes. For example, if you would like to +use one template to create general TODO entries, and another one for +journal entries, you could use: + +@example +(setq org-remember-templates + '((?t "* TODO %?\n %i\n %a" "~/org/TODO.org") + (?j "* %U %?\n\n %i\n %a" "~/org/JOURNAL.org"))) +@end example +@noindent In these entries, the character specifies how to select the +template, the first string specifies the template, and the second string +specifies a default file (overruling @code{org-default-notes-file}) as a +target for this note. + +When you call @kbd{M-x remember} to remember something, org will prompt +for a key to select the template and then prepare the buffer like +@example +* TODO + +@end example +@noindent or +@example +* [2006-03-21 Tue 15:37] + + +@end example + +@noindent See the variable @code{org-remember-templates} for more details. + +When you are finished composing a note with remember, you have to press +@kbd{C-c C-c} to exit remember-mode and to file the note away. The +handler first prompts for a target file - if you press @key{RET}, the +value of @code{org-default-notes-file} is used. Then the command offers +the headings tree of the selected file. You can either immediately +press @key{RET} to get the note appended to the file. Or you can use +vertical cursor motion (@key{up} and @key{down}) and visibility cycling +(@key{TAB}) to find a better place. Pressing @key{RET} or @key{left} or +@key{right} leads to the following result. + +@multitable @columnfractions 0.2 0.1 0.7 +@item @b{Cursor position} @tab @b{Key} @tab @b{Note gets inserted} +@item buffer-start @tab @key{RET} @tab as level 2 heading at end of file +@item on headline @tab @key{RET} @tab as sublevel of the heading at cursor +@item @tab @key{left} @tab as same level, before current heading +@item @tab @key{right} @tab as same level, after current heading +@item not on headline @tab @key{RET} + @tab at cursor position, level taken from context. + Or use prefix arg to specify level manually. +@end multitable + +So a fast way to store the note is to press @kbd{C-c C-c @key{RET} +@key{RET}} to append it to the default file. Even shorter would be +@kbd{C-u C-c C-c}, which does the same without even showing the tree. +But with little extra effort, you can push it directly to the correct +location. + +Before inserting the text into a tree, the function ensures that the +text has a headline, i.e. a first line that starts with a @samp{*}. +If not, a headline is constructed from the current date and some +additional data. If the variable @code{org-adapt-indentation} is +non-nil, the entire text is also indented so that it starts in the +same column as the headline (after the asterisks). + + +@node TODO items, Timestamps, Hyperlinks, Top +@chapter TODO items +@cindex TODO items + +Org-mode does not maintain TODO lists as a separate document. TODO +items are an integral part of the notes file, because TODO items +usually come up while taking notes! With Org-mode, you simply mark +any entry in a tree as being a TODO item. In this way, the +information is not duplicated, and the entire context from which the +item emerged is always present when you check. + +Of course, this technique causes TODO items to be scattered throughout +your file. Org-mode provides methods to give you an overview over all +things you have to do. + +@menu +* TODO basics:: Marking and displaying TODO entries +* Progress Logging:: Document your productivity +* TODO extensions:: Workflow and assignments +* Priorities:: Some things are more important than others +@end menu + +@node TODO basics, Progress Logging, TODO items, TODO items +@section Basic TODO functionality + +Any headline can become a TODO item by starting it with the word TODO, +for example + +@example +*** TODO Write letter to Sam Fortune +@end example + +@noindent +The most important commands to work with TODO entries are: + +@table @kbd +@kindex C-c C-t +@cindex cycling, of TODO states +@item C-c C-t +Rotate the TODO state of the current item between +@example +,-> (unmarked) -> TODO -> DONE --. +'--------------------------------' +@end example +The same rotation can also be done ``remotely'' from the timeline and +agenda buffers with the @kbd{t} command key (@pxref{Agenda commands}). +@kindex C-c C-v +@cindex sparse tree, for TODO +@item C-c C-v +View TODO items in a @emph{sparse tree} (@pxref{Sparse trees}). Folds +the entire buffer, but shows all TODO items and the headings hierarchy +above them. With prefix arg, show also the DONE entries. With +numerical prefix N, show the tree for the Nth keyword in the variable +@code{org-todo-keywords}. +@kindex C-c a t +@item C-c a t +Show the global TODO list. This collects the TODO items from all +agenda files (@pxref{Agenda Views}) into a single buffer. The buffer is in +@code{agenda-mode}, so there are commands to examine and manipulate +the TODO entries directly from that buffer (@pxref{Agenda commands}). +@xref{Global TODO list}, for more information. +@item @code{org-agenda-include-all-todo} +If you would like to have all your TODO items listed as part of your +agenda, customize the variable @code{org-agenda-include-all-todo}. +@end table + +@node Progress Logging, TODO extensions, TODO basics, TODO items +@section Progress Logging +@cindex progress logging +@cindex logging, of progress +If you want to keep track of @emph{when} a certain TODO item was +finished, turn on logging with +@lisp +(setq org-log-done t) +@end lisp +@noindent +Then each time you turn a TODO entry into DONE using either @kbd{C-c +C-t} in the Org-mode buffer or @kbd{t} in the agenda buffer, a line +@samp{CLOSED: [timestamp]} will be inserted just after the headline. +If you turn the entry back into a TODO item again through further +state cycling, that line will be removed again. In the timeline +(@pxref{Timeline}) and in the agenda (@pxref{Weekly/Daily Agenda}), +you can then use the @kbd{L} key to display the TODO items closed on +each day, giving you an overview of what has been done on a day. + +@node TODO extensions, Priorities, Progress Logging, TODO items +@section Extended use of TODO keywords +@cindex extended TODO keywords + +The default implementation of TODO entries is just two states: TODO +and DONE. You can, however, use the TODO feature for more +complicated things by configuring the variables +@code{org-todo-keywords} and @code{org-todo-interpretation}. Using +special setup, you can even use TODO keywords in different ways in +different org files. + +@menu +* Workflow states:: From TODO to DONE in steps +* TODO types:: I do this, Fred the rest +* Per file keywords:: Different files, different requirements +@end menu + +@node Workflow states, TODO types, TODO extensions, TODO extensions +@subsection TODO keywords as workflow states +@cindex TODO workflow +@cindex workflow states as TODO keywords + +You can use TODO keywords to indicate different states in the process +of working on an item, for example + +@lisp +(setq org-todo-keywords '("TODO" "FEEDBACK" "VERIFY" "DONE") + org-todo-interpretation 'sequence) +@end lisp + +@cindex completion, of TODO keywords +Changing these variables becomes only effective in a new Emacs session. +With this setup, the command @kbd{C-c C-t} will cycle an entry from +TODO to FEEDBACK, then to VERIFY, and finally to DONE. You may also +use a prefix argument to quickly select a specific state. For example +@kbd{C-3 C-c C-t} will change the state immediately to VERIFY. +If you define many keywords, you can use in-buffer completion (see +@ref{Completion}) to insert these words into the buffer. + +@node TODO types, Per file keywords, Workflow states, TODO extensions +@subsection TODO keywords as types +@cindex TODO types +@cindex names as TODO keywords +@cindex types as TODO keywords + +The second possibility is to use TODO keywords to indicate different +types of action items. For example, you might want to indicate that +items are for ``work'' or ``home''. If you are into David Allen's +@emph{Getting Things DONE}, you might want to use todo types +@samp{NEXTACTION}, @samp{WAITING}, @samp{MAYBE}. Or, when you work +with several people on a single project, you might want to assign +action items directly to persons, by using their names as TODO +keywords. This would be set up like this: + +@lisp +(setq org-todo-keywords '("Fred" "Sara" "Lucy" "Mike" "DONE") + org-todo-interpretation 'type) +@end lisp + +In this case, different keywords do not indicate a sequence, but +rather different types. So it is normally not useful to change from +one type to another. Therefore, in this case the behavior of the +command @kbd{C-c C-t} is changed slightly@footnote{This is also true +for the @kbd{t} command in the timeline and agenda buffers.}. When +used several times in succession, it will still cycle through all +names. But when you return to the item after some time and execute +@kbd{C-c C-t} again, it will switch from each name directly to DONE. +Use prefix arguments or completion to quickly select a specific name. +You can also review the items of a specific TODO type in a sparse tree +by using a numeric prefix to @kbd{C-c C-v}. For example, to see all +things Lucy has to do, you would use @kbd{C-3 C-c C-v}. To collect +collect Lucy's items from all agenda files into a single buffer, you +would use the prefix arg as well when creating the global todo list: +@kbd{C-3 C-c t}. + +@node Per file keywords, , TODO types, TODO extensions +@subsection Setting up TODO keywords for individual files +@cindex keyword options +@cindex per file keywords + +It can be very useful to use different aspects of the TODO mechanism +in different files, which is not possible with the global settings +described above. For file-local settings, you need to add special +lines to the file which set the keywords and interpretation for that +file only. For example, to set one of the two examples discussed +above, you need one of the following lines, starting in column zero +anywhere in the file: + +@example +#+SEQ_TODO: TODO FEEDBACK VERIFY DONE +#+TYP_TODO: Fred Sara Lucy Mike DONE +@end example + +@cindex Completion, of option keywords +@kindex M-@key{TAB} +@noindent To make sure you are using the correct keyword, type +@samp{#+} into the buffer and then use @kbd{M-@key{TAB}} completion. + +@cindex DONE, final TODO keyword +Remember that the last keyword must always mean that the item is DONE +(you may use a different word, though). Also note that in each file, +only one of the two aspects of TODO keywords can be used. After +changing one of these lines, use @kbd{C-c C-c} with the cursor still +in the line to make the changes known to Org-mode@footnote{Org-mode +parses these lines only when Org-mode is activated after visiting a +file. @kbd{C-c C-c} with the cursor in a line starting with @samp{#+} +is simply restarting Org-mode, making sure that these changes will be +respected.}. + +If you want to use very many keywords, for example when working with a +large group of people, you may split the names over several lines: + +@example +#+TYP_TODO: Fred Sara Lucy Mike +#+TYP_TODO: Luis George Jules Jessica +#+TYP_TODO: Kim Arnold Peter +#+TYP_TODO: DONE +@end example + +@node Priorities, , TODO extensions, TODO items +@section Priorities +@cindex priorities + +If you use Org-mode extensively to organize your work, you may end up +with a number of TODO entries so large that you'd like to prioritize +them. This can be done by placing a @emph{priority cookie} into the +headline, like this + +@example +*** TODO [#A] Write letter to Sam Fortune +@end example + +@noindent +With its standard setup, Org-mode supports priorities @samp{A}, +@samp{B}, and @samp{C}. @samp{A} is the highest priority. An entry +without a cookie is treated as priority @samp{B}. Priorities make a +difference only in the agenda (@pxref{Weekly/Daily Agenda}). + +@table @kbd +@kindex @kbd{C-c ,} +@item @kbd{C-c ,} +Set the priority of the current item. The command prompts for a +priority character @samp{A}, @samp{B} or @samp{C}. When you press +@key{SPC} instead, the priority cookie is removed from the headline. +The priorities can also be changed ``remotely'' from the timeline and +agenda buffer with the @kbd{,} command (@pxref{Agenda commands}). + +@kindex S-@key{up} +@kindex S-@key{down} +@item S-@key{up} +@itemx S-@key{down} +Increase/decrease priority of current item. Note that these keys are +also used to modify time stamps (@pxref{Creating timestamps}). +Furthermore, these keys are also used by CUA-mode +(@pxref{Interaction}). +@end table + +@node Timestamps, Agenda Views, TODO items, Top +@chapter Timestamps + +Items can be labeled with timestamps to make them useful for project +planning. + +@menu +* Time stamps:: Assigning a time to a tree entry +* Creating timestamps:: Commands which insert timestamps +@end menu + + +@node Time stamps, Creating timestamps, Timestamps, Timestamps +@section Time stamps, deadlines and scheduling +@cindex time stamps +@cindex ranges, time +@cindex date stamps +@cindex deadlines +@cindex scheduling + +A time stamp is a specification of a date (possibly with time) in a +special format, either @samp{<2003-09-16 Tue>} or @samp{<2003-09-16 +Tue 09:39>}. A time stamp can appear anywhere in the headline or body +of an org-tree entry. Its presence allows to show entries on specific +dates in the agenda (@pxref{Weekly/Daily Agenda}). We distinguish: + +@table @var +@cindex timestamp +@item TIMESTAMP +A simple time stamp just assigns a date/time to an item. In the +timeline and agenda displays, the headline of the entry will be shown +exactly on that date. + +@item TIMERANGE +@cindex timerange +Two time stamps connected by @samp{--} denote a time range. The +headline will be shown on the first and last day of the range, and on +any dates that are displayed and fall in the range. Here is an +example: + +@example +** Meeting in Amsterdam + <2004-08-23 Mon>--<2004-08-26 Thu> +@end example + +@item DEADLINE +@cindex DEADLINE keyword +If a time stamp is preceded by the word @samp{DEADLINE:}, the task +(most likely a TODO item) is supposed to be finished on that date, and +it will be listed then. In addition, the compilation for @emph{today} +will carry a warning about the approaching or missed deadline, +starting @code{org-deadline-warning-days} before the due date, and +continuing until the entry is marked DONE. An example: + +@example +*** TODO write article about the Earth for the Guide + The editor in charge is + DEADLINE: <2004-02-29 Sun> +@end example + +@item SCHEDULED +@cindex SCHEDULED keyword +If a time stamp is preceded by the word @samp{SCHEDULED:}, it means +you are planning to start working on that task on the given date. The +headline will be listed under the given date. In addition, a reminder +that the scheduled date has passed will be present in the compilation +for @emph{today}, until the entry is marked DONE. I.e., the +task will automatically be forwarded. +@end table + +@node Creating timestamps, , Time stamps, Timestamps +@section Creating timestamps +@cindex creating timestamps +@cindex timestamps, creating + +For Org-mode to recognize time stamps, they need to be in the specific +format. All commands listed below produce time stamps in the correct +format. + +@table @kbd +@kindex C-c . +@item C-c . +Prompt for a date and insert a corresponding time stamp. When the +cursor is at a previously used time stamp, it is updated to NOW. When +this command is used twice in succession, a time range is inserted. + +@kindex C-u C-c . +@item C-u C-c . +Like @kbd{C-c .}, but use the alternative format which contains date +and time. The default time can be rounded to to multiples of 5 minutes, +see the option @code{org-time-stamp-rounding-minutes}. + +@kindex C-c ! +@item C-c ! +Like @kbd{C-c .}, but insert an inactive time stamp not triggering the +agenda. + +@kindex C-c < +@item C-c < +Insert a time stamp corresponding to the cursor date in the Calendar. + +@kindex C-c > +@item C-c > +Access the Emacs calendar for the current date. If there is a +timestamp in the current line, goto the corresponding date +instead. + +@kindex C-c C-o +@item C-c C-o +Access the agenda for the date given by the time stamp at point +(@pxref{Weekly/Daily Agenda}). + +@kindex C-c C-d +@item C-c C-d +Insert @samp{DEADLINE} keyword along with a stamp. +@kindex C-c C-w +@cindex sparse tree, for deadlines +@item C-c C-w +Create a sparse tree with all deadlines that are either past-due, or +which will become due within @code{org-deadline-warning-days}. +With @kbd{C-u} prefix, show all deadlines in the file. With a numeric +prefix, check that many days. For example, @kbd{C-1 C-c C-w} shows +all deadlines due tomorrow. + +@kindex C-c C-s +@item C-c C-s +Insert @samp{SCHEDULED} keyword along with a stamp. + +@kindex S-@key{left} +@kindex S-@key{right} +@item S-@key{left} +@itemx S-@key{right} +Change date at cursor by one day. These key bindings conflict with +CUA-mode (@pxref{Interaction}). + +@kindex S-@key{up} +@kindex S-@key{down} +@item S-@key{up} +@itemx S-@key{down} +Change the item under the cursor in a timestamp. The cursor can be on +a year, month, day, hour or minute. Note that if the cursor is not at +a time stamp, these same keys modify the priority of an item. +(@pxref{Priorities}). The key bindings also conflict with CUA-mode +(@pxref{Interaction}). + + +@kindex C-c C-y +@cindex evaluate time range +@item C-c C-y +Evaluate a time range by computing the difference between start and +end. With prefix arg, insert result after the time range (in a table: +into the following column). +@end table + +@cindex date, reading in minibuffer +@cindex time, reading in minibuffer +@cindex calendar, for selecting date +When Org-mode prompts for a date/time, the function reading your input +will replace anything you choose not to specify with the current date +and time. For details, see the documentation string of +@command{org-read-date}. Also, a calender will pop up to allow +selecting a date. The calendar can be fully controlled from the +minibuffer, and a date can be selected with the following commands: + +@table @kbd +@kindex < +@item < +Scroll calendar backwards by one month. +@kindex > +@item > +Scroll calendar forwards by one month. +@kindex mouse-1 +@item mouse-1 +Select date by clicking on it. +@kindex S-@key{right} +@item S-@key{right} +One day forward. +@kindex S-@key{left} +@item S-@key{left} +One day back. +@kindex S-@key{down} +@item S-@key{down} +One week forward. +@kindex S-@key{up} +@item S-@key{up} +One week back. +@kindex M-S-@key{right} +@item M-S-@key{right} +One month forward. +@kindex M-S-@key{left} +@item M-S-@key{left} +One month back. +@kindex @key{RET} +@item @key{RET} +Choose date in calendar (only if nothing typed into minibuffer). +@end table + +@node Agenda Views, Exporting, Timestamps, Top +@chapter Agenda Views +@cindex agenda views + +Due to the way Org-mode works, TODO items and time-stamped items can +be scattered throughout a file or even a number of files. To get an +overview over open action items, or over events that are important for +a particular date, this information must be collected, sorted and +displayed in an organized way. + +Org-mode can select items based on various criteria, and display them +in a separate buffer. Three different views are provided: +@itemize @bullet +@item +an @emph{agenda} that is like a calendar and shows information +for specific dates +@item +a @emph{TODO list} that covers all unfinished +action items, and +@item +a @emph{tags view} that shows information based on +the tags associated with headlines in the outline tree. +@end itemize +@noindent +The extracted information is displayed in a special @emph{agenda +buffer}. This buffer is read-only, but provides commands to visit the +corresponding locations in the original Org-mode files, and even to +edit these files remotely. + +@menu +* Agenda files:: Files being searched for agenda information +* Agenda dispatcher:: Keyboard access to agenda views +* Weekly/Daily Agenda:: The calendar page with current tasks +* Global TODO list:: All unfinished action items +* Matching headline tags:: Structured information with fine-tuned search +* Timeline:: Time-sorted view for single file +* Agenda commands:: Remote editing of org trees +@end menu + +@node Agenda files, Agenda dispatcher, Agenda Views, Agenda Views +@section Agenda files + +The information to be shown is collected from all @emph{agenda files}, +the files listed in the variable @code{org-agenda-files}. Thus even +if you only work with a single Org-mode file, this file should be put +into that list@footnote{When using the dispatcher pressing @kbd{1} +before selecting a command will actually limit the command to the +current file, and ignore @code{org-agenda-files} until the next +dispatcher command.}. You can customize @code{org-agenda-files}, but +the easiest way to maintain it is through the following commands + +@cindex files, adding to agenda list +@table @kbd +@kindex C-c [ +@item C-c [ +Add current file to the list of agenda files. The file is added to +the front of the list. If it was already in the list, it is moved to +the front. With prefix arg, file is added/moved to the end. +@kindex C-c ] +@item C-c ] +Remove current file from the list of agenda files. +@kindex C-, +@item C-, +Cycle through agenda file list. +@end table +@noindent +The Org menu contains the current list of files and can be used +to visit any of them. + +@node Agenda dispatcher, Weekly/Daily Agenda, Agenda files, Agenda Views +@section The agenda dispatcher +@cindex agenda dispatcher +@cindex dispatching agenda commands +@cindex custom agenda commands +@cindex agenda commands, custom +The views are created through a dispatcher that should be bound to a +global key, for example @kbd{C-c a} (@pxref{Installation and +Activation}). In the following we will assume that @kbd{C-c a} is +indeed how the dispatcher is accessed and list keyboard access to +commands accordingly. After pressing @kbd{C-c a}, an additional +letter is required to execute a command. The dispatcher offers the +following default commands: +@table @kbd +@item a +Create the calendar-like agenda (@pxref{Weekly/Daily Agenda}). +@item t / T +Create a list of all TODO items (@pxref{Global TODO list}). +@item m / M +Create a list of headline matching a TAGS expression (@pxref{Matching +headline tags}). +@end table + +You can also define custom commands that will be accessible through +the dispatcher, just like the default commands. Custom commands are +global searches for tags and specific TODO keywords, or a variety of +sparse tree creating commands (@pxref{Sparse trees}). As sparse trees +are only defined for a single org-mode file, these latter commands act +on the current buffer instead of the list of agenda files. + +@kindex C-c a C +Custom commands are configured in the variable +@code{org-agenda-custom-commands}. You can customize this variable, +for example by pressing @kbd{C-c a C}. You can also directly set it +with Emacs Lisp in @file{.emacs}. For example: +@lisp +(setq org-agenda-custom-commands + '(("w" todo "WAITING") + ("u" tags "+BOSS-URGENT") + ("U" tags-tree "+BOSS-URGENT") + ("f" occur-tree "\\"))) +@end lisp +@noindent will define @kbd{C-c a w} as a global search for +TODO entries with @samp{WAITING} as todo keyword, @kbd{C-c a u} as a +global tags search for headlines marked @samp{:BOSS:} but not +@samp{:URGENT:}, @kbd{C-c a U} to do the same search but only in the +current buffer and display the result as a sparse tree, and @kbd{C-c a +f} to create a sparse tree with all entries containing the word +@samp{FIXME}. For more information, look at the documentation string +of the variable @code{org-agenda-custom-commands}. + +@node Weekly/Daily Agenda, Global TODO list, Agenda dispatcher, Agenda Views +@section The weekly/daily agenda +@cindex agenda + +The purpose of the weekly/daily @emph{agenda} is to act like a page of +a paper agenda, showing all the tasks for the current week or day. + +@table @kbd +@cindex org-agenda, command +@kindex C-c a a +@item C-c a a +Compile an agenda for the current week from a list of org files. The +agenda shows the entries for each day. With a @kbd{C-u} prefix (or +when the variable @code{org-agenda-include-all-todo} is @code{t}), all +unfinished TODO items (also those without a date) are also listed at +the beginning of the buffer, before the first date.@* +@end table + +Remote editing from the agenda buffer means for example that you can +change the dates of deadlines and appointments from the agenda buffer. +The commands available in the Agenda buffer are listed in @ref{Agenda +commands}. + +@menu +* Categories:: Not all tasks are equal +* Time-of-day specifications:: How the agenda knows the time +* Calendar/Diary integration:: Integrating Anniversaries and more +* Sorting of agenda items:: The order of things +@end menu + +@node Categories, Time-of-day specifications, Weekly/Daily Agenda, Weekly/Daily Agenda +@subsection Categories + +@cindex category +In the agenda buffer, each entry is preceded by a @emph{category}, +which is derived from the file name. The category can also be set +with a special line anywhere in the buffer, looking like this: +@example +#+CATEGORY: Thesis +@end example +If there are several such lines in a file, each specifies the category +for the text below it. The display in the agenda buffer looks best if +the category is not longer than 10 characters. + +@node Time-of-day specifications, Calendar/Diary integration, Categories, Weekly/Daily Agenda +@subsection Time-of-Day Specifications + +Org-mode checks each agenda item for a time-of-day specification. The +time can be part of the time stamp that triggered inclusion into the +agenda, for example as in @w{@samp{<2005-05-10 Tue 19:00>}}. Time +ranges can be specified with two time stamps, like +@c +@w{@samp{<2005-05-10 Tue 20:30>--<2005-05-10 Tue 22:15>}}. + +In the headline of the entry itself, a time(range) may also appear as +plain text (like @samp{12:45} or a @samp{8:30-1pm}. If the agenda +integrates the Emacs diary (@pxref{Calendar/Diary integration}), time +specifications in diary entries are recognized as well. + +For agenda display, Org-mode extracts the time and displays it in a +standard 24 hour format as part of the prefix. The example times in +the previous paragraphs would end up in the agenda like this: + +@example + 8:30-13:00 Arthur Dent lies in front of the bulldozer + 12:45...... Ford Prefect arrives and takes Arthur to the pub + 19:00...... The Vogon reads his poem + 20:30-22:15 Marwin escorts the Hitchhikers to the bridge +@end example + +If the agenda is in single-day mode, or for the display of today, the +timed entries are embedded in a time grid, like + +@example + 8:00...... ------------------ + 8:30-13:00 Arthur Dent lies in front of the bulldozer + 10:00...... ------------------ + 12:00...... ------------------ + 12:45...... Ford Prefect arrives and takes Arthur to the pub + 14:00...... ------------------ + 16:00...... ------------------ + 18:00...... ------------------ + 19:00...... The Vogon reads his poem + 20:00...... ------------------ + 20:30-22:15 Marwin escorts the Hitchhikers to the bridge +@end example + +The time grid can be turned on and off with the variable +@code{org-agenda-use-time-grid}, and can be configured with +@code{org-agenda-time-grid}. + + +@node Calendar/Diary integration, Sorting of agenda items, Time-of-day specifications, Weekly/Daily Agenda +@subsection Calendar/Diary integration +@cindex calendar integration +@cindex diary integration + +Emacs contains the calendar and diary by Edward M. Reingold. The +calendar displays a three-month calendar with holidays from different +countries and cultures. The diary allows to keep track of +anniversaries, lunar phases, sunrise/set, recurrent appointments +(weekly, monthly) and more. In this way, it is quite complementary to +Org-mode. It can be very useful to combine output from Org-mode with +the diary. + +In order to include entries from the Emacs diary into Org-mode's +agenda, you only need to customize the variable + +@lisp +(setq org-agenda-include-diary t) +@end lisp +@noindent + +@noindent After that, everything will happen automatically. All diary +entries including holidays, anniversaries etc will be included in the +agenda buffer created by Org-mode. @key{SPC}, @key{TAB}, and +@key{RET} can be used from the agenda buffer to jump to the diary +file, in order to edit existing diary entries. The @kbd{i} command to +insert new entries for the current date works in the agenda buffer, as +well as the commands @kbd{S}, @kbd{M}, and @kbd{C} to display +Sunrise/Sunset times, show lunar phases and to convert to other +calendars, respectively. @kbd{c} can be used to switch back and forth +between calendar and agenda. + +@node Sorting of agenda items, , Calendar/Diary integration, Weekly/Daily Agenda +@subsection Sorting of agenda items +@cindex sorting, of agenda items +@cindex priorities, of agenda items +The entries for each day are sorted. The default order is to first +collect all items containing an explicit time-of-day specification. +These entries will be shown at the beginning of the list, as a +@emph{schedule} for the day. After that, items remain grouped in +categories, in the sequence given by @code{org-agenda-files}. Within +each category, items are sorted by priority (@pxref{Priorities}). + +The priority is a numerical quantity composed of the base priority +(2000 for priority @samp{A}, 1000 for @samp{B}, and 0 for @samp{C}), +plus additional increments for overdue scheduled or deadline items. + +Sorting can be customized using the variable +@code{org-agenda-sorting-strategy}. + + +@node Global TODO list, Matching headline tags, Weekly/Daily Agenda, Agenda Views +@section The global TODO list +@cindex global TODO list +@cindex TODO list, global + +The global TODO list contains all unfinished TODO items, formatted and +collected into a single place. + +@table @kbd +@kindex C-c a t +@item C-c a t +Show the global TODO list. This collects the TODO items from all +agenda files (@pxref{Agenda Views}) into a single buffer. The buffer is in +@code{agenda-mode}, so there are commands to examine and manipulate +the TODO entries directly from that buffer (@pxref{Agenda commands}). +@xref{Global TODO list}, for more information. +@kindex C-c a T +@item C-c a T +Like the above, but allow to select a specific TODO keyword. You can +also do this by specifying a prefix argument to @kbd{C-c a t}. With a +@kbd{C-u} prefix you are prompted for a keyword. With a numeric +prefix, the Nth keyword in @code{org-todo-keywords} is selected. +@kindex r +The @kbd{r} key in the agenda buffer regenerates it, and you can give +a prefix argument to this command to change the selected TODO keyword, +for example @kbd{3 r}. If you often need a search for a specific +keyword, define a custom command for it (@pxref{Agenda dispatcher}). +@end table + +Remote editing of TODO items means that you can change the state of a +TODO entry with a single key press. The commands available in the +TODO list are described in @ref{Agenda commands}. + +@node Matching headline tags, Timeline, Global TODO list, Agenda Views +@section Matching headline tags +@cindex matching, of tags +@cindex tags view + +If headlines in the agenda files are marked with @emph{tags} +(@pxref{Tags}), you can select headlines based on the tags that apply +to them and collect them into an agenda buffer. + +@table @kbd +@kindex C-c a m +@item C-c a m +Produce a list of all headlines that match a given set of tags. The +command prompts for a selection criterion, which is a boolean logic +expression with tags, like @samp{+WORK+URGENT-WITHBOSS} or +@samp{WORK|HOME} (@pxref{Tags}). If you often need a specific search, +define a custom command for it (@pxref{Agenda dispatcher}). +@kindex C-c a M +@item C-c a M +Like @kbd{C-c a m}, but only select headlines that are also TODO items +and force checking subitems (see variable +@code{org-tags-match-list-sublevels}. +@end table + +The commands available in the tags list are described in @ref{Agenda +commands}. + +@node Timeline, Agenda commands, Matching headline tags, Agenda Views +@section Timeline for a single file +@cindex single file summary +@cindex agenda, for single file +@cindex timeline, single file +@cindex time-sorted view + +The timeline is not really an agenda view, because it only summarizes +items from a single Org-mode file. But it also uses the agenda buffer +and provides similar commands, so we discuss it here. The timeline +shows all time-stamped items in a single Org-mode file (or the +selected part of it), in @emph{time-sorted view}. The main purpose of +this command is to give an overview over events in a project. + +@table @kbd +@kindex C-c C-r +@item C-c C-r +Show a time-sorted view of the org file, with all time-stamped items. +When called with a @kbd{C-u} prefix, all unfinished TODO entries +(scheduled or not) are also listed under the current date. +@end table +@noindent + +The commands available in the timeline buffer are listed in +@ref{Agenda commands}. + +@node Agenda commands, , Timeline, Agenda Views +@section Commands in the agenda buffer +@cindex commands, in agenda buffer + +Entries in the agenda buffer are linked back to the org file or diary +file where they originate. You are not allowed to edit the agenda +buffer itself, but commands are provided to show and jump to the +original entry location, and to edit the org-files ``remotely'' from +the agenda buffer. In this way, all information is stored only once, +and you don't risk that your agenda and note files diverge. + +Some commands can be executed with mouse clicks on agenda lines. For +the other commands, the cursor needs to be in the desired line. + +@table @kbd +@tsubheading{Motion} +@kindex n +@item n +Next line (same as @key{up}). +@kindex p +@item p +Previous line (same as @key{down}). +@tsubheading{View/GoTo org file} +@kindex mouse-3 +@kindex @key{SPC} +@item mouse-3 +@itemx @key{SPC} +Display the original location of the item in another window. + +@kindex L +@item L +Display original location and recenter that window. + +@kindex mouse-2 +@kindex mouse-1 +@kindex @key{TAB} +@item mouse-2 +@itemx mouse-1 +@itemx @key{TAB} +Go to the original location of the item in another window. Under Emacs +22, also @kbd{mouse-1} will works for this. + +@kindex @key{RET} +@itemx @key{RET} +Go to the original location of the item and delete other windows. + +@kindex f +@item f +Toggle Follow mode. In Follow mode, as you move the cursor through +the agenda buffer, the other window always shows the corresponding +location in the org file. + +@kindex l +@item l +Toggle Logbook mode. In Logbook mode, entries that where marked DONE while +logging was on (variable @code{org-log-done}) are shown in the agenda. + +@tsubheading{Change display} +@kindex o +@item o +Delete other windows. + +@kindex w +@item w +Switch to weekly view (7 days displayed together) + +@kindex d +@item d +Switch to daily view (just one day displayed) + +@kindex D +@item D +Toggle the inclusion of diary entries. See @ref{Calendar/Diary integration}. + +@kindex g +@item g +Toggle the time grid on and off. See also the variables +@code{org-agenda-use-time-grid} and @code{org-agenda-time-grid}. + +@kindex r +@item r +Recreate the agenda buffer, for example to reflect the changes +after modification of the time stamps of items with S-@key{left} and +S-@key{right}. When the buffer is the global todo list, a prefix +argument is interpreted to create a selective list for a specific TODO +keyword. + +@kindex @key{right} +@item @key{right} +Display the following @code{org-agenda-ndays} days. For example, if +the display covers a week, switch to the following week. With prefix +arg, go forward that many times @code{org-agenda-ndays} days. + +@kindex @key{left} +@item @key{left} +Display the previous dates. + +@kindex . +@item . +Goto today. + +@tsubheading{Remote editing} + +@item 0-9 +Digit argument. + +@kindex t +@item t +Change the TODO state of the item, both in the agenda and in the +original org file. + +@kindex T +@item T +Show all tags assiciated with the current item. Because of +inheritance, this may be more than the tags listed in the line itself. + +@kindex : +@item : +Set tags for the current headline. + +@kindex , +@item , +Set the priority for the current item. Org-mode prompts for the +priority character. If you reply with @key{SPC}, the priority cookie +is removed from the entry. + +@kindex P +@item p +Display weighted priority of current item. + +@kindex + +@kindex S-@key{up} +@item + +@itemx S-@key{up} +Increase the priority of the current item. The priority is changed in +the original buffer, but the agenda is not resorted. Use the @kbd{r} +key for this. + +@kindex - +@kindex S-@key{down} +@item - +@itemx S-@key{down} +Decrease the priority of the current item. + +@kindex S-@key{right} +@item S-@key{right} +Change the time stamp associated with the current line by one day into +the future. With prefix argument, change it by that many days. For +example, @kbd{3 6 5 S-@key{right}} will change it by a year. The +stamp is changed in the original org file, but the change is not +directly reflected in the agenda buffer. Use the +@kbd{r} key to update the buffer. + +@kindex S-@key{left} +@item S-@key{left} +Change the time stamp associated with the current line by one day +into the past. + +@kindex > +@item > +Change the time stamp associated with the current line to today. +The key @kbd{>} has been chosen, because it is the same as @kbd{S-.} +on my keyboard. + +@cindex diary entries, creating from agenda +@kindex i +@item i +Insert a new entry into the diary. Prompts for the type of entry +(day, weekly, monthly, yearly, anniversary, cyclic) and creates a new +entry in the diary, just like @kbd{i d} etc. would do in the calendar. +The date is taken from the cursor position. + +@tsubheading{Calendar commands} +@kindex c +@item c +Open the Emacs calendar and move to the date at the agenda cursor. + +@item c +When in the calendar, compute and show the Org-mode agenda for the +date at the cursor. + +@kindex M +@item M +Show the phases of the moon for three month around current date. + +@kindex S +@item S +Show sunrise and sunset times. The geographical location must be set +with calendar variables, see documentation of the Emacs calendar. + +@kindex C +@item C +Convert the date at cursor into many other cultural and historic +calendars. + +@kindex H +@item H +Show holidays for three month around the cursor date. + +@kindex C-c C-x C-c +@item C-c C-x C-c +Export a single iCalendar file containing entries from all agenda files. + +@tsubheading{Quit and Exit} +@kindex q +@item q +Quit Agenda, remove the agenda buffer. + +@kindex x +@cindex agenda files, removing buffers +@item x +Exit agenda, remove the agenda buffer and all buffers loaded by Emacs +for the compilation of the agenda. Buffers created by the user to +visit org files will not be removed. + +@end table + +@node Exporting, Miscellaneous, Agenda Views, Top +@chapter Exporting +@cindex exporting + +For printing and sharing of notes, Org-mode documents can be exported +as ASCII or HTML files. To incorporate entries with associated times +like deadlines or appointments into a desktop calendar program like +iCal, Org-mode can also produce extracts in the iCalendar format. + +@menu +* ASCII export:: Export as a structured ASCII file +* HTML export:: Export as an HTML file +* iCalendar export:: Create calendar entries. +@end menu + +@node ASCII export, HTML export, Exporting, Exporting +@section ASCII export +@cindex ASCII export + +@cindex region, active +@cindex active region +@cindex transient-mark-mode +@table @kbd +@kindex C-c C-x a +@item C-c C-x a +Export as ASCII file. If there is an active region, only the region +will be exported. For an org file @file{myfile.org}, the ASCII file +will be @file{myfile.txt}. The file will be overwritten without +warning. +@end table + +@cindex headline levels, for exporting +In the exported version, the first 3 outline levels will become +headlines, defining a general document structure. Additional levels +will be exported as itemize lists. If you want that transition to occur +at a different level, specify it with a prefix argument. For example, +@example +@kbd{C-1 C-c C-x a org-export-as-ascii} +@end example +@noindent +creates only top level headlines and does the rest as items. Lines +starting with @samp{#} and subtrees starting with the word @samp{COMMENT} +will not be exported. + +@node HTML export, iCalendar export, ASCII export, Exporting +@section HTML export +@cindex HTML export + +Org-mode contains an HTML exporter with extensive HTML formatting, in +ways similar to John Grubers @emph{markdown} language, but with +additional support for tables. + +@cindex region, active +@cindex active region +@cindex transient-mark-mode +@table @kbd +@kindex C-c C-x h +@item C-c C-x h +Export as HTML file @file{myfile.html}. +@kindex C-c C-x b +@item C-c C-x b +Export as HTML file and open it with a browser. +@kindex C-c C-x t +@item C-c C-x t +Insert template with export options, see below. +@kindex C-c : +@item C-c : +Toggle fixed-width for entry (QUOTE) or region, see below. +@end table + +@cindex headline levels, for exporting +In the exported version, the first 3 outline levels will become +headlines, defining a general document structure. Additional levels +will be exported as itemize lists. If you want that transition to occur +at a different level, specify it with a prefix argument. For example, +@example +@kbd{C-2 C-c C-x b} +@end example +@noindent +creates two levels of headings and does the rest as items. + +@menu +* HTML formatting:: Interpretation of the buffer content +* Export options:: How to influence exports +* Comment lines:: Lines which will not be exported +@end menu + +@node HTML formatting, Export options, HTML export, HTML export +@subsection HTML formatting + +Not all text is transferred literally to the exported HTML file. The +exporter implements the following interpretation: + +@itemize @bullet + +@cindex hand-formatted lists +@cindex lists, hand-formatted +@item +Hand-formatted lists with @samp{-}, @samp{*} or @samp{+} as +bullet, or with @samp{1.} or @samp{2)} as enumerator will be recognized and +transformed into HTML lists. See @xref{Plain Lists}. + +@cindex underlined text +@cindex bold text +@cindex italic text +@item +You can make words @b{*bold*}, @i{/italic/}, and _underlined_ + +@cindex @TeX{} interpretation +@item +Simple @TeX{}-like math constructs are interpreted: + +@cindex completion, of @TeX{} symbols +@itemize @minus +@item +@samp{10^22} and @samp{J_n} are super- and subscripts. You can quote +@samp{^} and @samp{_} with a backslash: @samp{\_} and @samp{\^} +@item +@samp{\alpha} indicates a Greek letter, @samp{\to} an arrow. You can +use completion for these macros, just type @samp{\} and maybe a few +letters, and press @kbd{M-@key{TAB}} to see possible completions. +@end itemize + +@cindex tables, export to HTML +@item +Tables are transformed into HTML tables. Data fields before the first +horizontal separator line will be formatted as table header fields. + +@cindex fixed width +@item +If a headline starts with the word @samp{QUOTE}, the text below the +headline will be typeset as fixed-width, to allow quoting of computer +codes etc. Lines starting with @samp{:} are also typeset in +fixed-width font. + +@cindex HTML tags +@item +If you want to include HTML tags which should be interpreted as such, +mark them with a @samp{@@} like in @samp{@@bold text@@}. +Plain @samp{<} and @samp{>} are always transformed to @samp{<} and +@samp{>} in HTML export. +@end itemize + +If these conversions conflict with your habits of typing ASCII text, +they can all be turned off with corresponding variables. + +@node Export options, Comment lines, HTML formatting, HTML export +@subsection Export options +@cindex options, for export + +@cindex completion, of option keywords +The exporter recognizes special lines in the buffer which provide +additional information. These lines may be put anywhere in the file. +The whole set of lines can be inserted into the buffer with @kbd{C-c +C-x t}. For individual lines, a good way to make sure the keyword is +correct is to type @samp{#+} and then use @kbd{M-@key{TAB}} completion +(@pxref{Completion}). + +@example +#+TITLE: the title to be shown (default is the buffer name) +#+AUTHOR: the author (default taken from @code{user-full-name}) +#+EMAIL: his/her email address (default from @code{user-mail-address}) +#+LANGUAGE: language for HTML, e.g. @samp{en} (@code{org-export-default-language}) +#+TEXT: Some descriptive text to be inserted at the beginning. +#+TEXT: Several lines may be given. +#+OPTIONS: H:2 num:t toc:t \n:nil @:t ::t |:t ^:t *:nil TeX:t +@end example +@noindent +The OPTIONS line is a compact form to specify export settings. Here +you can +@cindex headline levels +@cindex section-numbers +@cindex table of contents +@cindex linebreak preservation +@cindex quoted html tags +@cindex fixed-width sections +@cindex tables +@cindex @TeX{}-like syntax for sub- and superscripts +@cindex emphasized text +@cindex @TeX{} macros +@example +H: @r{set the number of headline levels for export} +num: @r{turn on/off section-numbers} +toc: @r{turn on/off table of contents} +\n: @r{turn on/off linebreak-preservation} +@@: @r{turn on/off quoted html tags} +:: @r{turn on/off fixed-width sections} +|: @r{turn on/off tables} +^: @r{turn on/off @TeX{}-like syntax for sub- and superscripts.} +*: @r{turn on/off emphasized text (bold, italic, underlined)} +TeX: @r{turn on/off @TeX{} macros} +@end example + +You can also give style information for the exported file. The +default specification can be configured through the option +@code{org-export-html-style}. If you want to use a file-local style, +you may use file variables, best wrapped into a COMMENT section at the +end of the outline tree. For example: + +@example +* COMMENT HTML style specifications + +# Local Variables: +# org-export-html-style: " " +# End: *** +@end example + +Remember to execute @kbd{M-x normal-mode} after changing this to make +the new style visible to Emacs. + +@node Comment lines, , Export options, HTML export +@subsection Comment lines +@cindex comment lines +@cindex exporting, not + +Lines starting with @samp{#} in column zero are treated as comments +and will never be exported. Also entire subtrees starting with the +word @samp{COMMENT} will never be exported. Finally, any text before +the first headline will not be exported either. This applies also for +ASCII export. + +@table @kbd +@kindex C-c ; +@item C-c ; +Toggle the COMMENT keyword at the beginning of an entry. +@end table + +@node iCalendar export, , HTML export, Exporting +@section iCalendar export +@cindex iCalendar export + +Some people like to use Org-mode for keeping track of projects, but +still prefer a standard calendar application for anniversaries and +appointments. In this case it can be useful to have deadlines and +other time-stamped items in Org-mode files show up in the calendar +application. Org-mode can export calendar information in the standard +iCalendar format. + +@table @kbd +@kindex C-c C-x i +@item C-c C-x i +Create iCalendar entries for the current file and store them in the same +directory, using a file extension @file{.ics}. +@kindex C-c C-x C-i +@item C-c C-x C-i +Like @kbd{C-c C-x i}, but do this for all files in +@code{org-agenda-files}. For each of these files, a separate iCalendar +file will be written. +@kindex C-c C-x c +@item C-c C-x c +Create a single large iCalendar file from all files in +@code{org-agenda-files} and write it to the file given by +@code{org-combined-agenda-icalendar-file}. +@end table + +How this calendar is best read and updated, depends on the application +you are using. For example, when using iCal under Apple MacOS X, you +could create a new calendar @samp{OrgMode} (the default name for the +calendar created by @kbd{C-c C-x c}, see the variables +@code{org-icalendar-combined-name} and +@code{org-combined-agenda-icalendar-file}). Then set Org-mode to +overwrite the corresponding file +@file{~/Library/Calendars/OrgMode.ics}. You may even use AppleScript +to make iCal re-read the calendar files each time a new version of +@file{OrgMode.ics} is produced. Here is the setup needed for this: + +@cindex applescript, for calendar update +@lisp +(setq org-combined-agenda-icalendar-file + "~/Library/Calendars/OrgMode.ics") +(add-hook 'org-after-save-iCalendar-file-hook + (lambda () + (shell-command + "osascript -e 'tell application \"iCal\" to reload calendars'"))) +@end lisp + +@node Miscellaneous, Index, Exporting, Top +@chapter Miscellaneous + +@menu +* Completion:: M-TAB knows what you need +* Customization:: Adapting Org-mode to your taste +* Clean view:: Getting rid of leading stars in the outline +* TTY keys:: Using Org-mode on a tty +* FAQ:: Frequently asked questions +* Interaction:: Other Emacs packages +* Bugs:: Things which do not work perfectly +* Acknowledgments:: These people provided feedback and more +@end menu + +@node Completion, Customization, Miscellaneous, Miscellaneous +@section Completion +@cindex completion, of @TeX{} symbols +@cindex completion, of TODO keywords +@cindex completion, of dictionary words +@cindex completion, of option keywords +@cindex completion, of CamelCase links +@cindex completion, of tags +@cindex @TeX{} symbol completion +@cindex TODO keywords completion +@cindex dictionary word completion +@cindex option keyword completion +@cindex CamelCase link completion +@cindex tag completion + +Org-mode supports in-buffer completion. This type of completion does +not make use of the minibuffer. You simply type a few letters into +the buffer and use the key to complete text right there. + +@table @kbd +@kindex M-@key{TAB} +@item M-@key{TAB} +Complete word at point +@itemize @bullet +@item +At the beginning of a headline, complete TODO keywords. +@item +After @samp{\}, complete @TeX{} symbols supported by the exporter. +@item +After @samp{*}, complete CamelCase versions of all headlines in the +buffer. +@item +After @samp{:}, complete tags used elsewhere in the buffer. +@item +After @samp{#+}, complete the special keywords like @samp{TYP_TODO} or +@samp{OPTIONS} which set file-specific options for Org-mode. When the +option keyword is already complete, pressing @kbd{M-@key{TAB}} again +will insert example settings for this keyword. +@item +Elsewhere, complete dictionary words using ispell. +@end itemize +@end table + + +@node Customization, Clean view, Completion, Miscellaneous +@section Customization +@cindex customization +@cindex options, for customization +@cindex variables, for customization + +There are more than 100 variables that can be used to customize +Org-mode. For the sake of compactness of the manual, we are not +describing the variables here. A structured overview of customization +variables is available with @kbd{M-x org-customize}. Or select +@code{Browse Org Group} from the @code{Org->Customization} menu. + +@node Clean view, TTY keys, Customization, Miscellaneous +@section A cleaner outline view +@cindex hiding leading stars +@cindex clean outline view + +Some people find it noisy and distracting that the Org-mode headlines +are starting with a potentially large number of stars. For example in +the example tree from @ref{Headlines}: + +@example +* Top level headline +** Second level +*** 3rd level + some text +*** 3rd level + more text +* Another top level headline +@end example + +@noindent +Unfortunately this is deeply ingrained into the code of Org-mode and +cannot be easily changed. You can, however, modify the display in such +a way that all leading stars become invisible and the outline more easy +to read. To do this, customize the variable +@code{org-hide-leading-stars} like this: + +@lisp +(setq org-hide-leading-stars t) +@end lisp + +@noindent +or change this on a per-file basis with one of the lines (anywhere in +the buffer) + +@example +#+STARTUP: showstars +#+STARTUP: hidestars +@end example +@noindent +Press @kbd{C-c C-c} with the cursor in a @samp{STARTUP} line to activate +the modifications. + +With stars hidden, the tree becomes: + +@example +* Top level headline + * Second level + * 3rd level + some text + * 3rd level + more text +* Another top level headline +@end example + +@noindent +Note that the leading stars are not truly replaced by whitespace, they +are only fontified with the face @code{org-hide} that uses the +background color as font color. If are are not using either white or +black background, you may have to customize this face to get the wanted +effect. Another possibility is to set this font such that the extra +stars are @i{almost} invisible, for example using the color +@code{grey90} on a white background. + +Things become cleaner still if you skip all the even levels and use only +odd levels 1, 3, 5..., effectively adding two stars to go from one +outline level to the next: + +@example +* Top level headline + * Second level + * 3rd level + some text + * 3rd level + more text +* Another top level headline +@end example + +@noindent +In order to make the structure editing and export commands handle this +convention correctly, use + +@lisp +(setq org-odd-levels-only t) +@end lisp + +@noindent +or set this on a per-file basis with one of the following lines (don't +forget to press @kbd{C-c C-c} with the cursor in the startup line to +activate changes immediately). + +@example +#+STARTUP: odd +#+STARTUP: oddeven +@end example + +You can convert an Org-mode file from single-star-per-level to +double-star-per-level convention with @kbd{M-x org-convert-to-odd-levels +RET} in that file. There is no command for the back conversion because +such a command might merge levels and in this way destroy the +structure of the tree. +@c FIXME: Maybe we should have such a command... + +@node TTY keys, FAQ, Clean view, Miscellaneous +@section Using org-mode on a tty +@cindex tty keybindings + +Org-mode uses a number of keys that are not accessible on a tty. This +applies to most special keys like cursor keys, @key{TAB} and +@key{RET}, when these are combined with modifier keys like @key{Meta} +and/or @key{Shift}. Org-mode uses these bindings because it needs to +provide keys for a large number of commands, and because these keys +appeared particularly easy to remember. In order to still be able to +access the core functionality of Org-mode on a tty, alternative +bindings are provided. Here is a complete list of these bindings, +which are obviously more cumbersome to use. Note that sometimes a +work-around can be better. For example changing a time stamp is +really only fun with @kbd{S-@key{cursor}} keys. On a tty you would +rather use @kbd{C-c .} to re-insert the timestamp. + +@multitable @columnfractions 0.15 0.2 0.2 +@item @b{Default} @tab @b{Alternative 1} @tab @b{Alternative 2} +@item @kbd{S-@key{TAB}} @tab @kbd{C-u @key{TAB}} @tab +@item @kbd{M-@key{left}} @tab @kbd{C-c C-x l} @tab @kbd{@key{Esc} @key{left}} +@item @kbd{M-S-@key{left}} @tab @kbd{C-c C-x L} @tab +@item @kbd{M-@key{right}} @tab @kbd{C-c C-x r} @tab @kbd{@key{Esc} @key{right}} +@item @kbd{M-S-@key{right}} @tab @kbd{C-c C-x R} @tab +@item @kbd{M-@key{up}} @tab @kbd{C-c C-x u} @tab @kbd{@key{Esc} @key{up}} +@item @kbd{M-S-@key{up}} @tab @kbd{C-c C-x U} @tab +@item @kbd{M-@key{down}} @tab @kbd{C-c C-x d} @tab @kbd{@key{Esc} @key{down}} +@item @kbd{M-S-@key{down}} @tab @kbd{C-c C-x D} @tab +@item @kbd{S-@key{RET}} @tab @kbd{C-c C-x c} @tab +@item @kbd{M-@key{RET}} @tab @kbd{C-c C-x m} @tab @kbd{@key{Esc} @key{RET}} +@item @kbd{M-S-@key{RET}} @tab @kbd{C-c C-x M} @tab +@item @kbd{S-@key{left}} @tab @kbd{C-c C-x @key{left}} @tab +@item @kbd{S-@key{right}} @tab @kbd{C-c C-x @key{right}} @tab +@item @kbd{S-@key{up}} @tab @kbd{C-c C-x @key{up}} @tab +@item @kbd{S-@key{down}} @tab @kbd{C-c C-x @key{down}} @tab +@end multitable + +@node FAQ, Interaction, TTY keys, Miscellaneous +@section Frequently asked questions +@cindex FAQ + +@enumerate +@item @b{Org-mode seems to be a useful default mode for the various +@file{README} files I have scattered through my directories. How do I +turn it on for all @file{README} files?} +@example +(add-to-list 'auto-mode-alist '("README$" . org-mode)) +@end example + +@item @b{All these stars are driving me mad, I just find the Emacs +outlines unreadable. Can't you just put white space and a single star as a +starter for headlines?}@* +See @ref{Clean view}. + +@item @b{I would like to have two windows on the same Org-mode +file, but with different outline visibility. Is that possible?}@* +@cindex @code{make-indirect-buffer} +@cindex indirect buffers +In GNU Emacs, you may use @emph{indirect buffers} which do exactly +this. See the documentation on the command +@code{make-indirect-buffer}. In XEmacs, this is currently not +possible because of the different outline implementation. + +@item @b{Is there an easy way to insert links to web locations?}@* +@cindex URL, paste into buffer +Sure, just type or paste them into the buffer. A plain-text URL-like +string is directly interpreted as a link. + +@item @b{When I export my TODO list, every TODO item becomes a +separate section. How do I enforce these items to be exported as an +itemized list?}@* +If you plan to use ASCII or HTML export, make sure things you want to +be exported as item lists are level 4 at least, even if that does mean +there is a level jump. For example + +@example +* Todays top priorities +**** TODO write a letter to xyz +**** TODO Finish the paper +**** Pick up kids at the school +@end example + +Alternatively, if you need a specific value for the heading/item +transition in a particular file, use the @samp{+OPTIONS} line to +configure the @samp{H} switch. + +@example ++OPTIONS: H:2; ... +@end example + +@item @b{I would like to export only a subtree of my file to HTML. How?}@* +@cindex exporting a subtree +If you want to export a subtree, mark the subtree as region and then +export. Marking can be done with @kbd{C-c @@ C-x C-x}, for example. + +@item @b{Org-mode takes over the S-cursor keys. I also want to use +CUA-mode, is there a way to fix this conflict?}@* +Yes, see @ref{Interaction} + +@item @b{Is there an easy way to insert an empty table template with a +default number of rows and columns?}@* +@cindex table, empty template +To insert an empty table template, just type @samp{|-} and use +@key{TAB}. The default size can be changed with the variable +@code{org-table-default-size}. However, just starting to type the +first line is usually much easier. + +@item @b{One of my table columns has started to fill up with +@samp{#ERROR}. What is going on?}@* +Org-mode tried to compute the column from other fields using a +formula stored in the @samp{#+TBLFMT:} line just below the table, and +the evaluation of the formula fails. Fix the fields used in the +formula, or fix the formula, or remove it! + +@item @b{When I am in the last column of a table and just above a +horizontal line in the table, pressing TAB creates a new table line +@i{before} the horizontal line. How can I quickly move to the line +@i{below} the horizontal line instead?}@* +Press @key{down} (to get on the separator line) and then @key{TAB}. +Or configure the variable @code{org-table-tab-jumps-over-hlines}. + +@item @b{How can I change the indentation of an entire table without +fixing every line by hand?}@* +@cindex indentation, of tables +The indentation of a table is set by the first line. So just fix the +indentation of the first line and realign with @key{TAB}. + +@item @b{Is it possible to include entries from org-mode files into my +emacs diary?}@* +Since the org-mode agenda is much more powerful and can contain the +diary (@pxref{Calendar/Diary integration}), you should think twice +before deciding to do this. Inegrating org-mode information into the +diary is, however, possible. The following steps are necessary: +Autoload the function @command{org-diary} as shown above under +@ref{Installation and Activation}. You also need to use @emph{fancy +diary display} by setting in @file{.emacs}: + +@lisp +(add-hook 'diary-display-hook 'fancy-diary-display) +@end lisp + +Then include the following line into your @file{~/diary} file, in +order to get the entries from all files listed in the variable +@code{org-agenda-files}: + +@example +&%%(org-diary) +@end example +@noindent +You may also select specific files with + +@example +&%%(org-diary) ~/path/to/some/org-file.org +&%%(org-diary) ~/path/to/another/org-file.org +@end example + +If you now launch the calendar and press @kbd{d} to display a diary, +the headlines of entries containing a timestamp, date range, schedule, +or deadline referring to the selected date will be listed. Just like +in Org-mode's agenda view, the diary for @emph{today} contains +additional entries for overdue deadlines and scheduled items. See +also the documentation of the @command{org-diary} function. + +@end enumerate + + +@node Interaction, Bugs, FAQ, Miscellaneous +@section Interaction with other packages +@cindex packages, interaction with other +Org-mode can cooperate with the following packages: + +@table @asis +@cindex @file{org-mouse.el} +@item @file{org-mouse.el} by Piotr Zielinski +This package implements extended mouse functionality for Org-mode. It +allows to cycle visibility and to edit the document structure with the +mouse. It also provides a context-sensitive menu that changes depending +on the context of a mouse-click. Use a search engine to find this +package on the web. +@cindex @file{table.el} +@item @file{table.el} by Takaaki Ota +Org mode cooperates with table.el, see @ref{table.el}. @file{table.el} +is part of Emacs 22. +@cindex @file{calc.el} +@item @file{calc.el} by Dave Gillespie +Org-mode uses the calc package for implementing spreadsheet +functionality in its tables (@pxref{Table calculations}). Org-modes +checks for the availability of calc by looking for the function +@code{calc-eval} which should be autoloaded in your setup if calc has +been installed properly. As of Emacs 22, calc is part of the Emacs +distribution. Another possibility for interaction between the two +packages is using calc for embedded calculations. @xref{Embedded Mode, +, Embedded Mode, calc, GNU Emacs Calc Manual}. +@cindex @file{constants.el} +@item @file{constants.el} by Carsten Dominik +In a table formula (@pxref{Table calculations}), it is possible to use +names for natural constants or units. Instead of defining you own +constants in the variable @code{org-table-formula-constants}, install +the @file{constants} package which defines a large number of constants +and units, and lets you use unit prefixes like @samp{M} for +@samp{Mega} etc. You will need version 2.0 of this package, available +at @url{http://www.astro.uva.nl/~dominik/Tools}. Org-mode checks for +the function @code{constants-get}, which has to be autoloaded in your +setup. See the installation instructions in the file +@file{constants.el}. +@cindex @file{remember.el} +@cindex @file{CUA.el} +@item @file{CUA.el} by Kim. F. Storm +Keybindings in Org-mode conflict with the @kbd{S-} keys +used by CUA-mode (as well as pc-select-mode and s-region-mode) to +select and extend the region. If you want to use one of these +packages along with Org-mode, configure the variable +@code{org-CUA-compatible}. When set, Org-mode will move the following +keybindings in org-mode files, and in the agenda buffer (but not +during date selection). +@example +S-UP -> M-p S-DOWN -> M-n +S-LEFT -> M-- S-RIGHT -> M-+ +S-RET -> C-S-RET +@end example +Yes, these are unfortunately more difficult to remember. If you want +to have other replacement keys, look at the variable +@code{org-disputed-keys}. +@item @file{remember.el} by John Wiegley +Org mode cooperates with remember, see @ref{Remember}. +@file{Remember.el} is not part of Emacs, find it on the web. +@cindex @file{planner.el} +@item @file{planner.el} by John Wiegley +Planner is another tool to plan work and keep track of tasks. Planner +uses a multi-file approach with project pages and day pages. Is based +on Emacs-Wiki. If Planner is your primary tool, it can be useful to +display the agenda entries resulting from org files in day-pages of +the planner. This can be done through the diary of the calendar: +Integrate org files into the diary as described above, and then turn +on the diary support of planner. Planner is not part of Emacs, find it +on the web. +@end table + +@node Bugs, Acknowledgments, Interaction, Miscellaneous +@section Bugs +@cindex bugs + +Here is a list of things which should work differently, but which I +have found too hard to fix. + +@itemize @bullet +@item +Text in an entry protected with the @samp{QUOTE} keyword should not +autowrap. +@item +When the application called by @kbd{C-c C-o} to open a file link fails +(for example because the application does not exits or refuses to open +the file), it does so silently. No error message is displayed. +@item +Plain list items should be able to hold a TODO item. Unfortunately this +has so many technical problems that I will only consider this change for +the next major release (5.0). +@item +The remote-editing commands in the agenda buffer cannot be undone with +@code{undo} called from within the agenda buffer. But you can go to +the corresponding buffer (using @key{TAB} or @key{RET} and execute +@code{undo} there. +@item +Recalculating a table line applies the formulas from left to right. +If a formula uses @emph{calculated} fields further down the row, +multiple recalculation may be needed to get all fields consistent. +@item +Under XEmacs, if Org-mode entries are included into the diary, it is +not possible to jump back from the diary to the org file. Apparently, +the text properties are lost when the fancy-diary-display is used. +However, from Org-mode's timeline and agenda buffers (created with +@kbd{C-c C-r} and @kbd{C-c a}), things do work correctly. +@item +You can only make a single word boldface or italic. To emphasize +several words in a row, each must have the emphasize markers, like in +@samp{*three* *bold* *words*}. +@item +The exporters work well, but could be made more efficient. +@end itemize + +@page + +@node Acknowledgments, , Bugs, Miscellaneous +@section Acknowledgments +@cindex acknowledgments +@cindex thanks + +Org-mode was written by Carsten Dominik, who still maintains it at the +Org-mode homepage @uref{http://www.astro.uva.nl/~dominik/Tools/org/}. +The following people (in alphabetic order) have helped the development +along with ideas, suggestions and patches. Many thanks to all of you, +Org-mode would not be what it is without your input. + +@itemize @bullet +@item +Thomas Baumann contributed the code for links to the MH-E email system. +@item +Alex Bochannek provided a patch for rounding time stamps. +@item +Charles Cave's suggestion sparked the implementation of templates for +Remember. +@item +Pavel Chalmoviansky influenced the agenda treatment of items with +specified time. +@item +Sacha Chua suggested to copy linking code from Planner (we did take +some). +@item +Christian Egli converted the documentation into TeXInfo format, patched +CSS formatting into the HTML exporter, and inspired the agenda. +@item +Kai Grossjohann pointed out key-binding conflicts caused by Org-mode. +@item +Stefan Monnier provided a patch to keep the Emacs-Lisp compiler happy. +@item +Tim O'Callaghan suggested in-file links, search options for +general file links, and TAGS. +@item +Oliver Oppitz suggested multi-state TODO items. +@item +Pete Phillips helped the development of the TAGS feature. +@item +Matthias Rempe (Oelde) provided ideas, Windows support, and quality +control. +@item +Kevin Rogers contributed code to access VM files on remote hosts. +@item +Philip Rooke created the Org-mode reference card and provided lots of feedback. +@item +Christian Schlauer proposed angular brackets around links, among other +things. +@item +Linking to VM/BBDB/GNUS was inspired by Tom Shannon's +@file{organizer-mode.el}. +@item +J@"urgen Vollmer contributed code generating the table of contents +in HTML output. +@item +Chris Wallace provided a patch implementing the @samp{QUOTE} keyword. +@item +David Wainberg suggested archiving, and improvements to the linking +system. +@item +Scheduling TODO items was inspired by John Wiegley's @file{planner.el}. +@item +Carsten Wimmer suggested some changes and helped fix a bug in linking +to GNUS. +@item +Roland Winkler requested additional keybindings to make Org-mode +work on a tty. +@item +Piotr Zielinski wrote @file{org-mouse.el} and showed how to follow links +with mouse-1. +@end itemize + +@node Index, Key Index, Miscellaneous, Top +@chapter Index + +@printindex cp + +@node Key Index, , Index, Top +@chapter Key Index + +@printindex ky + +@bye + +@ignore + arch-tag: 7893d1fe-cc57-4d13-b5e5-f494a1bcc7ac +@end ignore diff --git a/orgcard.pdf b/orgcard.pdf new file mode 100644 index 000000000..e37f44786 Binary files /dev/null and b/orgcard.pdf differ diff --git a/orgcard.tex b/orgcard.tex new file mode 100644 index 000000000..288c65a20 --- /dev/null +++ b/orgcard.tex @@ -0,0 +1,747 @@ +% Reference Card for Org Mode 4.12 +% +%**start of header +\newcount\columnsperpage + +% This file can be printed with 1, 2, or 3 columns per page (see below). +% At the moment this card works quite nicely in 3 column format and +% currently takes 2 full pages. It is thus suited to producing one +% double-side page when printed. + +% There are a couple of tweaks in the format of this card which make it work +% slightly better on A4 paper. The changes due, I think, to Stephen Eglen, +% are commented below. Revert the changes if you want letter sized paper. + +% Try running something like +% tex org-mode-ref.tex; dvips -t landscape org-mode-ref.dvi +% to print the card + +\columnsperpage=3 + +% Copyright (c) 2004 Philip Rooke, 2005, 2006 Free Software Foundation + +% 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 2, or (at your option) +% any later version. + +% GNU Emacs is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. + +% You should have received a copy of the GNU General Public License +% along with GNU Emacs; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. + +% This file is intended to be processed by plain TeX (TeX82). +% +% The final reference card has six columns, three on each side. +% This file can be used to produce it in any of three ways: +% 1 column per page +% produces six separate pages, each of which needs to be reduced to 80%. +% This gives the best resolution. +% 2 columns per page +% produces three already-reduced pages. +% You will still need to cut and paste. +% 3 columns per page +% produces two pages which must be printed sideways to make a +% ready-to-use 8.5 x 11 inch reference card. +% For this you need a dvi device driver that can print sideways. +% Which mode to use is controlled by setting \columnsperpage above. +% +% Author: +% Stephen Gildea +% Internet: gildea@stop.mail-abuse.org +% +% Thanks to Paul Rubin, Bob Chassell, Len Tower, and Richard Mlynarik +% for their many good ideas. + +\def\orgversionnumber{4.12} +\def\year{2006} + +\def\shortcopyrightnotice{\vskip 1ex plus 2 fill + \centerline{\small \copyright\ 2004, 2005, 2006\ Free Software Foundation, Inc. + Permissions on back. v\orgversionnumber}} + +\def\copyrightnotice{ +\vskip 1ex plus 100 fill\begingroup\small +\centerline{Copyright \copyright\ \year\ Free Software Foundation, Inc.} +\centerline{v\orgversionnumber{} for Org-Mode \orgversionnumber{}, \year} +\centerline{Author: Philip Rooke} +\centerline{based on refcard design and format by Stephen Gildea} + +Permission is granted to make and distribute copies of +this card provided the copyright notice and this permission notice +are preserved on all copies. + +\endgroup} + +% make \bye not \outer so that the \def\bye in the \else clause below +% can be scanned without complaint. +\def\bye{\par\vfill\supereject\end} + +\newdimen\intercolumnskip %horizontal space between columns +\newbox\columna %boxes to hold columns already built +\newbox\columnb + +\def\ncolumns{\the\columnsperpage} + +\message{[\ncolumns\space + column\if 1\ncolumns\else s\fi\space per page]} + +\def\scaledmag#1{ scaled \magstep #1} + +% This multi-way format was designed by Stephen Gildea October 1986. +% Note that the 1-column format is fontfamily-independent. +\if 1\ncolumns %one-column format uses normal size + \hsize 4in + \vsize 10in + \voffset -.7in + \font\titlefont=\fontname\tenbf \scaledmag3 + \font\headingfont=\fontname\tenbf \scaledmag2 + \font\smallfont=\fontname\sevenrm + \font\smallsy=\fontname\sevensy + + \footline{\hss\folio} + \def\makefootline{\baselineskip10pt\hsize6.5in\line{\the\footline}} +\else %2 or 3 columns uses prereduced size + \hsize 3.2in + +% FIXME - Try to make things more A4 friendly +% \vsize 7.95in + \vsize 7.65in +% \hoffset -.75in + \hoffset -.25in + \voffset -.745in + \font\titlefont=cmbx10 \scaledmag2 + \font\headingfont=cmbx10 \scaledmag1 + \font\smallfont=cmr6 + \font\smallsy=cmsy6 + \font\eightrm=cmr8 + \font\eightbf=cmbx8 + \font\eightit=cmti8 + \font\eighttt=cmtt8 + \font\eightmi=cmmi8 + \font\eightsy=cmsy8 + \textfont0=\eightrm + \textfont1=\eightmi + \textfont2=\eightsy + \def\rm{\eightrm} + \def\bf{\eightbf} + \def\it{\eightit} + \def\tt{\eighttt} + +% FIXME - Try to make things more A4 friendly +% \normalbaselineskip=.8\normalbaselineskip + \normalbaselineskip=.7\normalbaselineskip + \normallineskip=.8\normallineskip + \normallineskiplimit=.8\normallineskiplimit + \normalbaselines\rm %make definitions take effect + + \if 2\ncolumns + \let\maxcolumn=b + \footline{\hss\rm\folio\hss} + \def\makefootline{\vskip 2in \hsize=6.86in\line{\the\footline}} + \else \if 3\ncolumns + \let\maxcolumn=c + \nopagenumbers + \else + \errhelp{You must set \columnsperpage equal to 1, 2, or 3.} + \errmessage{Illegal number of columns per page} + \fi\fi + + \intercolumnskip=.46in + \def\abc{a} + \output={% %see The TeXbook page 257 + % This next line is useful when designing the layout. + %\immediate\write16{Column \folio\abc\space starts with \firstmark} + \if \maxcolumn\abc \multicolumnformat \global\def\abc{a} + \else\if a\abc + \global\setbox\columna\columnbox \global\def\abc{b} + %% in case we never use \columnb (two-column mode) + \global\setbox\columnb\hbox to -\intercolumnskip{} + \else + \global\setbox\columnb\columnbox \global\def\abc{c}\fi\fi} + \def\multicolumnformat{\shipout\vbox{\makeheadline + \hbox{\box\columna\hskip\intercolumnskip + \box\columnb\hskip\intercolumnskip\columnbox} + \makefootline}\advancepageno} + \def\columnbox{\leftline{\pagebody}} + + \def\bye{\par\vfill\supereject + \if a\abc \else\null\vfill\eject\fi + \if a\abc \else\null\vfill\eject\fi + \end} +\fi + +% we won't be using math mode much, so redefine some of the characters +% we might want to talk about +%\catcode`\^=12 +\catcode`\_=12 + +% we also need the tilde, for file names. +\catcode`\~=12 + +\chardef\\=`\\ +\chardef\{=`\{ +\chardef\}=`\} + +\hyphenation{mini-buf-fer} + +\parindent 0pt +\parskip 1ex plus .5ex minus .5ex + +\def\small{\smallfont\textfont2=\smallsy\baselineskip=.8\baselineskip} + +% newcolumn - force a new column. Use sparingly, probably only for +% the first column of a page, which should have a title anyway. +\outer\def\newcolumn{\vfill\eject} + +% title - page title. Argument is title text. +\outer\def\title#1{{\titlefont\centerline{#1}}\vskip 1ex plus .5ex} + +% section - new major section. Argument is section name. +\outer\def\section#1{\par\filbreak + \vskip 3ex plus 2ex minus 2ex {\headingfont #1}\mark{#1}% + \vskip 2ex plus 1ex minus 1.5ex} + +\newdimen\keyindent + +% beginindentedkeys...endindentedkeys - key definitions will be +% indented, but running text, typically used as headings to group +% definitions, will not. +\def\beginindentedkeys{\keyindent=1em} +\def\endindentedkeys{\keyindent=0em} +\endindentedkeys + +% paralign - begin paragraph containing an alignment. +% If an \halign is entered while in vertical mode, a parskip is never +% inserted. Using \paralign instead of \halign solves this problem. +\def\paralign{\vskip\parskip\halign} + +% \<...> - surrounds a variable name in a code example +\def\<#1>{{\it #1\/}} + +% kbd - argument is characters typed literally. Like the Texinfo command. +\def\kbd#1{{\tt#1}\null} %\null so not an abbrev even if period follows + +% beginexample...endexample - surrounds literal text, such a code example. +% typeset in a typewriter font with line breaks preserved +\def\beginexample{\par\leavevmode\begingroup + \obeylines\obeyspaces\parskip0pt\tt} +{\obeyspaces\global\let =\ } +\def\endexample{\endgroup} + +% key - definition of a key. +% \key{description of key}{key-name} +% prints the description left-justified, and the key-name in a \kbd +% form near the right margin. +\def\key#1#2{\leavevmode\hbox to \hsize{\vtop + {\hsize=.75\hsize\rightskip=1em + \hskip\keyindent\relax#1}\kbd{#2}\hfil}} + +\newbox\metaxbox +\setbox\metaxbox\hbox{\kbd{M-x }} +\newdimen\metaxwidth +\metaxwidth=\wd\metaxbox + +% metax - definition of a M-x command. +% \metax{description of command}{M-x command-name} +% Tries to justify the beginning of the command name at the same place +% as \key starts the key name. (The "M-x " sticks out to the left.) +\def\metax#1#2{\leavevmode\hbox to \hsize{\hbox to .75\hsize + {\hskip\keyindent\relax#1\hfil}% + \hskip -\metaxwidth minus 1fil + \kbd{#2}\hfil}} + +% threecol - like "key" but with two key names. +% for example, one for doing the action backward, and one for forward. +\def\threecol#1#2#3{\hskip\keyindent\relax#1\hfil&\kbd{#2}\hfil\quad + &\kbd{#3}\hfil\quad\cr} + +%**end of header + + +\title{Org-Mode Reference Card (1/2)} + +\centerline{(for version \orgversionnumber)} + +\section{Getting Started} +% +%Put the following in your \kbd{~/.emacs}$^1$ +\vskip -1mm +\beginexample% +%(autoload 'org-mode "org" "Org mode" t) +%(autoload 'org-diary "org" "Org mode diary entries") +%(autoload 'org-agenda "org" "Agenda from Org files" t) +%(autoload 'org-todo-list "org" "Global TODO list" t) +%(autoload 'org-store-link "org" "Store org link" t) +%(autoload 'orgtbl-mode "org" "Orgtbl minor mode" t) +%(autoload 'turn-on-orgtbl "org" "Orgtbl minor mode") +(add-to-list 'auto-mode-alist '("\\\\.org\$" . org-mode)) +(define-key global-map "\\C-cl" 'org-store-link)$^2$ +(define-key global-map "\\C-ca" 'org-agenda)$^2$ +\endexample +% +\metax{For the many customization options try}{M-x org-customize} +\metax{To read the on-line documentation try}{M-x org-info} + +\section{Visibility Cycling} + +\key{rotate current subtree between states}{TAB} +\key{rotate entire buffer between states}{S-TAB} +\key{show the whole file}{C-c C-a} +%\key{show branches}{C-c C-k} + +\section{Motion} + +\key{next heading}{C-c C-n} +\key{previous heading}{C-c C-p} +\key{next heading, same level}{C-c C-f} +\key{previous heading, same level}{C-c C-b} +\key{backward to higher level heading}{C-c C-u} +\key{jump to another place in document}{C-c C-j} + +\section{Structure Editing} + +\key{insert new heading/item at current level}{M-RET} +\key{insert new TODO entry}{M-S-RET} + +\key{promote current heading up one level}{M-LEFT} +\key{demote current heading down one level}{M-RIGHT} +\key{promote current subtree up one level}{M-S-LEFT} +\key{demote current subtree down one level}{M-S-RIGHT} + +\key{move subtree/list item up}{M-S-UP} +\key{move subtree/list item down}{M-S-DOWN} +\key{kill subtree}{C-c C-x C-w} +\key{copy subtree}{C-c C-x M-w} +\key{yank subtree}{C-c C-x C-y} + +\key{archive subtree}{C-c \$} +To set archive location for current file, add a line like$^3$: +\vskip -1mm +\beginexample% +\#+ARCHIVE: archfile::* Archived Tasks +\endexample + +\section{Filtering and Sparse Trees} + +\key{show sparse tree for all matches of a regexp}{C-c /} +\key{view TODO's in sparse tree}{C-c C-v} +\key{global TODO list in agenda mode}{C-c t$^2$} +\key{create sparse tree with all deadlines due}{C-c C-w} +\key{time sorted view of current org file}{C-c C-r} +%\key{agenda for the week}{C-c a$^2$} +%\key{agenda for date at cursor}{C-c C-o} + +\section{Tags} + +\key{set tags for current heading}{C-c C-c} +\key{realign tags in all headings}{C-u C-c C-c} +\key{create sparse tree with matching tags}{C-c \\} +\key{globally (agenda) match tags at cursor}{C-c C-o} + +\section{TODO Items} + +\key{rotate the state of the current item}{C-c C-t} +\key{view TODO items in a sparse tree}{C-c C-v} +\key{view 3rd TODO keyword's sparse tree}{C-3 C-c C-v} + +\key{set the priority of the current item}{C-c , [ABC]} +\key{remove priority cookie from current item}{C-c , SPC} +\key{raise priority of current item}{S-UP$^4$} +\key{lower priority of current item}{S-DOWN$^4$} + +\key{\kbd{\#+SEQ_TODO: TODO TRY BLUFF DONE}}{\rm todo workflow} +\key{\kbd{\#+TYP_TODO: Phil home work DONE}}{\rm todo types} + +\section{Timestamps} + +\key{prompt for date and insert timestamp}{C-c .} +\key{like \kbd{C-c} . but insert date and time format}{C-u C-c .} +\key{Like \kbd{C-c .} but make stamp inactive}{C-c !} % FIXME +\key{insert DEADLINE timestamp}{C-c C-d} +\key{insert SCHEDULED timestamp}{C-c C-s} +\key{create sparse tree with all deadlines due}{C-c C-w} +\key{the time between 2 dates in a time range}{C-c C-y} +\key{change timestamp at cursor by $-1$ day}{S-LEFT$^4$} +\key{change timestamp at cursor by $+1$ day}{S-RIGHT$^4$} +\key{change year/month/day at cursor by $-1$}{S-DOWN$^4$} +\key{change year/month/day at cursor by $+1$}{S-UP$^4$} +\key{access the calendar for the current date}{C-c >} +\key{insert timestamp matching date in calendar}{C-c <} +\key{access agenda for current date}{C-c C-o} +\key{Select date while prompted}{mouse-1/RET} +%\key{... select date in calendar}{mouse-1/RET} +%\key{... scroll calendar back/forward one month}{< / >} +%\key{... forward/backward one day}{S-LEFT/RIGHT} +%\key{... forward/backward one week}{S-UP/DOWN} +%\key{... forward/backward one month}{M-S-LEFT/RIGT} + +\section{Links} + +\key{globally store link to the current location}{C-c l$^2$} +\key{insert a link (TAB completes stored links)}{C-c C-l} +\key{insert file link with file name completion}{C-u C-c C-l} + +\key{open file links in emacs (\kbd{C-u} : in emacs)}{C-c C-o} +\key{open link at point (3: in emacs)}{mouse-2/3} +%\key{open file links in emacs}{mouse-3} +\key{record a position in mark ring}{C-c \%} +\key{jump back to last followed link(s)}{C-c \&} + +{\bf Internal Links} + +\key{\kbd{<>}}{\rm target} +\key{\kbd{<<>>}}{\rm radio target$^3$} +\key{\kbd{[[*this text]]}}{\rm find headline} +\metax{\kbd{[[this text]]}}{\rm find target or text in buffer} + +{\bf External Links} + +\key{\kbd{}}{\rm file, absolute} +\key{\kbd{}}{\rm file, relative} +\key{\kbd{}}{\rm find headline} +\key{\kbd{}}{\rm find tgt/string} +\key{\kbd{}}{\rm regexp search} +\key{\kbd{}}{\rm on the web} +\key{\kbd{}}{\rm EMail address} +\key{\kbd{}}{\rm Usenet group} +\key{\kbd{}}{\rm BBDB person} +\key{\kbd{}}{\rm shell command} +\key{\kbd{}}{\rm GNUS group} +\key{\kbd{}}{\rm GNUS message} +\key{\kbd{}}{\rm Mail folder} +\key{\kbd{}}{\rm Mail message} +%\key{\kbd{}}{\rm VM remote} + +\section{Tables} + +%Org-mode has its own built-in intuitive table editor with unique +%capabilities. + +{\bf Creating a table} + +\metax{insert a new Org-mode table}{M-x org-table-create} +\metax{... or just start typing, e.g.}{|Name|Phone|Age RET |- TAB} +\key{convert region to table}{C-c C-c} +\key{... separator at least 3 spaces}{C-3 C-c C-c} +%\key{... prompt for separator regexp}{C-u C-c C-c} + +{\bf Commands available inside tables} + +The following commands work when the cursor is {\it inside a table}. +Outside of tables, the same keys may have other functionality. + +{\bf Re-aligning and field motion} + +\key{re-align the table without moving the cursor}{C-c C-c} +\key{re-align the table, move to next field}{TAB} +\key{move to previous field}{S-TAB} +\key{re-align the table, move to next row}{RET} + +{\bf Row and column editing} + +\key{move the current column left}{M-LEFT} +\key{move the current column right}{M-RIGHT} +\key{kill the current column}{M-S-LEFT} +\key{insert new column to left of cursor position}{M-S-RIGHT} + +\key{move the current row up}{M-UP} +\key{move the current row down}{M-DOWN} +\key{kill the current row or horizontal line}{M-S-UP} +\key{insert new row above the current row}{M-S-DOWN} +\key{insert horizontal line below the current row}{C-c -} +\key{insert horizontal line above the current row}{C-u C-c -} +\key{sort lines in region}{C-c \^{}} + +{\bf Regions} + +\key{cut rectangular region}{C-c C-x C-w} +\key{copy rectangular region}{C-c C-x M-w} +\key{paste rectangular region}{C-c C-x C-y} +\key{fill paragraph across selected cells}{C-c C-q} + +{\bf Calculations} + +These need the Emacs calc package installed. + +\key{set and eval column formula}{C-c =} +\key{set and eval named-field formula}{C-u C-c =} +\key{edit formulas in separate buffer}{C-c '} +\key{re-apply all stored equations to current line}{C-c *} +\key{re-apply all stored equations to entire table}{C-u C-c *} + +\kbd{TAB}, \kbd{RET} and \kbd{C-c C-c} trigger automatic recalculation +in lines starting with: {\tt | \# |}. + +\key{rotate calculation mark through \# * ! \^ \_ \$}{C-\#} + +\key{display column number cursor is in}{C-c ?} +\key{sum numbers in current column/rectangle}{C-c +} +\key{copy down with increment}{S-RET$^4$} + +A formula can also be typed directly into into a field and will +executed by \kbd{TAB}, \kbd{RET} and \kbd{C-c C-c}. A leading \kbd{=} +introduces a column formula, \kbd{:=} a named-field formula. + +\key{Example: Add Col1 and Col2}{=\$1+\$2} +\key{... with printf format specification}{=\$1+\$2;\%.2f} +\key{... with constants from constants.el}{=\$1/\$c/\$cm} +\key{sum from 3rd hline above to here}{:=vsum(\&III)} +\key{apply current column formula}{=} + +{\bf Miscellaneous} + +\key{toggle visibility of vertical lines}{C-c |} +\metax{export as tab-separated file}{M-x org-table-export} +\metax{import tab-separated file}{M-x org-table-import} + +{\bf Tables created with the \kbd{table.el} package} + +\key{insert a new \kbd{table.el} table}{C-c ~} +\key{recognize existing table.el table}{C-c C-c} +\key{convert table (Org-mode $\leftrightarrow$ table.el)}{C-c ~} + +\newcolumn +\title{Org-Mode Reference Card (2/2)} + +\centerline{(for version \orgversionnumber)} + +\section{Agenda Views} + +\key{add/move current file to front of agenda}{C-c [} +\key{remove current file from your agenda}{C-c ]} +\key{cycle through agenda file list}{C-,} + +\key{compile agenda for the current week}{C-c a a$^2$} +\key{compile global TODO list}{C-c a t$^2$} +\key{compile TODO list for specific keyword}{C-c a T$^2$} +\key{match tags in agenda files}{C-c a m$^2$} +\key{agenda for date at cursor}{C-c C-o} +\key{show timeline of current org file}{C-c C-r} + +\vskip 1mm +To set categories, add lines like$^3$: +\vskip -1mm +\beginexample% +\#+CATEGORY: MyCateg +\endexample + +{\bf Commands available in an agenda buffer} + +{\bf View Org file} + +\key{show original location of item}{SPC} +\key{... also available with}{mouse-3} +\key{show and recenter window}{L} +\key{goto original location in other window}{TAB} +\key{... also available with}{mouse-2} +\key{goto original location, delete other windows}{RET} +\key{toggle follow-mode}{f} + +{\bf Change display} + +\key{delete other windows}{o} +\key{switch to daily / weekly view}{d / w} +\key{toggle inclusion of diary entries}{D} +\key{toggle time grid for daily schedule}{g} +\key{toggle display of logbook entries}{l} +\key{refresh agenda buffer with any changes}{r} +\key{display the following \kbd{org-agenda-ndays}}{RIGHT} +\key{display the previous \kbd{org-agenda-ndays}}{LEFT} +\key{goto today}{.} + +{\bf Remote editing} + +\key{digit argument}{0-9} +\key{change state of current TODO item}{t} +\key{show tags of current headline}{T} +\key{set tags for current headline}{:} +\key{set priority of current item}{p} +\key{raise/lower priority of current item}{S-UP/DOWN$^4$} +%\key{lower priority of current item}{S-DOWN$^4$} +\key{display weighted priority of current item}{P} +\key{change timestamp to one day earlier/later}{S-LEFT/RIGHT$^4$} +%\key{change timestamp to one day earlier}{S-LEFT$^4$} +%\key{change timestamp to one day later}{S-RIGHT$^4$} +\key{change timestamp to today}{>} +\key{insert new entry into diary}{i} + +{\bf Calendar commands} + +\key{find agenda cursor date in calendar}{c} +\key{compute agenda for calendar cursor date}{c} +\key{show phases of the moon}{M} +\key{show sunrise/sunset times}{S} +\key{show holidays}{H} +\key{convert date to other calendars}{C} + +{\bf Quit and Exit} + +\key{quit agenda, remove agenda buffer}{q} +\key{exit agenda, remove all agenda buffers}{x} + +\section{Exporting} + +Exporting creates files with extensions {\it .txt\/} and {\it .html\/} +in the current directory. + +\key{export as ASCII file}{C-c C-x a} +\key{export visible text only (e.g. for printing)}{C-c C-x v} +\key{export as HTML file}{C-c C-x h} +\key{export as HTML and open in browser}{C-c C-x b} +\key{prefix arg sets nb. of headline levels, e.g.}{C-3 C-c C-x h} + +\key{export as iCalendar file}{C-c C-x i} +\key{export all agenda files as iCalendar files}{C-c C-x C-i} +\key{combine all agenda files to single iCal file}{C-c C-x C-c} + +\key{insert template of export options}{C-c C-x t} + +\key{toggle fixed width for entry or region}{C-c :} + +{\bf HTML formatting} + +\key{make words {\bf bold}}{*bold*} +\key{make words {\it italic}}{/italic/} +\key{make words \underbar{underlined}}{_underlined_} +\key{sub- and superscripts}{x\^{}3, J_dust} +\key{\TeX{}-like macros}{\\alpha, \\to} +\key{typeset lines in fixed width font}{start with :} +\key{tables are exported as HTML tables}{start with |} +\key{links become HTML links}{http:... etc} +\key{include html tags}{@...@} + +{\bf Export options} + +Include additional information for export by putting these anywhere in the +org file. Use {\tt M-TAB} completion to make sure to get the right +keywords. {\tt M-TAB} again just after keyword is complete inserts examples. + +\key{the title to be shown}{\#+TITLE:} +\key{the author}{\#+AUTHOR:} +\key{authors email address}{\#+EMAIL:} +\key{language code for html}{\#+LANGUAGE:} +\key{free text description of file}{\#+TEXT:} +\key{... which can carry over multiple lines}{\#+TEXT:} +\key{settings for the export process - see below}{\#+OPTIONS:} + +{\bf Settings for the OPTIONS line} + +\key{set number of headline levels for export}{H:2} +\key{turn on/off section numbers}{num:t} +\key{turn on/off table of contents}{toc:t} +\key{turn on/off linebreak preservation}{\\n:nil} +\key{turn on/off quoted html tags}{@:t} +\key{turn on/off fixed width sections}{::t} +\key{turn on/off tables}{|:t} +\key{turn on/off \TeX\ syntax for sub/super-scripts}{\^{}:t} +\key{turn on/off emphasised text}{*:nil} +\key{turn on/off \TeX\ macros}{TeX:t} + +{\bf Comments: Text not being exported} + +Text before the first headline is not considered part of the document +and is therefore never exported. +Lines starting with \kbd{\#} are comments and are not exported. +Subtrees whose header starts with COMMENT are never exported. + +\key{toggle COMMENT keyword on entry}{C-c ;} + +\section{Completion} + +In-buffer completion completes TODO keywords at headline start, TeX +macros after ``{\tt \\}'', option keywords after ``{\tt \#-}'', TAGS +after ``{\tt :}'', and dictionary words elsewhere. + +\key{Complete word at point}{M-TAB} + +\newcolumn + +\section{Calendar and Diary Integration} + +To include entries from the Emacs diary in your Org-mode agenda: +\beginexample% +(setq org-agenda-include-diary t) +\endexample + +To include the Org-mode agenda in the normal diary, make sure you're +using the fancy diary display +% +%\beginexample% +%(add-hook 'diary-display-hook 'fancy-diary-display) +%\endexample +% +and in the \kbd{~/diary} file add + +\beginexample% +\&\%\%(org-diary) +\endexample + +to include all the files listed in \kbd{org-agenda-files}. For more +selective file inclusion use a line for each file: + +\beginexample% +\&\%\%(org-diary) ~/path/to/some/org-file.org +\endexample + +\section{Remember-mode Integration} + +See the manual for how to make remember.el use Org-mode links and +files. The note-finishing command \kbd{C-c C-c} will first prompt for +an org file. In the file, find a location with: + +\key{rotate subtree visibility}{TAB} +\key{next heading}{DOWN} +\key{previous heading}{UP} + +Insert the note with one of the following: + +\key{as sublevel of heading at cursor}{RET} +\key{right here (cursor not on heading)}{RET} +\key{before current heading}{LEFT} +\key{after current heading}{RIGHT} +\key{shortcut to end of buffer (cursor at buf-start)}{RET} +\key{Abort}{q} + +\section{CUA and pc-select compatibility} + +Configure the variable {\tt org-CUA-compatibility} to make Org-mode +avoid the \kbd{S-} bindings used by these modes. When set, +Org-mode will change the following keybindings (also in the agenda +buffer, but not during date selection). See note mark four$^4$ +throughout the reference card. +%\vskip-mm +\beginexample +S-UP $\to$ M-p S-DOWN $\to$ M-n +S-LEFT $\to$ M-- S-RIGHT $\to$ M-+ +S-RET $\to$ C-S-RET +\endexample + +\section{Notes} +$^1$ The six autoload forms are only needed if Org-mode is not part of +Emacs, or an XEmacs package. + +$^2$ This is only a suggestion for a binding of this command. Choose +you own key as shown under INSTALLATION. + +$^3$ After changing a \kbd{\#+KEYWORD} or \kbd{<<>>} line, +press \kbd{C-c C-c} with the cursor still in the line to update. + +$^4$ Keybinding affected by {\tt org-CUA-compatibility}. + +\copyrightnotice + +\bye + + +% arch-tag: 139f6750-5cfc-49ca-92b5-237fe5795290 + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: