Update to Org 9.4.1

This commit is contained in:
Bastien Guerry 2020-12-13 13:44:15 +01:00
parent 6aa9fe3e1b
commit f22856a5c5
118 changed files with 9010 additions and 6270 deletions

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,546 @@ See the end of the file for license conditions.
Please send Org bug reports to mailto:emacs-orgmode@gnu.org. Please send Org bug reports to mailto:emacs-orgmode@gnu.org.
* Version 9.4
** Incompatible changes
*** Possibly broken internal file links: please check and fix
A bug has been affecting internal links to headlines, like
: [[*Headline][A link to a headline]]
Storing a link to a headline may have been broken in your setup and
those links may appear as
: [[*TODO Headline][A link to a headline]]
Following the link above will result in an error: the TODO keyword
should not be part of internal file links.
You can use the following command to fix links in an Org buffer:
#+begin_src emacs-lisp
(defun org-fix-links ()
"Fix ill-formatted internal links.
E.g. replace [[*TODO Headline][headline]] by [[*Headline][headline]].
Go through the buffer and ask for the replacement."
(interactive)
(visible-mode 1)
(save-excursion
(goto-char (point-min))
(let ((regexp (format "\\[\\[\\*%s\\s-+"
(regexp-opt org-todo-keywords-1 t))))
(while (re-search-forward regexp nil t)
(when (and (save-excursion
(goto-char (match-beginning 0))
(looking-at-p org-link-bracket-re))
(y-or-n-p "Fix link (remove TODO keyword)? "))
(replace-match "[[*")))))
(visible-mode -1))
#+end_src
*** Calling conventions changes when opening or exporting custom links
This changes affects export back-ends, and libraries providing new
link types.
Function used in ~:follow~ link parameter is required to accept a
second argument. Likewise, function used in ~:export~ parameter needs
to accept a fourth argument. See ~org-link-set-parameters~ for
details.
Eventually, the function ~org-export-custom-protocol-maybe~ is now
called with a fourth argument. Even though the 3-arguments definition
is still supported, at least for now, we encourage back-end developers
to switch to the new signature.
*** Python session return values must be top-level expression statements
Python blocks with ~:session :results value~ header arguments now only
return a value if the last line is a top-level expression statement.
Also, when a None value is returned, "None" will be printed under
"#+RESULTS:", as it already did with ~:results value~ for non-session
blocks.
*** In HTML export, change on how outline-container-* is set
When the headline has a =CUSTOM_ID=, use this custom id to build the
div id. For example, if you have =:CUSTOM_ID: my-headline= then the
resulting <div> will be ~<div id="outline-container-my-headline">~.
You may want to check whether your HTML files are rendered differently
after this change.
*** New keybinding =<C-c C-TAB>= for ~org-force-cycle-archived~
~org-force-cycle-archived~ used to be associated with =<C-TAB>= but
this keybinding is used in Emacs for navigating tabs in Emacs. The
new keybinding is =<C-c C-TAB>=.
** New default settings for some options
These options now default to =t=:
- ~org-loop-over-headlines-in-active-region~
- ~org-fontify-done-headline~
- ~org-src-tab-acts-natively~
You may want to read the docstrings of these options to understand the
consequences of this change.
Also, ~org-startup-folded~ now defaults to ~showeverything~.
** New features
*** Looping agenda commands over headlines
~org-agenda-loop-over-headlines-in-active-region~ allows you to loop
agenda commands over the active region.
When set to =t= (the default), loop over all headlines. When set to
='start-level=, loop over headlines with the same level as the first
headline in the region. When set to a string, loop over lines
matching this regular expression.
*** New minor mode ~org-table-header-line-mode~
Turn on the display of the first data row of the table at point in the
window header line when this first row is not visible anymore in the
buffer.
You can activate this minor mode by default by setting the option
~org-table-header-line-p~ to =t=. You can also change the face for
the header line by customizing the ~org-table-header~ face.
*** New minor mode ~org-list-checkbox-radio-mode~
When this minor mode is on, checkboxes behave as radio buttons: if a
checkbox is turned on, other checkboxes at the same level are turned
off.
If you want to occasionally toggle a checkbox as a radio button
without turning this minor mode on, you can use =<C-c C-x C-r>= to
call ~org-toggle-radio-button~.
You can also add =#+ATTR_ORG: :radio t= right before the list to tell
Org to use radio buttons for this list only.
*** New allowed value for ~org-adapt-indentation~
~org-adapt-indentation~ now accepts a new value, ='headline-data=.
When set to this value, Org will only adapt indentation of headline
data lines, such as planning/clock lines and property/logbook drawers.
Also, with this setting, =org-indent-mode= will keep these data lines
correctly aligned with the headline above.
*** Numeric priorities are now allowed (up to 65)
You can now set ~org-priority-highest/lowest/default~ to integers to
use numeric priorities globally or set, for example
#+PRIORITIES: 1 10 5
to define a buffer-local range and default for priorities. Priority
commands should work as usual. You cannot use numbers superior to 64
for numeric priorities, as it would clash with priorities like [#A]
where the "A" is internally converted to its numeric value of 65.
*** Property drawers allowed before first headline
Property drawers are now allowed before the first headline.
Org mode is moving more towards making things before the first
headline behave just as if it was at outline level 0. Inheritance for
properties will work also for this level. In other words: defining
things in a property drawer before the first headline will make them
"inheritable" for all headlines.
*** Refinement in window behavior on exiting Org source buffer
After editing a source block, Org will restore the window layout when
~org-src-window-setup~ is set to a value that modifies the layout.
*** Display remote inline images
Org now knows how to display remote images inline.
Whether the images are actually displayed is controlled by the new
option ~org-display-remote-inline-images~.
*** New option to resolve open clock at a provided time
~org-resolve-clocks~ now has a `t' option, which works just like the
`k' option, but the user specifies a time of day, not a number of
minutes.
*** New step value =semimonth= accepted for clock tables
*** Allow text rescaling in column view
You can now use =C-x C-+= in column view: the columns face size will
increase or decrease, together with the column header size.
*** New startup option =#+startup: num=
When this startup option is set, display headings as numerated.
Use =#+startup: nonum= to turn this off.
*** New tool for custom links
Org provides a new tool ~org-link-open-as-file~, useful when defining
new link types similar to "file"-type links. See docstring for
details.
*** New optional numeric argument for ~org-return~
In situations where ~org-return~ calls ~newline~, multiple newlines
can now be inserted with this prefix argument.
*** New source code block header argument =:file-mode=
Source code block header argument =:file-mode= can set file
permissions if =:file= argument is provided.
*** =RET= and =C-j= now obey ~electric-indent-mode~
Since Emacs 24.4, ~electric-indent-mode~ is enabled by default. In
most major modes, this causes =RET= to reindent the current line and
indent the new line, and =C-j= to insert a newline without indenting.
Org mode now obeys this minor mode: when ~electric-indent-mode~ is
enabled, and point is neither in a table nor on a timestamp or a link:
- =RET= (bound to ~org-return~) reindents the current line and indents
the new line;
- =C-j= (bound to the new command ~org-return-and-maybe-indent~)
merely inserts a newline.
To get the previous behaviour back, disable ~electric-indent-mode~
explicitly:
#+begin_src emacs-lisp
(add-hook 'org-mode-hook (lambda () (electric-indent-local-mode -1)))
#+end_src
Alternatively, if you wish to keep =RET= as the "smart-return" key,
but dislike Org's default indentation of sections, you may prefer to
customize ~org-adapt-indentation~ to either =nil= or ='headline-data=.
*** =ob-C.el= allows the inclusion of non-system header files
In C and C++ blocks, ~:includes~ arguments that do not start with a
~<~ character will now be formatted as double-quoted ~#include~
statements.
*** =ob-clojure.el= supports inf-clojure.el and ClojureScript evaluation
You can now set ~(setq org-babel-clojure-backend 'inf-clojure)~ and
evaluate Clojure source blocks using [[https://github.com/clojure-emacs/inf-clojure][inf-clojure]]. With a header
argument like =:alias "alias"= the Clojure REPL will boot with
=clojure -Aalias=. Otherwise Clojure will boot with =lein=, =boot= or
=tools.deps=, depending on whether the current directory contains a
=project.clj=, =build.boot= or =deps.edn=, falling back on
~inf-clojure-generic-cmd~ in case no such file is present.
Also, when using [[https://github.com/clojure-emacs/cider][cider]], you can now use =#+begin_src clojurescript= to
execute ClojureScript code from Org files. Note that this works only
if your Org file is associated with a cider session that knows how to
run ClojureScript code. A bare =lein repl= session outside of a
directory configured for ClojureScript will /not/ work.
*** =ob-java.el= supports Java command line arguments
Babel Java blocks recognize header argument =:cmdargs= and pass its
value in call to =java=.
*** =ob-screen.el= now accepts =:screenrc= header argument
Screen blocks now recognize the =:screenrc= header argument and pass
its value to the screen command via the "-c" option. The default
remains =/dev/null= (i.e. a clean screen session)
*** =ob-plantuml=: now supports using PlantUML executable to generate diagrams
Set =org-plantuml-exec-mode= to ='plantuml= in order to use the
executable instead of JAR. When using an executable it is also
possible to configure executable location as well as arguments via:
=org-plantuml-executable-path= and =org-plantuml-executable-args=.
** New commands
*** ~org-table-header-line-mode~
Turn on a minor mode to display the first data row of the table at
point in the header-line when the beginning of the table is invisible.
*** ~org-agenda-ctrl-c-ctrl-c~
Hitting =<C-c C-c>= in an agenda view now calls ~org-agenda-set-tags~.
*** ~org-hide-entry~
This command is the counterpart of ~org-show-entry~.
*** ~org-columns-toggle-or-columns-quit~
=<C-c C-c>= bound to ~org-columns-toggle-or-columns-quit~ replaces the
recent ~org-columns-set-tags-or-toggle~. Tag setting is still
possible via column view value edit or with =<C-c C-q>=.
*** ~org-datetree-find-month-create~
Find or create a month entry for a date.
** New options and settings
*** New option ~org-html-prefer-user-labels~
When non-nil, use =NAME= affiliated keyword, or raw target values, to
generate anchor's ID. Otherwise, consistently use internal naming
scheme.
=CUSTOM_ID= values are still always used, when available.
*** New option for using tabs in ~org-agenda-window-setup~
Choosing ~other-tab~ for ~org-agenda-window-setup~ will open the
agenda view in a new tab. This will work with versions of Emacs since
27.1 when ~tab-bar-mode~ was introduced.
*** New option ~org-table-header-line-p~
Setting this option to =t= will activate ~org-table-header-line-mode~
in org-mode buffers.
*** New option ~org-startup-numerated~
When this option is =t=, Org files will start using ~(org-num-mode 1)~
and headings will be visually numerated.
You can turn this on/off on a per-file basis with =#+startup: num= or
=#+startup: nonum=.
*** New option ~org-clock-auto-clockout-timer~
When this option is set to a number and the user configuration
contains =(org-clock-auto-clockout-insinuate)=, Org will clock out the
currently clocked in task after that number of seconds of idle time.
This is useful when you often forget to clock out before being idle
and don't want to have to manually set the clocking time to take into
account.
*** New option to group captured datetime entries by month
A new `:tree-type month' option was added to org-capture-templates to
group new datetime entries by month.
*** New option to show source buffers using "plain" display-buffer
There is a new option ~plain~ to ~org-src-window-setup~ to show source
buffers using ~display-buffer~. This allows users to control how
source buffers are displayed by modifying ~display-buffer-alist~ or
~display-buffer-base-action~.
*** New option ~org-archive-subtree-save-file-p~
Archiving a subtree used to always save the target archive buffer.
Commit [[https://code.orgmode.org/bzg/org-mode/commit/b186d1d7][b186d1d7]] changed this behavior by always not saving the target
buffer, because batch archiving from agenda could take too much time.
This new option ~org-archive-subtree-save-file-p~ defaults to the
value =from-org= so that archiving a subtree will save the target
buffer when done from an org-mode buffer, but not from the agenda.
You can also set this option to =t= or to =from-agenda=.
*** New option ~org-show-notification-timeout~
This option will add a timeout to notifications.
*** New option ~org-latex-to-html-convert-command~
This new option allows you to convert a LaTeX fragment directly into
HTML.
*** New option ~org-babel-shell-results-defaults-to-output~
By default, source code blocks are executed in "functional mode": it
means that the results of executing them are the value of their last
statement (see [[https://orgmode.org/manual/Results-of-Evaluation.html][the documentation]].)
The value of a shell script's execution is its exit code. But most
users expect the results of executing a shell script to be its output,
not its exit code.
So we introduced this option, that you can set to =nil= if you want
to stick using ~:results value~ as the implicit header.
In all Babel libraries, the absence of a ~:results~ header should
produce the same result than setting ~:results value~, unless there is
an option to explicitly create an exception.
See [[https://orgmode.org/list/CA+A2iZaziAfMeGpBqL6qGrzrWEVvLvC0DUw++T4gCF3NGuW-DQ@mail.gmail.com/][this thread]] for more context.
*** New option in ~org-attach-store-link-p~
~org-attach-store-link-p~ has a new option to store a file link to the
attachment.
*** New option ~org-fontify-todo-headline~
This feature is the same as ~org-fontify-done-headline~, but for TODO
headlines instead. This allows you to distinguish TODO headlines from
normal headlines. The face can be customized via ~org-headline-todo~.
*** New default value for ~org-file-apps~
The new value uses Emacs as the application for opening directory.
*** New hook ~org-agenda-filter-hook~
Functions in this hook are run after ~org-agenda-filter~ is called.
** Removed or renamed functions and variables
*** Deprecated ~org-flag-drawer~ function
Use ~org-hide-drawer-toggle~ instead.
*** Deprecated ~org-hide-block-toggle-maybe~ function
Use ~org-hide-block-toggle~ instead.
*** Deprecated ~org-hide-block-toggle-all~ function
This function was not used in the code base, and has no clear use
either. It has been marked for future removal. Please contact the
mailing list if you use this function.
*** Deprecated ~org-return-indent~ function
In Elisp code, use ~(org-return t)~ instead. Interactively, =C-j= is
now bound to ~org-return-and-maybe-indent~, which indents the new line
when ~electric-indent-mode~ is disabled.
*** Removed ~org-maybe-keyword-time-regexp~
The variable was not used in the code base.
*** Removed ~org-export-special-keywords~
The variable was not used in the code base.
*** Renamed ~org-at-property-block-p~
The new name is ~org-at-property-drawer-p~, which is less confusing.
*** Renamed ~org-columns-set-tags-or-toggle~
See [[*~org-columns-toggle-or-columns-quit~]].
*** Renamed priority options
From ~org-lowest-priority~ to ~org-priority-lowest~.
From ~org-default-priority~ to ~org-priority-default~.
From ~org-highest-priority~ to ~org-priority-highest~.
From ~org-enable-priority-commands~ to ~org-priority-enable-commands~.
From ~org-show-priority~ to ~org-priority-show~.
** Miscellaneous
*** =ob-screen.el= now respects screen =:session= name
Screen babel session are now named based on the =:session= header
argument (defaults to ~default~).
Previously all session names had ~org-babel-session-~ prepended.
*** Forward/backward paragraph functions in line with the rest of Emacs
~org-forward-paragraph~ and ~org-backward-paragraph~, bound to
~<C-UP>~ and ~<C-DOWN>~ functions mimic more closely behaviour of
~forward-paragraph~ and ~backward-paragraph~ functions when
available.
They also accept an optional argument for multiple calls.
See their docstring for details.
*** ~org-table-to-lisp~ no longer checks if point is at a table
The caller is now responsible for the check. It can use, e.g.,
~org-at-table-p~.
The function is also much more efficient than it used to be, even on
very large tables.
*** New function ~org-collect-keywords~
*** Drawers' folding use an API similar to block's
Tooling for folding drawers interactively or programmatically is now
on par with block folding. In particular, ~org-hide-drawer-toggle~,
a new function, is the central place for drawer folding.
*** Duration can be read and written in compact form
~org-duration-to-minutes~ understands =1d3h5min= as a duration,
whereas ~org-duration-from-minutes~ can output this compact form if
the duration format contains the symbol ~compact~.
*** C-n, C-p, SPC and DEL in agenda commands dispatch window
You can now use =<C-n>=, =<C-p>=, =<SPC>= and =<DEL>= key to scroll up
and down the agenda and attach dispatch window.
*** =<C-c C-c>= in agenda calls ~org-agenda-set-tags~
Both =<C-c C-q>= and =<C-c C-c>= set the tags of the headline in the
Org buffer. Both keybindings are now available from the agenda too.
*** Allow to use an empty HTML extension
Using =(setq org-html-extension "")= or setting the HTML extension in
any fashion will produce the expected output, with no trailing period
to the resulting HTML file.
*** Handle repeated tasks with =.+= type and hours step
A task using a =.+= repeater and hours step is repeated starting from
now. E.g.,
#+begin_example
,,** TODO Wash my hands
DEADLINE: <2019-04-05 08:00 Sun .+1h>
Marking this DONE shifts the date to exactly one hour from now.
#+end_example
*** The format of equation reference in HTML export can now be specified
By default, HTML (via MathJax) and LaTeX export equation references
using different commands. LaTeX must use ~\ref{%s}~ because it is used
for all labels; however, HTML (via MathJax) uses ~\eqref{%s}~ for
equations producing inconsistent output. New option
~org-html-equation-reference-format~ sets the command used in HTML
export.
*** =ob-haskell.el= supports compilation with =:compile= header argument
By default, Haskell blocks are interpreted. By adding =:compile yes=
to a Haskell source block, it will be compiled, executed and the
results will be displayed.
*** Support for ~org-edit-special~ with LaTeX fragments
Calling ~org-edit-special~ on an inline LaTeX fragment calls a new
function, ~org-edit-latex-fragment~. This functions in a comparable
manner to editing inline source blocks, bringing up a minibuffer set
to LaTeX mode. The math-mode deliminators are read only.
*** ~org-capture-current-plist~ is now accessible during ~org-capture-mode-hook~
*** New =org-refile.el= file
Org refile variables and functions have been moved to a new file.
*** The end of a 7 years old bug
This bug [[https://lists.gnu.org/archive/html/emacs-orgmode/2013-08/msg00072.html][originally reported]] by Matt Lundin and investigated by Andrew
Hyatt has been fixed. Thanks to both of them.
* Version 9.3 * Version 9.3
** Incompatible changes ** Incompatible changes
@ -19,15 +559,11 @@ Org used to percent-encode sensitive characters in the URI part of the
bracket links. bracket links.
Now, escaping mechanism uses the usual backslash character, according Now, escaping mechanism uses the usual backslash character, according
to the following rules, applied in order: to the following rules:
1. All consecutive =\= characters at the end of the link must be 1. All =[= and =]= characters in the URI must be escaped;
escaped; 2. Every =\= character preceding either =[= or =]= must be escaped;
2. Any =]= character at the very end of the link must be escaped; 3. Every =\= character at the end of the URI must be escaped.
3. All consecutive =\= characters preceding =][= or =]]= patterns must
be escaped;
4. Any =]= character followed by either =[= or =]= must be escaped;
5. Others =]= and =\= characters need not be escaped.
When in doubt, use the function ~org-link-escape~ in order to turn When in doubt, use the function ~org-link-escape~ in order to turn
a link string into its properly escaped form. a link string into its properly escaped form.
@ -141,7 +677,7 @@ Export ignore done tasks with a deadline when
Likewise, scheduled done tasks are also ignored when Likewise, scheduled done tasks are also ignored when
~org-icalendar-use-scheduled~ contains the same symbol. ~org-icalendar-use-scheduled~ contains the same symbol.
*** Add split-window-right option for src block edit window placement *** Add ~split-window-right~ option for src block edit window placement
Given the increasing popularity of wide screen monitors, splitting Given the increasing popularity of wide screen monitors, splitting
horizontally may make more sense than splitting vertically. An horizontally may make more sense than splitting vertically. An
@ -364,7 +900,6 @@ the headline to use for making the table of contents.
,* Another section ,* Another section
,#+TOC: headlines 1 :target "#TargetSection" ,#+TOC: headlines 1 :target "#TargetSection"
#+end_example #+end_example
** New functions ** New functions
*** ~org-dynamic-block-insert-dblock~ *** ~org-dynamic-block-insert-dblock~
@ -474,6 +1009,16 @@ I.e. treat the whole file as if it was a subtree.
*** Respect narrowing when agenda command is restricted to buffer *** Respect narrowing when agenda command is restricted to buffer
*** ~org-table-insert-column~ inserts the column at point position
Before, the new column was inserted to the right of the column at
point position.
*** Table column deletion now consistent with row deletion
Point stays in the column at deletion, except when deleting the
rightmost column.
* Version 9.2 * Version 9.2
** Incompatible changes ** Incompatible changes
*** Removal of OrgStruct mode mode and radio lists *** Removal of OrgStruct mode mode and radio lists
@ -484,7 +1029,7 @@ and ~org-list-radio-lists-templates~) are removed from the code base.
Note that only radio /lists/ have been removed, not radio tables. Note that only radio /lists/ have been removed, not radio tables.
If you want to manipulate lists like in Org in other modes, we suggest If you want to manipulate lists like in Org in other modes, we suggest
to use orgalist.el, which you can install from GNU ELPA. to use =orgalist.el=, which you can install from GNU ELPA.
If you want to use Org folding outside of Org buffers, you can have a If you want to use Org folding outside of Org buffers, you can have a
look at the outshine package in the MELPA repository. look at the outshine package in the MELPA repository.
@ -1276,9 +1821,9 @@ removed from Gnus circa September 2010.
*** ~org-agenda-repeating-timestamp-show-all~ is removed. *** ~org-agenda-repeating-timestamp-show-all~ is removed.
For an equivalent to a ~nil~ value, set For an equivalent to a =nil= value, set
~org-agenda-show-future-repeats~ to nil and ~org-agenda-show-future-repeats~ to nil and
~org-agenda-prefer-last-repeat~ to ~t~. ~org-agenda-prefer-last-repeat~ to =t=.
*** ~org-gnus-nnimap-query-article-no-from-file~ is removed. *** ~org-gnus-nnimap-query-article-no-from-file~ is removed.
@ -1296,7 +1841,7 @@ equivalent to the removed format string.
*** ~org-enable-table-editor~ is removed. *** ~org-enable-table-editor~ is removed.
Setting it to a ~nil~ value broke some other features (e.g., speed Setting it to a =nil= value broke some other features (e.g., speed
keys). keys).
*** ~org-export-use-babel~ cannot be set to ~inline-only~ *** ~org-export-use-babel~ cannot be set to ~inline-only~
@ -1377,16 +1922,20 @@ is now obsolete.
Now ~=...=~ markup uses ~@samp{}~ instead of ~@verb{}~. You can use Now ~=...=~ markup uses ~@samp{}~ instead of ~@verb{}~. You can use
~@verb{}~ again by customizing the variable. ~@verb{}~ again by customizing the variable.
*** Texinfo exports example blocks as ~@example~ *** Texinfo exports example blocks as ~@example~
*** Texinfo exports inline source blocks as ~@code{}~ *** Texinfo exports inline source blocks as ~@code{}~
*** Texinfo default table markup is ~@asis~ *** Texinfo default table markup is ~@asis~
It used to be ~@samp~ but ~@asis~ is neutral and, therefore, more It used to be ~@samp~ but ~@asis~ is neutral and, therefore, more
suitable as a default value. suitable as a default value.
*** Texinfo default process includes ~--no-split~ option *** Texinfo default process includes ~--no-split~ option
*** New entities : ~\dollar~ and ~\USD~ *** New entities : ~\dollar~ and ~\USD~
*** Support for date style URLs in =org-protocol://open-source= *** Support for date style URLs in =org-protocol://open-source=
URLs like =https://cool-blog.com/2017/05/20/cool-post/= are
covered by rewrite rules. URLs like =https://cool-blog.com/2017/05/20/cool-post/= are covered by
rewrite rules.
*** Add (C) =COMMENT= support to ~org-structure-template-alist~ *** Add (C) =COMMENT= support to ~org-structure-template-alist~
@ -1476,7 +2025,7 @@ Moreover, ~:export-block~ keyword used in ~org-export-define-backend~ and
~org-export-define-derived-backend~ is no longer used and needs to be ~org-export-define-derived-backend~ is no longer used and needs to be
removed. removed.
*** Footnotes *** Footnotes changes
**** [1]-like constructs are not valid footnotes **** [1]-like constructs are not valid footnotes
@ -2216,7 +2765,7 @@ without changing the headline.
*** Hierarchies of tags *** Hierarchies of tags
The functionality of nesting tags in hierarchies is added to org-mode. The functionality of nesting tags in hierarchies is added to Org mode.
This is the generalization of what was previously called "Tag groups" This is the generalization of what was previously called "Tag groups"
in the manual. That term is now changed to "Tag hierarchy". in the manual. That term is now changed to "Tag hierarchy".
@ -4105,7 +4654,7 @@ See https://orgmode.org/elpa/
You can temporarily activate continuous clocking with =C-u C-u You can temporarily activate continuous clocking with =C-u C-u
C-u M-x= [[doc::org-clock-in][org-clock-in]] =RET= (three universal prefix arguments) C-u M-x= [[doc::org-clock-in][org-clock-in]] =RET= (three universal prefix arguments)
and =C-u C-u M-x= [[org-clock-in-last][org-clock-in-last]] =RET= (two universal prefix and =C-u C-u M-x= [[doc::org-clock-in-last][org-clock-in-last]] =RET= (two universal prefix
arguments). arguments).
@ -4581,7 +5130,7 @@ that Calc formulas can operate on them.
The new system has a technically cleaner implementation and more The new system has a technically cleaner implementation and more
possibilities for capturing different types of data. See possibilities for capturing different types of data. See
[[http://thread.gmane.org/gmane.emacs.orgmode/26441/focus%3D26441][Carsten's announcement]] for more details. [[https://orgmode.org/list/C46F10DC-DE51-43D4-AFFE-F71E440D1E1F@gmail.com][Carsten's announcement]] for more details.
To switch over to the new system: To switch over to the new system:
@ -4712,7 +5261,7 @@ that Calc formulas can operate on them.
**** Modified link escaping **** Modified link escaping
David Maus worked on `org-link-escape'. See [[http://article.gmane.org/gmane.emacs.orgmode/37888][his message]]: David Maus worked on `org-link-escape'. See [[https://orgmode.org/list/87k4gysacq.wl%dmaus@ictsoc.de][his message]]:
: Percent escaping is used in Org mode to escape certain characters : Percent escaping is used in Org mode to escape certain characters
: in links that would either break the parser (e.g. square brackets : in links that would either break the parser (e.g. square brackets
@ -5151,7 +5700,7 @@ that Calc formulas can operate on them.
Thanks to Nicolas Goaziou for coding these changes. Thanks to Nicolas Goaziou for coding these changes.
**** A property value of "nil" now means to unset a property **** A property value of =nil= now means to unset a property
This can be useful in particular with property inheritance, if This can be useful in particular with property inheritance, if
some upper level has the property, and some grandchild of it some upper level has the property, and some grandchild of it

View file

@ -1,5 +1,5 @@
% Reference Card for Org Mode % Reference Card for Org Mode
\def\orgversionnumber{9.3} \def\orgversionnumber{9.4.1}
\def\versionyear{2019} % latest update \def\versionyear{2019} % latest update
\input emacsver.tex \input emacsver.tex
@ -17,7 +17,7 @@
\pdflayout=(0l) \pdflayout=(0l)
% Nothing else needs to be changed below this line. % Nothing else needs to be changed below this line.
% Copyright (C) 1987, 1993, 1996--1997, 2001--2020 Free Software % Copyright (C) 1987, 1993, 1996-1997, 2001-2020 Free Software
% Foundation, Inc. % Foundation, Inc.
% This document is free software: you can redistribute it and/or modify % This document is free software: you can redistribute it and/or modify
@ -79,6 +79,9 @@
\centerline{Released under the terms of the GNU General Public License} \centerline{Released under the terms of the GNU General Public License}
\centerline{version 3 or later.} \centerline{version 3 or later.}
\centerline{For more Emacs documentation, and the \TeX{} source for this card, see}
\centerline{the Emacs distribution, or {\tt https://www.gnu.org/software/emacs}}
\endgroup} \endgroup}
% make \bye not \outer so that the \def\bye in the \else clause below % make \bye not \outer so that the \def\bye in the \else clause below
@ -515,7 +518,7 @@ \section{Properties and Column View}
\key{special commands in property lines}{C-c C-c} \key{special commands in property lines}{C-c C-c}
\key{next/previous allowed value}{S-LEFT/RIGHT} \key{next/previous allowed value}{S-LEFT/RIGHT}
\key{turn on column view}{C-c C-x C-c} \key{turn on column view}{C-c C-x C-c}
\key{capture columns view in dynamic block}{C-c C-x i} \key{capture columns view in dynamic block}{C-c C-x x}
\key{quit column view}{q} \key{quit column view}{q}
\key{show full value}{v} \key{show full value}{v}
@ -558,7 +561,7 @@ \section{Timestamps}
\key{stop/cancel clock on current item}{C-c C-x C-o/x} \key{stop/cancel clock on current item}{C-c C-x C-o/x}
\key{display total subtree times}{C-c C-x C-d} \key{display total subtree times}{C-c C-x C-d}
\key{remove displayed times}{C-c C-c} \key{remove displayed times}{C-c C-c}
\key{insert/update table with clock report}{C-c C-x C-r} \key{insert/update table with clock report}{C-c C-x C-x}
\section{Agenda Views} \section{Agenda Views}

View file

@ -182,7 +182,7 @@ or `org-babel-execute:C++' or `org-babel-execute:D'."
cmdline))) cmdline)))
""))) "")))
(when results (when results
(setq results (org-trim (org-remove-indentation results))) (setq results (org-remove-indentation results))
(org-babel-reassemble-table (org-babel-reassemble-table
(org-babel-result-cond (cdr (assq :result-params params)) (org-babel-result-cond (cdr (assq :result-params params))
(org-babel-read results t) (org-babel-read results t)
@ -232,7 +232,13 @@ its header arguments."
(list (list
;; includes ;; includes
(mapconcat (mapconcat
(lambda (inc) (format "#include %s" inc)) (lambda (inc)
;; :includes '(<foo> <bar>) gives us a list of
;; symbols; convert those to strings.
(when (symbolp inc) (setq inc (symbol-name inc)))
(if (string-prefix-p "<" inc)
(format "#include %s" inc)
(format "#include \"%s\"" inc)))
includes "\n") includes "\n")
;; defines ;; defines
(mapconcat (mapconcat

View file

@ -3,6 +3,7 @@
;; Copyright (C) 2011-2020 Free Software Foundation, Inc. ;; Copyright (C) 2011-2020 Free Software Foundation, Inc.
;; Author: Oleh Krehel ;; Author: Oleh Krehel
;; Maintainer: Joseph Novakovich <josephnovakovich@gmail.com>
;; Keywords: literate programming, reproducible research ;; Keywords: literate programming, reproducible research
;; Homepage: https://orgmode.org ;; Homepage: https://orgmode.org
@ -76,6 +77,8 @@ This function is called by `org-babel-execute-src-block'."
(message "executing J source code block") (message "executing J source code block")
(let* ((processed-params (org-babel-process-params params)) (let* ((processed-params (org-babel-process-params params))
(sessionp (cdr (assq :session params))) (sessionp (cdr (assq :session params)))
(sit-time (let ((sit (assq :sit params)))
(if sit (cdr sit) .1)))
(full-body (org-babel-expand-body:J (full-body (org-babel-expand-body:J
body params processed-params)) body params processed-params))
(tmp-script-file (org-babel-temp-file "J-src"))) (tmp-script-file (org-babel-temp-file "J-src")))
@ -86,9 +89,9 @@ This function is called by `org-babel-execute-src-block'."
(with-temp-file tmp-script-file (with-temp-file tmp-script-file
(insert full-body)) (insert full-body))
(org-babel-eval (format "%s < %s" org-babel-J-command tmp-script-file) "")) (org-babel-eval (format "%s < %s" org-babel-J-command tmp-script-file) ""))
(org-babel-J-eval-string full-body))))) (org-babel-J-eval-string full-body sit-time)))))
(defun org-babel-J-eval-string (str) (defun org-babel-J-eval-string (str sit-time)
"Sends STR to the `j-console-cmd' session and executes it." "Sends STR to the `j-console-cmd' session and executes it."
(let ((session (j-console-ensure-session))) (let ((session (j-console-ensure-session)))
(with-current-buffer (process-buffer session) (with-current-buffer (process-buffer session)
@ -96,7 +99,7 @@ This function is called by `org-babel-execute-src-block'."
(insert (format "\n%s\n" str)) (insert (format "\n%s\n" str))
(let ((beg (point))) (let ((beg (point)))
(comint-send-input) (comint-send-input)
(sit-for .1) (sit-for sit-time)
(buffer-substring-no-properties (buffer-substring-no-properties
beg (point-max)))))) beg (point-max))))))

View file

@ -193,7 +193,8 @@ This function is called by `org-babel-execute-src-block'."
(org-babel-comint-in-buffer session (org-babel-comint-in-buffer session
(mapc (lambda (var) (mapc (lambda (var)
(end-of-line 1) (insert var) (comint-send-input nil t) (end-of-line 1) (insert var) (comint-send-input nil t)
(org-babel-comint-wait-for-output session)) var-lines)) (org-babel-comint-wait-for-output session))
var-lines))
session)) session))
(defun org-babel-load-session:R (session body params) (defun org-babel-load-session:R (session body params)
@ -459,11 +460,11 @@ last statement in BODY, as elisp."
"R-specific processing of return value. "R-specific processing of return value.
Insert hline if column names in output have been requested." Insert hline if column names in output have been requested."
(if column-names-p (if column-names-p
(cons (car result) (cons 'hline (cdr result))) (condition-case nil
(cons (car result) (cons 'hline (cdr result)))
(error "Could not parse R result"))
result)) result))
(provide 'ob-R) (provide 'ob-R)
;;; ob-R.el ends here ;;; ob-R.el ends here

View file

@ -4,8 +4,7 @@
;; Author: William Waites ;; Author: William Waites
;; Keywords: literate programming, music ;; Keywords: literate programming, music
;; Homepage: http://www.tardis.ed.ac.uk/wwaites ;; Homepage: https://www.tardis.ed.ac.uk/~wwaites
;; Version: 0.01
;; This file is part of GNU Emacs. ;; This file is part of GNU Emacs.
@ -87,4 +86,5 @@
(error "ABC does not support sessions")) (error "ABC does not support sessions"))
(provide 'ob-abc) (provide 'ob-abc)
;;; ob-abc.el ends here ;;; ob-abc.el ends here

View file

@ -134,6 +134,4 @@ Otherwise, it is either `real', if some elements are floats, or
(provide 'ob-asymptote) (provide 'ob-asymptote)
;;; ob-asymptote.el ends here ;;; ob-asymptote.el ends here

View file

@ -106,6 +106,4 @@ This function is called by `org-babel-execute-src-block'."
(provide 'ob-awk) (provide 'ob-awk)
;;; ob-awk.el ends here ;;; ob-awk.el ends here

View file

@ -105,6 +105,4 @@
(provide 'ob-calc) (provide 'ob-calc)
;;; ob-calc.el ends here ;;; ob-calc.el ends here

View file

@ -30,80 +30,70 @@
;; - clojure (at least 1.2.0) ;; - clojure (at least 1.2.0)
;; - clojure-mode ;; - clojure-mode
;; - either cider or SLIME ;; - inf-clojure, cider or SLIME
;; For Cider, see https://github.com/clojure-emacs/cider ;; For clojure-mode, see https://github.com/clojure-emacs/clojure-mode
;; For cider, see https://github.com/clojure-emacs/cider
;; For inf-clojure, see https://github.com/clojure-emacs/cider
;; For SLIME, the best way to install these components is by following ;; For SLIME, the best way to install these components is by following
;; the directions as set out by Phil Hagelberg (Technomancy) on the ;; the directions as set out by Phil Hagelberg (Technomancy) on the
;; web page: http://technomancy.us/126 ;; web page: http://technomancy.us/126
;;; Code: ;;; Code:
(require 'cl-lib)
(require 'ob) (require 'ob)
(require 'org-macs)
(declare-function cider-jack-in "ext:cider" (&optional prompt-project cljs-too))
(declare-function cider-current-connection "ext:cider-client" (&optional type)) (declare-function cider-current-connection "ext:cider-client" (&optional type))
(declare-function cider-current-ns "ext:cider-client" ()) (declare-function cider-current-ns "ext:cider-client" ())
(declare-function cider-repls "ext:cider-connection" (&optional type ensure)) (declare-function inf-clojure "ext:inf-clojure" (cmd))
(declare-function nrepl--merge "ext:nrepl-client" (dict1 dict2)) (declare-function inf-clojure-cmd "ext:inf-clojure" (project-type))
(declare-function inf-clojure-eval-string "ext:inf-clojure" (code))
(declare-function inf-clojure-project-type "ext:inf-clojure" ())
(declare-function nrepl-dict-get "ext:nrepl-client" (dict key)) (declare-function nrepl-dict-get "ext:nrepl-client" (dict key))
(declare-function nrepl-dict-put "ext:nrepl-client" (dict key value))
(declare-function nrepl-request:eval "ext:nrepl-client" (input callback connection &optional ns line column additional-params tooling))
(declare-function nrepl-sync-request:eval "ext:nrepl-client" (input connection &optional ns tooling)) (declare-function nrepl-sync-request:eval "ext:nrepl-client" (input connection &optional ns tooling))
(declare-function sesman-start-session "ext:sesman" (system))
(declare-function slime-eval "ext:slime" (sexp &optional package)) (declare-function slime-eval "ext:slime" (sexp &optional package))
(defvar nrepl-sync-request-timeout)
(defvar cider-buffer-ns) (defvar cider-buffer-ns)
(defvar sesman-system)
(defvar cider-version)
(defvar org-babel-tangle-lang-exts) (defvar org-babel-tangle-lang-exts)
(add-to-list 'org-babel-tangle-lang-exts '("clojure" . "clj")) (add-to-list 'org-babel-tangle-lang-exts '("clojure" . "clj"))
(add-to-list 'org-babel-tangle-lang-exts '("clojurescript" . "cljs"))
(defvar org-babel-default-header-args:clojure '()) (defvar org-babel-default-header-args:clojure '())
(defvar org-babel-header-args:clojure '((ns . :any) (defvar org-babel-header-args:clojure '((ns . :any) (package . :any)))
(package . :any))) (defvar org-babel-default-header-args:clojurescript '())
(defvar org-babel-header-args:clojurescript '((package . :any)))
(defcustom org-babel-clojure-sync-nrepl-timeout 10 (defcustom org-babel-clojure-backend nil
"Timeout value, in seconds, of a Clojure sync call.
If the value is nil, timeout is disabled."
:group 'org-babel
:type 'integer
:version "26.1"
:package-version '(Org . "9.1")
:safe #'wholenump)
(defcustom org-babel-clojure-backend
(cond ((featurep 'cider) 'cider)
(t 'slime))
"Backend used to evaluate Clojure code blocks." "Backend used to evaluate Clojure code blocks."
:group 'org-babel :group 'org-babel
:type '(choice :type '(choice
(const :tag "inf-clojure" inf-clojure)
(const :tag "cider" cider) (const :tag "cider" cider)
(const :tag "SLIME" slime))) (const :tag "slime" slime)
(const :tag "Not configured yet" nil)))
(defcustom org-babel-clojure-default-ns "user" (defcustom org-babel-clojure-default-ns "user"
"Default Clojure namespace for source block when finding ns failed." "Default Clojure namespace for source block when finding ns failed."
:type 'string :type 'string
:group 'org-babel) :group 'org-babel)
(defun org-babel-clojure-cider-current-ns ()
"Like `cider-current-ns' except `cider-find-ns'."
(or cider-buffer-ns
(let ((repl-buf (cider-current-connection)))
(and repl-buf (buffer-local-value 'cider-buffer-ns repl-buf)))
org-babel-clojure-default-ns))
(defun org-babel-expand-body:clojure (body params) (defun org-babel-expand-body:clojure (body params)
"Expand BODY according to PARAMS, return the expanded body." "Expand BODY according to PARAMS, return the expanded body."
(let* ((vars (org-babel--get-vars params)) (let* ((vars (org-babel--get-vars params))
(ns (or (cdr (assq :ns params)) (ns (or (cdr (assq :ns params))
(org-babel-clojure-cider-current-ns))) (if (eq org-babel-clojure-backend 'cider)
(or cider-buffer-ns
(let ((repl-buf (cider-current-connection)))
(and repl-buf (buffer-local-value
'cider-buffer-ns repl-buf))))
org-babel-clojure-default-ns)))
(result-params (cdr (assq :result-params params))) (result-params (cdr (assq :result-params params)))
(print-level nil) (print-level nil)
(print-length nil) (print-length nil)
;; Remove comments, they break (let [...] ...) bindings
(body (replace-regexp-in-string "^[ ]*;+.*$" "" body))
(body (org-trim (body (org-trim
(concat (concat
;; Source block specified namespace :ns. ;; Source block specified namespace :ns.
@ -113,7 +103,7 @@ If the value is nil, timeout is disabled."
(format "(let [%s]\n%s)" (format "(let [%s]\n%s)"
(mapconcat (mapconcat
(lambda (var) (lambda (var)
(format "%S (quote %S)" (car var) (cdr var))) (format "%S %S" (car var) (cdr var)))
vars vars
"\n ") "\n ")
body)))))) body))))))
@ -122,161 +112,141 @@ If the value is nil, timeout is disabled."
(format "(clojure.pprint/pprint (do %s))" body) (format "(clojure.pprint/pprint (do %s))" body)
body))) body)))
(defun org-babel-execute:clojure (body params) (defvar ob-clojure-inf-clojure-filter-out)
"Execute a block of Clojure code with Babel. (defvar ob-clojure-inf-clojure-tmp-output)
The underlying process performed by the code block can be output (defun ob-clojure-inf-clojure-output (s)
using the :show-process parameter." "Store a trimmed version of S in a variable and return S."
(let* ((expanded (org-babel-expand-body:clojure body params)) (let ((s0 (org-trim
(response (list 'dict)) (replace-regexp-in-string
result) ob-clojure-inf-clojure-filter-out "" s))))
(cl-case org-babel-clojure-backend (push s0 ob-clojure-inf-clojure-tmp-output))
(cider s)
(require 'cider)
(let ((result-params (cdr (assq :result-params params)))
(show (cdr (assq :show-process params))))
(if (member show '(nil "no"))
;; Run code without showing the process.
(progn
(setq response
(let ((nrepl-sync-request-timeout
org-babel-clojure-sync-nrepl-timeout))
(nrepl-sync-request:eval expanded
(cider-current-connection))))
(setq result
(concat
(nrepl-dict-get response
(if (or (member "output" result-params)
(member "pp" result-params))
"out"
"value"))
(nrepl-dict-get response "ex")
(nrepl-dict-get response "root-ex")
(nrepl-dict-get response "err"))))
;; Show the process in an output buffer/window.
(let ((process-buffer (switch-to-buffer-other-window
"*Clojure Show Process Sub Buffer*"))
status)
;; Run the Clojure code in nREPL.
(nrepl-request:eval
expanded
(lambda (resp)
(when (member "out" resp)
;; Print the output of the nREPL in the output buffer.
(princ (nrepl-dict-get resp "out") process-buffer))
(when (member "ex" resp)
;; In case there is an exception, then add it to the
;; output buffer as well.
(princ (nrepl-dict-get resp "ex") process-buffer)
(princ (nrepl-dict-get resp "root-ex") process-buffer))
(when (member "err" resp)
;; In case there is an error, then add it to the
;; output buffer as well.
(princ (nrepl-dict-get resp "err") process-buffer))
(nrepl--merge response resp)
;; Update the status of the nREPL output session.
(setq status (nrepl-dict-get response "status")))
(cider-current-connection))
;; Wait until the nREPL code finished to be processed. (defmacro ob-clojure-with-temp-expanded (expanded params &rest body)
(while (not (member "done" status)) "Run BODY on EXPANDED code block with PARAMS."
(nrepl-dict-put response "status" (remove "need-input" status)) (declare (debug (body)) (indent 2))
(accept-process-output nil 0.01) `(with-temp-buffer
(redisplay)) (insert ,expanded)
(goto-char (point-min))
(while (not (looking-at "\\s-*\\'"))
(let* ((beg (point))
(end (progn (forward-sexp) (point)))
(exp (org-babel-expand-body:clojure
(buffer-substring beg end) ,params)))
(sit-for .1)
,@body))))
;; Delete the show buffer & window when the processing is (defsubst ob-clojure-string-or-list (l)
;; finalized. "Convert list L into a string or a list of list."
(mapc #'delete-window (if (and (listp l) (= (length l) 1))
(get-buffer-window-list process-buffer nil t)) (car l)
(kill-buffer process-buffer) (mapcar #'list l)))
;; Put the output or the value in the result section of (defvar inf-clojure-buffer)
;; the code block. (defvar comint-prompt-regexp)
(setq result (defvar inf-clojure-comint-prompt-regexp)
(concat (defun ob-clojure-eval-with-inf-clojure (expanded params)
(nrepl-dict-get response "Evaluate EXPANDED code block with PARAMS using inf-clojure."
(if (or (member "output" result-params) (condition-case nil (require 'inf-clojure)
(member "pp" result-params)) (user-error "inf-clojure not available"))
"out" ;; Maybe initiate the inf-clojure session
"value")) (unless (and inf-clojure-buffer
(buffer-live-p (get-buffer inf-clojure-buffer)))
(save-window-excursion
(let* ((alias (cdr (assq :alias params)))
(cmd0 (inf-clojure-cmd (inf-clojure-project-type)))
(cmd (if alias (replace-regexp-in-string
"clojure" (format "clojure -A%s" alias)
cmd0)
cmd0)))
(setq comint-prompt-regexp inf-clojure-comint-prompt-regexp)
(funcall-interactively #'inf-clojure cmd)
(goto-char (point-max))))
(sit-for 1))
;; Now evaluate the code
(setq ob-clojure-inf-clojure-filter-out
(concat "^nil\\|nil$\\|\\s-*"
(or (cdr (assq :ns params))
org-babel-clojure-default-ns)
"=>\\s-*"))
(add-hook 'comint-preoutput-filter-functions
#'ob-clojure-inf-clojure-output)
(setq ob-clojure-inf-clojure-tmp-output nil)
(ob-clojure-with-temp-expanded expanded nil
(inf-clojure-eval-string exp))
(sit-for .5)
(remove-hook 'comint-preoutput-filter-functions
#'ob-clojure-inf-clojure-output)
;; And return the result
(ob-clojure-string-or-list
(delete nil
(mapcar
(lambda (s)
(unless (or (equal "" s)
(string-match-p "^Clojure" s))
s))
(reverse ob-clojure-inf-clojure-tmp-output)))))
(defun ob-clojure-eval-with-cider (expanded params)
"Evaluate EXPANDED code block with PARAMS using cider."
(condition-case nil (require 'cider)
(user-error "cider not available"))
(let ((connection (cider-current-connection (cdr (assq :target params))))
(result-params (cdr (assq :result-params params)))
result0)
(unless connection (sesman-start-session 'CIDER))
(if (not connection)
;; Display in the result instead of using `user-error'
(setq result0 "Please reevaluate when nREPL is connected")
(ob-clojure-with-temp-expanded expanded params
(let ((response (nrepl-sync-request:eval exp connection)))
(push (or (nrepl-dict-get response "root-ex")
(nrepl-dict-get response "ex") (nrepl-dict-get response "ex")
(nrepl-dict-get response "root-ex") (nrepl-dict-get
(nrepl-dict-get response "err"))))))) response (if (or (member "output" result-params)
(slime (member "pp" result-params))
(require 'slime) "out"
(with-temp-buffer "value")))
(insert expanded) result0)))
(setq result (ob-clojure-string-or-list
(slime-eval (reverse (delete "" (mapcar (lambda (r)
`(swank:eval-and-grab-output (replace-regexp-in-string "nil" "" r))
,(buffer-substring-no-properties (point-min) (point-max))) result0)))))))
(cdr (assq :package params)))))))
(org-babel-result-cond (cdr (assq :result-params params)) (defun ob-clojure-eval-with-slime (expanded params)
"Evaluate EXPANDED code block with PARAMS using slime."
(condition-case nil (require 'slime)
(user-error "slime not available"))
(with-temp-buffer
(insert expanded)
(slime-eval
`(swank:eval-and-grab-output
,(buffer-substring-no-properties (point-min) (point-max)))
(cdr (assq :package params)))))
(defun org-babel-execute:clojure (body params)
"Execute a block of Clojure code with Babel."
(unless org-babel-clojure-backend
(user-error "You need to customize org-babel-clojure-backend"))
(let* ((expanded (org-babel-expand-body:clojure body params))
(result-params (cdr (assq :result-params params)))
result)
(setq result
(cond
((eq org-babel-clojure-backend 'inf-clojure)
(ob-clojure-eval-with-inf-clojure expanded params))
((eq org-babel-clojure-backend 'cider)
(ob-clojure-eval-with-cider expanded params))
((eq org-babel-clojure-backend 'slime)
(ob-clojure-eval-with-slime expanded params))))
(org-babel-result-cond result-params
result result
(condition-case nil (org-babel-script-escape result) (condition-case nil (org-babel-script-escape result)
(error result))))) (error result)))))
(defun org-babel-clojure-initiate-session (&optional session _params) (defun org-babel-execute:clojurescript (body params)
"Initiate a session named SESSION according to PARAMS." "Evaluate BODY with PARAMS as ClojureScript code."
(when (and session (not (string= session "none"))) (org-babel-execute:clojure body (cons '(:target . "cljs") params)))
(save-window-excursion
(cond
((org-babel-comint-buffer-livep session) nil)
;; CIDER jack-in to the Clojure project directory.
((eq org-babel-clojure-backend 'cider)
(require 'cider)
(let ((session-buffer
(save-window-excursion
(if (version< cider-version "0.18.0")
;; Older CIDER (without sesman) still need to use
;; old way.
(cider-jack-in nil) ;jack-in without project
;; New CIDER (with sesman to manage sessions).
(unless (cider-repls)
(let ((sesman-system 'CIDER))
(call-interactively 'sesman-link-with-directory))))
(current-buffer))))
(when (org-babel-comint-buffer-livep session-buffer)
(sit-for .25)
session-buffer)))
((eq org-babel-clojure-backend 'slime)
(error "Session evaluation with SLIME is not supported"))
(t
(error "Session initiate failed")))
(get-buffer session))))
(defun org-babel-prep-session:clojure (session params)
"Prepare SESSION according to the header arguments specified in PARAMS."
(let ((session (org-babel-clojure-initiate-session session))
(var-lines (org-babel-variable-assignments:clojure params)))
(when session
(org-babel-comint-in-buffer session
(dolist (var var-lines)
(insert var)
(comint-send-input nil t)
(org-babel-comint-wait-for-output session)
(sit-for .1)
(goto-char (point-max)))))
session))
(defun org-babel-clojure-var-to-clojure (var)
"Convert src block's VAR to Clojure variable."
(cond
((listp var)
(replace-regexp-in-string "(" "'(" var))
((stringp var)
;; Wrap Babel passed-in header argument value with quotes in Clojure.
(format "\"%s\"" var))
(t
(format "%S" var))))
(defun org-babel-variable-assignments:clojure (params)
"Return a list of Clojure statements assigning the block's variables in PARAMS."
(mapcar
(lambda (pair)
(format "(def %s %s)"
(car pair)
(org-babel-clojure-var-to-clojure (cdr pair))))
(org-babel--get-vars params)))
(provide 'ob-clojure) (provide 'ob-clojure)

View file

@ -151,6 +151,4 @@ FILE exists at end of evaluation."
(provide 'ob-comint) (provide 'ob-comint)
;;; ob-comint.el ends here ;;; ob-comint.el ends here

View file

@ -27,7 +27,7 @@
;; session evaluation is supported. Requires both coq.el and ;; session evaluation is supported. Requires both coq.el and
;; coq-inferior.el, both of which are distributed with Coq. ;; coq-inferior.el, both of which are distributed with Coq.
;; ;;
;; http://coq.inria.fr/ ;; https://coq.inria.fr/
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
@ -76,3 +76,5 @@ create one. Return the initialized session."
(get-buffer org-babel-coq-buffer)) (get-buffer org-babel-coq-buffer))
(provide 'ob-coq) (provide 'ob-coq)
;;; ob-coq.el ends here

View file

@ -38,6 +38,7 @@
(defvar org-link-file-path-type) (defvar org-link-file-path-type)
(defvar org-src-lang-modes) (defvar org-src-lang-modes)
(defvar org-src-preserve-indentation) (defvar org-src-preserve-indentation)
(defvar org-babel-tangle-uncomment-comments)
(declare-function org-at-item-p "org-list" ()) (declare-function org-at-item-p "org-list" ())
(declare-function org-at-table-p "org" (&optional table-type)) (declare-function org-at-table-p "org" (&optional table-type))
@ -59,6 +60,7 @@
(declare-function org-element-type "org-element" (element)) (declare-function org-element-type "org-element" (element))
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil)) (declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
(declare-function org-escape-code-in-region "org-src" (beg end)) (declare-function org-escape-code-in-region "org-src" (beg end))
(declare-function org-forward-heading-same-level "org" (arg &optional invisible-ok))
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance)) (declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
(declare-function org-indent-line "org" ()) (declare-function org-indent-line "org" ())
(declare-function org-list-get-list-end "org-list" (item struct prevs)) (declare-function org-list-get-list-end "org-list" (item struct prevs))
@ -67,7 +69,6 @@
(declare-function org-list-to-generic "org-list" (LIST PARAMS)) (declare-function org-list-to-generic "org-list" (LIST PARAMS))
(declare-function org-list-to-lisp "org-list" (&optional delete)) (declare-function org-list-to-lisp "org-list" (&optional delete))
(declare-function org-macro-escape-arguments "org-macro" (&rest args)) (declare-function org-macro-escape-arguments "org-macro" (&rest args))
(declare-function org-make-options-regexp "org" (kwds &optional extra))
(declare-function org-mark-ring-push "org" (&optional pos buffer)) (declare-function org-mark-ring-push "org" (&optional pos buffer))
(declare-function org-narrow-to-subtree "org" ()) (declare-function org-narrow-to-subtree "org" ())
(declare-function org-next-block "org" (arg &optional backward block-regexp)) (declare-function org-next-block "org" (arg &optional backward block-regexp))
@ -78,6 +79,7 @@
(declare-function org-src-coderef-regexp "org-src" (fmt &optional label)) (declare-function org-src-coderef-regexp "org-src" (fmt &optional label))
(declare-function org-src-get-lang-mode "org-src" (lang)) (declare-function org-src-get-lang-mode "org-src" (lang))
(declare-function org-table-align "org-table" ()) (declare-function org-table-align "org-table" ())
(declare-function org-table-convert-region "org-table" (beg0 end0 &optional separator))
(declare-function org-table-end "org-table" (&optional table-type)) (declare-function org-table-end "org-table" (&optional table-type))
(declare-function org-table-import "org-table" (file arg)) (declare-function org-table-import "org-table" (file arg))
(declare-function org-table-to-lisp "org-table" (&optional txt)) (declare-function org-table-to-lisp "org-table" (&optional txt))
@ -164,7 +166,6 @@ This string must include a \"%s\" which will be replaced by the results."
"Non-nil means show the time the code block was evaluated in the result hash." "Non-nil means show the time the code block was evaluated in the result hash."
:group 'org-babel :group 'org-babel
:type 'boolean :type 'boolean
:version "26.1"
:package-version '(Org . "9.0") :package-version '(Org . "9.0")
:safe #'booleanp) :safe #'booleanp)
@ -238,7 +239,8 @@ should be asked whether to allow evaluation."
(if (functionp org-confirm-babel-evaluate) (if (functionp org-confirm-babel-evaluate)
(funcall org-confirm-babel-evaluate (funcall org-confirm-babel-evaluate
;; Language, code block body. ;; Language, code block body.
(nth 0 info) (nth 1 info)) (nth 0 info)
(org-babel--expand-body info))
org-confirm-babel-evaluate)))) org-confirm-babel-evaluate))))
(cond (cond
(noeval nil) (noeval nil)
@ -400,6 +402,7 @@ then run `org-babel-switch-to-session'."
(file . :any) (file . :any)
(file-desc . :any) (file-desc . :any)
(file-ext . :any) (file-ext . :any)
(file-mode . ((#o755 #o555 #o444 :any)))
(hlines . ((no yes))) (hlines . ((no yes)))
(mkdirp . ((yes no))) (mkdirp . ((yes no)))
(no-expand) (no-expand)
@ -487,11 +490,21 @@ For the format of SAFE-LIST, see `org-babel-safe-header-args'."
"Regexp matching a NAME keyword.") "Regexp matching a NAME keyword.")
(defconst org-babel-result-regexp (defconst org-babel-result-regexp
(format "^[ \t]*#\\+%s\\(?:\\[\\(?:%s \\)?\\([[:alnum:]]+\\)\\]\\)?:[ \t]*" (rx (seq bol
org-babel-results-keyword (zero-or-more (any "\t "))
;; <%Y-%m-%d %H:%M:%S> "#+results"
"<\\(?:[0-9]\\{4\\}-[0-1][0-9]-[0-3][0-9] \ (opt "["
[0-2][0-9]\\(?::[0-5][0-9]\\)\\{2\\}\\)>") ;; Time stamp part.
(opt "("
(= 4 digit) (= 2 "-" (= 2 digit))
" "
(= 2 digit) (= 2 ":" (= 2 digit))
") ")
;; SHA1 hash.
(group (one-or-more hex-digit))
"]")
":"
(zero-or-more (any "\t "))))
"Regular expression used to match result lines. "Regular expression used to match result lines.
If the results are associated with a hash key then the hash will If the results are associated with a hash key then the hash will
be saved in match group 1.") be saved in match group 1.")
@ -622,6 +635,17 @@ a list with the following pattern:
(setf (nth 2 info) (org-babel-generate-file-param name (nth 2 info))) (setf (nth 2 info) (org-babel-generate-file-param name (nth 2 info)))
info)))) info))))
(defun org-babel--expand-body (info)
"Expand noweb references in body and remove any coderefs."
(let ((coderef (nth 6 info))
(expand
(if (org-babel-noweb-p (nth 2 info) :eval)
(org-babel-expand-noweb-references info)
(nth 1 info))))
(if (not coderef) expand
(replace-regexp-in-string
(org-src-coderef-regexp coderef) "" expand nil nil 1))))
;;;###autoload ;;;###autoload
(defun org-babel-execute-src-block (&optional arg info params) (defun org-babel-execute-src-block (&optional arg info params)
"Execute the current source code block. "Execute the current source code block.
@ -667,17 +691,7 @@ block."
((org-babel-confirm-evaluate info) ((org-babel-confirm-evaluate info)
(let* ((lang (nth 0 info)) (let* ((lang (nth 0 info))
(result-params (cdr (assq :result-params params))) (result-params (cdr (assq :result-params params)))
;; Expand noweb references in BODY and remove any (body (org-babel--expand-body info))
;; coderef.
(body
(let ((coderef (nth 6 info))
(expand
(if (org-babel-noweb-p params :eval)
(org-babel-expand-noweb-references info)
(nth 1 info))))
(if (not coderef) expand
(replace-regexp-in-string
(org-src-coderef-regexp coderef) "" expand nil nil 1))))
(dir (cdr (assq :dir params))) (dir (cdr (assq :dir params)))
(mkdirp (cdr (assq :mkdirp params))) (mkdirp (cdr (assq :mkdirp params)))
(default-directory (default-directory
@ -721,7 +735,11 @@ block."
(with-temp-file file (with-temp-file file
(insert (org-babel-format-result (insert (org-babel-format-result
result result
(cdr (assq :sep params)))))) (cdr (assq :sep params)))))
;; Set file permissions if header argument
;; `:file-mode' is provided.
(when (assq :file-mode params)
(set-file-modes file (cdr (assq :file-mode params)))))
(setq result file)) (setq result file))
;; Possibly perform post process provided its ;; Possibly perform post process provided its
;; appropriate. Dynamically bind "*this*" to the ;; appropriate. Dynamically bind "*this*" to the
@ -1301,10 +1319,9 @@ CONTEXT specifies the context of evaluation. It can be `:eval',
"Return the current in-buffer hash." "Return the current in-buffer hash."
(let ((result (org-babel-where-is-src-block-result nil info))) (let ((result (org-babel-where-is-src-block-result nil info)))
(when result (when result
(org-with-wide-buffer (org-with-point-at result
(goto-char result) (let ((case-fold-search t)) (looking-at org-babel-result-regexp))
(looking-at org-babel-result-regexp) (match-string-no-properties 1)))))
(match-string-no-properties 1)))))
(defun org-babel-hide-hash () (defun org-babel-hide-hash ()
"Hide the hash in the current results line. "Hide the hash in the current results line.
@ -1312,7 +1329,8 @@ Only the initial `org-babel-hash-show' characters of the hash
will remain visible." will remain visible."
(add-to-invisibility-spec '(org-babel-hide-hash . t)) (add-to-invisibility-spec '(org-babel-hide-hash . t))
(save-excursion (save-excursion
(when (and (re-search-forward org-babel-result-regexp nil t) (when (and (let ((case-fold-search t))
(re-search-forward org-babel-result-regexp nil t))
(match-string 1)) (match-string 1))
(let* ((start (match-beginning 1)) (let* ((start (match-beginning 1))
(hide-start (+ org-babel-hash-show start)) (hide-start (+ org-babel-hash-show start))
@ -1330,11 +1348,12 @@ Only the initial `org-babel-hash-show' characters of each hash
will remain visible. This function should be called as part of will remain visible. This function should be called as part of
the `org-mode-hook'." the `org-mode-hook'."
(save-excursion (save-excursion
(while (and (not org-babel-hash-show-time) (let ((case-fold-search t))
(re-search-forward org-babel-result-regexp nil t)) (while (and (not org-babel-hash-show-time)
(goto-char (match-beginning 0)) (re-search-forward org-babel-result-regexp nil t))
(org-babel-hide-hash) (goto-char (match-beginning 0))
(goto-char (match-end 0))))) (org-babel-hide-hash)
(goto-char (match-end 0))))))
(add-hook 'org-mode-hook 'org-babel-hide-all-hashes) (add-hook 'org-mode-hook 'org-babel-hide-all-hashes)
(defun org-babel-hash-at-point (&optional point) (defun org-babel-hash-at-point (&optional point)
@ -1363,9 +1382,10 @@ portions of results lines."
(interactive) (interactive)
(org-babel-show-result-all) (org-babel-show-result-all)
(save-excursion (save-excursion
(while (re-search-forward org-babel-result-regexp nil t) (let ((case-fold-search t))
(save-excursion (goto-char (match-beginning 0)) (while (re-search-forward org-babel-result-regexp nil t)
(org-babel-hide-result-toggle-maybe))))) (save-excursion (goto-char (match-beginning 0))
(org-babel-hide-result-toggle-maybe))))))
(defun org-babel-show-result-all () (defun org-babel-show-result-all ()
"Unfold all results in the current buffer." "Unfold all results in the current buffer."
@ -1377,52 +1397,50 @@ portions of results lines."
"Toggle visibility of result at point." "Toggle visibility of result at point."
(interactive) (interactive)
(let ((case-fold-search t)) (let ((case-fold-search t))
(if (save-excursion (and (org-match-line org-babel-result-regexp)
(beginning-of-line 1) (progn (org-babel-hide-result-toggle) t))))
(looking-at org-babel-result-regexp))
(progn (org-babel-hide-result-toggle)
t) ;; to signal that we took action
nil))) ;; to signal that we did not
(defun org-babel-hide-result-toggle (&optional force) (defun org-babel-hide-result-toggle (&optional force)
"Toggle the visibility of the current result." "Toggle the visibility of the current result."
(interactive) (interactive)
(save-excursion (save-excursion
(beginning-of-line) (beginning-of-line)
(if (re-search-forward org-babel-result-regexp nil t) (let ((case-fold-search t))
(let ((start (progn (beginning-of-line 2) (- (point) 1))) (unless (re-search-forward org-babel-result-regexp nil t)
(end (progn (error "Not looking at a result line")))
(while (looking-at org-babel-multi-line-header-regexp) (let ((start (progn (beginning-of-line 2) (1- (point))))
(forward-line 1)) (end (progn
(goto-char (- (org-babel-result-end) 1)) (point))) (while (looking-at org-babel-multi-line-header-regexp)
ov) (forward-line 1))
(if (memq t (mapcar (lambda (overlay) (goto-char (1- (org-babel-result-end)))
(eq (overlay-get overlay 'invisible) (point)))
'org-babel-hide-result)) ov)
(overlays-at start))) (if (memq t (mapcar (lambda (overlay)
(when (or (not force) (eq force 'off)) (eq (overlay-get overlay 'invisible)
(mapc (lambda (ov) 'org-babel-hide-result))
(when (member ov org-babel-hide-result-overlays) (overlays-at start)))
(setq org-babel-hide-result-overlays (when (or (not force) (eq force 'off))
(delq ov org-babel-hide-result-overlays))) (mapc (lambda (ov)
(when (eq (overlay-get ov 'invisible) (when (member ov org-babel-hide-result-overlays)
'org-babel-hide-result) (setq org-babel-hide-result-overlays
(delete-overlay ov))) (delq ov org-babel-hide-result-overlays)))
(overlays-at start))) (when (eq (overlay-get ov 'invisible)
(setq ov (make-overlay start end)) 'org-babel-hide-result)
(overlay-put ov 'invisible 'org-babel-hide-result) (delete-overlay ov)))
;; make the block accessible to isearch (overlays-at start)))
(overlay-put (setq ov (make-overlay start end))
ov 'isearch-open-invisible (overlay-put ov 'invisible 'org-babel-hide-result)
(lambda (ov) ;; make the block accessible to isearch
(when (member ov org-babel-hide-result-overlays) (overlay-put
(setq org-babel-hide-result-overlays ov 'isearch-open-invisible
(delq ov org-babel-hide-result-overlays))) (lambda (ov)
(when (eq (overlay-get ov 'invisible) (when (member ov org-babel-hide-result-overlays)
'org-babel-hide-result) (setq org-babel-hide-result-overlays
(delete-overlay ov)))) (delq ov org-babel-hide-result-overlays)))
(push ov org-babel-hide-result-overlays))) (when (eq (overlay-get ov 'invisible)
(error "Not looking at a result line")))) 'org-babel-hide-result)
(delete-overlay ov))))
(push ov org-babel-hide-result-overlays)))))
;; org-tab-after-check-for-cycling-hook ;; org-tab-after-check-for-cycling-hook
(add-hook 'org-tab-first-hook 'org-babel-hide-result-toggle-maybe) (add-hook 'org-tab-first-hook 'org-babel-hide-result-toggle-maybe)
@ -1654,7 +1672,8 @@ Note: this function removes any hlines in TABLE."
(mapcar (lambda (row) (mapcar (lambda (row)
(if (listp row) (if (listp row)
(cons (or (pop rownames) "") row) (cons (or (pop rownames) "") row)
row)) table) row))
table)
table)) table))
(defun org-babel-pick-name (names selector) (defun org-babel-pick-name (names selector)
@ -1879,9 +1898,9 @@ region is not active then the point is demarcated."
(block (and start (match-string 0))) (block (and start (match-string 0)))
(headers (and start (match-string 4))) (headers (and start (match-string 4)))
(stars (concat (make-string (or (org-current-level) 1) ?*) " ")) (stars (concat (make-string (or (org-current-level) 1) ?*) " "))
(lower-case-p (and block (upper-case-p (and block
(let (case-fold-search) (let (case-fold-search)
(string-match-p "#\\+begin_src" block))))) (string-match-p "#\\+BEGIN_SRC" block)))))
(if info (if info
(mapc (mapc
(lambda (place) (lambda (place)
@ -1895,9 +1914,9 @@ region is not active then the point is demarcated."
(delete-region (point-at-bol) (point-at-eol))) (delete-region (point-at-bol) (point-at-eol)))
(insert (concat (insert (concat
(if (looking-at "^") "" "\n") (if (looking-at "^") "" "\n")
indent (funcall (if lower-case-p 'downcase 'upcase) "#+end_src\n") indent (if upper-case-p "#+END_SRC\n" "#+end_src\n")
(if arg stars indent) "\n" (if arg stars indent) "\n"
indent (funcall (if lower-case-p 'downcase 'upcase) "#+begin_src ") indent (if upper-case-p "#+BEGIN_SRC " "#+begin_src ")
lang lang
(if (> (length headers) 1) (if (> (length headers) 1)
(concat " " headers) headers) (concat " " headers) headers)
@ -1918,14 +1937,16 @@ region is not active then the point is demarcated."
(if (org-region-active-p) (mark) (point)) (point)))) (if (org-region-active-p) (mark) (point)) (point))))
(insert (concat (if (looking-at "^") "" "\n") (insert (concat (if (looking-at "^") "" "\n")
(if arg (concat stars "\n") "") (if arg (concat stars "\n") "")
(funcall (if lower-case-p 'downcase 'upcase) "#+begin_src ") (if upper-case-p "#+BEGIN_SRC " "#+begin_src ")
lang "\n" lang "\n" body
body
(if (or (= (length body) 0) (if (or (= (length body) 0)
(string-suffix-p "\r" body) (string-suffix-p "\r" body)
(string-suffix-p "\n" body)) "" "\n") (string-suffix-p "\n" body))
(funcall (if lower-case-p 'downcase 'upcase) "#+end_src\n"))) ""
(goto-char start) (move-end-of-line 1))))) "\n")
(if upper-case-p "#+END_SRC\n" "#+end_src\n")))
(goto-char start)
(move-end-of-line 1)))))
(defun org-babel--insert-results-keyword (name hash) (defun org-babel--insert-results-keyword (name hash)
"Insert RESULTS keyword with NAME value at point. "Insert RESULTS keyword with NAME value at point.
@ -1938,7 +1959,7 @@ the results hash, or nil. Leave point before the keyword."
(cond ((not hash) nil) (cond ((not hash) nil)
(org-babel-hash-show-time (org-babel-hash-show-time
(format "[%s %s]" (format "[%s %s]"
(format-time-string "<%F %T>") (format-time-string "(%F %T)")
hash)) hash))
(t (format "[%s]" hash))) (t (format "[%s]" hash)))
":" ":"
@ -1964,7 +1985,7 @@ point, along with related contents. Do nothing if HASH is nil.
Return a non-nil value if results were cleared. In this case, Return a non-nil value if results were cleared. In this case,
leave point where new results should be inserted." leave point where new results should be inserted."
(when hash (when hash
(looking-at org-babel-result-regexp) (let ((case-fold-search t)) (looking-at org-babel-result-regexp))
(unless (string= (match-string 1) hash) (unless (string= (match-string 1) hash)
(let* ((e (org-element-at-point)) (let* ((e (org-element-at-point))
(post (copy-marker (org-element-property :post-affiliated e)))) (post (copy-marker (org-element-property :post-affiliated e))))
@ -2371,13 +2392,58 @@ INFO may provide the values of these header arguments (in the
(org-babel-chomp result "\n")))) (org-babel-chomp result "\n"))))
(t (goto-char beg) (insert result))) (t (goto-char beg) (insert result)))
(setq end (copy-marker (point) t)) (setq end (copy-marker (point) t))
;; possibly wrap result ;; Possibly wrap result.
(cond (cond
((assq :wrap (nth 2 info)) ((assq :wrap (nth 2 info))
(let ((name (or (cdr (assq :wrap (nth 2 info))) "results"))) (let* ((full (or (cdr (assq :wrap (nth 2 info))) "results"))
(funcall wrap (concat "#+begin_" name) (split (split-string full))
(concat "#+end_" (car (split-string name))) (type (car split))
nil nil (concat "{{{results(@@" name ":") "@@)}}}"))) (opening-line (concat "#+begin_" full))
(closing-line (concat "#+end_" type)))
(cond
;; Escape contents from "export" wrap. Wrap
;; inline results within an export snippet with
;; appropriate value.
((eq t (compare-strings type nil nil "export" nil nil t))
(let ((backend (pcase split
(`(,_) "none")
(`(,_ ,b . ,_) b))))
(funcall wrap
opening-line closing-line
nil nil
(format "{{{results(@@%s:"
backend) "@@)}}}")))
;; Escape contents from "example" wrap. Mark
;; inline results as verbatim.
((eq t (compare-strings type nil nil "example" nil nil t))
(funcall wrap
opening-line closing-line
nil nil
"{{{results(=" "=)}}}"))
;; Escape contents from "src" wrap. Mark
;; inline results as inline source code.
((eq t (compare-strings type nil nil "src" nil nil t))
(let ((inline-open
(pcase split
(`(,_)
"{{{results(src_none{")
(`(,_ ,language)
(format "{{{results(src_%s{" language))
(`(,_ ,language . ,rest)
(let ((r (mapconcat #'identity rest " ")))
(format "{{{results(src_%s[%s]{"
language r))))))
(funcall wrap
opening-line closing-line
nil nil
inline-open "})}}}")))
;; Do not escape contents in non-verbatim
;; blocks. Return plain inline results.
(t
(funcall wrap
opening-line closing-line
t nil
"{{{results(" ")}}}")))))
((member "html" result-params) ((member "html" result-params)
(funcall wrap "#+begin_export html" "#+end_export" nil nil (funcall wrap "#+begin_export html" "#+end_export" nil nil
"{{{results(@@html:" "@@)}}}")) "{{{results(@@html:" "@@)}}}"))
@ -2433,11 +2499,12 @@ INFO may provide the values of these header arguments (in the
(defun org-babel-remove-result (&optional info keep-keyword) (defun org-babel-remove-result (&optional info keep-keyword)
"Remove the result of the current source block." "Remove the result of the current source block."
(interactive) (interactive)
(let ((location (org-babel-where-is-src-block-result nil info))) (let ((location (org-babel-where-is-src-block-result nil info))
(case-fold-search t))
(when location (when location
(save-excursion (save-excursion
(goto-char location) (goto-char location)
(when (looking-at (concat org-babel-result-regexp ".*$")) (when (looking-at org-babel-result-regexp)
(delete-region (delete-region
(if keep-keyword (line-beginning-position 2) (if keep-keyword (line-beginning-position 2)
(save-excursion (save-excursion
@ -2488,7 +2555,7 @@ in the buffer."
(if (memq (org-element-type element) (if (memq (org-element-type element)
;; Possible results types. ;; Possible results types.
'(drawer example-block export-block fixed-width item '(drawer example-block export-block fixed-width item
plain-list src-block table)) plain-list special-block src-block table))
(save-excursion (save-excursion
(goto-char (min (point-max) ;for narrowed buffers (goto-char (min (point-max) ;for narrowed buffers
(org-element-property :end element))) (org-element-property :end element)))
@ -2502,16 +2569,19 @@ If the `default-directory' is different from the containing
file's directory then expand relative links." file's directory then expand relative links."
(when (stringp result) (when (stringp result)
(let ((same-directory? (let ((same-directory?
(and buffer-file-name (and (buffer-file-name (buffer-base-buffer))
(not (string= (expand-file-name default-directory) (not (string= (expand-file-name default-directory)
(expand-file-name (expand-file-name
(file-name-directory buffer-file-name))))))) (file-name-directory
(buffer-file-name (buffer-base-buffer)))))))))
(format "[[file:%s]%s]" (format "[[file:%s]%s]"
(if (and default-directory buffer-file-name same-directory?) (if (and default-directory
(buffer-file-name (buffer-base-buffer)) same-directory?)
(if (eq org-link-file-path-type 'adaptive) (if (eq org-link-file-path-type 'adaptive)
(file-relative-name (file-relative-name
(expand-file-name result default-directory) (expand-file-name result default-directory)
(file-name-directory (buffer-file-name))) (file-name-directory
(buffer-file-name (buffer-base-buffer))))
(expand-file-name result default-directory)) (expand-file-name result default-directory))
result) result)
(if description (concat "[" description "]") ""))))) (if description (concat "[" description "]") "")))))
@ -2707,117 +2777,110 @@ would set the value of argument \"a\" equal to \"9\". Note that
these arguments are not evaluated in the current source-code these arguments are not evaluated in the current source-code
block but are passed literally to the \"example-block\"." block but are passed literally to the \"example-block\"."
(let* ((parent-buffer (or parent-buffer (current-buffer))) (let* ((parent-buffer (or parent-buffer (current-buffer)))
(info (or info (org-babel-get-src-block-info 'light))) (info (or info (org-babel-get-src-block-info 'light)))
(lang (nth 0 info)) (lang (nth 0 info))
(body (nth 1 info)) (body (nth 1 info))
(ob-nww-start org-babel-noweb-wrap-start) (comment (string= "noweb" (cdr (assq :comments (nth 2 info)))))
(ob-nww-end org-babel-noweb-wrap-end) (noweb-re (format "\\(.*?\\)\\(%s\\)"
(new-body "") (with-current-buffer parent-buffer
(nb-add (lambda (text) (setq new-body (concat new-body text)))) (org-babel-noweb-wrap))))
index source-name evaluate prefix) (cache nil)
(with-temp-buffer (c-wrap
(setq-local org-babel-noweb-wrap-start ob-nww-start) (lambda (s)
(setq-local org-babel-noweb-wrap-end ob-nww-end) ;; Comment string S, according to LANG mode. Return new
(insert body) (goto-char (point-min)) ;; string.
(setq index (point)) (unless org-babel-tangle-uncomment-comments
(while (and (re-search-forward (org-babel-noweb-wrap) nil t)) (with-temp-buffer
(save-match-data (setf source-name (match-string 1))) (funcall (org-src-get-lang-mode lang))
(save-match-data (setq evaluate (string-match "(.*)" source-name))) (comment-region (point)
(save-match-data (progn (insert s) (point)))
(setq prefix (org-trim (buffer-string))))))
(buffer-substring (match-beginning 0) (expand-body
(save-excursion (lambda (i)
(beginning-of-line 1) (point))))) ;; Expand body of code represented by block info I.
;; add interval to new-body (removing noweb reference) (let ((b (if (org-babel-noweb-p (nth 2 i) :eval)
(goto-char (match-beginning 0)) (org-babel-expand-noweb-references i)
(funcall nb-add (buffer-substring index (point))) (nth 1 i))))
(goto-char (match-end 0)) (if (not comment) b
(setq index (point)) (let ((cs (org-babel-tangle-comment-links i)))
(funcall (concat (funcall c-wrap (car cs)) "\n"
nb-add b "\n"
(with-current-buffer parent-buffer (funcall c-wrap (cadr cs))))))))
(save-restriction (expand-references
(widen) (lambda (ref cache)
(mapconcat ;; Interpose PREFIX between every line. (pcase (gethash ref cache)
#'identity (`(,last . ,previous)
(split-string ;; Ignore separator for last block.
(if evaluate (let ((strings (list (funcall expand-body last))))
(let ((raw (org-babel-ref-resolve source-name))) (dolist (i previous)
(if (stringp raw) raw (format "%S" raw))) (let ((parameters (nth 2 i)))
(or ;; Since we're operating in reverse order, first
;; Retrieve from the Library of Babel. ;; push separator, then body.
(nth 2 (assoc-string source-name org-babel-library-of-babel)) (push (or (cdr (assq :noweb-sep parameters)) "\n")
;; Return the contents of headlines literally. strings)
(save-excursion (push (funcall expand-body i) strings)))
(when (org-babel-ref-goto-headline-id source-name) (mapconcat #'identity strings "")))
(org-babel-ref-headline-body))) ;; Raise an error about missing reference, or return the
;; Find the expansion of reference in this buffer. ;; empty string.
(save-excursion ((guard (or org-babel-noweb-error-all-langs
(goto-char (point-min)) (member lang org-babel-noweb-error-langs)))
(let* ((name-regexp (error "Cannot resolve %s (see `org-babel-noweb-error-langs')"
(org-babel-named-src-block-regexp-for-name (org-babel-noweb-wrap ref)))
source-name)) (_ "")))))
(comment (replace-regexp-in-string
(string= "noweb" noweb-re
(cdr (assq :comments (nth 2 info))))) (lambda (m)
(c-wrap (with-current-buffer parent-buffer
(lambda (s) (save-match-data
;; Comment, according to LANG mode, (let* ((prefix (match-string 1 m))
;; string S. Return new string. (id (match-string 3 m))
(with-temp-buffer (evaluate (string-match-p "(.*)" id))
(funcall (org-src-get-lang-mode lang)) (expansion
(comment-region (point) (cond
(progn (insert s) (point))) (evaluate
(org-trim (buffer-string))))) ;; Evaluation can potentially modify the buffer
(expand-body ;; and invalidate the cache: reset it.
(lambda (i) (setq cache nil)
;; Expand body of code blocked (let ((raw (org-babel-ref-resolve id)))
;; represented by block info I. (if (stringp raw) raw (format "%S" raw))))
(let ((b (if (org-babel-noweb-p (nth 2 i) :eval) ;; Retrieve from the Library of Babel.
(org-babel-expand-noweb-references i) ((nth 2 (assoc-string id org-babel-library-of-babel)))
(nth 1 i)))) ;; Return the contents of headlines literally.
(if (not comment) b ((org-babel-ref-goto-headline-id id)
(let ((cs (org-babel-tangle-comment-links i))) (org-babel-ref-headline-body))
(concat (funcall c-wrap (car cs)) "\n" ;; Look for a source block named SOURCE-NAME. If
b "\n" ;; found, assume it is unique; do not look after
(funcall c-wrap (cadr cs))))))))) ;; `:noweb-ref' header argument.
(if (and (re-search-forward name-regexp nil t) ((org-with-point-at 1
(not (org-in-commented-heading-p))) (let ((r (org-babel-named-src-block-regexp-for-name id)))
;; Found a source block named SOURCE-NAME. (and (re-search-forward r nil t)
;; Assume it is unique; do not look after (not (org-in-commented-heading-p))
;; `:noweb-ref' header argument. (funcall expand-body
(funcall expand-body (org-babel-get-src-block-info t))))))
(org-babel-get-src-block-info 'light)) ;; All Noweb references were cached in a previous
;; Though luck. We go into the long process ;; run. Extract the information from the cache.
;; of checking each source block and expand ((hash-table-p cache)
;; those with a matching Noweb reference. (funcall expand-references id cache))
(let ((expansion nil)) ;; Though luck. We go into the long process of
(org-babel-map-src-blocks nil ;; checking each source block and expand those
(unless (org-in-commented-heading-p) ;; with a matching Noweb reference. Since we're
(let* ((info ;; going to visit all source blocks in the
(org-babel-get-src-block-info 'light)) ;; document, cache information about them as well.
(parameters (nth 2 info))) (t
(when (equal source-name (setq cache (make-hash-table :test #'equal))
(cdr (assq :noweb-ref parameters))) (org-with-wide-buffer
(push (funcall expand-body info) expansion) (org-babel-map-src-blocks nil
(push (or (cdr (assq :noweb-sep parameters)) (if (org-in-commented-heading-p)
"\n") (org-forward-heading-same-level nil t)
expansion))))) (let* ((info (org-babel-get-src-block-info t))
(when expansion (ref (cdr (assq :noweb-ref (nth 2 info)))))
(mapconcat #'identity (push info (gethash ref cache))))))
(nreverse (cdr expansion)) (funcall expand-references id cache)))))
"")))))) ;; Interpose PREFIX between every line.
;; Possibly raise an error if named block doesn't exist. (mapconcat #'identity
(if (or org-babel-noweb-error-all-langs (split-string expansion "[\n\r]")
(member lang org-babel-noweb-error-langs)) (concat "\n" prefix))))))
(error "%s could not be resolved (see \ body t t 2)))
`org-babel-noweb-error-langs')"
(org-babel-noweb-wrap source-name))
"")))
"[\n\r]")
(concat "\n" prefix))))))
(funcall nb-add (buffer-substring index (point-max))))
new-body))
(defun org-babel--script-escape-inner (str) (defun org-babel--script-escape-inner (str)
(let (in-single in-double backslash out) (let (in-single in-double backslash out)
@ -2931,30 +2994,41 @@ situations in which is it not appropriate."
(defun org-babel--string-to-number (string) (defun org-babel--string-to-number (string)
"If STRING represents a number return its value. "If STRING represents a number return its value.
Otherwise return nil." Otherwise return nil."
(and (string-match-p "\\`-?\\([0-9]\\|\\([1-9]\\|[0-9]*\\.\\)[0-9]*\\)\\'" string) (unless (or (string-match-p "\\s-" (org-trim string))
(string-to-number string))) (not (string-match-p "^[0-9-e.+ ]+$" string)))
(let ((interned-string (ignore-errors (read string))))
(when (numberp interned-string)
interned-string))))
(defun org-babel-import-elisp-from-file (file-name &optional separator) (defun org-babel-import-elisp-from-file (file-name &optional separator)
"Read the results located at FILE-NAME into an elisp table. "Read the results located at FILE-NAME into an elisp table.
If the table is trivial, then return it as a scalar." If the table is trivial, then return it as a scalar."
(save-window-excursion (let ((result
(let ((result (with-temp-buffer
(with-temp-buffer (condition-case err
(condition-case err (progn
(progn (insert-file-contents file-name)
(org-table-import file-name separator) (delete-file file-name)
(delete-file file-name) (let ((pmax (point-max)))
(delq nil ;; If the file was empty, don't bother trying to
(mapcar (lambda (row) ;; convert the table.
(and (not (eq row 'hline)) (when (> pmax 1)
(mapcar #'org-babel-string-read row))) (org-table-convert-region (point-min) pmax separator)
(org-table-to-lisp)))) (delq nil
(error (message "Error reading results: %s" err) nil))))) (mapcar (lambda (row)
(pcase result (and (not (eq row 'hline))
(`((,scalar)) scalar) (mapcar #'org-babel-string-read row)))
(`((,_ ,_ . ,_)) result) (org-table-to-lisp))))))
(`(,scalar) scalar) (error
(_ result))))) (display-warning 'org-babel
(format "Error reading results: %S" err)
:error)
nil)))))
(pcase result
(`((,scalar)) scalar)
(`((,_ ,_ . ,_)) result)
(`(,scalar) scalar)
(_ result))))
(defun org-babel-string-read (cell) (defun org-babel-string-read (cell)
"Strip nested \"s from around strings." "Strip nested \"s from around strings."
@ -3053,9 +3127,8 @@ of `org-babel-temporary-directory'."
(if (eq t (car (file-attributes file))) (if (eq t (car (file-attributes file)))
(delete-directory file) (delete-directory file)
(delete-file file))) (delete-file file)))
;; We do not want to delete "." and "..".
(directory-files org-babel-temporary-directory 'full (directory-files org-babel-temporary-directory 'full
(rx (or (not ".") "...")))) directory-files-no-dot-files-regexp))
(delete-directory org-babel-temporary-directory)) (delete-directory org-babel-temporary-directory))
(error (error
(message "Failed to remove temporary Org-babel directory %s" (message "Failed to remove temporary Org-babel directory %s"

View file

@ -43,6 +43,4 @@ CSS does not support sessions."
(provide 'ob-css) (provide 'ob-css)
;;; ob-css.el ends here ;;; ob-css.el ends here

View file

@ -119,6 +119,4 @@ This function is called by `org-babel-execute-src-block'."
(provide 'ob-ditaa) (provide 'ob-ditaa)
;;; ob-ditaa.el ends here ;;; ob-ditaa.el ends here

View file

@ -87,6 +87,4 @@ This function is called by `org-babel-execute-src-block'."
(provide 'ob-dot) (provide 'ob-dot)
;;; ob-dot.el ends here ;;; ob-dot.el ends here

View file

@ -5,7 +5,6 @@
;; Author: Michael Gauland ;; Author: Michael Gauland
;; Keywords: literate programming, reproducible research ;; Keywords: literate programming, reproducible research
;; Homepage: https://orgmode.org ;; Homepage: https://orgmode.org
;; Version: 1.00
;; This file is part of GNU Emacs. ;; This file is part of GNU Emacs.
@ -24,18 +23,18 @@
;;; Commentary: ;;; Commentary:
;;; Org-Babel support for using ebnf2ps to generate encapsulated postscript ;; Org-Babel support for using ebnf2ps to generate encapsulated postscript
;;; railroad diagrams. It recognizes these arguments: ;; railroad diagrams. It recognizes these arguments:
;;; ;;
;;; :file is required; it must include the extension '.eps.' All the rules ;; :file is required; it must include the extension '.eps.' All the rules
;;; in the block will be drawn in the same file. This is done by ;; in the block will be drawn in the same file. This is done by
;;; inserting a '[<file>' comment at the start of the block (see the ;; inserting a '[<file>' comment at the start of the block (see the
;;; documentation for ebnf-eps-buffer for more information). ;; documentation for ebnf-eps-buffer for more information).
;;; ;;
;;; :style specifies a value in ebnf-style-database. This provides the ;; :style specifies a value in ebnf-style-database. This provides the
;;; ability to customize the output. The style can also specify the ;; ability to customize the output. The style can also specify the
;;; grammar syntax (by setting ebnf-syntax); note that only ebnf, ;; grammar syntax (by setting ebnf-syntax); note that only ebnf,
;;; iso-ebnf, and yacc are supported by this file. ;; iso-ebnf, and yacc are supported by this file.
;;; Requirements: ;;; Requirements:
@ -78,4 +77,5 @@ This function is called by `org-babel-execute-src-block'."
result))) result)))
(provide 'ob-ebnf) (provide 'ob-ebnf)
;;; ob-ebnf.el ends here ;;; ob-ebnf.el ends here

View file

@ -61,31 +61,30 @@ by `org-edit-src-code'.")
(defun org-babel-execute:emacs-lisp (body params) (defun org-babel-execute:emacs-lisp (body params)
"Execute a block of emacs-lisp code with Babel." "Execute a block of emacs-lisp code with Babel."
(save-window-excursion (let* ((lexical (cdr (assq :lexical params)))
(let* ((lexical (cdr (assq :lexical params))) (result-params (cdr (assq :result-params params)))
(result-params (cdr (assq :result-params params))) (body (format (if (member "output" result-params)
(body (format (if (member "output" result-params) "(with-output-to-string %s\n)"
"(with-output-to-string %s\n)" "(progn %s\n)")
"(progn %s\n)") (org-babel-expand-body:emacs-lisp body params)))
(org-babel-expand-body:emacs-lisp body params))) (result (eval (read (if (or (member "code" result-params)
(result (eval (read (if (or (member "code" result-params) (member "pp" result-params))
(member "pp" result-params)) (concat "(pp " body ")")
(concat "(pp " body ")") body))
body)) (org-babel-emacs-lisp-lexical lexical))))
(org-babel-emacs-lisp-lexical lexical)))) (org-babel-result-cond result-params
(org-babel-result-cond result-params (let ((print-level nil)
(let ((print-level nil) (print-length nil))
(print-length nil)) (if (or (member "scalar" result-params)
(if (or (member "scalar" result-params) (member "verbatim" result-params))
(member "verbatim" result-params)) (format "%S" result)
(format "%S" result) (format "%s" result)))
(format "%s" result))) (org-babel-reassemble-table
(org-babel-reassemble-table result
result (org-babel-pick-name (cdr (assq :colname-names params))
(org-babel-pick-name (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
(cdr (assq :colnames params))) (org-babel-pick-name (cdr (assq :rowname-names params))
(org-babel-pick-name (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))))
(cdr (assq :rownames params))))))))
(defun org-babel-emacs-lisp-lexical (lexical) (defun org-babel-emacs-lisp-lexical (lexical)
"Interpret :lexical source block argument. "Interpret :lexical source block argument.
@ -108,6 +107,4 @@ corresponding :lexical source block argument."
(provide 'ob-emacs-lisp) (provide 'ob-emacs-lisp)
;;; ob-emacs-lisp.el ends here ;;; ob-emacs-lisp.el ends here

View file

@ -144,6 +144,4 @@ This buffer is named by `org-babel-error-buffer-name'."
(provide 'ob-eval) (provide 'ob-eval)
;;; ob-eval.el ends here ;;; ob-eval.el ends here

View file

@ -33,6 +33,7 @@
(declare-function org-escape-code-in-string "org-src" (s)) (declare-function org-escape-code-in-string "org-src" (s))
(declare-function org-export-copy-buffer "ox" ()) (declare-function org-export-copy-buffer "ox" ())
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance)) (declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
(declare-function org-in-archived-heading-p "org" (&optional no-inheritance))
(defvar org-src-preserve-indentation) (defvar org-src-preserve-indentation)
@ -157,7 +158,8 @@ this template."
;; encountered. ;; encountered.
(goto-char (point-min)) (goto-char (point-min))
(while (re-search-forward regexp nil t) (while (re-search-forward regexp nil t)
(unless (save-match-data (org-in-commented-heading-p)) (unless (save-match-data (or (org-in-commented-heading-p)
(org-in-archived-heading-p)))
(let* ((object? (match-end 1)) (let* ((object? (match-end 1))
(element (save-match-data (element (save-match-data
(if object? (org-element-context) (if object? (org-element-context)
@ -403,9 +405,7 @@ inhibit insertion of results into the buffer."
(`lob (`lob
(save-excursion (save-excursion
(goto-char (nth 5 info)) (goto-char (nth 5 info))
(let (org-confirm-babel-evaluate) (org-babel-execute-src-block nil info))))))))
(org-babel-execute-src-block nil info)))))))))
(provide 'ob-exp) (provide 'ob-exp)

View file

@ -76,7 +76,8 @@ This function is called by `org-babel-execute-src-block'."
;; Report errors. ;; Report errors.
(org-babel-eval-error-notify 1 (org-babel-eval-error-notify 1
(buffer-substring (buffer-substring
(+ (match-beginning 0) 1) (point-max))) nil)))) (+ (match-beginning 0) 1) (point-max)))
nil))))
(split-string (org-trim (split-string (org-trim
(org-babel-expand-body:generic body params)) (org-babel-expand-body:generic body params))
"\n" "\n"

View file

@ -101,12 +101,13 @@ its header arguments."
(concat (concat
;; variables ;; variables
(mapconcat 'org-babel-fortran-var-to-fortran vars "\n") (mapconcat 'org-babel-fortran-var-to-fortran vars "\n")
body) params) body)
params)
body) "\n") "\n"))) body) "\n") "\n")))
(defun org-babel-fortran-ensure-main-wrap (body params) (defun org-babel-fortran-ensure-main-wrap (body params)
"Wrap body in a \"program ... end program\" block if none exists." "Wrap body in a \"program ... end program\" block if none exists."
(if (string-match "^[ \t]*program[ \t]*.*" (capitalize body)) (if (string-match "^[ \t]*program\\>" (capitalize body))
(let ((vars (org-babel--get-vars params))) (let ((vars (org-babel--get-vars params)))
(when vars (error "Cannot use :vars if `program' statement is present")) (when vars (error "Cannot use :vars if `program' statement is present"))
body) body)

View file

@ -35,7 +35,7 @@
;; - gnuplot :: http://www.gnuplot.info/ ;; - gnuplot :: http://www.gnuplot.info/
;; ;;
;; - gnuplot-mode :: http://cars9.uchicago.edu/~ravel/software/gnuplot-mode.html ;; - gnuplot-mode :: you can search the web for the latest active one.
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
@ -278,6 +278,4 @@ Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE."
(provide 'ob-gnuplot) (provide 'ob-gnuplot)
;;; ob-gnuplot.el ends here ;;; ob-gnuplot.el ends here

View file

@ -65,7 +65,6 @@ This function is called by `org-babel-execute-src-block'."
(cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))) (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
(defvar org-babel-groovy-wrapper-method (defvar org-babel-groovy-wrapper-method
"class Runner extends Script { "class Runner extends Script {
def out = new PrintWriter(new ByteArrayOutputStream()) def out = new PrintWriter(new ByteArrayOutputStream())
def run() { %s } def run() { %s }
@ -74,7 +73,6 @@ This function is called by `org-babel-execute-src-block'."
println(new Runner().run()) println(new Runner().run())
") ")
(defun org-babel-groovy-evaluate (defun org-babel-groovy-evaluate
(session body &optional result-type result-params) (session body &optional result-type result-params)
"Evaluate BODY in external Groovy process. "Evaluate BODY in external Groovy process.
@ -111,6 +109,4 @@ supported in Groovy."
(provide 'ob-groovy) (provide 'ob-groovy)
;;; ob-groovy.el ends here ;;; ob-groovy.el ends here

View file

@ -23,20 +23,19 @@
;;; Commentary: ;;; Commentary:
;; Org-Babel support for evaluating haskell source code. This one will ;; Org Babel support for evaluating Haskell source code.
;; be sort of tricky because haskell programs must be compiled before ;; Haskell programs must be compiled before
;; they can be run, but haskell code can also be run through an ;; they can be run, but haskell code can also be run through an
;; interactive interpreter. ;; interactive interpreter.
;; ;;
;; For now lets only allow evaluation using the haskell interpreter. ;; By default we evaluate using the Haskell interpreter.
;; To use the compiler, specify :compile yes in the header.
;;; Requirements: ;;; Requirements:
;; - haskell-mode :: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode ;; - haskell-mode: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
;; ;; - inf-haskell: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
;; - inf-haskell :: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode ;; - (optionally) lhs2tex: http://people.cs.uu.nl/andres/lhs2tex/
;;
;; - (optionally) lhs2tex :: http://people.cs.uu.nl/andres/lhs2tex/
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
@ -47,6 +46,7 @@
(declare-function run-haskell "ext:inf-haskell" (&optional arg)) (declare-function run-haskell "ext:inf-haskell" (&optional arg))
(declare-function inferior-haskell-load-file (declare-function inferior-haskell-load-file
"ext:inf-haskell" (&optional reload)) "ext:inf-haskell" (&optional reload))
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
(defvar org-babel-tangle-lang-exts) (defvar org-babel-tangle-lang-exts)
(add-to-list 'org-babel-tangle-lang-exts '("haskell" . "hs")) (add-to-list 'org-babel-tangle-lang-exts '("haskell" . "hs"))
@ -60,8 +60,63 @@
(defvar haskell-prompt-regexp) (defvar haskell-prompt-regexp)
(defun org-babel-execute:haskell (body params) (defcustom org-babel-haskell-compiler "ghc"
"Execute a block of Haskell code." "Command used to compile a Haskell source code file into an executable.
May be either a command in the path, like \"ghc\" or an absolute
path name, like \"/usr/local/bin/ghc\". The command can include
a parameter, such as \"ghc -v\"."
:group 'org-babel
:package-version '(Org "9.4")
:type 'string)
(defconst org-babel-header-args:haskell '(compile . :any)
"Haskell-specific header arguments.")
(defun org-babel-haskell-execute (body params)
"This function should only be called by `org-babel-execute:haskell'"
(let* ((tmp-src-file (org-babel-temp-file "Haskell-src-" ".hs"))
(tmp-bin-file
(org-babel-process-file-name
(org-babel-temp-file "Haskell-bin-" org-babel-exeext)))
(cmdline (cdr (assq :cmdline params)))
(cmdline (if cmdline (concat " " cmdline) ""))
(flags (cdr (assq :flags params)))
(flags (mapconcat #'identity
(if (listp flags)
flags
(list flags))
" "))
(libs (org-babel-read
(or (cdr (assq :libs params))
(org-entry-get nil "libs" t))
nil))
(libs (mapconcat #'identity
(if (listp libs) libs (list libs))
" ")))
(with-temp-file tmp-src-file (insert body))
(org-babel-eval
(format "%s -o %s %s %s %s"
org-babel-haskell-compiler
tmp-bin-file
flags
(org-babel-process-file-name tmp-src-file)
libs)
"")
(let ((results (org-babel-eval (concat tmp-bin-file cmdline) "")))
(when results
(setq results (org-trim (org-remove-indentation results)))
(org-babel-reassemble-table
(org-babel-result-cond (cdr (assq :result-params params))
(org-babel-read results t)
(let ((tmp-file (org-babel-temp-file "Haskell-")))
(with-temp-file tmp-file (insert results))
(org-babel-import-elisp-from-file tmp-file)))
(org-babel-pick-name
(cdr (assq :colname-names params)) (cdr (assq :colnames params)))
(org-babel-pick-name
(cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))))
(defun org-babel-interpret-haskell (body params)
(require 'inf-haskell) (require 'inf-haskell)
(add-hook 'inferior-haskell-hook (add-hook 'inferior-haskell-hook
(lambda () (lambda ()
@ -87,7 +142,7 @@
(org-babel-reassemble-table (org-babel-reassemble-table
(let ((result (let ((result
(pcase result-type (pcase result-type
(`output (mapconcat #'identity (reverse (cdr results)) "\n")) (`output (mapconcat #'identity (reverse results) "\n"))
(`value (car results))))) (`value (car results)))))
(org-babel-result-cond (cdr (assq :result-params params)) (org-babel-result-cond (cdr (assq :result-params params))
result (org-babel-script-escape result))) result (org-babel-script-escape result)))
@ -96,6 +151,13 @@
(org-babel-pick-name (cdr (assq :rowname-names params)) (org-babel-pick-name (cdr (assq :rowname-names params))
(cdr (assq :rowname-names params)))))) (cdr (assq :rowname-names params))))))
(defun org-babel-execute:haskell (body params)
"Execute a block of Haskell code."
(let ((compile (string= "yes" (cdr (assq :compile params)))))
(if (not compile)
(org-babel-interpret-haskell body params)
(org-babel-haskell-execute body params))))
(defun org-babel-haskell-initiate-session (&optional _session _params) (defun org-babel-haskell-initiate-session (&optional _session _params)
"Initiate a haskell session. "Initiate a haskell session.
If there is not a current inferior-process-buffer in SESSION If there is not a current inferior-process-buffer in SESSION
@ -215,6 +277,4 @@ constructs (header arguments, no-web syntax etc...) are ignored."
(provide 'ob-haskell) (provide 'ob-haskell)
;;; ob-haskell.el ends here ;;; ob-haskell.el ends here

View file

@ -30,6 +30,8 @@
;; probably ~/.hledger.journal (it may not notice your $LEDGER_FILE env var). ;; probably ~/.hledger.journal (it may not notice your $LEDGER_FILE env var).
;; So make ~/.hledger.journal a symbolic link to the real file if necessary. ;; So make ~/.hledger.journal a symbolic link to the real file if necessary.
;; TODO Unit tests are more than welcome, too.
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
@ -64,7 +66,4 @@ This function is called by `org-babel-execute-src-block'."
(provide 'ob-hledger) (provide 'ob-hledger)
;;; ob-hledger.el ends here ;;; ob-hledger.el ends here
;; TODO Unit tests are more than welcome, too.

View file

@ -90,7 +90,6 @@ in BODY as elisp."
raw raw
(org-babel-script-escape raw))))))) (org-babel-script-escape raw)))))))
(defun org-babel-prep-session:io (_session _params) (defun org-babel-prep-session:io (_session _params)
"Prepare SESSION according to the header arguments specified in PARAMS." "Prepare SESSION according to the header arguments specified in PARAMS."
(error "Sessions are not (yet) supported for Io")) (error "Sessions are not (yet) supported for Io"))
@ -103,6 +102,4 @@ supported in Io."
(provide 'ob-io) (provide 'ob-io)
;;; ob-io.el ends here ;;; ob-io.el ends here

View file

@ -58,6 +58,7 @@ parameters may be used, like javac -verbose"
(src-file (concat classname ".java")) (src-file (concat classname ".java"))
(cmpflag (or (cdr (assq :cmpflag params)) "")) (cmpflag (or (cdr (assq :cmpflag params)) ""))
(cmdline (or (cdr (assq :cmdline params)) "")) (cmdline (or (cdr (assq :cmdline params)) ""))
(cmdargs (or (cdr (assq :cmdargs params)) ""))
(full-body (org-babel-expand-body:generic body params))) (full-body (org-babel-expand-body:generic body params)))
(with-temp-file src-file (insert full-body)) (with-temp-file src-file (insert full-body))
(org-babel-eval (org-babel-eval
@ -66,10 +67,10 @@ parameters may be used, like javac -verbose"
(unless (or (not packagename) (file-exists-p packagename)) (unless (or (not packagename) (file-exists-p packagename))
(make-directory packagename 'parents)) (make-directory packagename 'parents))
(let ((results (org-babel-eval (concat org-babel-java-command (let ((results (org-babel-eval (concat org-babel-java-command
" " cmdline " " classname) ""))) " " cmdline " " classname " " cmdargs) "")))
(org-babel-reassemble-table (org-babel-reassemble-table
(org-babel-result-cond (cdr (assq :result-params params)) (org-babel-result-cond (cdr (assq :result-params params))
(org-babel-read results) (org-babel-read results t)
(let ((tmp-file (org-babel-temp-file "c-"))) (let ((tmp-file (org-babel-temp-file "c-")))
(with-temp-file tmp-file (insert results)) (with-temp-file tmp-file (insert results))
(org-babel-import-elisp-from-file tmp-file))) (org-babel-import-elisp-from-file tmp-file)))
@ -80,6 +81,4 @@ parameters may be used, like javac -verbose"
(provide 'ob-java) (provide 'ob-java)
;;; ob-java.el ends here ;;; ob-java.el ends here

View file

@ -30,11 +30,11 @@
;;; Requirements: ;;; Requirements:
;; - a non-browser javascript engine such as node.js http://nodejs.org/ ;; - a non-browser javascript engine such as node.js https://nodejs.org/
;; or mozrepl http://wiki.github.com/bard/mozrepl/ ;; or mozrepl https://wiki.github.com/bard/mozrepl/
;; ;;
;; - for session based evaluation mozrepl and moz.el are required see ;; - for session based evaluation mozrepl and moz.el are required see
;; http://wiki.github.com/bard/mozrepl/emacs-integration for ;; https://wiki.github.com/bard/mozrepl/emacs-integration for
;; configuration instructions ;; configuration instructions
;;; Code: ;;; Code:
@ -65,7 +65,7 @@
:safe #'stringp) :safe #'stringp)
(defvar org-babel-js-function-wrapper (defvar org-babel-js-function-wrapper
"require('sys').print(require('sys').inspect(function(){\n%s\n}()));" "require('process').stdout.write(require('util').inspect(function(){%s}()));"
"Javascript code to print value of body.") "Javascript code to print value of body.")
(defun org-babel-execute:js (body params) (defun org-babel-execute:js (body params)
@ -201,6 +201,4 @@ then create. Return the initialized session."
(provide 'ob-js) (provide 'ob-js)
;;; ob-js.el ends here ;;; ob-js.el ends here

View file

@ -84,7 +84,8 @@
(regexp-quote (format "%S" (car pair))) (regexp-quote (format "%S" (car pair)))
(if (stringp (cdr pair)) (if (stringp (cdr pair))
(cdr pair) (format "%S" (cdr pair))) (cdr pair) (format "%S" (cdr pair)))
body))) (org-babel--get-vars params)) body)))
(org-babel--get-vars params))
(org-trim body)) (org-trim body))
(defun org-babel-execute:latex (body params) (defun org-babel-execute:latex (body params)
@ -108,8 +109,11 @@ This function is called by `org-babel-execute-src-block'."
(append (cdr (assq :packages params)) org-latex-packages-alist))) (append (cdr (assq :packages params)) org-latex-packages-alist)))
(cond (cond
((and (string-suffix-p ".png" out-file) (not imagemagick)) ((and (string-suffix-p ".png" out-file) (not imagemagick))
(org-create-formula-image (let ((org-format-latex-header
body out-file org-format-latex-options in-buffer)) (concat org-format-latex-header "\n"
(mapconcat #'identity headers "\n"))))
(org-create-formula-image
body out-file org-format-latex-options in-buffer)))
((string-suffix-p ".tikz" out-file) ((string-suffix-p ".tikz" out-file)
(when (file-exists-p out-file) (delete-file out-file)) (when (file-exists-p out-file) (delete-file out-file))
(with-temp-file out-file (with-temp-file out-file
@ -221,6 +225,6 @@ This function is called by `org-babel-execute-src-block'."
"Return an error because LaTeX doesn't support sessions." "Return an error because LaTeX doesn't support sessions."
(error "LaTeX does not support sessions")) (error "LaTeX does not support sessions"))
(provide 'ob-latex) (provide 'ob-latex)
;;; ob-latex.el ends here ;;; ob-latex.el ends here

View file

@ -65,6 +65,4 @@ called by `org-babel-execute-src-block'."
(provide 'ob-ledger) (provide 'ob-ledger)
;;; ob-ledger.el ends here ;;; ob-ledger.el ends here

View file

@ -67,12 +67,15 @@ the midi file is not automatically played. Default value is t")
(defvar org-babel-lilypond-ly-command "" (defvar org-babel-lilypond-ly-command ""
"Command to execute lilypond on your system. "Command to execute lilypond on your system.
Do not set it directly. Customize `org-babel-lilypond-commands' instead.") Do not set it directly. Customize `org-babel-lilypond-commands' instead.")
(defvar org-babel-lilypond-pdf-command "" (defvar org-babel-lilypond-pdf-command ""
"Command to show a PDF file on your system. "Command to show a PDF file on your system.
Do not set it directly. Customize `org-babel-lilypond-commands' instead.") Do not set it directly. Customize `org-babel-lilypond-commands' instead.")
(defvar org-babel-lilypond-midi-command "" (defvar org-babel-lilypond-midi-command ""
"Command to play a MIDI file on your system. "Command to play a MIDI file on your system.
Do not set it directly. Customize `org-babel-lilypond-commands' instead.") Do not set it directly. Customize `org-babel-lilypond-commands' instead.")
(defcustom org-babel-lilypond-commands (defcustom org-babel-lilypond-commands
(cond (cond
((eq system-type 'darwin) ((eq system-type 'darwin)
@ -94,7 +97,8 @@ you can leave the string empty on this case."
:version "24.4" :version "24.4"
:package-version '(Org . "8.2.7") :package-version '(Org . "8.2.7")
:set :set
(lambda (_symbol value) (lambda (symbol value)
(set symbol value)
(setq (setq
org-babel-lilypond-ly-command (nth 0 value) org-babel-lilypond-ly-command (nth 0 value)
org-babel-lilypond-pdf-command (nth 1 value) org-babel-lilypond-pdf-command (nth 1 value)
@ -201,7 +205,7 @@ If error in compilation, attempt to mark the error in lilypond org file."
(delete-file org-babel-lilypond-temp-file)) (delete-file org-babel-lilypond-temp-file))
(rename-file org-babel-lilypond-tangled-file (rename-file org-babel-lilypond-tangled-file
org-babel-lilypond-temp-file)) org-babel-lilypond-temp-file))
(switch-to-buffer-other-window "*lilypond*") (org-switch-to-buffer-other-window "*lilypond*")
(erase-buffer) (erase-buffer)
(org-babel-lilypond-compile-lilyfile org-babel-lilypond-temp-file) (org-babel-lilypond-compile-lilyfile org-babel-lilypond-temp-file)
(goto-char (point-min)) (goto-char (point-min))
@ -258,7 +262,7 @@ FILE-NAME is full path to lilypond file."
"Mark the erroneous lines in the lilypond org buffer. "Mark the erroneous lines in the lilypond org buffer.
FILE-NAME is full path to lilypond file. FILE-NAME is full path to lilypond file.
LINE is the erroneous line." LINE is the erroneous line."
(switch-to-buffer-other-window (org-switch-to-buffer-other-window
(concat (file-name-nondirectory (concat (file-name-nondirectory
(org-babel-lilypond-switch-extension file-name ".org")))) (org-babel-lilypond-switch-extension file-name ".org"))))
(let ((temp (point))) (let ((temp (point)))
@ -387,7 +391,8 @@ If TEST is non-nil, the shell command is returned and is not run."
(defun org-babel-lilypond-switch-extension (file-name ext) (defun org-babel-lilypond-switch-extension (file-name ext)
"Utility command to swap current FILE-NAME extension with EXT." "Utility command to swap current FILE-NAME extension with EXT."
(concat (file-name-sans-extension (concat (file-name-sans-extension
file-name) ext)) file-name)
ext))
(defun org-babel-lilypond-get-header-args (mode) (defun org-babel-lilypond-get-header-args (mode)
"Default arguments to use when evaluating a lilypond source block. "Default arguments to use when evaluating a lilypond source block.

View file

@ -122,6 +122,4 @@ a property list containing the parameters of the block."
(provide 'ob-lisp) (provide 'ob-lisp)
;;; ob-lisp.el ends here ;;; ob-lisp.el ends here

View file

@ -107,7 +107,8 @@ VARS contains resolved variable references."
(org-babel-comint-in-buffer session (org-babel-comint-in-buffer session
(mapc (lambda (var) (mapc (lambda (var)
(end-of-line 1) (insert var) (comint-send-input) (end-of-line 1) (insert var) (comint-send-input)
(org-babel-comint-wait-for-output session)) var-lines)) (org-babel-comint-wait-for-output session))
var-lines))
session)) session))
(defun org-babel-load-session:lua (session body params) (defun org-babel-load-session:lua (session body params)
@ -397,6 +398,4 @@ fd:close()"
(provide 'ob-lua) (provide 'ob-lua)
;;; ob-lua.el ends here ;;; ob-lua.el ends here

View file

@ -43,6 +43,4 @@ does not support sessions."
(provide 'ob-makefile) (provide 'ob-makefile)
;;; ob-makefile.el ends here ;;; ob-makefile.el ends here

View file

@ -42,6 +42,4 @@
(provide 'ob-matlab) (provide 'ob-matlab)
;;; ob-matlab.el ends here ;;; ob-matlab.el ends here

View file

@ -27,9 +27,7 @@
;; Org-Babel support for evaluating maxima entries. ;; Org-Babel support for evaluating maxima entries.
;; ;;
;; This differs from most standard languages in that ;; This differs from most standard languages in that
;;
;; 1) there is no such thing as a "session" in maxima ;; 1) there is no such thing as a "session" in maxima
;;
;; 2) we are adding the "cmdline" header argument ;; 2) we are adding the "cmdline" header argument
;;; Code: ;;; Code:
@ -125,9 +123,6 @@ of the same value."
(concat "[" (mapconcat #'org-babel-maxima-elisp-to-maxima val ", ") "]") (concat "[" (mapconcat #'org-babel-maxima-elisp-to-maxima val ", ") "]")
(format "%s" val))) (format "%s" val)))
(provide 'ob-maxima) (provide 'ob-maxima)
;;; ob-maxima.el ends here ;;; ob-maxima.el ends here

View file

@ -68,8 +68,7 @@ mscgen supported formats."
(let* ((out-file (or (cdr (assq :file params)) "output.png" )) (let* ((out-file (or (cdr (assq :file params)) "output.png" ))
(filetype (or (cdr (assq :filetype params)) "png" ))) (filetype (or (cdr (assq :filetype params)) "png" )))
(unless (cdr (assq :file params)) (unless (cdr (assq :file params))
(error " (error "ERROR: no output file specified. Add \":file name.png\" to the src header"))
ERROR: no output file specified. Add \":file name.png\" to the src header"))
(org-babel-eval (concat "mscgen -T " filetype " -o " out-file) body) (org-babel-eval (concat "mscgen -T " filetype " -o " out-file) body)
nil)) ;; signal that output has already been written to file nil)) ;; signal that output has already been written to file
@ -79,6 +78,4 @@ ERROR: no output file specified. Add \":file name.png\" to the src header"))
(provide 'ob-mscgen) (provide 'ob-mscgen)
;;; ob-msc.el ends here ;;; ob-msc.el ends here

View file

@ -166,6 +166,4 @@ Emacs-lisp table, otherwise return the results as a string."
(provide 'ob-ocaml) (provide 'ob-ocaml)
;;; ob-ocaml.el ends here ;;; ob-ocaml.el ends here

View file

@ -136,7 +136,8 @@ specifying a variable of the same value."
(org-babel-comint-in-buffer session (org-babel-comint-in-buffer session
(mapc (lambda (var) (mapc (lambda (var)
(end-of-line 1) (insert var) (comint-send-input nil t) (end-of-line 1) (insert var) (comint-send-input nil t)
(org-babel-comint-wait-for-output session)) var-lines)) (org-babel-comint-wait-for-output session))
var-lines))
session)) session))
(defun org-babel-matlab-initiate-session (&optional session params) (defun org-babel-matlab-initiate-session (&optional session params)
@ -230,7 +231,8 @@ value of the last statement in BODY, as elisp."
org-babel-octave-eoe-indicator org-babel-octave-eoe-indicator
org-babel-octave-eoe-output) org-babel-octave-eoe-output)
t full-body) t full-body)
(insert full-body) (comint-send-input nil t)))) results) (insert full-body) (comint-send-input nil t))))
results)
(pcase result-type (pcase result-type
(`value (`value
(org-babel-octave-import-elisp-from-file tmp-file)) (org-babel-octave-import-elisp-from-file tmp-file))
@ -259,6 +261,4 @@ This removes initial blank and comment lines and then calls
(provide 'ob-octave) (provide 'ob-octave)
;;; ob-octave.el ends here ;;; ob-octave.el ends here

View file

@ -67,6 +67,4 @@ This function is called by `org-babel-execute-src-block'."
(provide 'ob-org) (provide 'ob-org)
;;; ob-org.el ends here ;;; ob-org.el ends here

View file

@ -152,6 +152,4 @@ return the value of the last statement in BODY, as elisp."
(provide 'ob-perl) (provide 'ob-perl)
;;; ob-perl.el ends here ;;; ob-perl.el ends here

View file

@ -111,11 +111,11 @@ This function is called by `org-babel-execute-src-block'."
(cond (cond
((or (member "code" result-params) ((or (member "code" result-params)
(member "pp" result-params)) (member "pp" result-params))
(format "(pretty (out \"/dev/null\" %s))" full-body)) (format "(pretty (out \"%s\" %s))" null-device full-body))
((and (member "value" result-params) (not session)) ((and (member "value" result-params) (not session))
(format "(print (out \"/dev/null\" %s))" full-body)) (format "(print (out \"%s\" %s))" null-device full-body))
((member "value" result-params) ((member "value" result-params)
(format "(out \"/dev/null\" %s)" full-body)) (format "(out \"%s\" %s)" null-device full-body))
(t full-body))) (t full-body)))
(result (result
(if (not (string= session-name "none")) (if (not (string= session-name "none"))
@ -182,6 +182,4 @@ then create. Return the initialized session."
(provide 'ob-picolisp) (provide 'ob-picolisp)
;;; ob-picolisp.el ends here ;;; ob-picolisp.el ends here

View file

@ -26,12 +26,12 @@
;; Org-Babel support for evaluating plantuml script. ;; Org-Babel support for evaluating plantuml script.
;; ;;
;; Inspired by Ian Yang's org-export-blocks-format-plantuml ;; Inspired by Ian Yang's org-export-blocks-format-plantuml
;; http://www.emacswiki.org/emacs/org-export-blocks-format-plantuml.el ;; https://www.emacswiki.org/emacs/org-export-blocks-format-plantuml.el
;;; Requirements: ;;; Requirements:
;; plantuml | http://plantuml.sourceforge.net/ ;; plantuml | http://plantuml.sourceforge.net/
;; plantuml.jar | `org-plantuml-jar-path' should point to the jar file ;; plantuml.jar | `org-plantuml-jar-path' should point to the jar file (when exec mode is `jar')
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
@ -46,6 +46,31 @@
:version "24.1" :version "24.1"
:type 'string) :type 'string)
(defcustom org-plantuml-exec-mode 'jar
"Method to use for PlantUML diagram generation.
`jar' means to use java together with the JAR.
The JAR can be configured via `org-plantuml-jar-path'.
`plantuml' means to use the PlantUML executable.
The executable can be configured via `org-plantuml-executable-path'.
You can also configure extra arguments via `org-plantuml-executable-args'."
:group 'org-babel
:package-version '(Org . "9.4")
:type 'symbol
:options '(jar plantuml))
(defcustom org-plantuml-executable-path "plantuml"
"File name of the PlantUML executable."
:group 'org-babel
:package-version '(Org . "9.4")
:type 'string)
(defcustom org-plantuml-executable-args (list "-headless")
"The arguments passed to plantuml executable when executing PlantUML."
:group 'org-babel
:package-version '(Org . "9.4")
:type '(repeat string))
(defun org-babel-variable-assignments:plantuml (params) (defun org-babel-variable-assignments:plantuml (params)
"Return a list of PlantUML statements assigning the block's variables. "Return a list of PlantUML statements assigning the block's variables.
PARAMS is a property list of source block parameters, which may PARAMS is a property list of source block parameters, which may
@ -69,10 +94,11 @@ function to convert variables to PlantUML assignments.
If BODY does not contain @startXXX ... @endXXX clauses, @startuml If BODY does not contain @startXXX ... @endXXX clauses, @startuml
... @enduml will be added." ... @enduml will be added."
(let ((assignments (org-babel-variable-assignments:plantuml params))) (let ((full-body
(if (string-prefix-p "@start" body t) assignments (org-babel-expand-body:generic
(format "@startuml\n%s\n@enduml" body params (org-babel-variable-assignments:plantuml params))))
(org-babel-expand-body:generic body params assignments))))) (if (string-prefix-p "@start" body t) full-body
(format "@startuml\n%s\n@enduml" full-body))))
(defun org-babel-execute:plantuml (body params) (defun org-babel-execute:plantuml (body params)
"Execute a block of plantuml code with org-babel. "Execute a block of plantuml code with org-babel.
@ -82,40 +108,41 @@ This function is called by `org-babel-execute-src-block'."
(cmdline (cdr (assq :cmdline params))) (cmdline (cdr (assq :cmdline params)))
(in-file (org-babel-temp-file "plantuml-")) (in-file (org-babel-temp-file "plantuml-"))
(java (or (cdr (assq :java params)) "")) (java (or (cdr (assq :java params)) ""))
(executable (cond ((eq org-plantuml-exec-mode 'plantuml) org-plantuml-executable-path)
(t "java")))
(executable-args (cond ((eq org-plantuml-exec-mode 'plantuml) org-plantuml-executable-args)
((string= "" org-plantuml-jar-path)
(error "`org-plantuml-jar-path' is not set"))
((not (file-exists-p org-plantuml-jar-path))
(error "Could not find plantuml.jar at %s" org-plantuml-jar-path))
(t (list java
"-jar"
(shell-quote-argument (expand-file-name org-plantuml-jar-path))))))
(full-body (org-babel-plantuml-make-body body params)) (full-body (org-babel-plantuml-make-body body params))
(cmd (if (string= "" org-plantuml-jar-path) (cmd (mapconcat #'identity
(error "`org-plantuml-jar-path' is not set") (append
(concat "java " java " -jar " (list executable)
(shell-quote-argument executable-args
(expand-file-name org-plantuml-jar-path)) (pcase (file-name-extension out-file)
(if (string= (file-name-extension out-file) "png") ("png" '("-tpng"))
" -tpng" "") ("svg" '("-tsvg"))
(if (string= (file-name-extension out-file) "svg") ("eps" '("-teps"))
" -tsvg" "") ("pdf" '("-tpdf"))
(if (string= (file-name-extension out-file) "eps") ("tex" '("-tlatex"))
" -teps" "") ("vdx" '("-tvdx"))
(if (string= (file-name-extension out-file) "pdf") ("xmi" '("-txmi"))
" -tpdf" "") ("scxml" '("-tscxml"))
(if (string= (file-name-extension out-file) "tex") ("html" '("-thtml"))
" -tlatex" "") ("txt" '("-ttxt"))
(if (string= (file-name-extension out-file) "vdx") ("utxt" '("-utxt")))
" -tvdx" "") (list
(if (string= (file-name-extension out-file) "xmi") "-p"
" -txmi" "") cmdline
(if (string= (file-name-extension out-file) "scxml") "<"
" -tscxml" "") (org-babel-process-file-name in-file)
(if (string= (file-name-extension out-file) "html") ">"
" -thtml" "") (org-babel-process-file-name out-file)))
(if (string= (file-name-extension out-file) "txt") " ")))
" -ttxt" "")
(if (string= (file-name-extension out-file) "utxt")
" -utxt" "")
" -p " cmdline " < "
(org-babel-process-file-name in-file)
" > "
(org-babel-process-file-name out-file)))))
(unless (file-exists-p org-plantuml-jar-path)
(error "Could not find plantuml.jar at %s" org-plantuml-jar-path))
(with-temp-file in-file (insert full-body)) (with-temp-file in-file (insert full-body))
(message "%s" cmd) (org-babel-eval cmd "") (message "%s" cmd) (org-babel-eval cmd "")
nil)) ;; signal that output has already been written to file nil)) ;; signal that output has already been written to file
@ -126,6 +153,4 @@ This function is called by `org-babel-execute-src-block'."
(provide 'ob-plantuml) (provide 'ob-plantuml)
;;; ob-plantuml.el ends here ;;; ob-plantuml.el ends here

View file

@ -4,6 +4,7 @@
;; Authors: Eric Schulte ;; Authors: Eric Schulte
;; Dan Davison ;; Dan Davison
;; Maintainer: Jack Kamm <jackkamm@gmail.com>
;; Keywords: literate programming, reproducible research ;; Keywords: literate programming, reproducible research
;; Homepage: https://orgmode.org ;; Homepage: https://orgmode.org
@ -29,10 +30,11 @@
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
(require 'org-macs) (require 'org-macs)
(require 'python)
(declare-function py-shell "ext:python-mode" (&optional argprompt)) (declare-function py-shell "ext:python-mode" (&rest args))
(declare-function py-toggle-shells "ext:python-mode" (arg)) (declare-function py-toggle-shells "ext:python-mode" (arg))
(declare-function run-python "ext:python" (&optional cmd dedicated show)) (declare-function py-shell-send-string "ext:python-mode" (strg &optional process))
(defvar org-babel-tangle-lang-exts) (defvar org-babel-tangle-lang-exts)
(add-to-list 'org-babel-tangle-lang-exts '("python" . "py")) (add-to-list 'org-babel-tangle-lang-exts '("python" . "py"))
@ -104,7 +106,8 @@ VARS contains resolved variable references."
(org-babel-comint-in-buffer session (org-babel-comint-in-buffer session
(mapc (lambda (var) (mapc (lambda (var)
(end-of-line 1) (insert var) (comint-send-input) (end-of-line 1) (insert var) (comint-send-input)
(org-babel-comint-wait-for-output session)) var-lines)) (org-babel-comint-wait-for-output session))
var-lines))
session)) session))
(defun org-babel-load-session:python (session body params) (defun org-babel-load-session:python (session body params)
@ -177,42 +180,40 @@ Emacs-lisp table, otherwise return the results as a string."
"Initiate a python session. "Initiate a python session.
If there is not a current inferior-process-buffer in SESSION If there is not a current inferior-process-buffer in SESSION
then create. Return the initialized session." then create. Return the initialized session."
(require org-babel-python-mode)
(save-window-excursion (save-window-excursion
(let* ((session (if session (intern session) :default)) (let* ((session (if session (intern session) :default))
(python-buffer (org-babel-python-session-buffer session)) (py-buffer (org-babel-python-session-buffer session))
(cmd (if (member system-type '(cygwin windows-nt ms-dos)) (cmd (if (member system-type '(cygwin windows-nt ms-dos))
(concat org-babel-python-command " -i") (concat org-babel-python-command " -i")
org-babel-python-command))) org-babel-python-command)))
(cond (cond
((and (eq 'python org-babel-python-mode) ((eq 'python org-babel-python-mode) ; python.el
(fboundp 'run-python)) ; python.el (unless py-buffer
(if (not (version< "24.1" emacs-version)) (setq py-buffer (org-babel-python-with-earmuffs session)))
(run-python cmd) (let ((python-shell-buffer-name
(unless python-buffer (org-babel-python-without-earmuffs py-buffer)))
(setq python-buffer (org-babel-python-with-earmuffs session))) (run-python cmd)
(let ((python-shell-buffer-name (sleep-for 0 10)))
(org-babel-python-without-earmuffs python-buffer)))
(run-python cmd))))
((and (eq 'python-mode org-babel-python-mode) ((and (eq 'python-mode org-babel-python-mode)
(fboundp 'py-shell)) ; python-mode.el (fboundp 'py-shell)) ; python-mode.el
(require 'python-mode)
;; Make sure that py-which-bufname is initialized, as otherwise ;; Make sure that py-which-bufname is initialized, as otherwise
;; it will be overwritten the first time a Python buffer is ;; it will be overwritten the first time a Python buffer is
;; created. ;; created.
(py-toggle-shells py-default-interpreter) (py-toggle-shells py-default-interpreter)
;; `py-shell' creates a buffer whose name is the value of ;; `py-shell' creates a buffer whose name is the value of
;; `py-which-bufname' with '*'s at the beginning and end ;; `py-which-bufname' with '*'s at the beginning and end
(let* ((bufname (if (and python-buffer (buffer-live-p python-buffer)) (let* ((bufname (if (and py-buffer (buffer-live-p py-buffer))
(replace-regexp-in-string ;; zap surrounding * (replace-regexp-in-string ;; zap surrounding *
"^\\*\\([^*]+\\)\\*$" "\\1" python-buffer) "^\\*\\([^*]+\\)\\*$" "\\1" py-buffer)
(concat "Python-" (symbol-name session)))) (concat "Python-" (symbol-name session))))
(py-which-bufname bufname)) (py-which-bufname bufname))
(py-shell) (setq py-buffer (org-babel-python-with-earmuffs bufname))
(setq python-buffer (org-babel-python-with-earmuffs bufname)))) (py-shell nil nil t org-babel-python-command py-buffer nil nil t nil)))
(t (t
(error "No function available for running an inferior Python"))) (error "No function available for running an inferior Python")))
(setq org-babel-python-buffers (setq org-babel-python-buffers
(cons (cons session python-buffer) (cons (cons session py-buffer)
(assq-delete-all session org-babel-python-buffers))) (assq-delete-all session org-babel-python-buffers)))
session))) session)))
@ -222,8 +223,9 @@ then create. Return the initialized session."
(org-babel-python-session-buffer (org-babel-python-session-buffer
(org-babel-python-initiate-session-by-key session)))) (org-babel-python-initiate-session-by-key session))))
(defvar org-babel-python-eoe-indicator "'org_babel_python_eoe'" (defvar org-babel-python-eoe-indicator "org_babel_python_eoe"
"A string to indicate that evaluation has completed.") "A string to indicate that evaluation has completed.")
(defconst org-babel-python-wrapper-method (defconst org-babel-python-wrapper-method
" "
def main(): def main():
@ -238,14 +240,39 @@ def main():
open('%s', 'w').write( pprint.pformat(main()) )") open('%s', 'w').write( pprint.pformat(main()) )")
(defconst org-babel-python--exec-tmpfile (defconst org-babel-python--exec-tmpfile "\
(concat with open('%s') as __org_babel_python_tmpfile:
"__org_babel_python_fname = '%s'; " exec(compile(__org_babel_python_tmpfile.read(), __org_babel_python_tmpfile.name, 'exec'))"
"__org_babel_python_fh = open(__org_babel_python_fname); " "Template for Python session command with output results.
"exec(compile("
"__org_babel_python_fh.read(), __org_babel_python_fname, 'exec'" Has a single %s escape, the tempfile containing the source code
")); " to evaluate.")
"__org_babel_python_fh.close()"))
(defun org-babel-python-format-session-value
(src-file result-file result-params)
"Return Python code to evaluate SRC-FILE and write result to RESULT-FILE."
(format "\
import ast
with open('%s') as __org_babel_python_tmpfile:
__org_babel_python_ast = ast.parse(__org_babel_python_tmpfile.read())
__org_babel_python_final = __org_babel_python_ast.body[-1]
if isinstance(__org_babel_python_final, ast.Expr):
__org_babel_python_ast.body = __org_babel_python_ast.body[:-1]
exec(compile(__org_babel_python_ast, '<string>', 'exec'))
__org_babel_python_final = eval(compile(ast.Expression(
__org_babel_python_final.value), '<string>', 'eval'))
with open('%s', 'w') as __org_babel_python_tmpfile:
if %s:
import pprint
__org_babel_python_tmpfile.write(pprint.pformat(__org_babel_python_final))
else:
__org_babel_python_tmpfile.write(str(__org_babel_python_final))
else:
exec(compile(__org_babel_python_ast, '<string>', 'exec'))
__org_babel_python_final = None"
(org-babel-process-file-name src-file 'noquote)
(org-babel-process-file-name result-file 'noquote)
(if (member "pp" result-params) "True" "False")))
(defun org-babel-python-evaluate (defun org-babel-python-evaluate
(session body &optional result-type result-params preamble) (session body &optional result-type result-params preamble)
@ -256,6 +283,19 @@ open('%s', 'w').write( pprint.pformat(main()) )")
(org-babel-python-evaluate-external-process (org-babel-python-evaluate-external-process
body result-type result-params preamble))) body result-type result-params preamble)))
(defun org-babel-python--shift-right (body &optional count)
(with-temp-buffer
(python-mode)
(insert body)
(goto-char (point-min))
(while (not (eobp))
(unless (python-syntax-context 'string)
(python-indent-shift-right (line-beginning-position)
(line-end-position)
count))
(forward-line 1))
(buffer-string)))
(defun org-babel-python-evaluate-external-process (defun org-babel-python-evaluate-external-process
(body &optional result-type result-params preamble) (body &optional result-type result-params preamble)
"Evaluate BODY in external python process. "Evaluate BODY in external python process.
@ -276,89 +316,70 @@ last statement in BODY, as elisp."
(if (member "pp" result-params) (if (member "pp" result-params)
org-babel-python-pp-wrapper-method org-babel-python-pp-wrapper-method
org-babel-python-wrapper-method) org-babel-python-wrapper-method)
(mapconcat (org-babel-python--shift-right body)
(lambda (line) (format "\t%s" line))
(split-string (org-remove-indentation (org-trim body))
"[\r\n]")
"\n")
(org-babel-process-file-name tmp-file 'noquote)))) (org-babel-process-file-name tmp-file 'noquote))))
(org-babel-eval-read-file tmp-file)))))) (org-babel-eval-read-file tmp-file))))))
(org-babel-result-cond result-params (org-babel-result-cond result-params
raw raw
(org-babel-python-table-or-string (org-trim raw))))) (org-babel-python-table-or-string (org-trim raw)))))
(defun org-babel-python--send-string (session body)
"Pass BODY to the Python process in SESSION.
Return output."
(with-current-buffer session
(let* ((string-buffer "")
(comint-output-filter-functions
(cons (lambda (text) (setq string-buffer
(concat string-buffer text)))
comint-output-filter-functions))
(body (format "\
try:
%s
except:
raise
finally:
print('%s')"
(org-babel-python--shift-right body 4)
org-babel-python-eoe-indicator)))
(if (not (eq 'python-mode org-babel-python-mode))
(let ((python-shell-buffer-name
(org-babel-python-without-earmuffs session)))
(python-shell-send-string body))
(require 'python-mode)
(py-shell-send-string body (get-buffer-process session)))
;; same as `python-shell-comint-end-of-output-p' in emacs-25.1+
(while (not (string-match
org-babel-python-eoe-indicator
string-buffer))
(accept-process-output (get-buffer-process (current-buffer))))
(org-babel-chomp (substring string-buffer 0 (match-beginning 0))))))
(defun org-babel-python-evaluate-session (defun org-babel-python-evaluate-session
(session body &optional result-type result-params) (session body &optional result-type result-params)
"Pass BODY to the Python process in SESSION. "Pass BODY to the Python process in SESSION.
If RESULT-TYPE equals `output' then return standard output as a If RESULT-TYPE equals `output' then return standard output as a
string. If RESULT-TYPE equals `value' then return the value of the string. If RESULT-TYPE equals `value' then return the value of the
last statement in BODY, as elisp." last statement in BODY, as elisp."
(let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5))) (let* ((tmp-src-file (org-babel-temp-file "python-"))
(dump-last-value
(lambda
(tmp-file pp)
(mapc
(lambda (statement) (insert statement) (funcall send-wait))
(if pp
(list
"import pprint"
(format "open('%s', 'w').write(pprint.pformat(_))"
(org-babel-process-file-name tmp-file 'noquote)))
(list (format "open('%s', 'w').write(str(_))"
(org-babel-process-file-name tmp-file
'noquote)))))))
(last-indent 0)
(input-body (lambda (body)
(dolist (line (split-string body "[\r\n]"))
;; Insert a blank line to end an indent
;; block.
(let ((curr-indent (string-match "\\S-" line)))
(if curr-indent
(progn
(when (< curr-indent last-indent)
(insert "")
(funcall send-wait))
(setq last-indent curr-indent))
(setq last-indent 0)))
(insert line)
(funcall send-wait))
(funcall send-wait)))
(results (results
(pcase result-type (progn
(`output (with-temp-file tmp-src-file (insert body))
(let ((body (if (string-match-p ".\n+." body) ; Multiline (pcase result-type
(let ((tmp-src-file (org-babel-temp-file (`output
"python-"))) (let ((body (format org-babel-python--exec-tmpfile
(with-temp-file tmp-src-file (insert body)) (org-babel-process-file-name
(format org-babel-python--exec-tmpfile tmp-src-file 'noquote))))
tmp-src-file)) (org-babel-python--send-string session body)))
body))) (`value
(mapconcat (let* ((tmp-results-file (org-babel-temp-file "python-"))
#'org-trim (body (org-babel-python-format-session-value
(butlast tmp-src-file tmp-results-file result-params)))
(org-babel-comint-with-output (org-babel-python--send-string session body)
(session org-babel-python-eoe-indicator t body) (sleep-for 0 10)
(funcall input-body body) (org-babel-eval-read-file tmp-results-file)))))))
(funcall send-wait) (funcall send-wait) (org-babel-result-cond result-params
(insert org-babel-python-eoe-indicator) results
(funcall send-wait)) (org-babel-python-table-or-string results))))
2) "\n")))
(`value
(let ((tmp-file (org-babel-temp-file "python-")))
(org-babel-comint-with-output
(session org-babel-python-eoe-indicator nil body)
(let ((comint-process-echoes nil))
(funcall input-body body)
(funcall dump-last-value tmp-file
(member "pp" result-params))
(funcall send-wait) (funcall send-wait)
(insert org-babel-python-eoe-indicator)
(funcall send-wait)))
(org-babel-eval-read-file tmp-file))))))
(unless (string= (substring org-babel-python-eoe-indicator 1 -1) results)
(org-babel-result-cond result-params
results
(org-babel-python-table-or-string results)))))
(defun org-babel-python-read-string (string) (defun org-babel-python-read-string (string)
"Strip \\='s from around Python string." "Strip \\='s from around Python string."
@ -369,6 +390,4 @@ last statement in BODY, as elisp."
(provide 'ob-python) (provide 'ob-python)
;;; ob-python.el ends here ;;; ob-python.el ends here

View file

@ -143,7 +143,8 @@ Emacs Lisp representation of the value of the variable."
(org-babel-ref-split-args new-referent)))) (org-babel-ref-split-args new-referent))))
(when (> (length new-header-args) 0) (when (> (length new-header-args) 0)
(setq args (append (org-babel-parse-header-arguments (setq args (append (org-babel-parse-header-arguments
new-header-args) args))) new-header-args)
args)))
(setq ref new-refere))) (setq ref new-refere)))
(when (string-match "^\\(.+\\):\\(.+\\)$" ref) (when (string-match "^\\(.+\\):\\(.+\\)$" ref)
(setq split-file (match-string 1 ref)) (setq split-file (match-string 1 ref))
@ -240,7 +241,6 @@ to \"0:-1\"."
"Split ARG-STRING into top-level arguments of balanced parenthesis." "Split ARG-STRING into top-level arguments of balanced parenthesis."
(mapcar #'org-trim (org-babel-balanced-split arg-string 44))) (mapcar #'org-trim (org-babel-balanced-split arg-string 44)))
(provide 'ob-ref) (provide 'ob-ref)
;;; ob-ref.el ends here ;;; ob-ref.el ends here

View file

@ -30,16 +30,17 @@
;; - ruby and irb executables :: http://www.ruby-lang.org/ ;; - ruby and irb executables :: http://www.ruby-lang.org/
;; ;;
;; - ruby-mode :: Can be installed through ELPA, or from ;; - ruby-mode :: Can be installed through ELPA, or from
;; http://github.com/eschulte/rinari/raw/master/util/ruby-mode.el ;; https://github.com/eschulte/rinari/raw/master/util/ruby-mode.el
;; ;;
;; - inf-ruby mode :: Can be installed through ELPA, or from ;; - inf-ruby mode :: Can be installed through ELPA, or from
;; http://github.com/eschulte/rinari/raw/master/util/inf-ruby.el ;; https://github.com/eschulte/rinari/raw/master/util/inf-ruby.el
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
(require 'org-macs) (require 'org-macs)
(declare-function run-ruby "ext:inf-ruby" (&optional command name)) (declare-function run-ruby-or-pop-to-buffer "ext:inf-ruby" (command &optional name buffer))
(declare-function inf-ruby-buffer "ext:inf-ruby" ())
(declare-function xmp "ext:rcodetools" (&optional option)) (declare-function xmp "ext:rcodetools" (&optional option))
(defvar inf-ruby-default-implementation) (defvar inf-ruby-default-implementation)
@ -51,7 +52,8 @@
(defvar org-babel-default-header-args:ruby '()) (defvar org-babel-default-header-args:ruby '())
(defvar org-babel-ruby-command "ruby" (defvar org-babel-ruby-command "ruby"
"Name of command to use for executing ruby code.") "Name of command to use for executing ruby code.
It's possible to override it by using a header argument `:ruby'")
(defcustom org-babel-ruby-hline-to "nil" (defcustom org-babel-ruby-hline-to "nil"
"Replace hlines in incoming tables with this when translating to ruby." "Replace hlines in incoming tables with this when translating to ruby."
@ -71,9 +73,12 @@
"Execute a block of Ruby code with Babel. "Execute a block of Ruby code with Babel.
This function is called by `org-babel-execute-src-block'." This function is called by `org-babel-execute-src-block'."
(let* ((session (org-babel-ruby-initiate-session (let* ((session (org-babel-ruby-initiate-session
(cdr (assq :session params)))) (cdr (assq :session params)) params))
(result-params (cdr (assq :result-params params))) (result-params (cdr (assq :result-params params)))
(result-type (cdr (assq :result-type params))) (result-type (cdr (assq :result-type params)))
(org-babel-ruby-command
(or (cdr (assq :ruby params))
org-babel-ruby-command))
(full-body (org-babel-expand-body:generic (full-body (org-babel-expand-body:generic
body params (org-babel-variable-assignments:ruby params))) body params (org-babel-variable-assignments:ruby params)))
(result (if (member "xmp" result-params) (result (if (member "xmp" result-params)
@ -103,7 +108,8 @@ This function is called by `org-babel-execute-src-block'."
(mapc (lambda (var) (mapc (lambda (var)
(insert var) (comint-send-input nil t) (insert var) (comint-send-input nil t)
(org-babel-comint-wait-for-output session) (org-babel-comint-wait-for-output session)
(sit-for .1) (goto-char (point-max))) var-lines)) (sit-for .1) (goto-char (point-max)))
var-lines))
session)) session))
(defun org-babel-load-session:ruby (session body params) (defun org-babel-load-session:ruby (session body params)
@ -147,17 +153,21 @@ Emacs-lisp table, otherwise return the results as a string."
res) res)
res))) res)))
(defun org-babel-ruby-initiate-session (&optional session _params) (defun org-babel-ruby-initiate-session (&optional session params)
"Initiate a ruby session. "Initiate a ruby session.
If there is not a current inferior-process-buffer in SESSION If there is not a current inferior-process-buffer in SESSION
then create one. Return the initialized session." then create one. Return the initialized session."
(unless (string= session "none") (unless (string= session "none")
(require 'inf-ruby) (require 'inf-ruby)
(let* ((cmd (cdr (assoc inf-ruby-default-implementation (let* ((cmd (cdr (or (assq :ruby params)
inf-ruby-implementations))) (assoc inf-ruby-default-implementation
inf-ruby-implementations))))
(buffer (get-buffer (format "*%s*" session))) (buffer (get-buffer (format "*%s*" session)))
(session-buffer (or buffer (save-window-excursion (session-buffer (or buffer (save-window-excursion
(run-ruby cmd session) (run-ruby-or-pop-to-buffer
cmd (or session "ruby")
(unless session
(inf-ruby-buffer)))
(current-buffer))))) (current-buffer)))))
(if (org-babel-comint-buffer-livep session-buffer) (if (org-babel-comint-buffer-livep session-buffer)
(progn (sit-for .25) session-buffer) (progn (sit-for .25) session-buffer)
@ -263,6 +273,4 @@ return the value of the last statement in BODY, as elisp."
(provide 'ob-ruby) (provide 'ob-ruby)
;;; ob-ruby.el ends here ;;; ob-ruby.el ends here

View file

@ -35,7 +35,7 @@
;;; Requirements: ;;; Requirements:
;; - sass-mode :: http://github.com/nex3/haml/blob/master/extra/sass-mode.el ;; - sass-mode :: https://github.com/nex3/haml/blob/master/extra/sass-mode.el
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
@ -65,6 +65,4 @@ This function is called by `org-babel-execute-src-block'."
(provide 'ob-sass) (provide 'ob-sass)
;;; ob-sass.el ends here ;;; ob-sass.el ends here

View file

@ -43,6 +43,7 @@
(require 'geiser-impl nil t) (require 'geiser-impl nil t)
(defvar geiser-repl--repl) ; Defined in geiser-repl.el (defvar geiser-repl--repl) ; Defined in geiser-repl.el
(defvar geiser-impl--implementation) ; Defined in geiser-impl.el (defvar geiser-impl--implementation) ; Defined in geiser-impl.el
(defvar geiser-scheme-implementation) ; Defined in geiser-impl.el
(defvar geiser-default-implementation) ; Defined in geiser-impl.el (defvar geiser-default-implementation) ; Defined in geiser-impl.el
(defvar geiser-active-implementations) ; Defined in geiser-impl.el (defvar geiser-active-implementations) ; Defined in geiser-impl.el
(defvar geiser-debug-show-debug-p) ; Defined in geiser-debug.el (defvar geiser-debug-show-debug-p) ; Defined in geiser-debug.el
@ -71,7 +72,8 @@
(defun org-babel-expand-body:scheme (body params) (defun org-babel-expand-body:scheme (body params)
"Expand BODY according to PARAMS, return the expanded body." "Expand BODY according to PARAMS, return the expanded body."
(let ((vars (org-babel--get-vars params)) (let ((vars (org-babel--get-vars params))
(prepends (cdr (assq :prologue params)))) (prepends (cdr (assq :prologue params)))
(postpends (cdr (assq :epilogue params))))
(concat (and prepends (concat prepends "\n")) (concat (and prepends (concat prepends "\n"))
(if (null vars) body (if (null vars) body
(format "(let (%s)\n%s\n)" (format "(let (%s)\n%s\n)"
@ -80,7 +82,8 @@
(format "%S" (print `(,(car var) ',(cdr var))))) (format "%S" (print `(,(car var) ',(cdr var)))))
vars vars
"\n ") "\n ")
body))))) body))
(and postpends (concat "\n" postpends)))))
(defvar org-babel-scheme-repl-map (make-hash-table :test #'equal) (defvar org-babel-scheme-repl-map (make-hash-table :test #'equal)
@ -175,7 +178,8 @@ is true; otherwise returns the last value."
(geiser-debug-show-debug-p nil)) (geiser-debug-show-debug-p nil))
(let ((ret (geiser-eval-region (point-min) (point-max)))) (let ((ret (geiser-eval-region (point-min) (point-max))))
(setq result (if output (setq result (if output
(geiser-eval--retort-output ret) (or (geiser-eval--retort-output ret)
"Geiser Interpreter produced no output")
(geiser-eval--retort-result-str ret ""))))) (geiser-eval--retort-result-str ret "")))))
(when (not repl) (when (not repl)
(save-current-buffer (set-buffer repl-buffer) (save-current-buffer (set-buffer repl-buffer)
@ -208,6 +212,7 @@ This function is called by `org-babel-execute-src-block'."
(let* ((result-type (cdr (assq :result-type params))) (let* ((result-type (cdr (assq :result-type params)))
(impl (or (when (cdr (assq :scheme params)) (impl (or (when (cdr (assq :scheme params))
(intern (cdr (assq :scheme params)))) (intern (cdr (assq :scheme params))))
geiser-scheme-implementation
geiser-default-implementation geiser-default-implementation
(car geiser-active-implementations))) (car geiser-active-implementations)))
(session (org-babel-scheme-make-session-name (session (org-babel-scheme-make-session-name

View file

@ -40,7 +40,8 @@
In case you want to use a different screen than one selected by your $PATH") In case you want to use a different screen than one selected by your $PATH")
(defvar org-babel-default-header-args:screen (defvar org-babel-default-header-args:screen
'((:results . "silent") (:session . "default") (:cmd . "sh") (:terminal . "xterm")) `((:results . "silent") (:session . "default") (:cmd . "sh")
(:terminal . "xterm") (:screenrc . ,null-device))
"Default arguments to use when running screen source blocks.") "Default arguments to use when running screen source blocks.")
(defun org-babel-execute:screen (body params) (defun org-babel-execute:screen (body params)
@ -59,11 +60,11 @@ In case you want to use a different screen than one selected by your $PATH")
(let* ((session (cdr (assq :session params))) (let* ((session (cdr (assq :session params)))
(cmd (cdr (assq :cmd params))) (cmd (cdr (assq :cmd params)))
(terminal (cdr (assq :terminal params))) (terminal (cdr (assq :terminal params)))
(screenrc (cdr (assq :screenrc params)))
(process-name (concat "org-babel: terminal (" session ")"))) (process-name (concat "org-babel: terminal (" session ")")))
(apply 'start-process process-name "*Messages*" (apply 'start-process process-name "*Messages*"
terminal `("-T" ,(concat "org-babel: " session) "-e" ,org-babel-screen-location terminal `("-T" ,(concat "org-babel: " session) "-e" ,org-babel-screen-location
"-c" "/dev/null" "-mS" ,(concat "org-babel-session-" session) "-c" ,screenrc "-mS" ,session ,cmd))
,cmd))
;; XXX: Is there a better way than the following? ;; XXX: Is there a better way than the following?
(while (not (org-babel-screen-session-socketname session)) (while (not (org-babel-screen-session-socketname session))
;; wait until screen session is available before returning ;; wait until screen session is available before returning
@ -97,9 +98,8 @@ In case you want to use a different screen than one selected by your $PATH")
nil nil
(mapcar (mapcar
(lambda (x) (lambda (x)
(when (string-match (and (string-match-p (regexp-quote session) x)
(concat "org-babel-session-" session) x) x))
x))
sockets))))) sockets)))))
(when match-socket (car (split-string match-socket))))) (when match-socket (car (split-string match-socket)))))
@ -108,6 +108,7 @@ In case you want to use a different screen than one selected by your $PATH")
(let ((tmpfile (org-babel-temp-file "screen-"))) (let ((tmpfile (org-babel-temp-file "screen-")))
(with-temp-file tmpfile (with-temp-file tmpfile
(insert body) (insert body)
(insert "\n")
;; org-babel has superfluous spaces ;; org-babel has superfluous spaces
(goto-char (point-min)) (goto-char (point-min))
@ -126,7 +127,7 @@ The terminal should shortly flicker."
;; XXX: need to find a better way to do the following ;; XXX: need to find a better way to do the following
(while (not (file-readable-p tmpfile)) (while (not (file-readable-p tmpfile))
;; do something, otherwise this will be optimized away ;; do something, otherwise this will be optimized away
(format "org-babel-screen: File not readable yet.")) (message "org-babel-screen: File not readable yet."))
(setq tmp-string (with-temp-buffer (setq tmp-string (with-temp-buffer
(insert-file-contents-literally tmpfile) (insert-file-contents-literally tmpfile)
(buffer-substring (point-min) (point-max)))) (buffer-substring (point-min) (point-max))))
@ -138,6 +139,4 @@ The terminal should shortly flicker."
(provide 'ob-screen) (provide 'ob-screen)
;;; ob-screen.el ends here ;;; ob-screen.el ends here

View file

@ -4,7 +4,6 @@
;; Author: Bjarte Johansen ;; Author: Bjarte Johansen
;; Keywords: literate programming, reproducible research ;; Keywords: literate programming, reproducible research
;; Version: 0.1.1
;; This file is part of GNU Emacs. ;; This file is part of GNU Emacs.
@ -68,7 +67,8 @@ function is called by `org-babel-execute-src-block'."
(in-file (cdr (assq :in-file params))) (in-file (cdr (assq :in-file params)))
(code-file (let ((file (org-babel-temp-file "sed-"))) (code-file (let ((file (org-babel-temp-file "sed-")))
(with-temp-file file (with-temp-file file
(insert body)) file)) (insert body))
file))
(stdin (let ((stdin (cdr (assq :stdin params)))) (stdin (let ((stdin (cdr (assq :stdin params))))
(when stdin (when stdin
(let ((tmp (org-babel-temp-file "sed-stdin-")) (let ((tmp (org-babel-temp-file "sed-stdin-"))
@ -102,4 +102,5 @@ function is called by `org-babel-execute-src-block'."
(cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))) (cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
(provide 'ob-sed) (provide 'ob-sed)
;;; ob-sed.el ends here ;;; ob-sed.el ends here

View file

@ -71,6 +71,19 @@ outside the Customize interface."
(set-default symbol value) (set-default symbol value)
(org-babel-shell-initialize))) (org-babel-shell-initialize)))
(defcustom org-babel-shell-results-defaults-to-output t
"Let shell execution defaults to \":results output\".
When set to t, use \":results output\" when no :results setting
is set. This is especially useful for inline source blocks.
When set to nil, stick to the convention of using :results value
as the default setting when no :results is set, the \"value\" of
a shell execution being its exit code."
:group 'org-babel
:type 'boolean
:package-version '(Org . "9.4"))
(defun org-babel-execute:shell (body params) (defun org-babel-execute:shell (body params)
"Execute a block of Shell commands with Babel. "Execute a block of Shell commands with Babel.
This function is called by `org-babel-execute-src-block'." This function is called by `org-babel-execute-src-block'."
@ -79,9 +92,17 @@ This function is called by `org-babel-execute-src-block'."
(stdin (let ((stdin (cdr (assq :stdin params)))) (stdin (let ((stdin (cdr (assq :stdin params))))
(when stdin (org-babel-sh-var-to-string (when stdin (org-babel-sh-var-to-string
(org-babel-ref-resolve stdin))))) (org-babel-ref-resolve stdin)))))
(results-params (cdr (assq :result-params params)))
(value-is-exit-status
(or (and
(equal '("replace") results-params)
(not org-babel-shell-results-defaults-to-output))
(member "value" results-params)))
(cmdline (cdr (assq :cmdline params))) (cmdline (cdr (assq :cmdline params)))
(full-body (org-babel-expand-body:generic (full-body (concat
body params (org-babel-variable-assignments:shell params)))) (org-babel-expand-body:generic
body params (org-babel-variable-assignments:shell params))
(when value-is-exit-status "\necho $?"))))
(org-babel-reassemble-table (org-babel-reassemble-table
(org-babel-sh-evaluate session full-body params stdin cmdline) (org-babel-sh-evaluate session full-body params stdin cmdline)
(org-babel-pick-name (org-babel-pick-name
@ -96,7 +117,8 @@ This function is called by `org-babel-execute-src-block'."
(org-babel-comint-in-buffer session (org-babel-comint-in-buffer session
(mapc (lambda (var) (mapc (lambda (var)
(insert var) (comint-send-input nil t) (insert var) (comint-send-input nil t)
(org-babel-comint-wait-for-output session)) var-lines)) (org-babel-comint-wait-for-output session))
var-lines))
session)) session))
(defun org-babel-load-session:shell (session body params) (defun org-babel-load-session:shell (session body params)
@ -129,15 +151,15 @@ This function is called by `org-babel-execute-src-block'."
(varname values &optional sep hline) (varname values &optional sep hline)
"Return a list of statements declaring the values as bash associative array." "Return a list of statements declaring the values as bash associative array."
(format "unset %s\ndeclare -A %s\n%s" (format "unset %s\ndeclare -A %s\n%s"
varname varname varname varname
(mapconcat (mapconcat
(lambda (items) (lambda (items)
(format "%s[%s]=%s" (format "%s[%s]=%s"
varname varname
(org-babel-sh-var-to-sh (car items) sep hline) (org-babel-sh-var-to-sh (car items) sep hline)
(org-babel-sh-var-to-sh (cdr items) sep hline))) (org-babel-sh-var-to-sh (cdr items) sep hline)))
values values
"\n"))) "\n")))
(defun org-babel--variable-assignments:bash (varname values &optional sep hline) (defun org-babel--variable-assignments:bash (varname values &optional sep hline)
"Represent the parameters as useful Bash shell variables." "Represent the parameters as useful Bash shell variables."
@ -208,6 +230,12 @@ If RESULT-TYPE equals `output' then return a list of the outputs
of the statements in BODY, if RESULT-TYPE equals `value' then of the statements in BODY, if RESULT-TYPE equals `value' then
return the value of the last statement in BODY." return the value of the last statement in BODY."
(let* ((shebang (cdr (assq :shebang params))) (let* ((shebang (cdr (assq :shebang params)))
(results-params (cdr (assq :result-params params)))
(value-is-exit-status
(or (and
(equal '("replace") results-params)
(not org-babel-shell-results-defaults-to-output))
(member "value" results-params)))
(results (results
(cond (cond
((or stdin cmdline) ; external shell script w/STDIN ((or stdin cmdline) ; external shell script w/STDIN
@ -259,8 +287,9 @@ return the value of the last statement in BODY."
(insert body)) (insert body))
(set-file-modes script-file #o755) (set-file-modes script-file #o755)
(org-babel-eval script-file ""))) (org-babel-eval script-file "")))
(t (t (org-babel-eval shell-file-name (org-trim body))))))
(org-babel-eval shell-file-name (org-trim body)))))) (when value-is-exit-status
(setq results (car (reverse (split-string results "\n" t)))))
(when results (when results
(let ((result-params (cdr (assq :result-params params)))) (let ((result-params (cdr (assq :result-params params))))
(org-babel-result-cond result-params (org-babel-result-cond result-params
@ -277,6 +306,4 @@ return the value of the last statement in BODY."
(provide 'ob-shell) (provide 'ob-shell)
;;; ob-shell.el ends here ;;; ob-shell.el ends here

View file

@ -75,4 +75,5 @@ This function is called by `org-babel-execute-src-block'."
(error results)))))) (error results))))))
(provide 'ob-shen) (provide 'ob-shen)
;;; ob-shen.el ends here ;;; ob-shen.el ends here

View file

@ -55,7 +55,7 @@
;; - dbi ;; - dbi
;; - mssql ;; - mssql
;; - sqsh ;; - sqsh
;; - postgresql ;; - postgresql (postgres)
;; - oracle ;; - oracle
;; - vertica ;; - vertica
;; ;;
@ -73,6 +73,7 @@
(declare-function orgtbl-to-csv "org-table" (table params)) (declare-function orgtbl-to-csv "org-table" (table params))
(declare-function org-table-to-lisp "org-table" (&optional txt)) (declare-function org-table-to-lisp "org-table" (&optional txt))
(declare-function cygwin-convert-file-name-to-windows "cygw32.c" (file &optional absolute-p)) (declare-function cygwin-convert-file-name-to-windows "cygw32.c" (file &optional absolute-p))
(declare-function sql-set-product "sql" (product))
(defvar sql-connection-alist) (defvar sql-connection-alist)
(defvar org-babel-default-header-args:sql '()) (defvar org-babel-default-header-args:sql '())
@ -92,6 +93,13 @@
(org-babel-sql-expand-vars (org-babel-sql-expand-vars
body (org-babel--get-vars params))) body (org-babel--get-vars params)))
(defun org-babel-edit-prep:sql (info)
"Set `sql-product' in Org edit buffer.
Set `sql-product' in Org edit buffer according to the
corresponding :engine source block header argument."
(let ((product (cdr (assq :engine (nth 2 info)))))
(sql-set-product product)))
(defun org-babel-sql-dbstring-mysql (host port user password database) (defun org-babel-sql-dbstring-mysql (host port user password database)
"Make MySQL cmd line args for database connection. Pass nil to omit that arg." "Make MySQL cmd line args for database connection. Pass nil to omit that arg."
(combine-and-quote-strings (combine-and-quote-strings
@ -211,64 +219,64 @@ This function is called by `org-babel-execute-src-block'."
(out-file (or (cdr (assq :out-file params)) (out-file (or (cdr (assq :out-file params))
(org-babel-temp-file "sql-out-"))) (org-babel-temp-file "sql-out-")))
(header-delim "") (header-delim "")
(command (pcase (intern engine) (command (cl-case (intern engine)
(`dbi (format "dbish --batch %s < %s | sed '%s' > %s" (dbi (format "dbish --batch %s < %s | sed '%s' > %s"
(or cmdline "") (or cmdline "")
(org-babel-process-file-name in-file) (org-babel-process-file-name in-file)
"/^+/d;s/^|//;s/(NULL)/ /g;$d" "/^+/d;s/^|//;s/(NULL)/ /g;$d"
(org-babel-process-file-name out-file))) (org-babel-process-file-name out-file)))
(`monetdb (format "mclient -f tab %s < %s > %s" (monetdb (format "mclient -f tab %s < %s > %s"
(or cmdline "") (or cmdline "")
(org-babel-process-file-name in-file) (org-babel-process-file-name in-file)
(org-babel-process-file-name out-file))) (org-babel-process-file-name out-file)))
(`mssql (format "sqlcmd %s -s \"\t\" %s -i %s -o %s" (mssql (format "sqlcmd %s -s \"\t\" %s -i %s -o %s"
(or cmdline "")
(org-babel-sql-dbstring-mssql
dbhost dbuser dbpassword database)
(org-babel-sql-convert-standard-filename
(org-babel-process-file-name in-file))
(org-babel-sql-convert-standard-filename
(org-babel-process-file-name out-file))))
(`mysql (format "mysql %s %s %s < %s > %s"
(org-babel-sql-dbstring-mysql
dbhost dbport dbuser dbpassword database)
(if colnames-p "" "-N")
(or cmdline "")
(org-babel-process-file-name in-file)
(org-babel-process-file-name out-file)))
(`postgresql (format
"%spsql --set=\"ON_ERROR_STOP=1\" %s -A -P \
footer=off -F \"\t\" %s -f %s -o %s %s"
(if dbpassword
(format "PGPASSWORD=%s " dbpassword)
"")
(if colnames-p "" "-t")
(org-babel-sql-dbstring-postgresql
dbhost dbport dbuser database)
(org-babel-process-file-name in-file)
(org-babel-process-file-name out-file)
(or cmdline "")))
(`sqsh (format "sqsh %s %s -i %s -o %s -m csv"
(or cmdline "") (or cmdline "")
(org-babel-sql-dbstring-sqsh (org-babel-sql-dbstring-mssql
dbhost dbuser dbpassword database) dbhost dbuser dbpassword database)
(org-babel-sql-convert-standard-filename (org-babel-sql-convert-standard-filename
(org-babel-process-file-name in-file)) (org-babel-process-file-name in-file))
(org-babel-sql-convert-standard-filename (org-babel-sql-convert-standard-filename
(org-babel-process-file-name out-file)))) (org-babel-process-file-name out-file))))
(`vertica (format "vsql %s -f %s -o %s %s" (mysql (format "mysql %s %s %s < %s > %s"
(org-babel-sql-dbstring-vertica (org-babel-sql-dbstring-mysql
dbhost dbport dbuser dbpassword database) dbhost dbport dbuser dbpassword database)
(org-babel-process-file-name in-file) (if colnames-p "" "-N")
(org-babel-process-file-name out-file) (or cmdline "")
(or cmdline ""))) (org-babel-process-file-name in-file)
(`oracle (format (org-babel-process-file-name out-file)))
"sqlplus -s %s < %s > %s" ((postgresql postgres) (format
(org-babel-sql-dbstring-oracle "%spsql --set=\"ON_ERROR_STOP=1\" %s -A -P \
dbhost dbport dbuser dbpassword database) footer=off -F \"\t\" %s -f %s -o %s %s"
(org-babel-process-file-name in-file) (if dbpassword
(org-babel-process-file-name out-file))) (format "PGPASSWORD=%s " dbpassword)
(_ (error "No support for the %s SQL engine" engine))))) "")
(if colnames-p "" "-t")
(org-babel-sql-dbstring-postgresql
dbhost dbport dbuser database)
(org-babel-process-file-name in-file)
(org-babel-process-file-name out-file)
(or cmdline "")))
(sqsh (format "sqsh %s %s -i %s -o %s -m csv"
(or cmdline "")
(org-babel-sql-dbstring-sqsh
dbhost dbuser dbpassword database)
(org-babel-sql-convert-standard-filename
(org-babel-process-file-name in-file))
(org-babel-sql-convert-standard-filename
(org-babel-process-file-name out-file))))
(vertica (format "vsql %s -f %s -o %s %s"
(org-babel-sql-dbstring-vertica
dbhost dbport dbuser dbpassword database)
(org-babel-process-file-name in-file)
(org-babel-process-file-name out-file)
(or cmdline "")))
(oracle (format
"sqlplus -s %s < %s > %s"
(org-babel-sql-dbstring-oracle
dbhost dbport dbuser dbpassword database)
(org-babel-process-file-name in-file)
(org-babel-process-file-name out-file)))
(t (user-error "No support for the %s SQL engine" engine)))))
(with-temp-file in-file (with-temp-file in-file
(insert (insert
(pcase (intern engine) (pcase (intern engine)
@ -301,7 +309,7 @@ SET COLSEP '|'
(progn (insert-file-contents-literally out-file) (buffer-string))) (progn (insert-file-contents-literally out-file) (buffer-string)))
(with-temp-buffer (with-temp-buffer
(cond (cond
((memq (intern engine) '(dbi mysql postgresql sqsh vertica)) ((memq (intern engine) '(dbi mysql postgresql postgres sqsh vertica))
;; Add header row delimiter after column-names header in first line ;; Add header row delimiter after column-names header in first line
(cond (cond
(colnames-p (colnames-p
@ -365,6 +373,4 @@ SET COLSEP '|'
(provide 'ob-sql) (provide 'ob-sql)
;;; ob-sql.el ends here ;;; ob-sql.el ends here

View file

@ -133,11 +133,12 @@ This function is called by `org-babel-execute-src-block'."
"If RESULT looks like a trivial table, then unwrap it." "If RESULT looks like a trivial table, then unwrap it."
(if (and (equal 1 (length result)) (if (and (equal 1 (length result))
(equal 1 (length (car result)))) (equal 1 (length (car result))))
(org-babel-read (caar result)) (org-babel-read (caar result) t)
(mapcar (lambda (row) (mapcar (lambda (row)
(if (eq 'hline row) (if (eq 'hline row)
'hline 'hline
(mapcar #'org-babel-string-read row))) result))) (mapcar #'org-babel-string-read row)))
result)))
(defun org-babel-sqlite-offset-colnames (table headers-p) (defun org-babel-sqlite-offset-colnames (table headers-p)
"If HEADERS-P is non-nil then offset the first row as column names." "If HEADERS-P is non-nil then offset the first row as column names."
@ -152,6 +153,4 @@ Prepare SESSION according to the header arguments specified in PARAMS."
(provide 'ob-sqlite) (provide 'ob-sqlite)
;;; ob-sqlite.el ends here ;;; ob-sqlite.el ends here

View file

@ -41,7 +41,7 @@
;; For more information and usage examples, visit ;; For more information and usage examples, visit
;; https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-stan.html ;; https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-stan.html
;; ;;
;; [1] http://mc-stan.org/ ;; [1] https://mc-stan.org/
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
@ -82,4 +82,5 @@ Otherwise, write the Stan code directly to the named file."
(user-error "Stan does not support sessions")) (user-error "Stan does not support sessions"))
(provide 'ob-stan) (provide 'ob-stan)
;;; ob-stan.el ends here ;;; ob-stan.el ends here

View file

@ -62,7 +62,8 @@ If STRING ends in a newline character, then remove the newline
character and replace it with ellipses." character and replace it with ellipses."
(if (and (stringp string) (string-match "[\n\r]\\(.\\)?" string)) (if (and (stringp string) (string-match "[\n\r]\\(.\\)?" string))
(concat (substring string 0 (match-beginning 0)) (concat (substring string 0 (match-beginning 0))
(when (match-string 1 string) "...")) string)) (when (match-string 1 string) "..."))
string))
(defmacro org-sbe (source-block &rest variables) (defmacro org-sbe (source-block &rest variables)
"Return the results of calling SOURCE-BLOCK with VARIABLES. "Return the results of calling SOURCE-BLOCK with VARIABLES.
@ -147,6 +148,4 @@ as shown in the example below.
(provide 'ob-table) (provide 'ob-table)
;;; ob-table.el ends here ;;; ob-table.el ends here

View file

@ -41,6 +41,7 @@
(declare-function org-element-type "org-element" (element)) (declare-function org-element-type "org-element" (element))
(declare-function org-heading-components "org" ()) (declare-function org-heading-components "org" ())
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance)) (declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
(declare-function org-in-archived-heading-p "org" (&optional no-inheritance))
(declare-function outline-previous-heading "outline" ()) (declare-function outline-previous-heading "outline" ())
(defcustom org-babel-tangle-lang-exts (defcustom org-babel-tangle-lang-exts
@ -166,13 +167,14 @@ evaluating BODY."
(def-edebug-spec org-babel-with-temp-filebuffer (form body)) (def-edebug-spec org-babel-with-temp-filebuffer (form body))
;;;###autoload ;;;###autoload
(defun org-babel-tangle-file (file &optional target-file lang) (defun org-babel-tangle-file (file &optional target-file lang-re)
"Extract the bodies of source code blocks in FILE. "Extract the bodies of source code blocks in FILE.
Source code blocks are extracted with `org-babel-tangle'. Source code blocks are extracted with `org-babel-tangle'.
Optional argument TARGET-FILE can be used to specify a default Optional argument TARGET-FILE can be used to specify a default
export file for all source blocks. Optional argument LANG can be export file for all source blocks. Optional argument LANG-RE can
used to limit the exported source code blocks by language. be used to limit the exported source code blocks by languages
Return a list whose CAR is the tangled file name." matching a regular expression. Return a list whose CAR is the
tangled file name."
(interactive "fFile to tangle: \nP") (interactive "fFile to tangle: \nP")
(let ((visited-p (find-buffer-visiting (expand-file-name file))) (let ((visited-p (find-buffer-visiting (expand-file-name file)))
to-be-removed) to-be-removed)
@ -180,7 +182,7 @@ Return a list whose CAR is the tangled file name."
(save-window-excursion (save-window-excursion
(find-file file) (find-file file)
(setq to-be-removed (current-buffer)) (setq to-be-removed (current-buffer))
(mapcar #'expand-file-name (org-babel-tangle nil target-file lang))) (mapcar #'expand-file-name (org-babel-tangle nil target-file lang-re)))
(unless visited-p (unless visited-p
(kill-buffer to-be-removed))))) (kill-buffer to-be-removed)))))
@ -192,7 +194,7 @@ Return a list whose CAR is the tangled file name."
(mapc (lambda (el) (copy-file el pub-dir t)) (org-babel-tangle-file filename))) (mapc (lambda (el) (copy-file el pub-dir t)) (org-babel-tangle-file filename)))
;;;###autoload ;;;###autoload
(defun org-babel-tangle (&optional arg target-file lang) (defun org-babel-tangle (&optional arg target-file lang-re)
"Write code blocks to source-specific files. "Write code blocks to source-specific files.
Extract the bodies of all source code blocks from the current Extract the bodies of all source code blocks from the current
file into their own source-specific files. file into their own source-specific files.
@ -200,8 +202,9 @@ With one universal prefix argument, only tangle the block at point.
When two universal prefix arguments, only tangle blocks for the When two universal prefix arguments, only tangle blocks for the
tangle file of the block at point. tangle file of the block at point.
Optional argument TARGET-FILE can be used to specify a default Optional argument TARGET-FILE can be used to specify a default
export file for all source blocks. Optional argument LANG can be export file for all source blocks. Optional argument LANG-RE can
used to limit the exported source code blocks by language." be used to limit the exported source code blocks by languages
matching a regular expression."
(interactive "P") (interactive "P")
(run-hooks 'org-babel-pre-tangle-hook) (run-hooks 'org-babel-pre-tangle-hook)
;; Possibly Restrict the buffer to the current code block ;; Possibly Restrict the buffer to the current code block
@ -286,7 +289,7 @@ used to limit the exported source code blocks by language."
specs))) specs)))
(if (equal arg '(4)) (if (equal arg '(4))
(org-babel-tangle-single-block 1 t) (org-babel-tangle-single-block 1 t)
(org-babel-tangle-collect-blocks lang tangle-file))) (org-babel-tangle-collect-blocks lang-re tangle-file)))
(message "Tangled %d code block%s from %s" block-counter (message "Tangled %d code block%s from %s" block-counter
(if (= block-counter 1) "" "s") (if (= block-counter 1) "" "s")
(file-name-nondirectory (file-name-nondirectory
@ -364,13 +367,14 @@ that the appropriate major-mode is set. SPEC has the form:
(org-fill-template (org-fill-template
org-babel-tangle-comment-format-end link-data))))) org-babel-tangle-comment-format-end link-data)))))
(defun org-babel-tangle-collect-blocks (&optional language tangle-file) (defun org-babel-tangle-collect-blocks (&optional lang-re tangle-file)
"Collect source blocks in the current Org file. "Collect source blocks in the current Org file.
Return an association list of source-code block specifications of Return an association list of source-code block specifications of
the form used by `org-babel-spec-to-string' grouped by language. the form used by `org-babel-spec-to-string' grouped by language.
Optional argument LANGUAGE can be used to limit the collected Optional argument LANG-RE can be used to limit the collected
source code blocks by language. Optional argument TANGLE-FILE source code blocks by languages matching a regular expression.
can be used to limit the collected code blocks by target file." Optional argument TANGLE-FILE can be used to limit the collected
code blocks by target file."
(let ((counter 0) last-heading-pos blocks) (let ((counter 0) last-heading-pos blocks)
(org-babel-map-src-blocks (buffer-file-name) (org-babel-map-src-blocks (buffer-file-name)
(let ((current-heading-pos (let ((current-heading-pos
@ -379,13 +383,14 @@ can be used to limit the collected code blocks by target file."
(if (eq last-heading-pos current-heading-pos) (cl-incf counter) (if (eq last-heading-pos current-heading-pos) (cl-incf counter)
(setq counter 1) (setq counter 1)
(setq last-heading-pos current-heading-pos))) (setq last-heading-pos current-heading-pos)))
(unless (org-in-commented-heading-p) (unless (or (org-in-commented-heading-p)
(org-in-archived-heading-p))
(let* ((info (org-babel-get-src-block-info 'light)) (let* ((info (org-babel-get-src-block-info 'light))
(src-lang (nth 0 info)) (src-lang (nth 0 info))
(src-tfile (cdr (assq :tangle (nth 2 info))))) (src-tfile (cdr (assq :tangle (nth 2 info)))))
(unless (or (string= src-tfile "no") (unless (or (string= src-tfile "no")
(and tangle-file (not (equal tangle-file src-tfile))) (and tangle-file (not (equal tangle-file src-tfile)))
(and language (not (string= language src-lang)))) (and lang-re (not (string-match-p lang-re src-lang))))
;; Add the spec for this block to blocks under its ;; Add the spec for this block to blocks under its
;; language. ;; language.
(let ((by-lang (assoc src-lang blocks)) (let ((by-lang (assoc src-lang blocks))
@ -471,9 +476,9 @@ non-nil, return the full association list to be used by
file) file)
(if (and org-babel-tangle-use-relative-file-links (if (and org-babel-tangle-use-relative-file-links
(string-match org-link-types-re link) (string-match org-link-types-re link)
(string= (match-string 0 link) "file")) (string= (match-string 1 link) "file"))
(concat "file:" (concat "file:"
(file-relative-name (match-string 1 link) (file-relative-name (substring link (match-end 0))
(file-name-directory (file-name-directory
(cdr (assq :tangle params))))) (cdr (assq :tangle params)))))
link) link)
@ -513,14 +518,16 @@ which enable the original code blocks to be found."
(goto-char (point-min)) (goto-char (point-min))
(let ((counter 0) new-body end) (let ((counter 0) new-body end)
(while (re-search-forward org-link-bracket-re nil t) (while (re-search-forward org-link-bracket-re nil t)
(when (re-search-forward (if (and (match-string 2)
(concat " " (regexp-quote (match-string 2)) " ends here")) (re-search-forward
(setq end (match-end 0)) (concat " " (regexp-quote (match-string 2)) " ends here") nil t))
(forward-line -1) (progn (setq end (match-end 0))
(save-excursion (forward-line -1)
(when (setq new-body (org-babel-tangle-jump-to-org)) (save-excursion
(org-babel-update-block-body new-body))) (when (setq new-body (org-babel-tangle-jump-to-org))
(setq counter (+ 1 counter))) (org-babel-update-block-body new-body)))
(setq counter (+ 1 counter)))
(setq end (point)))
(goto-char end)) (goto-char end))
(prog1 counter (message "Detangled %d code blocks" counter))))) (prog1 counter (message "Detangled %d code blocks" counter)))))
@ -541,7 +548,8 @@ which enable the original code blocks to be found."
(save-match-data (save-match-data
(re-search-forward (re-search-forward
(concat " " (regexp-quote block-name) (concat " " (regexp-quote block-name)
" ends here") nil t) " ends here")
nil t)
(setq end (line-beginning-position)))))))) (setq end (line-beginning-position))))))))
(unless (and start (< start mid) (< mid end)) (unless (and start (< start mid) (< mid end))
(error "Not in tangled code")) (error "Not in tangled code"))

View file

@ -26,7 +26,7 @@
;;; Commentary: ;;; Commentary:
;; ob-vala.el provides Babel support for the Vala language ;; ob-vala.el provides Babel support for the Vala language
;; (see http://live.gnome.org/Vala for details) ;; (see https://live.gnome.org/Vala for details)
;;; Requirements: ;;; Requirements:

View file

@ -98,7 +98,7 @@
(require 'org-macs) (require 'org-macs)
(require 'ol) (require 'ol)
;; Declare functions and variables ;;; Declare functions and variables
(declare-function bbdb "ext:bbdb-com" (string elidep)) (declare-function bbdb "ext:bbdb-com" (string elidep))
(declare-function bbdb-company "ext:bbdb-com" (string elidep)) (declare-function bbdb-company "ext:bbdb-com" (string elidep))
@ -126,9 +126,9 @@
(declare-function diary-ordinal-suffix "diary-lib" (n)) (declare-function diary-ordinal-suffix "diary-lib" (n))
(with-no-warnings (defvar date)) ;unprefixed, from calendar.el (with-no-warnings (defvar date)) ; unprefixed, from calendar.el
;; Customization ;;; Customization
(defgroup org-bbdb-anniversaries nil (defgroup org-bbdb-anniversaries nil
"Customizations for including anniversaries from BBDB into Agenda." "Customizations for including anniversaries from BBDB into Agenda."
@ -162,13 +162,13 @@ used."
'(("birthday" . '(("birthday" .
(lambda (name years suffix) (lambda (name years suffix)
(concat "Birthday: [[bbdb:" name "][" name " (" (concat "Birthday: [[bbdb:" name "][" name " ("
(format "%s" years) ; handles numbers as well as strings (format "%s" years) ; handles numbers as well as strings
suffix ")]]"))) suffix ")]]")))
("wedding" . ("wedding" .
(lambda (name years suffix) (lambda (name years suffix)
(concat "[[bbdb:" name "][" name "'s " (concat "[[bbdb:" name "][" name "'s "
(format "%s" years) (format "%s" years)
suffix " wedding anniversary]]")))) suffix " wedding anniversary]]"))))
"How different types of anniversaries should be formatted. "How different types of anniversaries should be formatted.
An alist of elements (STRING . FORMAT) where STRING is the name of an An alist of elements (STRING . FORMAT) where STRING is the name of an
anniversary class and format is either: anniversary class and format is either:
@ -221,7 +221,8 @@ date year)."
:complete #'org-bbdb-complete-link :complete #'org-bbdb-complete-link
:store #'org-bbdb-store-link) :store #'org-bbdb-store-link)
;; Implementation ;;; Implementation
(defun org-bbdb-store-link () (defun org-bbdb-store-link ()
"Store a link to a BBDB database entry." "Store a link to a BBDB database entry."
(when (eq major-mode 'bbdb-mode) (when (eq major-mode 'bbdb-mode)
@ -236,7 +237,7 @@ date year)."
:link link :description name) :link link :description name)
link))) link)))
(defun org-bbdb-export (path desc format) (defun org-bbdb-export (path desc format _)
"Create the export version of a BBDB link specified by PATH or DESC. "Create the export version of a BBDB link specified by PATH or DESC.
If exporting to either HTML or LaTeX FORMAT the link will be If exporting to either HTML or LaTeX FORMAT the link will be
italicized, in all other cases it is left unchanged." italicized, in all other cases it is left unchanged."
@ -249,7 +250,7 @@ italicized, in all other cases it is left unchanged."
(format "<text:span text:style-name=\"Emphasis\">%s</text:span>" desc)) (format "<text:span text:style-name=\"Emphasis\">%s</text:span>" desc))
(t desc))) (t desc)))
(defun org-bbdb-open (name) (defun org-bbdb-open (name _)
"Follow a BBDB link to NAME." "Follow a BBDB link to NAME."
(require 'bbdb-com) (require 'bbdb-com)
(let ((inhibit-redisplay (not debug-on-error))) (let ((inhibit-redisplay (not debug-on-error)))
@ -362,7 +363,9 @@ This is used by Org to re-create the anniversary hash table."
;;;###autoload ;;;###autoload
(defun org-bbdb-anniversaries () (defun org-bbdb-anniversaries ()
"Extract anniversaries from BBDB for display in the agenda." "Extract anniversaries from BBDB for display in the agenda.
When called programmatically, this function expects the `date'
variable to be globally bound."
(require 'bbdb) (require 'bbdb)
(require 'diary-lib) (require 'diary-lib)
(unless (hash-table-p org-bbdb-anniv-hash) (unless (hash-table-p org-bbdb-anniv-hash)
@ -380,7 +383,7 @@ This is used by Org to re-create the anniversary hash table."
(text ()) (text ())
rec recs) rec recs)
;; we don't want to miss people born on Feb. 29th ;; We don't want to miss people born on Feb. 29th
(when (and (= m 3) (= d 1) (when (and (= m 3) (= d 1)
(not (null (gethash (list 2 29) org-bbdb-anniv-hash))) (not (null (gethash (list 2 29) org-bbdb-anniv-hash)))
(not (calendar-leap-year-p y))) (not (calendar-leap-year-p y)))
@ -415,8 +418,9 @@ This is used by Org to re-create the anniversary hash table."
)) ))
text)) text))
;;; Return list of anniversaries for today and the next n-1 (default: n=7) days. ;;; Return the list of anniversaries for today and the next n-1
;;; This is meant to be used in an org file instead of org-bbdb-anniversaries: ;;; (default: n=7) days. This is meant to be used in an org file
;;; instead of org-bbdb-anniversaries:
;;; ;;;
;;; %%(org-bbdb-anniversaries-future) ;;; %%(org-bbdb-anniversaries-future)
;;; ;;;
@ -442,15 +446,14 @@ for the same event depending on if it occurs in the next few days
or far away in the future." or far away in the future."
(let ((delta (- (calendar-absolute-from-gregorian anniv-date) (let ((delta (- (calendar-absolute-from-gregorian anniv-date)
(calendar-absolute-from-gregorian agenda-date)))) (calendar-absolute-from-gregorian agenda-date))))
(cond (cond
((= delta 0) " -- today\\&") ((= delta 0) " -- today\\&")
((= delta 1) " -- tomorrow\\&") ((= delta 1) " -- tomorrow\\&")
((< delta org-bbdb-general-anniversary-description-after) (format " -- in %d days\\&" delta)) ((< delta org-bbdb-general-anniversary-description-after)
(format " -- in %d days\\&" delta))
((pcase-let ((`(,month ,day ,year) anniv-date)) ((pcase-let ((`(,month ,day ,year) anniv-date))
(format " -- %d-%02d-%02d\\&" year month day)))))) (format " -- %d-%02d-%02d\\&" year month day))))))
(defun org-bbdb-anniversaries-future (&optional n) (defun org-bbdb-anniversaries-future (&optional n)
"Return list of anniversaries for today and the next n-1 days (default n=7)." "Return list of anniversaries for today and the next n-1 days (default n=7)."
(let ((n (or n 7))) (let ((n (or n 7)))

View file

@ -95,7 +95,7 @@
;; The link creation part has been part of Org for a long time. ;; The link creation part has been part of Org for a long time.
;; ;;
;; Creating better capture template information was inspired by a request ;; Creating better capture template information was inspired by a request
;; of Austin Frank: http://article.gmane.org/gmane.emacs.orgmode/4112 ;; of Austin Frank: https://orgmode.org/list/m0myu03vbx.fsf@gmail.com
;; and then implemented by Bastien Guerry. ;; and then implemented by Bastien Guerry.
;; ;;
;; Eric Schulte eventually added the functions for translating between ;; Eric Schulte eventually added the functions for translating between
@ -134,7 +134,6 @@
(declare-function org-insert-heading "org" (&optional arg invisible-ok top)) (declare-function org-insert-heading "org" (&optional arg invisible-ok top))
(declare-function org-map-entries "org" (func &optional match scope &rest skip)) (declare-function org-map-entries "org" (func &optional match scope &rest skip))
(declare-function org-narrow-to-subtree "org" ()) (declare-function org-narrow-to-subtree "org" ())
(declare-function org-open-file "org" (path &optional in-emacs line search))
(declare-function org-set-property "org" (property value)) (declare-function org-set-property "org" (property value))
(declare-function org-toggle-tag "org" (tag &optional onoff)) (declare-function org-toggle-tag "org" (tag &optional onoff))
@ -483,12 +482,11 @@ With optional argument OPTIONAL, also prompt for optional fields."
:follow #'org-bibtex-open :follow #'org-bibtex-open
:store #'org-bibtex-store-link) :store #'org-bibtex-store-link)
(defun org-bibtex-open (path) (defun org-bibtex-open (path arg)
"Visit the bibliography entry on PATH." "Visit the bibliography entry on PATH.
(let* ((search (when (string-match "::\\(.+\\)\\'" path) ARG, when non-nil, is a universal prefix argument. See
(match-string 1 path))) `org-open-file' for details."
(path (substring path 0 (match-beginning 0)))) (org-link-open-as-file path arg))
(org-open-file path t nil search)))
(defun org-bibtex-store-link () (defun org-bibtex-store-link ()
"Store a link to a BibTeX entry." "Store a link to a BibTeX entry."
@ -556,7 +554,8 @@ With optional argument OPTIONAL, also prompt for optional fields."
;; We construct a regexp that searches for "@entrytype{" followed by the key ;; We construct a regexp that searches for "@entrytype{" followed by the key
(goto-char (point-min)) (goto-char (point-min))
(and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*" (and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*"
(regexp-quote s) "[ \t\n]*,") nil t) (regexp-quote s) "[ \t\n]*,")
nil t)
(goto-char (match-beginning 0))) (goto-char (match-beginning 0)))
(if (and (match-beginning 0) (equal current-prefix-arg '(16))) (if (and (match-beginning 0) (equal current-prefix-arg '(16)))
;; Use double prefix to indicate that any web link should be browsed ;; Use double prefix to indicate that any web link should be browsed
@ -596,7 +595,8 @@ Headlines are exported using `org-bibtex-headline'."
(with-temp-file filename (with-temp-file filename
(insert (mapconcat #'identity bibtex-entries "\n"))) (insert (mapconcat #'identity bibtex-entries "\n")))
(message "Successfully exported %d BibTeX entries to %s" (message "Successfully exported %d BibTeX entries to %s"
(length bibtex-entries) filename) nil)))) (length bibtex-entries) filename)
nil))))
(when error-point (when error-point
(goto-char error-point) (goto-char error-point)
(message "Bibtex error at %S" (nth 4 (org-heading-components)))))) (message "Bibtex error at %S" (nth 4 (org-heading-components))))))
@ -661,7 +661,8 @@ This uses `bibtex-parse-entry'."
(when (and (> (length str) 1) (when (and (> (length str) 1)
(= (aref str 0) (car pair)) (= (aref str 0) (car pair))
(= (aref str (1- (length str))) (cdr pair))) (= (aref str (1- (length str))) (cdr pair)))
(setf str (substring str 1 (1- (length str)))))) str))) (setf str (substring str 1 (1- (length str))))))
str)))
(push (mapcar (push (mapcar
(lambda (pair) (lambda (pair)
(cons (let ((field (funcall keyword (car pair)))) (cons (let ((field (funcall keyword (car pair))))

View file

@ -68,7 +68,7 @@
((eq format 'ascii) (format "%s (%s)" desc path)) ((eq format 'ascii) (format "%s (%s)" desc path))
(t path))))) (t path)))))
(defun org-docview-open (link) (defun org-docview-open (link _)
(string-match "\\(.*?\\)\\(?:::\\([0-9]+\\)\\)?$" link) (string-match "\\(.*?\\)\\(?:::\\([0-9]+\\)\\)?$" link)
(let ((path (match-string 1 link)) (let ((path (match-string 1 link))
(page (and (match-beginning 2) (page (and (match-beginning 2)
@ -98,7 +98,6 @@ and append it."
"::" "::"
(read-from-minibuffer "Page:" "1"))) (read-from-minibuffer "Page:" "1")))
(provide 'ol-docview) (provide 'ol-docview)
;;; ol-docview.el ends here ;;; ol-docview.el ends here

View file

@ -33,7 +33,7 @@
:follow #'org-eshell-open :follow #'org-eshell-open
:store #'org-eshell-store-link) :store #'org-eshell-store-link)
(defun org-eshell-open (link) (defun org-eshell-open (link _)
"Switch to an eshell buffer and execute a command line. "Switch to an eshell buffer and execute a command line.
The link can be just a command line (executed in the default The link can be just a command line (executed in the default
eshell buffer) or a command line prefixed by a buffer name eshell buffer) or a command line prefixed by a buffer name

View file

@ -46,17 +46,22 @@
;;; Code: ;;; Code:
(require 'ol) (require 'ol)
(require 'cl-lib) (require 'cl-lib)
(require 'eww)
;; For Emacsen < 25.
(defvar eww-current-title) (defvar eww-current-title)
(defvar eww-current-url) (defvar eww-current-url)
(defvar eww-data)
(defvar eww-mode-map)
(declare-function eww-current-url "eww")
;; Store Org link in Eww mode buffer ;; Store Org link in Eww mode buffer
(org-link-set-parameters "eww" :follow #'eww :store #'org-eww-store-link) (org-link-set-parameters "eww"
:follow #'org-eww-open
:store #'org-eww-store-link)
(defun org-eww-open (url _)
"Open URL with Eww in the current buffer."
(eww url))
(defun org-eww-store-link () (defun org-eww-store-link ()
"Store a link to the url of an EWW buffer." "Store a link to the url of an EWW buffer."
(when (eq major-mode 'eww-mode) (when (eq major-mode 'eww-mode)

View file

@ -34,7 +34,8 @@
(require 'gnus-sum) (require 'gnus-sum)
(require 'gnus-util) (require 'gnus-util)
(require 'nnheader) (require 'nnheader)
(require 'nnir) (or (require 'nnselect nil t) ; Emacs >= 28
(require 'nnir nil t)) ; Emacs < 28
(require 'ol) (require 'ol)
@ -61,7 +62,7 @@
;;; Customization variables ;;; Customization variables
(defcustom org-gnus-prefer-web-links nil (defcustom org-gnus-prefer-web-links nil
"If non-nil, `org-store-link' creates web links to Google groups or Gmane. "If non-nil, `org-store-link' creates web links to Google groups.
\\<org-mode-map>When nil, Gnus will be used for such links. \\<org-mode-map>When nil, Gnus will be used for such links.
Using a prefix argument to the command `\\[org-store-link]' (`org-store-link') Using a prefix argument to the command `\\[org-store-link]' (`org-store-link')
negates this setting for the duration of the command." negates this setting for the duration of the command."
@ -87,8 +88,8 @@ negates this setting for the duration of the command."
(defun org-gnus-group-link (group) (defun org-gnus-group-link (group)
"Create a link to the Gnus group GROUP. "Create a link to the Gnus group GROUP.
If GROUP is a newsgroup and `org-gnus-prefer-web-links' is If GROUP is a newsgroup and `org-gnus-prefer-web-links' is
non-nil, create a link to groups.google.com or gmane.org. non-nil, create a link to groups.google.com. Otherwise create a
Otherwise create a link to the group inside Gnus. link to the group inside Gnus.
If `org-store-link' was called with a prefix arg the meaning of If `org-store-link' was called with a prefix arg the meaning of
`org-gnus-prefer-web-links' is reversed." `org-gnus-prefer-web-links' is reversed."
@ -96,10 +97,7 @@ If `org-store-link' was called with a prefix arg the meaning of
(if (and (string-prefix-p "nntp" group) ;; Only for nntp groups (if (and (string-prefix-p "nntp" group) ;; Only for nntp groups
(org-xor current-prefix-arg (org-xor current-prefix-arg
org-gnus-prefer-web-links)) org-gnus-prefer-web-links))
(concat (if (string-match "gmane" unprefixed-group) (concat "https://groups.google.com/group/" unprefixed-group)
"http://news.gmane.org/"
"http://groups.google.com/group/")
unprefixed-group)
(concat "gnus:" group)))) (concat "gnus:" group))))
(defun org-gnus-article-link (group newsgroups message-id x-no-archive) (defun org-gnus-article-link (group newsgroups message-id x-no-archive)
@ -110,7 +108,7 @@ parameters are the Gnus GROUP, the NEWSGROUPS the article was
posted to and the X-NO-ARCHIVE header value of that article. posted to and the X-NO-ARCHIVE header value of that article.
If GROUP is a newsgroup and `org-gnus-prefer-web-links' is If GROUP is a newsgroup and `org-gnus-prefer-web-links' is
non-nil, create a link to groups.google.com or gmane.org. non-nil, create a link to groups.google.com.
Otherwise create a link to the article inside Gnus. Otherwise create a link to the article inside Gnus.
If `org-store-link' was called with a prefix arg the meaning of If `org-store-link' was called with a prefix arg the meaning of
@ -118,9 +116,7 @@ If `org-store-link' was called with a prefix arg the meaning of
(if (and (org-xor current-prefix-arg org-gnus-prefer-web-links) (if (and (org-xor current-prefix-arg org-gnus-prefer-web-links)
newsgroups ;make web links only for nntp groups newsgroups ;make web links only for nntp groups
(not x-no-archive)) ;and if X-No-Archive isn't set (not x-no-archive)) ;and if X-No-Archive isn't set
(format (if (string-match-p "gmane\\." newsgroups) (format "https://groups.google.com/groups/search?as_umsgid=%s"
"http://mid.gmane.org/%s"
"http://groups.google.com/groups/search?as_umsgid=%s")
(url-encode-url message-id)) (url-encode-url message-id))
(concat "gnus:" group "#" message-id))) (concat "gnus:" group "#" message-id)))
@ -140,9 +136,15 @@ If `org-store-link' was called with a prefix arg the meaning of
(`(nnvirtual . ,_) (`(nnvirtual . ,_)
(save-excursion (save-excursion
(car (nnvirtual-map-article (gnus-summary-article-number))))) (car (nnvirtual-map-article (gnus-summary-article-number)))))
(`(nnir . ,_) (`(,(or `nnselect `nnir) . ,_) ; nnir is for Emacs < 28.
(save-excursion (save-excursion
(nnir-article-group (gnus-summary-article-number)))) (cond
((fboundp 'nnselect-article-group)
(nnselect-article-group (gnus-summary-article-number)))
((fboundp 'nnir-article-group)
(nnir-article-group (gnus-summary-article-number)))
(t
(error "No article-group variant bound")))))
(_ gnus-newsgroup-name))) (_ gnus-newsgroup-name)))
(header (if (eq major-mode 'gnus-article-mode) (header (if (eq major-mode 'gnus-article-mode)
;; When in an article, first move to summary ;; When in an article, first move to summary
@ -215,7 +217,7 @@ If `org-store-link' was called with a prefix arg the meaning of
(format "nntp+%s:%s" (or (cdr server) (car server)) group) (format "nntp+%s:%s" (or (cdr server) (car server)) group)
article))) article)))
(defun org-gnus-open (path) (defun org-gnus-open (path _)
"Follow the Gnus message or folder link specified by PATH." "Follow the Gnus message or folder link specified by PATH."
(unless (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path) (unless (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)
(error "Error in Gnus link %S" path)) (error "Error in Gnus link %S" path))

View file

@ -59,7 +59,7 @@
:link link :desc desc) :link link :desc desc)
link))) link)))
(defun org-info-open (path) (defun org-info-open (path _)
"Follow an Info file and node link specified by PATH." "Follow an Info file and node link specified by PATH."
(org-info-follow-link path)) (org-info-follow-link path))

View file

@ -78,7 +78,7 @@
:store #'org-irc-store-link :store #'org-irc-store-link
:export #'org-irc-export) :export #'org-irc-export)
(defun org-irc-visit (link) (defun org-irc-visit (link _)
"Parse LINK and dispatch to the correct function based on the client found." "Parse LINK and dispatch to the correct function based on the client found."
(let ((link (org-irc-parse-link link))) (let ((link (org-irc-parse-link link)))
(cond (cond

View file

@ -96,7 +96,7 @@ supported by MH-E."
(org-link-add-props :link link :description desc) (org-link-add-props :link link :description desc)
link)))) link))))
(defun org-mhe-open (path) (defun org-mhe-open (path _)
"Follow an MH-E message link specified by PATH." "Follow an MH-E message link specified by PATH."
(let (folder article) (let (folder article)
(if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))

View file

@ -43,7 +43,9 @@
(defvar rmail-file-name) ; From rmail.el (defvar rmail-file-name) ; From rmail.el
;; Install the link type ;; Install the link type
(org-link-set-parameters "rmail" :follow #'org-rmail-open :store #'org-rmail-store-link) (org-link-set-parameters "rmail"
:follow #'org-rmail-open
:store #'org-rmail-store-link)
;; Implementation ;; Implementation
(defun org-rmail-store-link () (defun org-rmail-store-link ()
@ -75,7 +77,7 @@
(rmail-show-message rmail-current-message) (rmail-show-message rmail-current-message)
link))))) link)))))
(defun org-rmail-open (path) (defun org-rmail-open (path _)
"Follow an Rmail message link to the specified PATH." "Follow an Rmail message link to the specified PATH."
(let (folder article) (let (folder article)
(if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))

View file

@ -45,6 +45,7 @@
(declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep)) (declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
(declare-function org-at-heading-p "org" (&optional _)) (declare-function org-at-heading-p "org" (&optional _))
(declare-function org-back-to-heading "org" (&optional invisible-ok)) (declare-function org-back-to-heading "org" (&optional invisible-ok))
(declare-function org-before-first-heading-p "org" ())
(declare-function org-do-occur "org" (regexp &optional cleanup)) (declare-function org-do-occur "org" (regexp &optional cleanup))
(declare-function org-element-at-point "org-element" ()) (declare-function org-element-at-point "org-element" ())
(declare-function org-element-cache-refresh "org-element" (pos)) (declare-function org-element-cache-refresh "org-element" (pos))
@ -57,7 +58,6 @@
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil)) (declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
(declare-function org-find-property "org" (property &optional value)) (declare-function org-find-property "org" (property &optional value))
(declare-function org-get-heading "org" (&optional no-tags no-todo no-priority no-comment)) (declare-function org-get-heading "org" (&optional no-tags no-todo no-priority no-comment))
(declare-function org-heading-components "org" ())
(declare-function org-id-find-id-file "org-id" (id)) (declare-function org-id-find-id-file "org-id" (id))
(declare-function org-id-store-link "org-id" ()) (declare-function org-id-store-link "org-id" ())
(declare-function org-insert-heading "org" (&optional arg invisible-ok top)) (declare-function org-insert-heading "org" (&optional arg invisible-ok top))
@ -85,42 +85,94 @@
:group 'org) :group 'org)
(defcustom org-link-parameters nil (defcustom org-link-parameters nil
"An alist of properties that defines all the links in Org mode. "Alist of properties that defines all the links in Org mode.
The key in each association is a string of the link type. The key in each association is a string of the link type.
Subsequent optional elements make up a plist of link properties. Subsequent optional elements make up a property list for that
type.
:follow - A function that takes the link path as an argument. All properties are optional. However, the most important ones
are, in this order, `:follow', `:export', and `:store', described
below.
:export - A function that takes the link path, description and `:follow'
export-backend as arguments.
:store - A function responsible for storing the link. See the Function used to follow the link, when the `org-open-at-point'
function `org-store-link-functions'. command runs on it. It is called with two arguments: the path,
as a string, and a universal prefix argument.
:complete - A function that inserts a link with completion. The Here, you may use `org-link-open-as-file' helper function for
function takes one optional prefix argument. types similar to \"file\".
:face - A face for the link, or a function that returns a face. `:export'
The function takes one argument which is the link path. The
default face is `org-link'.
:mouse-face - The mouse-face. The default is `highlight'. Function that accepts four arguments:
- the path, as a string,
- the description as a string, or nil,
- the export back-end,
- the export communication channel, as a plist.
:display - `full' will not fold the link in descriptive When nil, export for that type of link is delegated to the
display. Default is `org-link'. back-end.
:help-echo - A string or function that takes (window object position) `:store'
as arguments and returns a string.
:keymap - A keymap that is active on the link. The default is Function responsible for storing the link. See the function
`org-mouse-map'. `org-store-link-functions' for a description of the expected
arguments.
:htmlize-link - A function for the htmlize-link. Defaults Additional properties provide more specific control over the
to (list :uri \"type:path\") link.
:activate-func - A function to run at the end of font-lock `:activate-func'
activation. The function must accept (link-start link-end path bracketp)
as arguments." Function to run at the end of Font Lock activation. It must
accept four arguments:
- the buffer position at the start of the link,
- the buffer position at its end,
- the path, as a string,
- a boolean, non-nil when the link has brackets.
`:complete'
Function that inserts a link with completion. The function
takes one optional prefix argument.
`:display'
Value for `invisible' text property on the hidden parts of the
link. The most useful value is `full', which will not fold the
link in descriptive display. Default is `org-link'.
`:face'
Face for the link, or a function returning a face. The
function takes one argument, which is the path.
The default face is `org-link'.
`:help-echo'
String or function used as a value for the `help-echo' text
property. The function is called with one argument, the help
string to display, and should return a string.
`:htmlize-link'
Function or plist for the `htmlize-link' text property. The
function takes no argument.
Default is (:uri \"type:path\")
`:keymap'
Active keymap when point is on the link. Default is
`org-mouse-map'.
`:mouse-face'
Face used when hovering over the link. Default is
`highlight'."
:group 'org-link :group 'org-link
:package-version '(Org . "9.1") :package-version '(Org . "9.1")
:type '(alist :tag "Link display parameters" :type '(alist :tag "Link display parameters"
@ -408,7 +460,7 @@ This is for example useful to limit the length of the subject.
Examples: \"%f on: %.30s\", \"Email from %f\", \"Email %c\"" Examples: \"%f on: %.30s\", \"Email from %f\", \"Email %c\""
:group 'org-link-store :group 'org-link-store
:package-version '(Org . 9.3) :package-version '(Org . "9.3")
:type 'string :type 'string
:safe #'stringp) :safe #'stringp)
@ -674,6 +726,44 @@ White spaces are not significant."
(goto-char origin) (goto-char origin)
(user-error "No match for radio target: %s" target)))) (user-error "No match for radio target: %s" target))))
(defun org-link--context-from-region ()
"Return context string from active region, or nil."
(when (org-region-active-p)
(let ((context (buffer-substring (region-beginning) (region-end))))
(when (and (wholenump org-link-context-for-files)
(> org-link-context-for-files 0))
(let ((lines (org-split-string context "\n")))
(setq context
(mapconcat #'identity
(cl-subseq lines 0 org-link-context-for-files)
"\n"))))
context)))
(defun org-link--normalize-string (string &optional context)
"Remove ignored contents from STRING string and return it.
This function removes contiguous white spaces and statistics
cookies. When optional argument CONTEXT is non-nil, it assumes
STRING is a context string, and also removes special search
syntax around the string."
(let ((string
(org-trim
(replace-regexp-in-string
(rx (one-or-more (any " \t")))
" "
(replace-regexp-in-string
;; Statistics cookie regexp.
(rx (seq "[" (0+ digit) (or "%" (seq "/" (0+ digit))) "]"))
" "
string)))))
(when context
(while (cond ((and (string-prefix-p "(" string)
(string-suffix-p ")" string))
(setq string (org-trim (substring string 1 -1))))
((string-match "\\`[#*]+[ \t]*" string)
(setq string (substring string (match-end 0))))
(t nil))))
string))
;;; Public API ;;; Public API
@ -692,6 +782,8 @@ TYPE is a string and KEY is a plist keyword. See
"Set link TYPE properties to PARAMETERS. "Set link TYPE properties to PARAMETERS.
PARAMETERS should be keyword value pairs. See PARAMETERS should be keyword value pairs. See
`org-link-parameters' for supported keys." `org-link-parameters' for supported keys."
(when (member type '("coderef" "custom-id" "fuzzy" "radio"))
(error "Cannot override reserved link type: %S" type))
(let ((data (assoc type org-link-parameters))) (let ((data (assoc type org-link-parameters)))
(if data (setcdr data (org-combine-plists (cdr data) parameters)) (if data (setcdr data (org-combine-plists (cdr data) parameters))
(push (cons type parameters) org-link-parameters) (push (cons type parameters) org-link-parameters)
@ -716,12 +808,10 @@ This should be called after the variable `org-link-parameters' has changed."
(rx (seq "[[" (rx (seq "[["
;; URI part: match group 1. ;; URI part: match group 1.
(group (group
;; Allow an even number of backslashes right (one-or-more
;; before the closing bracket. (or (not (any "[]\\"))
(or (one-or-more "\\\\") (and "\\" (zero-or-more "\\\\") (any "[]"))
(and (*? anything) (and (one-or-more "\\") (not (any "[]"))))))
(not (any "\\"))
(zero-or-more "\\\\"))))
"]" "]"
;; Description (optional): match group 2. ;; Description (optional): match group 2.
(opt "[" (group (+? anything)) "]") (opt "[" (group (+? anything)) "]")
@ -838,37 +928,26 @@ E.g. \"%C3%B6\" becomes the german o-Umlaut."
(defun org-link-escape (link) (defun org-link-escape (link)
"Backslash-escape sensitive characters in string LINK." "Backslash-escape sensitive characters in string LINK."
;; Escape closing square brackets followed by another square bracket (replace-regexp-in-string
;; or at the end of the link. Also escape final backslashes so that (rx (seq (group (zero-or-more "\\")) (group (or string-end (any "[]")))))
;; we do not escape inadvertently URI's closing bracket. (lambda (m)
(with-temp-buffer (concat (match-string 1 m)
(insert link) (match-string 1 m)
(insert (make-string (- (skip-chars-backward "\\\\")) (and (/= (match-beginning 2) (match-end 2)) "\\")))
?\\)) link nil t 1))
(while (search-backward "\]" nil t)
(when (looking-at-p "\\]\\(?:[][]\\|\\'\\)")
(insert (make-string (1+ (- (skip-chars-backward "\\\\")))
?\\))))
(buffer-string)))
(defun org-link-unescape (link) (defun org-link-unescape (link)
"Remove escaping backslash characters from string LINK." "Remove escaping backslash characters from string LINK."
(with-temp-buffer (replace-regexp-in-string
(save-excursion (insert link)) (rx (group (one-or-more "\\")) (or string-end (any "[]")))
(while (re-search-forward "\\(\\\\+\\)\\]\\(?:[][]\\|\\'\\)" nil t) (lambda (_)
(replace-match (make-string (/ (- (match-end 1) (match-beginning 1)) 2) (concat (make-string (/ (- (match-end 1) (match-beginning 1)) 2) ?\\)))
?\\) link nil t 1))
nil t nil 1))
(goto-char (point-max))
(delete-char (/ (- (skip-chars-backward "\\\\")) 2))
(buffer-string)))
(defun org-link-make-string (link &optional description) (defun org-link-make-string (link &optional description)
"Make a bracket link, consisting of LINK and DESCRIPTION. "Make a bracket link, consisting of LINK and DESCRIPTION.
LINK is escaped with backslashes for inclusion in buffer." LINK is escaped with backslashes for inclusion in buffer."
(unless (org-string-nw-p link) (error "Empty link")) (let* ((zero-width-space (string ?\x200B))
(let* ((uri (org-link-escape link))
(zero-width-space (string ?\x200B))
(description (description
(and (org-string-nw-p description) (and (org-string-nw-p description)
;; Description cannot contain two consecutive square ;; Description cannot contain two consecutive square
@ -881,9 +960,10 @@ LINK is escaped with backslashes for inclusion in buffer."
(replace-regexp-in-string "]\\'" (replace-regexp-in-string "]\\'"
(concat "\\&" zero-width-space) (concat "\\&" zero-width-space)
(org-trim description)))))) (org-trim description))))))
(format "[[%s]%s]" (if (not (org-string-nw-p link)) description
uri (format "[[%s]%s]"
(if description (format "[%s]" description) "")))) (org-link-escape link)
(if description (format "[%s]" description) "")))))
(defun org-store-link-functions () (defun org-store-link-functions ()
"List of functions that are called to create and store a link. "List of functions that are called to create and store a link.
@ -930,7 +1010,8 @@ Abbreviations are defined in `org-link-abbrev-alist'."
((string-match "%(\\([^)]+\\))" rpl) ((string-match "%(\\([^)]+\\))" rpl)
(replace-match (replace-match
(save-match-data (save-match-data
(funcall (intern-soft (match-string 1 rpl)) tag)) t t rpl)) (funcall (intern-soft (match-string 1 rpl)) tag))
t t rpl))
((string-match "%s" rpl) (replace-match (or tag "") t t rpl)) ((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
((string-match "%h" rpl) ((string-match "%h" rpl)
(replace-match (url-hexify-string (or tag "")) t t rpl)) (replace-match (url-hexify-string (or tag "")) t t rpl))
@ -938,63 +1019,60 @@ Abbreviations are defined in `org-link-abbrev-alist'."
(defun org-link-open (link &optional arg) (defun org-link-open (link &optional arg)
"Open a link object LINK. "Open a link object LINK.
Optional argument is passed to `org-open-file' when S is
a \"file\" link." ARG is an optional prefix argument. Some link types may handle
it. For example, it determines what application to run when
opening a \"file\" link.
Functions responsible for opening the link are either hard-coded
for internal and \"file\" links, or stored as a parameter in
`org-link-parameters', which see."
(let ((type (org-element-property :type link)) (let ((type (org-element-property :type link))
(path (org-element-property :path link))) (path (org-element-property :path link)))
(cond (pcase type
((equal type "file") ;; Opening a "file" link requires special treatment since we
(if (string-match "[*?{]" (file-name-nondirectory path)) ;; first need to integrate search option, if any.
(dired path) ("file"
;; Look into `org-link-parameters' in order to find (let* ((option (org-element-property :search-option link))
;; a DEDICATED-FUNCTION to open file. The function will be (path (if option (concat path "::" option) path)))
;; applied on raw link instead of parsed link due to the (org-link-open-as-file path
;; limitation in `org-add-link-type' ("open" function called (pcase (org-element-property :application link)
;; with a single argument). If no such function is found, ((guard arg) arg)
;; fallback to `org-open-file'. ("emacs" 'emacs)
(let* ((option (org-element-property :search-option link)) ("sys" 'system)))))
(app (org-element-property :application link)) ;; Internal links.
(dedicated-function ((or "coderef" "custom-id" "fuzzy" "radio")
(org-link-get-parameter (if app (concat type "+" app) type) (unless (run-hook-with-args-until-success 'org-open-link-functions path)
:follow))) (if (not arg) (org-mark-ring-push)
(if dedicated-function (switch-to-buffer-other-window (org-link--buffer-for-internals)))
(funcall dedicated-function (let ((destination
(concat path (org-with-wide-buffer
(and option (concat "::" option)))) (if (equal type "radio")
(apply #'org-open-file (org-link--search-radio-target path)
path (org-link-search
(cond (arg) (pcase type
((equal app "emacs") 'emacs) ("custom-id" (concat "#" path))
((equal app "sys") 'system)) ("coderef" (format "(%s)" path))
(cond ((not option) nil) (_ path))
((string-match-p "\\`[0-9]+\\'" option) ;; Prevent fuzzy links from matching themselves.
(list (string-to-number option))) (and (equal type "fuzzy")
(t (list nil option)))))))) (+ 2 (org-element-property :begin link)))))
((functionp (org-link-get-parameter type :follow)) (point))))
(funcall (org-link-get-parameter type :follow) path)) (unless (and (<= (point-min) destination)
((member type '("coderef" "custom-id" "fuzzy" "radio")) (>= (point-max) destination))
(unless (run-hook-with-args-until-success 'org-open-link-functions path) (widen))
(if (not arg) (org-mark-ring-push) (goto-char destination))))
(switch-to-buffer-other-window (org-link--buffer-for-internals))) (_
(let ((destination ;; Look for a dedicated "follow" function in custom links.
(org-with-wide-buffer (let ((f (org-link-get-parameter type :follow)))
(if (equal type "radio") (when (functionp f)
(org-link--search-radio-target ;; Function defined in `:follow' parameter may use a single
(org-element-property :path link)) ;; argument, as it was mandatory before Org 9.4. This is
(org-link-search ;; deprecated, but support it for now.
(pcase type (condition-case nil
("custom-id" (concat "#" path)) (funcall (org-link-get-parameter type :follow) path arg)
("coderef" (format "(%s)" path)) (wrong-number-of-arguments
(_ path)) (funcall (org-link-get-parameter type :follow) path)))))))))
;; Prevent fuzzy links from matching themselves.
(and (equal type "fuzzy")
(+ 2 (org-element-property :begin link)))))
(point))))
(unless (and (<= (point-min) destination)
(>= (point-max) destination))
(widen))
(goto-char destination))))
(t (browse-url-at-point)))))
(defun org-link-open-from-string (s &optional arg) (defun org-link-open-from-string (s &optional arg)
"Open a link in the string S, as if it was in Org mode. "Open a link in the string S, as if it was in Org mode.
@ -1095,10 +1173,9 @@ of matched result, which is either `dedicated' or `fuzzy'."
(catch :name-match (catch :name-match
(goto-char (point-min)) (goto-char (point-min))
(while (re-search-forward name nil t) (while (re-search-forward name nil t)
(let ((element (org-element-at-point))) (let* ((element (org-element-at-point))
(when (equal words (name (org-element-property :name element)))
(split-string (when (and name (equal words (split-string name)))
(org-element-property :name element)))
(setq type 'dedicated) (setq type 'dedicated)
(beginning-of-line) (beginning-of-line)
(throw :name-match t)))) (throw :name-match t))))
@ -1111,18 +1188,14 @@ of matched result, which is either `dedicated' or `fuzzy'."
(format "%s.*\\(?:%s[ \t]\\)?.*%s" (format "%s.*\\(?:%s[ \t]\\)?.*%s"
org-outline-regexp-bol org-outline-regexp-bol
org-comment-string org-comment-string
(mapconcat #'regexp-quote words ".+"))) (mapconcat #'regexp-quote words ".+"))))
(cookie-re "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]")
(comment-re (format "\\`%s[ \t]+" org-comment-string)))
(goto-char (point-min)) (goto-char (point-min))
(catch :found (catch :found
(while (re-search-forward title-re nil t) (while (re-search-forward title-re nil t)
(when (equal words (when (equal words
(split-string (split-string
(replace-regexp-in-string (org-link--normalize-string
cookie-re "" (org-get-heading t t t t))))
(replace-regexp-in-string
comment-re "" (org-get-heading t t t)))))
(throw :found t))) (throw :found t)))
nil))) nil)))
(beginning-of-line) (beginning-of-line)
@ -1173,24 +1246,40 @@ of matched result, which is either `dedicated' or `fuzzy'."
type)) type))
(defun org-link-heading-search-string (&optional string) (defun org-link-heading-search-string (&optional string)
"Make search string for the current headline or STRING." "Make search string for the current headline or STRING.
(let ((s (or string
(and (derived-mode-p 'org-mode) Search string starts with an asterisk. COMMENT keyword and
(save-excursion statistics cookies are removed, and contiguous spaces are packed
(org-back-to-heading t) into a single one.
(org-element-property :raw-value
(org-element-at-point)))))) When optional argument STRING is non-nil, assume it a headline,
(lines org-link-context-for-files)) without any asterisk, TODO or COMMENT keyword, and without any
(unless string (setq s (concat "*" s))) ;Add * for headlines priority cookie or tag."
(setq s (replace-regexp-in-string "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" s)) (concat "*"
(when (and string (integerp lines) (> lines 0)) (org-link--normalize-string
(let ((slines (org-split-string s "\n"))) (or string (org-get-heading t t t t)))))
(when (< lines (length slines))
(setq s (mapconcat (defun org-link-open-as-file (path arg)
#'identity "Pretend PATH is a file name and open it.
(reverse (nthcdr (- (length slines) lines)
(reverse slines))) "\n"))))) According to \"file\"-link syntax, PATH may include additional
(mapconcat #'identity (split-string s) " "))) search options, separated from the file name with \"::\".
This function is meant to be used as a possible tool for
`:follow' property in `org-link-parameters'."
(let* ((option (and (string-match "::\\(.*\\)\\'" path)
(match-string 1 path)))
(file-name (if (not option) path
(substring path 0 (match-beginning 0)))))
(if (string-match "[*?{]" (file-name-nondirectory file-name))
(dired file-name)
(apply #'org-open-file
file-name
arg
(cond ((not option) nil)
((string-match-p "\\`[0-9]+\\'" option)
(list (string-to-number option)))
(t (list nil option)))))))
(defun org-link-display-format (s) (defun org-link-display-format (s)
"Replace links in string S with their description. "Replace links in string S with their description.
@ -1211,15 +1300,15 @@ If there is no description, use the link target."
;;; Built-in link types ;;; Built-in link types
;;;; "doi" link type ;;;; "doi" link type
(defun org-link--open-doi (path) (defun org-link--open-doi (path arg)
"Open a \"doi\" type link. "Open a \"doi\" type link.
PATH is a the path to search for, as a string." PATH is a the path to search for, as a string."
(browse-url (url-encode-url (concat org-link-doi-server-url path)))) (browse-url (url-encode-url (concat org-link-doi-server-url path)) arg))
(org-link-set-parameters "doi" :follow #'org-link--open-doi) (org-link-set-parameters "doi" :follow #'org-link--open-doi)
;;;; "elisp" link type ;;;; "elisp" link type
(defun org-link--open-elisp (path) (defun org-link--open-elisp (path _)
"Open a \"elisp\" type link. "Open a \"elisp\" type link.
PATH is the sexp to evaluate, as a string." PATH is the sexp to evaluate, as a string."
(if (or (and (org-string-nw-p org-link-elisp-skip-confirm-regexp) (if (or (and (org-string-nw-p org-link-elisp-skip-confirm-regexp)
@ -1240,7 +1329,7 @@ PATH is the sexp to evaluate, as a string."
(org-link-set-parameters "file" :complete #'org-link-complete-file) (org-link-set-parameters "file" :complete #'org-link-complete-file)
;;;; "help" link type ;;;; "help" link type
(defun org-link--open-help (path) (defun org-link--open-help (path _)
"Open a \"help\" type link. "Open a \"help\" type link.
PATH is a symbol name, as a string." PATH is a symbol name, as a string."
(pcase (intern path) (pcase (intern path)
@ -1254,10 +1343,11 @@ PATH is a symbol name, as a string."
(dolist (scheme '("ftp" "http" "https" "mailto" "news")) (dolist (scheme '("ftp" "http" "https" "mailto" "news"))
(org-link-set-parameters scheme (org-link-set-parameters scheme
:follow :follow
(lambda (url) (browse-url (concat scheme ":" url))))) (lambda (url arg)
(browse-url (concat scheme ":" url) arg))))
;;;; "shell" link type ;;;; "shell" link type
(defun org-link--open-shell (path) (defun org-link--open-shell (path _)
"Open a \"shell\" type link. "Open a \"shell\" type link.
PATH is the command to execute, as a string." PATH is the command to execute, as a string."
(if (or (and (org-string-nw-p org-link-shell-skip-confirm-regexp) (if (or (and (org-string-nw-p org-link-shell-skip-confirm-regexp)
@ -1375,7 +1465,7 @@ non-nil."
(move-beginning-of-line 2) (move-beginning-of-line 2)
(set-mark (point))))) (set-mark (point)))))
(setq org-store-link-plist nil) (setq org-store-link-plist nil)
(let (link cpltxt desc description search txt custom-id agenda-link) (let (link cpltxt desc description search custom-id agenda-link)
(cond (cond
;; Store a link using an external link type, if any function is ;; Store a link using an external link type, if any function is
;; available. If more than one can generate a link from current ;; available. If more than one can generate a link from current
@ -1465,10 +1555,16 @@ non-nil."
(org-link-store-props :type "calendar" :date cd))) (org-link-store-props :type "calendar" :date cd)))
((eq major-mode 'help-mode) ((eq major-mode 'help-mode)
(setq link (concat "help:" (save-excursion (let ((symbol (replace-regexp-in-string
(goto-char (point-min)) ;; Help mode escapes backquotes and backslashes
(looking-at "^[^ ]+") ;; before displaying them. E.g., "`" appears
(match-string 0)))) ;; as "\'" for reasons. Work around this.
(rx "\\" (group (or "`" "\\"))) "\\1"
(save-excursion
(goto-char (point-min))
(looking-at "^[^ ]+")
(match-string 0)))))
(setq link (concat "help:" symbol)))
(org-link-store-props :type "help")) (org-link-store-props :type "help"))
((eq major-mode 'w3-mode) ((eq major-mode 'w3-mode)
@ -1534,30 +1630,35 @@ non-nil."
(abbreviate-file-name (abbreviate-file-name
(buffer-file-name (buffer-base-buffer)))))))) (buffer-file-name (buffer-base-buffer))))))))
(t (t
;; Just link to current headline ;; Just link to current headline.
(setq cpltxt (concat "file:" (setq cpltxt (concat "file:"
(abbreviate-file-name (abbreviate-file-name
(buffer-file-name (buffer-base-buffer))))) (buffer-file-name (buffer-base-buffer)))))
;; Add a context search string ;; Add a context search string.
(when (org-xor org-link-context-for-files (equal arg '(4))) (when (org-xor org-link-context-for-files (equal arg '(4)))
(let* ((element (org-element-at-point)) (let* ((element (org-element-at-point))
(name (org-element-property :name element))) (name (org-element-property :name element))
(setq txt (cond (context
((org-at-heading-p) nil) (cond
(name) ((let ((region (org-link--context-from-region)))
((org-region-active-p) (and region (org-link--normalize-string region t))))
(buffer-substring (region-beginning) (region-end))))) (name)
(when (or (null txt) (string-match "\\S-" txt)) ((org-before-first-heading-p)
(setq cpltxt (org-link--normalize-string (org-current-line-string) t))
(concat cpltxt "::" (t (org-link-heading-search-string)))))
(condition-case nil (when (org-string-nw-p context)
(org-link-heading-search-string txt) (setq cpltxt (format "%s::%s" cpltxt context))
(error ""))) (setq desc
desc (or name (or name
(nth 4 (ignore-errors (org-heading-components))) ;; Although description is not a search
"NONE"))))) ;; string, use `org-link--normalize-string'
(when (string-match "::\\'" cpltxt) ;; to prettify it (contiguous white spaces)
(setq cpltxt (substring cpltxt 0 -2))) ;; and remove volatile contents (statistics
;; cookies).
(and (not (org-before-first-heading-p))
(org-link--normalize-string
(org-get-heading t t t t)))
"NONE")))))
(setq link cpltxt))))) (setq link cpltxt)))))
((buffer-file-name (buffer-base-buffer)) ((buffer-file-name (buffer-base-buffer))
@ -1565,16 +1666,16 @@ non-nil."
(setq cpltxt (concat "file:" (setq cpltxt (concat "file:"
(abbreviate-file-name (abbreviate-file-name
(buffer-file-name (buffer-base-buffer))))) (buffer-file-name (buffer-base-buffer)))))
;; Add a context string. ;; Add a context search string.
(when (org-xor org-link-context-for-files (equal arg '(4))) (when (org-xor org-link-context-for-files (equal arg '(4)))
(setq txt (if (org-region-active-p) (let ((context (org-link--normalize-string
(buffer-substring (region-beginning) (region-end)) (or (org-link--context-from-region)
(buffer-substring (point-at-bol) (point-at-eol)))) (org-current-line-string))
;; Only use search option if there is some text. t)))
(when (string-match "\\S-" txt) ;; Only use search option if there is some text.
(setq cpltxt (when (org-string-nw-p context)
(concat cpltxt "::" (org-link-heading-search-string txt)) (setq cpltxt (format "%s::%s" cpltxt context))
desc "NONE"))) (setq desc "NONE"))))
(setq link cpltxt)) (setq link cpltxt))
(interactive? (interactive?
@ -1589,15 +1690,19 @@ non-nil."
(cond ((not desc)) (cond ((not desc))
((equal desc "NONE") (setq desc nil)) ((equal desc "NONE") (setq desc nil))
(t (setq desc (org-link-display-format desc)))) (t (setq desc (org-link-display-format desc))))
;; Return the link ;; Store and return the link
(if (not (and interactive? link)) (if (not (and interactive? link))
(or agenda-link (and link (org-link-make-string link desc))) (or agenda-link (and link (org-link-make-string link desc)))
(push (list link desc) org-stored-links) (if (member (list link desc) org-stored-links)
(message "Stored: %s" (or desc link)) (message "This link already exists")
(when custom-id (push (list link desc) org-stored-links)
(setq link (concat "file:" (abbreviate-file-name (message "Stored: %s" (or desc link))
(buffer-file-name)) "::#" custom-id)) (when custom-id
(push (list link desc) org-stored-links)) (setq link (concat "file:"
(abbreviate-file-name
(buffer-file-name (buffer-base-buffer)))
"::#" custom-id))
(push (list link desc) org-stored-links)))
(car org-stored-links))))) (car org-stored-links)))))
;;;###autoload ;;;###autoload
@ -1737,13 +1842,14 @@ Use TAB to complete link prefixes, then RET for type-specific completion support
;; Check if we are linking to the current file with a search ;; Check if we are linking to the current file with a search
;; option If yes, simplify the link by using only the search ;; option If yes, simplify the link by using only the search
;; option. ;; option.
(when (and buffer-file-name (when (and (buffer-file-name (buffer-base-buffer))
(let ((case-fold-search nil)) (let ((case-fold-search nil))
(string-match "\\`file:\\(.+?\\)::" link))) (string-match "\\`file:\\(.+?\\)::" link)))
(let ((path (match-string-no-properties 1 link)) (let ((path (match-string-no-properties 1 link))
(search (substring-no-properties link (match-end 0)))) (search (substring-no-properties link (match-end 0))))
(save-match-data (save-match-data
(when (equal (file-truename buffer-file-name) (file-truename path)) (when (equal (file-truename (buffer-file-name (buffer-base-buffer)))
(file-truename path))
;; We are linking to this same file, with a search option ;; We are linking to this same file, with a search option
(setq link search))))) (setq link search)))))
@ -1903,7 +2009,10 @@ Also refresh fontification if needed."
(org-link-make-regexps) (org-link-make-regexps)
(provide 'ol) (provide 'ol)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; ol.el ends here ;;; ol.el ends here

File diff suppressed because it is too large Load diff

View file

@ -24,7 +24,7 @@
;; ;;
;;; Commentary: ;;; Commentary:
;; This file contains the face definitions for Org. ;; This file contains the archive functionality for Org.
;;; Code: ;;; Code:
@ -91,6 +91,25 @@ When a string, a %s formatter will be replaced by the file name."
(const :tag "When archiving a subtree to the same file" infile) (const :tag "When archiving a subtree to the same file" infile)
(const :tag "Always" t))) (const :tag "Always" t)))
(defcustom org-archive-subtree-save-file-p 'from-org
"Conditionally save the archive file after archiving a subtree.
This variable can be any of the following symbols:
t saves in all cases.
`from-org' prevents saving from an agenda-view.
`from-agenda' saves only when the archive is initiated from an agenda-view.
nil prevents saving in all cases.
Note that, regardless of this value, the archive buffer is never
saved when archiving into a location in the current buffer."
:group 'org-archive
:package-version '(Org . "9.4")
:type '(choice
(const :tag "Save archive buffer" t)
(const :tag "Save when archiving from agenda" from-agenda)
(const :tag "Save when archiving from an Org buffer" from-org)
(const :tag "Do not save")))
(defcustom org-archive-save-context-info '(time file olpath category todo itags) (defcustom org-archive-save-context-info '(time file olpath category todo itags)
"Parts of context info that should be stored as properties when archiving. "Parts of context info that should be stored as properties when archiving.
When a subtree is moved to an archive file, it loses information given by When a subtree is moved to an archive file, it loses information given by
@ -230,12 +249,20 @@ direct children of this heading."
((find-buffer-visiting afile)) ((find-buffer-visiting afile))
((find-file-noselect afile)) ((find-file-noselect afile))
(t (error "Cannot access file \"%s\"" afile)))) (t (error "Cannot access file \"%s\"" afile))))
(org-odd-levels-only
(if (local-variable-p 'org-odd-levels-only (current-buffer))
org-odd-levels-only
tr-org-odd-levels-only))
level datetree-date datetree-subheading-p) level datetree-date datetree-subheading-p)
(when (string-match "\\`datetree/" heading) (when (string-match "\\`datetree/\\(\\**\\)" heading)
;; Replace with ***, to represent the 3 levels of headings the ;; "datetree/" corresponds to 3 levels of headings.
;; datetree has. (let ((nsub (length (match-string 1 heading))))
(setq heading (replace-regexp-in-string "\\`datetree/" "***" heading)) (setq heading (concat (make-string
(setq datetree-subheading-p (> (length heading) 3)) (+ (if org-odd-levels-only 5 3)
(* (org-level-increment) nsub))
?*)
(substring heading (match-end 0))))
(setq datetree-subheading-p (> nsub 0)))
(setq datetree-date (org-date-to-gregorian (setq datetree-date (org-date-to-gregorian
(or (org-entry-get nil "CLOSED" t) time)))) (or (org-entry-get nil "CLOSED" t) time))))
(if (and (> (length heading) 0) (if (and (> (length heading) 0)
@ -290,11 +317,7 @@ direct children of this heading."
(org-todo-kwd-alist tr-org-todo-kwd-alist) (org-todo-kwd-alist tr-org-todo-kwd-alist)
(org-done-keywords tr-org-done-keywords) (org-done-keywords tr-org-done-keywords)
(org-todo-regexp tr-org-todo-regexp) (org-todo-regexp tr-org-todo-regexp)
(org-todo-line-regexp tr-org-todo-line-regexp) (org-todo-line-regexp tr-org-todo-line-regexp))
(org-odd-levels-only
(if (local-variable-p 'org-odd-levels-only (current-buffer))
org-odd-levels-only
tr-org-odd-levels-only)))
(goto-char (point-min)) (goto-char (point-min))
(org-show-all '(headings blocks)) (org-show-all '(headings blocks))
(if (and heading (not (and datetree-date (not datetree-subheading-p)))) (if (and heading (not (and datetree-date (not datetree-subheading-p))))
@ -361,6 +384,15 @@ direct children of this heading."
(point) (point)
(concat "ARCHIVE_" (upcase (symbol-name item))) (concat "ARCHIVE_" (upcase (symbol-name item)))
value)))) value))))
;; Save the buffer, if it is not the same buffer and
;; depending on `org-archive-subtree-save-file-p'.
(unless (eq this-buffer buffer)
(when (or (eq org-archive-subtree-save-file-p t)
(eq org-archive-subtree-save-file-p
(if (boundp 'org-archive-from-agenda)
'from-agenda
'from-org)))
(save-buffer)))
(widen)))) (widen))))
;; Here we are back in the original buffer. Everything seems ;; Here we are back in the original buffer. Everything seems
;; to have worked. So now run hooks, cut the tree and finish ;; to have worked. So now run hooks, cut the tree and finish

View file

@ -4,7 +4,6 @@
;; Author: John Wiegley <johnw@newartisans.com> ;; Author: John Wiegley <johnw@newartisans.com>
;; Keywords: org data attachment ;; Keywords: org data attachment
;; This file is part of GNU Emacs. ;; This file is part of GNU Emacs.
;; ;;
;; GNU Emacs is free software: you can redistribute it and/or modify ;; GNU Emacs is free software: you can redistribute it and/or modify
@ -41,6 +40,8 @@
(require 'org-id) (require 'org-id)
(declare-function dired-dwim-target-directory "dired-aux") (declare-function dired-dwim-target-directory "dired-aux")
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element))
(defgroup org-attach nil (defgroup org-attach nil
"Options concerning attachments in Org mode." "Options concerning attachments in Org mode."
@ -129,8 +130,7 @@ Selective means to respect the inheritance setting in
:type '(choice :type '(choice
(const :tag "Don't use inheritance" nil) (const :tag "Don't use inheritance" nil)
(const :tag "Inherit parent node attachments" t) (const :tag "Inherit parent node attachments" t)
(const :tag "Respect org-use-property-inheritance" selective)) (const :tag "Respect org-use-property-inheritance" selective)))
:type 'boolean)
(defcustom org-attach-store-link-p nil (defcustom org-attach-store-link-p nil
"Non-nil means store a link to a file when attaching it." "Non-nil means store a link to a file when attaching it."
@ -139,7 +139,8 @@ Selective means to respect the inheritance setting in
:type '(choice :type '(choice
(const :tag "Don't store link" nil) (const :tag "Don't store link" nil)
(const :tag "Link to origin location" t) (const :tag "Link to origin location" t)
(const :tag "Link to the attach-dir location" attached))) (const :tag "Attachment link to the attach-dir location" attached)
(const :tag "File link to the attach-dir location" file)))
(defcustom org-attach-archive-delete nil (defcustom org-attach-archive-delete nil
"Non-nil means attachments are deleted upon archiving a subtree. "Non-nil means attachments are deleted upon archiving a subtree.
@ -254,16 +255,16 @@ Shows a list of commands and prompts for another key to execute a command."
(get-text-property (point) 'org-marker))) (get-text-property (point) 'org-marker)))
(unless marker (unless marker
(error "No item in current line"))) (error "No item in current line")))
(save-excursion (org-with-point-at marker
(when marker (org-back-to-heading-or-point-min t)
(set-buffer (marker-buffer marker))
(goto-char marker))
(org-back-to-heading t)
(save-excursion (save-excursion
(save-window-excursion (save-window-excursion
(unless org-attach-expert (unless org-attach-expert
(with-output-to-temp-buffer "*Org Attach*" (org-switch-to-buffer-other-window "*Org Attach*")
(princ (erase-buffer)
(setq cursor-type nil
header-line-format "Use C-v, M-v, C-n or C-p to navigate.")
(insert
(concat "Attachment folder:\n" (concat "Attachment folder:\n"
(or dir (or dir
"Can't find an existing attachment-folder") "Can't find an existing attachment-folder")
@ -286,11 +287,14 @@ Shows a list of commands and prompts for another key to execute a command."
"Invalid `org-attach-commands' item: %S" "Invalid `org-attach-commands' item: %S"
entry)))) entry))))
org-attach-commands org-attach-commands
"\n")))))) "\n")))))
(org-fit-window-to-buffer (get-buffer-window "*Org Attach*")) (org-fit-window-to-buffer (get-buffer-window "*Org Attach*"))
(message "Select command: [%s]" (let ((msg (format "Select command: [%s]"
(concat (mapcar #'caar org-attach-commands))) (concat (mapcar #'caar org-attach-commands)))))
(setq c (read-char-exclusive)) (message msg)
(while (and (setq c (read-char-exclusive))
(memq c '(14 16 22 134217846)))
(org-scroll c t)))
(and (get-buffer "*Org Attach*") (kill-buffer "*Org Attach*")))) (and (get-buffer "*Org Attach*") (kill-buffer "*Org Attach*"))))
(let ((command (cl-some (lambda (entry) (let ((command (cl-some (lambda (entry)
(and (memq c (nth 0 entry)) (nth 1 entry))) (and (memq c (nth 0 entry)) (nth 1 entry)))
@ -457,14 +461,6 @@ DIR-property exists (that is different from the unset one)."
"Turn the autotag off." "Turn the autotag off."
(org-attach-tag 'off)) (org-attach-tag 'off))
(defun org-attach-store-link (file)
"Add a link to `org-stored-link' when attaching a file.
Only do this when `org-attach-store-link-p' is non-nil."
(setq org-stored-links
(cons (list (org-attach-expand-link file)
(file-name-nondirectory file))
org-stored-links)))
(defun org-attach-url (url) (defun org-attach-url (url)
(interactive "MURL of the file to attach: \n") (interactive "MURL of the file to attach: \n")
(let ((org-attach-method 'url)) (let ((org-attach-method 'url))
@ -491,7 +487,7 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
`org-attach-method'." `org-attach-method'."
(interactive (interactive
(list (list
(read-file-name "File to keep as an attachment:" (read-file-name "File to keep as an attachment: "
(or (progn (or (progn
(require 'dired-aux) (require 'dired-aux)
(dired-dwim-target-directory)) (dired-dwim-target-directory))
@ -501,22 +497,30 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
(setq method (or method org-attach-method)) (setq method (or method org-attach-method))
(let ((basename (file-name-nondirectory file))) (let ((basename (file-name-nondirectory file)))
(let* ((attach-dir (org-attach-dir 'get-create)) (let* ((attach-dir (org-attach-dir 'get-create))
(fname (expand-file-name basename attach-dir))) (attach-file (expand-file-name basename attach-dir)))
(cond (cond
((eq method 'mv) (rename-file file fname)) ((eq method 'mv) (rename-file file attach-file))
((eq method 'cp) (copy-file file fname)) ((eq method 'cp) (copy-file file attach-file))
((eq method 'ln) (add-name-to-file file fname)) ((eq method 'ln) (add-name-to-file file attach-file))
((eq method 'lns) (make-symbolic-link file fname)) ((eq method 'lns) (make-symbolic-link file attach-file))
((eq method 'url) (url-copy-file file fname))) ((eq method 'url) (url-copy-file file attach-file)))
(run-hook-with-args 'org-attach-after-change-hook attach-dir) (run-hook-with-args 'org-attach-after-change-hook attach-dir)
(org-attach-tag) (org-attach-tag)
(cond ((eq org-attach-store-link-p 'attached) (cond ((eq org-attach-store-link-p 'attached)
(org-attach-store-link fname)) (push (list (concat "attachment:" (file-name-nondirectory attach-file))
(file-name-nondirectory attach-file))
org-stored-links))
((eq org-attach-store-link-p t) ((eq org-attach-store-link-p t)
(org-attach-store-link file))) (push (list (concat "file:" file)
(file-name-nondirectory file))
org-stored-links))
((eq org-attach-store-link-p 'file)
(push (list (concat "file:" attach-file)
(file-name-nondirectory attach-file))
org-stored-links)))
(if visit-dir (if visit-dir
(dired attach-dir) (dired attach-dir)
(message "File %S is now an attachment." basename))))) (message "File %S is now an attachment" basename)))))
(defun org-attach-attach-cp () (defun org-attach-attach-cp ()
"Attach a file by copying it." "Attach a file by copying it."
@ -569,13 +573,18 @@ The attachment is created as an Emacs buffer."
(defun org-attach-delete-all (&optional force) (defun org-attach-delete-all (&optional force)
"Delete all attachments from the current outline node. "Delete all attachments from the current outline node.
This actually deletes the entire attachment directory. This actually deletes the entire attachment directory.
A safer way is to open the directory in dired and delete from there." A safer way is to open the directory in dired and delete from there.
With prefix argument FORCE, directory will be recursively deleted
with no prompts."
(interactive "P") (interactive "P")
(let ((attach-dir (org-attach-dir))) (let ((attach-dir (org-attach-dir)))
(when (and attach-dir (when (and attach-dir
(or force (or force
(yes-or-no-p "Really remove all attachments of this entry? "))) (yes-or-no-p "Really remove all attachments of this entry? ")))
(delete-directory attach-dir (yes-or-no-p "Recursive?") t) (delete-directory attach-dir
(or force (yes-or-no-p "Recursive?"))
t)
(message "Attachment directory removed") (message "Attachment directory removed")
(run-hook-with-args 'org-attach-after-change-hook attach-dir) (run-hook-with-args 'org-attach-after-change-hook attach-dir)
(org-attach-untag)))) (org-attach-untag))))
@ -642,37 +651,37 @@ See `org-attach-open'."
Basically, this adds the path to the attachment directory." Basically, this adds the path to the attachment directory."
(expand-file-name file (org-attach-dir))) (expand-file-name file (org-attach-dir)))
(defun org-attach-expand-link (file) (defun org-attach-expand-links (_)
"Return a file link pointing to the current entry's attachment file FILE. "Expand links in current buffer.
Basically, this adds the path to the attachment directory, and a \"file:\" It is meant to be added to `org-export-before-parsing-hook'."
prefix." (save-excursion
(concat "file:" (org-attach-expand file))) (while (re-search-forward "attachment:" nil t)
(let ((link (org-element-context)))
(when (and (eq 'link (org-element-type link))
(string-equal "attachment"
(org-element-property :type link)))
(let* ((description (and (org-element-property :contents-begin link)
(buffer-substring-no-properties
(org-element-property :contents-begin link)
(org-element-property :contents-end link))))
(file (org-element-property :path link))
(new-link (org-link-make-string
(concat "file:" (org-attach-expand file))
description)))
(goto-char (org-element-property :end link))
(skip-chars-backward " \t")
(delete-region (org-element-property :begin link) (point))
(insert new-link)))))))
(defun org-attach-follow (file arg)
"Open FILE attachment.
See `org-open-file' for details about ARG."
(org-link-open-as-file (org-attach-expand file) arg))
(org-link-set-parameters "attachment" (org-link-set-parameters "attachment"
:follow #'org-attach-open-link :follow #'org-attach-follow
:export #'org-attach-export-link
:complete #'org-attach-complete-link) :complete #'org-attach-complete-link)
(defun org-attach-open-link (link &optional in-emacs)
"Attachment link type LINK is expanded with the attached directory and opened.
With optional prefix argument IN-EMACS, Emacs will visit the file.
With a double \\[universal-argument] \\[universal-argument] \
prefix arg, Org tries to avoid opening in Emacs
and to use an external application to visit the file."
(interactive "P")
(let (line search)
(cond
((string-match "::\\([0-9]+\\)\\'" link)
(setq line (string-to-number (match-string 1 link))
link (substring link 0 (match-beginning 0))))
((string-match "::\\(.+\\)\\'" link)
(setq search (match-string 1 link)
link (substring link 0 (match-beginning 0)))))
(if (string-match "[*?{]" (file-name-nondirectory link))
(dired (org-attach-expand link))
(org-open-file (org-attach-expand link) in-emacs line search))))
(defun org-attach-complete-link () (defun org-attach-complete-link ()
"Advise the user with the available files in the attachment directory." "Advise the user with the available files in the attachment directory."
(let ((attach-dir (org-attach-dir))) (let ((attach-dir (org-attach-dir)))
@ -691,26 +700,6 @@ and to use an external application to visit the file."
(t (concat "attachment:" file)))) (t (concat "attachment:" file))))
(error "No attachment directory exist")))) (error "No attachment directory exist"))))
(defun org-attach-export-link (link description format)
"Translate attachment LINK from Org mode format to exported FORMAT.
Also includes the DESCRIPTION of the link in the export."
(save-excursion
(let (path desc)
(cond
((string-match "::\\([0-9]+\\)\\'" link)
(setq link (substring link 0 (match-beginning 0))))
((string-match "::\\(.+\\)\\'" link)
(setq link (substring link 0 (match-beginning 0)))))
(setq path (file-relative-name (org-attach-expand link))
desc (or description link))
(pcase format
(`html (format "<a target=\"_blank\" href=\"%s\">%s</a>" path desc))
(`latex (format "\\href{%s}{%s}" path desc))
(`texinfo (format "@uref{%s,%s}" path desc))
(`ascii (format "%s (%s)" desc path))
(`md (format "[%s](%s)" desc path))
(_ path)))))
(defun org-attach-archive-delete-maybe () (defun org-attach-archive-delete-maybe ()
"Maybe delete subtree attachments when archiving. "Maybe delete subtree attachments when archiving.
This function is called by `org-archive-hook'. The option This function is called by `org-archive-hook'. The option
@ -758,6 +747,7 @@ Idea taken from `gnus-dired-attach'."
(add-hook 'org-archive-hook 'org-attach-archive-delete-maybe) (add-hook 'org-archive-hook 'org-attach-archive-delete-maybe)
(add-hook 'org-export-before-parsing-hook 'org-attach-expand-links)
(provide 'org-attach) (provide 'org-attach)

View file

@ -49,11 +49,13 @@
(require 'cl-lib) (require 'cl-lib)
(require 'org) (require 'org)
(require 'org-refile)
(declare-function org-at-encrypted-entry-p "org-crypt" ()) (declare-function org-at-encrypted-entry-p "org-crypt" ())
(declare-function org-at-table-p "org-table" (&optional table-type)) (declare-function org-at-table-p "org-table" (&optional table-type))
(declare-function org-clock-update-mode-line "org-clock" (&optional refresh)) (declare-function org-clock-update-mode-line "org-clock" (&optional refresh))
(declare-function org-datetree-find-date-create "org-datetree" (date &optional keep-restriction)) (declare-function org-datetree-find-date-create "org-datetree" (date &optional keep-restriction))
(declare-function org-datetree-find-month-create (d &optional keep-restriction))
(declare-function org-decrypt-entry "org-crypt" ()) (declare-function org-decrypt-entry "org-crypt" ())
(declare-function org-element-at-point "org-element" ()) (declare-function org-element-at-point "org-element" ())
(declare-function org-element-lineage "org-element" (datum &optional types with-self)) (declare-function org-element-lineage "org-element" (datum &optional types with-self))
@ -68,6 +70,7 @@
(defvar dired-buffers) (defvar dired-buffers)
(defvar org-end-time-was-given) (defvar org-end-time-was-given)
(defvar org-keyword-properties)
(defvar org-remember-default-headline) (defvar org-remember-default-headline)
(defvar org-remember-templates) (defvar org-remember-templates)
(defvar org-store-link-plist) (defvar org-store-link-plist)
@ -156,14 +159,20 @@ description A short string describing the template, will be shown during
type The type of entry. Valid types are: type The type of entry. Valid types are:
entry an Org node, with a headline. Will be filed entry an Org node, with a headline. Will be filed
as the child of the target entry or as a as the child of the target entry or as a
top-level entry. top-level entry. Its default template is:
\"* %?\n %a\"
item a plain list item, will be placed in the item a plain list item, will be placed in the
first plain list at the target first plain list at the target location.
location. Its default template is:
\"- %?\"
checkitem a checkbox item. This differs from the checkitem a checkbox item. This differs from the
plain list item only in so far as it uses a plain list item only in so far as it uses a
different default template. different default template. Its default
template is:
\"- [ ] %?\"
table-line a new line in the first table at target location. table-line a new line in the first table at target location.
Its default template is:
\"| %? |\"
plain text to be inserted as it is. plain text to be inserted as it is.
target Specification of where the captured item should be placed. target Specification of where the captured item should be placed.
@ -211,9 +220,10 @@ target Specification of where the captured item should be placed.
Most general way: write your own function which both visits Most general way: write your own function which both visits
the file and moves point to the right location the file and moves point to the right location
template The template for creating the capture item. If you leave this template The template for creating the capture item.
empty, an appropriate default template will be used. See below If it is an empty string or nil, a default template based on
for more details. Instead of a string, this may also be one of the entry type will be used (see the \"type\" section above).
Instead of a string, this may also be one of:
(file \"/path/to/template-file\") (file \"/path/to/template-file\")
(function function-returning-the-template) (function function-returning-the-template)
@ -236,15 +246,15 @@ properties are:
:jump-to-captured When set, jump to the captured entry when finished. :jump-to-captured When set, jump to the captured entry when finished.
:empty-lines Set this to the number of lines the should be inserted :empty-lines Set this to the number of lines that should be inserted
before and after the new item. Default 0, only common before and after the new item. Default 0, only common
other value is 1. other value is 1.
:empty-lines-before Set this to the number of lines the should be inserted :empty-lines-before Set this to the number of lines that should be inserted
before the new item. Overrides :empty-lines for the before the new item. Overrides :empty-lines for the
number lines inserted before. number lines inserted before.
:empty-lines-after Set this to the number of lines the should be inserted :empty-lines-after Set this to the number of lines that should be inserted
after the new item. Overrides :empty-lines for the after the new item. Overrides :empty-lines for the
number of lines inserted after. number of lines inserted after.
@ -260,7 +270,9 @@ properties are:
:time-prompt Prompt for a date/time to be used for date/week trees :time-prompt Prompt for a date/time to be used for date/week trees
and when filling the template. and when filling the template.
:tree-type When `week', make a week tree instead of the month tree. :tree-type When `week', make a week tree instead of the month-day
tree. When `month', make a month tree instead of the
month-day tree.
:unnarrowed Do not narrow the target buffer, simply show the :unnarrowed Do not narrow the target buffer, simply show the
full buffer. Default is to narrow it so that you full buffer. Default is to narrow it so that you
@ -322,7 +334,7 @@ be replaced with content and expanded:
%^L Like %^C, but insert as link. %^L Like %^C, but insert as link.
%^{prop}p Prompt the user for a value for property `prop'. %^{prop}p Prompt the user for a value for property `prop'.
%^{prompt} Prompt the user for a string and replace this sequence with it. %^{prompt} Prompt the user for a string and replace this sequence with it.
A default value and a completion table ca be specified like this: A default value and a completion table can be specified like this:
%^{prompt|default|completion2|completion3|...}. %^{prompt|default|completion2|completion3|...}.
%? After completing the template, position cursor here. %? After completing the template, position cursor here.
%\\1 ... %\\N Insert the text entered at the nth %^{prompt}, where N %\\1 ... %\\N Insert the text entered at the nth %^{prompt}, where N
@ -625,7 +637,7 @@ of the day at point (if any) or the current HH:MM time."
(setq org-overriding-default-time (setq org-overriding-default-time
(org-get-cursor-date (equal goto 1)))) (org-get-cursor-date (equal goto 1))))
(cond (cond
((equal goto '(4)) (org-capture-goto-target)) ((equal goto '(4)) (org-capture-goto-target keys))
((equal goto '(16)) (org-capture-goto-last-stored)) ((equal goto '(16)) (org-capture-goto-last-stored))
(t (t
(let* ((orig-buf (current-buffer)) (let* ((orig-buf (current-buffer))
@ -698,21 +710,19 @@ of the day at point (if any) or the current HH:MM time."
(defun org-capture-get-template () (defun org-capture-get-template ()
"Get the template from a file or a function if necessary." "Get the template from a file or a function if necessary."
(let ((txt (org-capture-get :template)) file) (org-capture-put
(cond :template
((and (listp txt) (eq (car txt) 'file)) (pcase (org-capture-get :template)
(if (file-exists-p (`nil "")
(setq file (expand-file-name (nth 1 txt) org-directory))) ((and (pred stringp) template) template)
(setq txt (org-file-contents file)) (`(file ,file)
(setq txt (format "* Template file %s not found" (nth 1 txt))))) (let ((filename (expand-file-name file org-directory)))
((and (listp txt) (eq (car txt) 'function)) (if (file-exists-p filename) (org-file-contents filename)
(if (fboundp (nth 1 txt)) (format "* Template file %S not found" file))))
(setq txt (funcall (nth 1 txt))) (`(function ,f)
(setq txt (format "* Template function %s not found" (nth 1 txt))))) (if (functionp f) (funcall f)
((not txt) (setq txt "")) (format "* Template function %S not found" f)))
((stringp txt)) (_ "* Invalid capture template"))))
(t (setq txt "* Invalid capture template")))
(org-capture-put :template txt)))
(defun org-capture-finalize (&optional stay-with-capture) (defun org-capture-finalize (&optional stay-with-capture)
"Finalize the capture process. "Finalize the capture process.
@ -727,6 +737,11 @@ captured item after finalizing."
(run-hooks 'org-capture-prepare-finalize-hook) (run-hooks 'org-capture-prepare-finalize-hook)
;; Update `org-capture-plist' with the buffer-local value. Since
;; captures can be run concurrently, this is to ensure that
;; `org-capture-after-finalize-hook' accesses the proper plist.
(setq org-capture-plist org-capture-current-plist)
;; Did we start the clock in this capture buffer? ;; Did we start the clock in this capture buffer?
(when (and org-capture-clock-was-started (when (and org-capture-clock-was-started
org-clock-marker org-clock-marker
@ -996,11 +1011,13 @@ Store them in the capture property list."
(org-capture-put-target-region-and-position) (org-capture-put-target-region-and-position)
(widen) (widen)
;; Make a date/week tree entry, with the current date (or ;; Make a date/week tree entry, with the current date (or
;; yesterday, if we are extending dates for a couple of hours) ;; yesterday, if we are extending dates for a couple of
;; hours)
(funcall (funcall
(if (eq (org-capture-get :tree-type) 'week) (pcase (org-capture-get :tree-type)
#'org-datetree-find-iso-week-create (`week #'org-datetree-find-iso-week-create)
#'org-datetree-find-date-create) (`month #'org-datetree-find-month-create)
(_ #'org-datetree-find-date-create))
(calendar-gregorian-from-absolute (calendar-gregorian-from-absolute
(cond (cond
(org-overriding-default-time (org-overriding-default-time
@ -1021,7 +1038,7 @@ Store them in the capture property list."
(apply #'encode-time 0 0 (apply #'encode-time 0 0
org-extend-today-until org-extend-today-until
(cl-cdddr (decode-time prompt-time)))) (cl-cdddr (decode-time prompt-time))))
((string-match "\\([^ ]+\\)--?[^ ]+[ ]+\\(.*\\)" ((string-match "\\([^ ]+\\)-[^ ]+[ ]+\\(.*\\)"
org-read-date-final-answer) org-read-date-final-answer)
;; Replace any time range by its start. ;; Replace any time range by its start.
(apply #'encode-time (apply #'encode-time
@ -1058,7 +1075,7 @@ Store them in the capture property list."
(org-capture-put-target-region-and-position) (org-capture-put-target-region-and-position)
(widen) (widen)
(goto-char org-clock-hd-marker)) (goto-char org-clock-hd-marker))
(error "No running clock that could be used as capture target"))) (user-error "No running clock that could be used as capture target")))
(target (error "Invalid capture target specification: %S" target))) (target (error "Invalid capture target specification: %S" target)))
(org-capture-put :buffer (current-buffer) (org-capture-put :buffer (current-buffer)
@ -1115,8 +1132,8 @@ may have been stored before."
(`plain (org-capture-place-plain-text)) (`plain (org-capture-place-plain-text))
(`item (org-capture-place-item)) (`item (org-capture-place-item))
(`checkitem (org-capture-place-item))) (`checkitem (org-capture-place-item)))
(org-capture-mode 1) (setq-local org-capture-current-plist org-capture-plist)
(setq-local org-capture-current-plist org-capture-plist)) (org-capture-mode 1))
(defun org-capture-place-entry () (defun org-capture-place-entry ()
"Place the template as a new Org entry." "Place the template as a new Org entry."
@ -1129,7 +1146,14 @@ may have been stored before."
(when exact-position (goto-char exact-position)) (when exact-position (goto-char exact-position))
(cond (cond
;; Force insertion at point. ;; Force insertion at point.
((org-capture-get :insert-here) nil) (insert-here?
;; FIXME: level should probably set directly within (let ...).
(setq level (org-get-valid-level
(if (or (org-at-heading-p)
(ignore-errors
(save-excursion (org-back-to-heading t))))
(org-outline-level)
1))))
;; Insert as a child of the current entry. ;; Insert as a child of the current entry.
((org-capture-get :target-entry-p) ((org-capture-get :target-entry-p)
(setq level (org-get-valid-level (setq level (org-get-valid-level
@ -1150,14 +1174,11 @@ may have been stored before."
(when insert-here? (narrow-to-region beg beg)) (when insert-here? (narrow-to-region beg beg))
(org-paste-subtree level template 'for-yank)) (org-paste-subtree level template 'for-yank))
(org-capture-position-for-last-stored beg) (org-capture-position-for-last-stored beg)
(let ((end (if (org-at-heading-p) (line-end-position 0) (point)))) (org-capture-empty-lines-after)
(org-capture-empty-lines-after) (unless (org-at-heading-p) (outline-next-heading))
(unless (org-at-heading-p) (outline-next-heading)) (org-capture-mark-kill-region origin (point))
(org-capture-mark-kill-region origin (point)) (org-capture-narrow beg (if (eobp) (point) (1- (point))))
(org-capture-narrow beg end) (org-capture--position-cursor beg (point))))))
(when (or (search-backward "%?" beg t)
(search-forward "%?" end t))
(replace-match "")))))))
(defun org-capture-place-item () (defun org-capture-place-item ()
"Place the template as a new plain list item." "Place the template as a new plain list item."
@ -1269,9 +1290,7 @@ may have been stored before."
;; not narrow at the beginning of the next line, possibly ;; not narrow at the beginning of the next line, possibly
;; altering its structure (e.g., when it is a headline). ;; altering its structure (e.g., when it is a headline).
(org-capture-narrow beg (1- end)) (org-capture-narrow beg (1- end))
(when (or (search-backward "%?" beg t) (org-capture--position-cursor beg end)))))
(search-forward "%?" end t))
(replace-match ""))))))
(defun org-capture-place-table-line () (defun org-capture-place-table-line ()
"Place the template as a table line." "Place the template as a table line."
@ -1353,9 +1372,7 @@ may have been stored before."
;; TEXT is guaranteed to end with a newline character. Ignore ;; TEXT is guaranteed to end with a newline character. Ignore
;; it when narrowing so as to not alter data on the next line. ;; it when narrowing so as to not alter data on the next line.
(org-capture-narrow beg (1- end)) (org-capture-narrow beg (1- end))
(when (or (search-backward "%?" beg t) (org-capture--position-cursor beg (1- end))))))
(search-forward "%?" end t))
(replace-match ""))))))
(defun org-capture-place-plain-text () (defun org-capture-place-plain-text ()
"Place the template plainly. "Place the template plainly.
@ -1390,9 +1407,7 @@ Of course, if exact position has been required, just put it there."
(org-capture-empty-lines-after) (org-capture-empty-lines-after)
(org-capture-mark-kill-region origin (point)) (org-capture-mark-kill-region origin (point))
(org-capture-narrow beg end) (org-capture-narrow beg end)
(when (or (search-backward "%?" beg t) (org-capture--position-cursor beg end)))))
(search-forward "%?" end t))
(replace-match ""))))))
(defun org-capture-mark-kill-region (beg end) (defun org-capture-mark-kill-region (beg end)
"Mark the region that will have to be killed when aborting capture." "Mark the region that will have to be killed when aborting capture."
@ -1438,8 +1453,15 @@ Of course, if exact position has been required, just put it there."
(defun org-capture-narrow (beg end) (defun org-capture-narrow (beg end)
"Narrow, unless configuration says not to narrow." "Narrow, unless configuration says not to narrow."
(unless (org-capture-get :unnarrowed) (unless (org-capture-get :unnarrowed)
(narrow-to-region beg end) (narrow-to-region beg end)))
(goto-char beg)))
(defun org-capture--position-cursor (beg end)
"Move point to first \"%?\" location or at start of template.
BEG and END are buffer positions at the beginning and end position
of the template."
(goto-char beg)
(when (search-forward "%?" end t)
(replace-match "")))
(defun org-capture-empty-lines-before (&optional n) (defun org-capture-empty-lines-before (&optional n)
"Set the correct number of empty lines before the insertion point. "Set the correct number of empty lines before the insertion point.
@ -1736,11 +1758,11 @@ The template may still contain \"%?\" for cursor positioning."
(_ (error "Invalid `org-capture--clipboards' value: %S" (_ (error "Invalid `org-capture--clipboards' value: %S"
org-capture--clipboards))))) org-capture--clipboards)))))
("p" ("p"
;; We remove file properties inherited from ;; We remove keyword properties inherited from
;; target buffer so `org-read-property-value' has ;; target buffer so `org-read-property-value' has
;; a chance to find allowed values in sub-trees ;; a chance to find allowed values in sub-trees
;; from the target buffer. ;; from the target buffer.
(setq-local org-file-properties nil) (setq-local org-keyword-properties nil)
(let* ((origin (set-marker (make-marker) (let* ((origin (set-marker (make-marker)
(org-capture-get :pos) (org-capture-get :pos)
(org-capture-get :buffer))) (org-capture-get :buffer)))
@ -1925,4 +1947,8 @@ Assume sexps have been marked with
(provide 'org-capture) (provide 'org-capture)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-capture.el ends here ;;; org-capture.el ends here

View file

@ -35,11 +35,17 @@
(declare-function notifications-notify "notifications" (&rest params)) (declare-function notifications-notify "notifications" (&rest params))
(declare-function org-element-property "org-element" (property element)) (declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element)) (declare-function org-element-type "org-element" (element))
(declare-function org-inlinetask-at-task-p "org-inlinetask" ())
(declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
(declare-function org-inlinetask-goto-end "org-inlinetask" ())
(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
(declare-function org-link-display-format "ol" (s)) (declare-function org-link-display-format "ol" (s))
(declare-function org-link-heading-search-string "ol" (&optional string)) (declare-function org-link-heading-search-string "ol" (&optional string))
(declare-function org-link-make-string "ol" (link &optional description)) (declare-function org-link-make-string "ol" (link &optional description))
(declare-function org-table-goto-line "org-table" (n)) (declare-function org-table-goto-line "org-table" (n))
(declare-function org-dynamic-block-define "org" (type func)) (declare-function org-dynamic-block-define "org" (type func))
(declare-function w32-notification-notify "w32fns.c" (&rest params))
(declare-function w32-notification-close "w32fns.c" (&rest params))
(defvar org-frame-title-format-backup nil) (defvar org-frame-title-format-backup nil)
(defvar org-state) (defvar org-state)
@ -273,6 +279,15 @@ also using the face `org-mode-line-clock-overrun'."
(const :tag "Just mark the time string" nil) (const :tag "Just mark the time string" nil)
(string :tag "Text to prepend"))) (string :tag "Text to prepend")))
(defcustom org-show-notification-timeout 3
"Number of seconds to wait before closing Org notifications.
This is applied to notifications sent with `notifications-notify'
and `w32-notification-notify' only, not other mechanisms possibly
set through `org-show-notification-handler'."
:group 'org-clock
:package-version '(Org . "9.4")
:type 'integer)
(defcustom org-show-notification-handler nil (defcustom org-show-notification-handler nil
"Function or program to send notification with. "Function or program to send notification with.
The function or program will be called with the notification The function or program will be called with the notification
@ -457,6 +472,19 @@ Valid values are: `today', `yesterday', `thisweek', `lastweek',
(const :tag "Select range interactively" interactive)) (const :tag "Select range interactively" interactive))
:safe #'symbolp) :safe #'symbolp)
(defcustom org-clock-auto-clockout-timer nil
"Timer for auto clocking out when Emacs is idle.
When set to a number, auto clock out the currently clocked in
task after this number of seconds of idle time.
This is only effective when `org-clock-auto-clockout-insinuate'
is added to the user configuration."
:group 'org-clock
:package-version '(Org . "9.4")
:type '(choice
(integer :tag "Clock out after Emacs is idle for X seconds")
(const :tag "Never auto clock out" nil)))
(defvar org-clock-in-prepare-hook nil (defvar org-clock-in-prepare-hook nil
"Hook run when preparing the clock. "Hook run when preparing the clock.
This hook is run before anything happens to the task that This hook is run before anything happens to the task that
@ -698,7 +726,8 @@ If not, show simply the clocked time like 01:50."
(save-excursion (save-excursion
(let ((end (save-excursion (org-end-of-subtree)))) (let ((end (save-excursion (org-end-of-subtree))))
(when (re-search-forward (concat org-clock-string (when (re-search-forward (concat org-clock-string
".*\\]--\\(\\[[^]]+\\]\\)") end t) ".*\\]--\\(\\[[^]]+\\]\\)")
end t)
(org-time-string-to-time (match-string 1)))))) (org-time-string-to-time (match-string 1))))))
(defun org-clock-update-mode-line (&optional refresh) (defun org-clock-update-mode-line (&optional refresh)
@ -725,7 +754,8 @@ menu\nmouse-2 will jump to task"))
(setq org-mode-line-string (setq org-mode-line-string
(concat (propertize (concat (propertize
org-clock-task-overrun-text org-clock-task-overrun-text
'face 'org-mode-line-clock-overrun) org-mode-line-string))) 'face 'org-mode-line-clock-overrun)
org-mode-line-string)))
(force-mode-line-update)) (force-mode-line-update))
(defun org-clock-get-clocked-time () (defun org-clock-get-clocked-time ()
@ -808,15 +838,26 @@ If PLAY-SOUND is non-nil, it overrides `org-clock-sound'."
"Show notification. "Show notification.
Use `org-show-notification-handler' if defined, Use `org-show-notification-handler' if defined,
use libnotify if available, or fall back on a message." use libnotify if available, or fall back on a message."
(ignore-errors (require 'notifications))
(cond ((functionp org-show-notification-handler) (cond ((functionp org-show-notification-handler)
(funcall org-show-notification-handler notification)) (funcall org-show-notification-handler notification))
((stringp org-show-notification-handler) ((stringp org-show-notification-handler)
(start-process "emacs-timer-notification" nil (start-process "emacs-timer-notification" nil
org-show-notification-handler notification)) org-show-notification-handler notification))
((fboundp 'w32-notification-notify)
(let ((id (w32-notification-notify
:title "Org mode message"
:body notification
:urgency 'low)))
(run-with-timer
org-show-notification-timeout
nil
(lambda () (w32-notification-close id)))))
((fboundp 'notifications-notify) ((fboundp 'notifications-notify)
(notifications-notify (notifications-notify
:title "Org mode message" :title "Org mode message"
:body notification :body notification
:timeout (* org-show-notification-timeout 1000)
;; FIXME how to link to the Org icon? ;; FIXME how to link to the Org icon?
;; :app-icon "~/.emacs.d/icons/mail.png" ;; :app-icon "~/.emacs.d/icons/mail.png"
:urgency 'low)) :urgency 'low))
@ -859,7 +900,8 @@ If CLOCK-SOUND is non-nil, it overrides `org-clock-sound'."
(goto-char (point-min)) (goto-char (point-min))
(while (re-search-forward org-clock-re nil t) (while (re-search-forward org-clock-re nil t)
(push (cons (copy-marker (match-end 1) t) (push (cons (copy-marker (match-end 1) t)
(org-time-string-to-time (match-string 1))) clocks)))) (org-time-string-to-time (match-string 1)))
clocks))))
clocks)) clocks))
(defsubst org-is-active-clock (clock) (defsubst org-is-active-clock (clock)
@ -983,7 +1025,7 @@ CLOCK is a cons cell of the form (MARKER START-TIME)."
(let ((element (org-element-at-point))) (let ((element (org-element-at-point)))
(when (eq (org-element-type element) 'drawer) (when (eq (org-element-type element) 'drawer)
(when (> (org-element-property :end element) (car clock)) (when (> (org-element-property :end element) (car clock))
(org-flag-drawer nil element)) (org-hide-drawer-toggle 'off nil element))
(throw 'exit nil))))))))))) (throw 'exit nil)))))))))))
(defun org-clock-resolve (clock &optional prompt-fn last-valid fail-quietly) (defun org-clock-resolve (clock &optional prompt-fn last-valid fail-quietly)
@ -1022,6 +1064,9 @@ k/K Keep X minutes of the idle time (default is all). If this
that many minutes after the time that idling began, and then that many minutes after the time that idling began, and then
clocked back in at the present time. clocked back in at the present time.
t/T Like `k', but will ask you to specify a time (when you got
distracted away), instead of a number of minutes.
g/G Indicate that you \"got back\" X minutes ago. This is quite g/G Indicate that you \"got back\" X minutes ago. This is quite
different from `k': it clocks you out from the beginning of different from `k': it clocks you out from the beginning of
the idle period and clock you back in X minutes ago. the idle period and clock you back in X minutes ago.
@ -1041,19 +1086,24 @@ to be CLOCKED OUT."))))
(while (or (null char-pressed) (while (or (null char-pressed)
(and (not (memq char-pressed (and (not (memq char-pressed
'(?k ?K ?g ?G ?s ?S ?C '(?k ?K ?g ?G ?s ?S ?C
?j ?J ?i ?q))) ?j ?J ?i ?q ?t ?T)))
(or (ding) t))) (or (ding) t)))
(setq char-pressed (setq char-pressed
(read-char (concat (funcall prompt-fn clock) (read-char (concat (funcall prompt-fn clock)
" [jkKgGSscCiq]? ") " [jkKtTgGSscCiq]? ")
nil 45))) nil 45)))
(and (not (memq char-pressed '(?i ?q))) char-pressed))))) (and (not (memq char-pressed '(?i ?q))) char-pressed)))))
(default (default
(floor (org-time-convert-to-integer (org-time-since last-valid)) (floor (org-time-convert-to-integer (org-time-since last-valid))
60)) 60))
(keep (keep
(and (memq ch '(?k ?K)) (or (and (memq ch '(?k ?K))
(read-number "Keep how many minutes? " default))) (read-number "Keep how many minutes? " default))
(and (memq ch '(?t ?T))
(floor
(/ (float-time
(org-time-subtract (org-read-date t t) last-valid))
60)))))
(gotback (gotback
(and (memq ch '(?g ?G)) (and (memq ch '(?g ?G))
(read-number "Got back how many minutes ago? " default))) (read-number "Got back how many minutes ago? " default)))
@ -1068,7 +1118,7 @@ to be CLOCKED OUT."))))
(org-clock-resolve-clock clock 'now nil t nil fail-quietly)) (org-clock-resolve-clock clock 'now nil t nil fail-quietly))
(org-clock-jump-to-current-clock clock)) (org-clock-jump-to-current-clock clock))
((or (null ch) ((or (null ch)
(not (memq ch '(?k ?K ?g ?G ?s ?S ?C)))) (not (memq ch '(?k ?K ?g ?G ?s ?S ?C ?t ?T))))
(message "")) (message ""))
(t (t
(org-clock-resolve-clock (org-clock-resolve-clock
@ -1092,7 +1142,7 @@ to be CLOCKED OUT."))))
(t (t
(error "Unexpected, please report this as a bug"))) (error "Unexpected, please report this as a bug")))
(and gotback last-valid) (and gotback last-valid)
(memq ch '(?K ?G ?S)) (memq ch '(?K ?G ?S ?T))
(and start-over (and start-over
(not (memq ch '(?K ?G ?S ?C)))) (not (memq ch '(?K ?G ?S ?C))))
fail-quietly))))) fail-quietly)))))
@ -1315,7 +1365,6 @@ the default behavior."
(t (t
(insert-before-markers "\n") (insert-before-markers "\n")
(backward-char 1) (backward-char 1)
(org-indent-line)
(when (and (save-excursion (when (and (save-excursion
(end-of-line 0) (end-of-line 0)
(org-in-item-p))) (org-in-item-p)))
@ -1340,7 +1389,8 @@ the default behavior."
start-time start-time
(org-current-time org-clock-rounding-minutes t))) (org-current-time org-clock-rounding-minutes t)))
(setq ts (org-insert-time-stamp org-clock-start-time (setq ts (org-insert-time-stamp org-clock-start-time
'with-hm 'inactive)))) 'with-hm 'inactive))
(org-indent-line)))
(move-marker org-clock-marker (point) (buffer-base-buffer)) (move-marker org-clock-marker (point) (buffer-base-buffer))
(move-marker org-clock-hd-marker (move-marker org-clock-hd-marker
(save-excursion (org-back-to-heading t) (point)) (save-excursion (org-back-to-heading t) (point))
@ -1375,6 +1425,26 @@ the default behavior."
(message "Clock starts at %s - %s" ts org--msg-extra) (message "Clock starts at %s - %s" ts org--msg-extra)
(run-hooks 'org-clock-in-hook)))))) (run-hooks 'org-clock-in-hook))))))
(defun org-clock-auto-clockout ()
"Clock out the currently clocked in task if Emacs is idle.
See `org-clock-auto-clockout-timer' to set the idle time span.
This is only effective when `org-clock-auto-clockout-insinuate'
is present in the user configuration."
(when (and (numberp org-clock-auto-clockout-timer)
org-clock-current-task)
(run-with-idle-timer
org-clock-auto-clockout-timer nil #'org-clock-out)))
;;;###autoload
(defun org-clock-toggle-auto-clockout ()
(interactive)
(if (memq 'org-clock-auto-clockout org-clock-in-hook)
(progn (remove-hook 'org-clock-in-hook #'org-clock-auto-clockout)
(message "Auto clock-out after idle time turned off"))
(add-hook 'org-clock-in-hook #'org-clock-auto-clockout t)
(message "Auto clock-out after idle time turned on")))
;;;###autoload ;;;###autoload
(defun org-clock-in-last (&optional arg) (defun org-clock-in-last (&optional arg)
"Clock in the last closed clocked item. "Clock in the last closed clocked item.
@ -1512,7 +1582,7 @@ line and position cursor in that line."
(insert ":" drawer ":\n:END:\n") (insert ":" drawer ":\n:END:\n")
(org-indent-region beg (point)) (org-indent-region beg (point))
(org-flag-region (org-flag-region
(line-end-position -1) (1- (point)) t 'org-hide-drawer) (line-end-position -1) (1- (point)) t 'outline)
(forward-line -1)))) (forward-line -1))))
;; When a clock drawer needs to be created because of the ;; When a clock drawer needs to be created because of the
;; number of clock items or simply if it is missing, collect ;; number of clock items or simply if it is missing, collect
@ -1537,7 +1607,7 @@ line and position cursor in that line."
(let ((end (point-marker))) (let ((end (point-marker)))
(goto-char beg) (goto-char beg)
(save-excursion (insert ":" drawer ":\n")) (save-excursion (insert ":" drawer ":\n"))
(org-flag-region (line-end-position) (1- end) t 'org-hide-drawer) (org-flag-region (line-end-position) (1- end) t 'outline)
(org-indent-region (point) end) (org-indent-region (point) end)
(forward-line) (forward-line)
(unless org-log-states-order-reversed (unless org-log-states-order-reversed
@ -1579,7 +1649,7 @@ to, overriding the existing value of `org-clock-out-switch-to-state'."
org-clock-out-switch-to-state)) org-clock-out-switch-to-state))
(now (org-current-time org-clock-rounding-minutes)) (now (org-current-time org-clock-rounding-minutes))
ts te s h m remove) ts te s h m remove)
(setq org-clock-out-time now) (setq org-clock-out-time (or at-time now))
(save-excursion ; Do not replace this with `with-current-buffer'. (save-excursion ; Do not replace this with `with-current-buffer'.
(with-no-warnings (set-buffer (org-clocking-buffer))) (with-no-warnings (set-buffer (org-clocking-buffer)))
(save-restriction (save-restriction
@ -1724,7 +1794,7 @@ Optional argument N tells to change by that many units."
(delq 'org-mode-line-string global-mode-string)) (delq 'org-mode-line-string global-mode-string))
(org-clock-restore-frame-title-format) (org-clock-restore-frame-title-format)
(force-mode-line-update) (force-mode-line-update)
(error "No active clock")) (user-error "No active clock"))
(save-excursion ; Do not replace this with `with-current-buffer'. (save-excursion ; Do not replace this with `with-current-buffer'.
(with-no-warnings (set-buffer (org-clocking-buffer))) (with-no-warnings (set-buffer (org-clocking-buffer)))
(goto-char org-clock-marker) (goto-char org-clock-marker)
@ -1753,14 +1823,14 @@ With prefix arg SELECT, offer recently clocked tasks for selection."
(m (cond (m (cond
(select (select
(or (org-clock-select-task "Select task to go to: ") (or (org-clock-select-task "Select task to go to: ")
(error "No task selected"))) (user-error "No task selected")))
((org-clocking-p) org-clock-marker) ((org-clocking-p) org-clock-marker)
((and org-clock-goto-may-find-recent-task ((and org-clock-goto-may-find-recent-task
(car org-clock-history) (car org-clock-history)
(marker-buffer (car org-clock-history))) (marker-buffer (car org-clock-history)))
(setq recent t) (setq recent t)
(car org-clock-history)) (car org-clock-history))
(t (error "No active or recent clock task"))))) (t (user-error "No active or recent clock task")))))
(pop-to-buffer-same-window (marker-buffer m)) (pop-to-buffer-same-window (marker-buffer m))
(if (or (< m (point-min)) (> m (point-max))) (widen)) (if (or (< m (point-min)) (> m (point-max))) (widen))
(goto-char m) (goto-char m)
@ -1890,7 +1960,12 @@ PROPNAME lets you set a custom text property instead of :org-clock-minutes."
"Return time, clocked on current item in total." "Return time, clocked on current item in total."
(save-excursion (save-excursion
(save-restriction (save-restriction
(org-narrow-to-subtree) (if (and (featurep 'org-inlinetask)
(or (org-inlinetask-at-task-p)
(org-inlinetask-in-task-p)))
(narrow-to-region (save-excursion (org-inlinetask-goto-beginning) (point))
(save-excursion (org-inlinetask-goto-end) (point)))
(org-narrow-to-subtree))
(org-clock-sum tstart) (org-clock-sum tstart)
org-clock-file-total-minutes))) org-clock-file-total-minutes)))
@ -2067,7 +2142,10 @@ in the buffer and update it."
(start (goto-char start))) (start (goto-char start)))
(org-update-dblock)) (org-update-dblock))
(org-dynamic-block-define "clocktable" #'org-clock-report) ;;;###autoload
(eval-after-load 'org
'(progn
(org-dynamic-block-define "clocktable" #'org-clock-report)))
(defun org-day-of-week (day month year) (defun org-day-of-week (day month year)
"Return the day of the week as an integer." "Return the day of the week as an integer."
@ -2310,7 +2388,7 @@ the currently selected interval size."
(save-excursion (save-excursion
(goto-char (point-at-bol)) (goto-char (point-at-bol))
(if (not (looking-at "^[ \t]*#\\+BEGIN:[ \t]+clocktable\\>.*?:block[ \t]+\\(\\S-+\\)")) (if (not (looking-at "^[ \t]*#\\+BEGIN:[ \t]+clocktable\\>.*?:block[ \t]+\\(\\S-+\\)"))
(error "Line needs a :block definition before this command works") (user-error "Line needs a :block definition before this command works")
(let* ((b (match-beginning 1)) (e (match-end 1)) (let* ((b (match-beginning 1)) (e (match-end 1))
(s (match-string 1)) (s (match-string 1))
block shift ins y mw d date wp m) block shift ins y mw d date wp m)
@ -2369,7 +2447,7 @@ the currently selected interval size."
(encode-time 0 0 0 1 (+ mw n) y)))) (encode-time 0 0 0 1 (+ mw n) y))))
(y (y
(setq ins (number-to-string (+ y n)))))) (setq ins (number-to-string (+ y n))))))
(t (error "Cannot shift clocktable block"))) (t (user-error "Cannot shift clocktable block")))
(when ins (when ins
(goto-char b) (goto-char b)
(insert ins) (insert ins)
@ -2384,20 +2462,21 @@ the currently selected interval size."
(setq params (org-combine-plists org-clocktable-defaults params)) (setq params (org-combine-plists org-clocktable-defaults params))
(catch 'exit (catch 'exit
(let* ((scope (plist-get params :scope)) (let* ((scope (plist-get params :scope))
(base-buffer (org-base-buffer (current-buffer)))
(files (pcase scope (files (pcase scope
(`agenda (`agenda
(org-agenda-files t)) (org-agenda-files t))
(`agenda-with-archives (`agenda-with-archives
(org-add-archive-files (org-agenda-files t))) (org-add-archive-files (org-agenda-files t)))
(`file-with-archives (`file-with-archives
(and buffer-file-name (let ((base-file (buffer-file-name base-buffer)))
(org-add-archive-files (list buffer-file-name)))) (and base-file
(org-add-archive-files (list base-file)))))
((or `nil `file `subtree `tree ((or `nil `file `subtree `tree
(and (pred symbolp) (and (pred symbolp)
(guard (string-match "\\`tree\\([0-9]+\\)\\'" (guard (string-match "\\`tree\\([0-9]+\\)\\'"
(symbol-name scope))))) (symbol-name scope)))))
(or (buffer-file-name (buffer-base-buffer)) base-buffer)
(current-buffer)))
((pred functionp) (funcall scope)) ((pred functionp) (funcall scope))
((pred consp) scope) ((pred consp) scope)
(_ (user-error "Unknown scope: %S" scope)))) (_ (user-error "Unknown scope: %S" scope))))
@ -2421,7 +2500,7 @@ the currently selected interval size."
(when step (when step
;; Write many tables, in steps ;; Write many tables, in steps
(unless (or block (and ts te)) (unless (or block (and ts te))
(error "Clocktable `:step' can only be used with `:block' or `:tstart,:end'")) (user-error "Clocktable `:step' can only be used with `:block' or `:tstart, :end'"))
(org-clocktable-steps params) (org-clocktable-steps params)
(throw 'exit nil)) (throw 'exit nil))
@ -2527,7 +2606,7 @@ from the dynamic block definition."
(guard (string-match-p "\\`[0-9]+!\\'" (symbol-name narrow)))) (guard (string-match-p "\\`[0-9]+!\\'" (symbol-name narrow))))
(setq narrow-cut-p t) (setq narrow-cut-p t)
(setq narrow (string-to-number (symbol-name narrow)))) (setq narrow (string-to-number (symbol-name narrow))))
(_ (error "Invalid value %s of :narrow property in clock table" narrow))) (_ (user-error "Invalid value %s of :narrow property in clock table" narrow)))
;; Now we need to output this table stuff. ;; Now we need to output this table stuff.
(goto-char ipos) (goto-char ipos)
@ -2718,6 +2797,7 @@ a number of clock tables."
(pcase step (pcase step
(`day "Daily report: ") (`day "Daily report: ")
(`week "Weekly report starting on: ") (`week "Weekly report starting on: ")
(`semimonth "Semimonthly report starting on: ")
(`month "Monthly report starting on: ") (`month "Monthly report starting on: ")
(`year "Annual report starting on: ") (`year "Annual report starting on: ")
(_ (user-error "Unknown `:step' specification: %S" step)))) (_ (user-error "Unknown `:step' specification: %S" step))))
@ -2767,6 +2847,9 @@ a number of clock tables."
(let ((offset (if (= dow week-start) 7 (let ((offset (if (= dow week-start) 7
(mod (- week-start dow) 7)))) (mod (- week-start dow) 7))))
(list 0 0 org-extend-today-until (+ d offset) m y))) (list 0 0 org-extend-today-until (+ d offset) m y)))
(`semimonth (list 0 0 0
(if (< d 16) 16 1)
(if (< d 16) m (1+ m)) y))
(`month (list 0 0 0 month-start (1+ m) y)) (`month (list 0 0 0 month-start (1+ m) y))
(`year (list 0 0 org-extend-today-until 1 1 (1+ y))))))) (`year (list 0 0 org-extend-today-until 1 1 (1+ y)))))))
(table-begin (line-beginning-position 0)) (table-begin (line-beginning-position 0))
@ -2883,7 +2966,7 @@ PROPERTIES: The list properties specified in the `:properties' parameter
(org-trim (org-trim
(org-link-display-format (org-link-display-format
(replace-regexp-in-string (replace-regexp-in-string
"\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]" ""
headline))))))) headline)))))))
(tgs (and tags (org-get-tags))) (tgs (and tags (org-get-tags)))
(tsp (tsp

View file

@ -44,6 +44,8 @@
(declare-function org-dynamic-block-define "org" (type func)) (declare-function org-dynamic-block-define "org" (type func))
(declare-function org-link-display-format "ol" (s)) (declare-function org-link-display-format "ol" (s))
(declare-function org-link-open-from-string "ol" (s &optional arg)) (declare-function org-link-open-from-string "ol" (s &optional arg))
(declare-function face-remap-remove-relative "face-remap" (cookie))
(declare-function face-remap-add-relative "face-remap" (face &rest specs))
(defvar org-agenda-columns-add-appointments-to-effort-sum) (defvar org-agenda-columns-add-appointments-to-effort-sum)
(defvar org-agenda-columns-compute-summary-properties) (defvar org-agenda-columns-compute-summary-properties)
@ -164,7 +166,7 @@ See `org-columns-summary-types' for details.")
(org-defkey org-columns-map "o" 'org-overview) (org-defkey org-columns-map "o" 'org-overview)
(org-defkey org-columns-map "e" 'org-columns-edit-value) (org-defkey org-columns-map "e" 'org-columns-edit-value)
(org-defkey org-columns-map "\C-c\C-t" 'org-columns-todo) (org-defkey org-columns-map "\C-c\C-t" 'org-columns-todo)
(org-defkey org-columns-map "\C-c\C-c" 'org-columns-set-tags-or-toggle) (org-defkey org-columns-map "\C-c\C-c" 'org-columns-toggle-or-columns-quit)
(org-defkey org-columns-map "\C-c\C-o" 'org-columns-open-link) (org-defkey org-columns-map "\C-c\C-o" 'org-columns-open-link)
(org-defkey org-columns-map "v" 'org-columns-show-value) (org-defkey org-columns-map "v" 'org-columns-show-value)
(org-defkey org-columns-map "q" 'org-columns-quit) (org-defkey org-columns-map "q" 'org-columns-quit)
@ -257,6 +259,8 @@ value for ITEM property."
(if org-hide-leading-stars ?\s ?*)) (if org-hide-leading-stars ?\s ?*))
"* ")))) "* "))))
(concat stars (org-link-display-format value)))) (concat stars (org-link-display-format value))))
(`(,(or "DEADLINE" "SCHEDULED" "TIMESTAMP") . ,_)
(replace-regexp-in-string org-ts-regexp "[\\1]" value))
(`(,_ ,_ ,_ ,_ nil) value) (`(,_ ,_ ,_ ,_ nil) value)
;; If PRINTF is set, assume we are displaying a number and ;; If PRINTF is set, assume we are displaying a number and
;; obey to the format string. ;; obey to the format string.
@ -364,11 +368,18 @@ ORIGINAL is the real string, i.e., before it is modified by
("TODO" (propertize v 'face (org-get-todo-face original))) ("TODO" (propertize v 'face (org-get-todo-face original)))
(_ v))))) (_ v)))))
(defvar org-columns-header-line-remap nil
"Store the relative remapping of column header-line.
This is needed to later remove this relative remapping.")
(defun org-columns--display-here (columns &optional dateline) (defun org-columns--display-here (columns &optional dateline)
"Overlay the current line with column display. "Overlay the current line with column display.
COLUMNS is an alist (SPEC VALUE DISPLAYED). Optional argument COLUMNS is an alist (SPEC VALUE DISPLAYED). Optional argument
DATELINE is non-nil when the face used should be DATELINE is non-nil when the face used should be
`org-agenda-column-dateline'." `org-agenda-column-dateline'."
(when (ignore-errors (require 'face-remap))
(setq org-columns-header-line-remap
(face-remap-add-relative 'header-line '(:inherit default))))
(save-excursion (save-excursion
(beginning-of-line) (beginning-of-line)
(let* ((level-face (and (looking-at "\\(\\**\\)\\(\\* \\)") (let* ((level-face (and (looking-at "\\(\\**\\)\\(\\* \\)")
@ -378,8 +389,7 @@ DATELINE is non-nil when the face used should be
(org-get-at-bol 'face)) (org-get-at-bol 'face))
'default)) 'default))
(color (list :foreground (face-attribute ref-face :foreground))) (color (list :foreground (face-attribute ref-face :foreground)))
(font (list :height (face-attribute 'default :height) (font (list :family (face-attribute 'default :family)))
:family (face-attribute 'default :family)))
(face (list color font 'org-column ref-face)) (face (list color font 'org-column ref-face))
(face1 (list color font 'org-agenda-column-dateline ref-face))) (face1 (list color font 'org-agenda-column-dateline ref-face)))
;; Each column is an overlay on top of a character. So there has ;; Each column is an overlay on top of a character. So there has
@ -502,6 +512,9 @@ for the duration of the command.")
(defun org-columns-remove-overlays () (defun org-columns-remove-overlays ()
"Remove all currently active column overlays." "Remove all currently active column overlays."
(interactive) (interactive)
(when (and (fboundp 'face-remap-remove-relative)
org-columns-header-line-remap)
(face-remap-remove-relative org-columns-header-line-remap))
(when org-columns-overlays (when org-columns-overlays
(when (local-variable-p 'org-previous-header-line-format) (when (local-variable-p 'org-previous-header-line-format)
(setq header-line-format org-previous-header-line-format) (setq header-line-format org-previous-header-line-format)
@ -554,13 +567,19 @@ for the duration of the command.")
(interactive "P") (interactive "P")
(org-columns-edit-value "TODO")) (org-columns-edit-value "TODO"))
(defun org-columns-set-tags-or-toggle (&optional _arg) (defun org-columns-toggle-or-columns-quit ()
"Toggle checkbox at point, or set tags for current headline." "Toggle checkbox at point, or quit column view."
(interactive "P") (interactive)
(if (string-match "\\`\\[[ xX-]\\]\\'" (or (org-columns--toggle)
(get-char-property (point) 'org-columns-value)) (org-columns-quit)))
(org-columns-next-allowed-value)
(org-columns-edit-value "TAGS"))) (defun org-columns--toggle ()
"Toggle checkbox at point. Return non-nil if toggle happened, else nil.
See info documentation about realizing a suitable checkbox."
(when (string-match "\\`\\[[ xX-]\\]\\'"
(get-char-property (point) 'org-columns-value))
(org-columns-next-allowed-value)
t))
(defvar org-overriding-columns-format nil (defvar org-overriding-columns-format nil
"When set, overrides any other format definition for the agenda. "When set, overrides any other format definition for the agenda.
@ -1550,7 +1569,10 @@ PARAMS is a property list of parameters:
(id))))) (id)))))
(org-update-dblock)) (org-update-dblock))
(org-dynamic-block-define "columnview" #'org-columns-insert-dblock) ;;;###autoload
(eval-after-load 'org
'(progn
(org-dynamic-block-define "columnview" #'org-columns-insert-dblock)))
;;; Column view in the agenda ;;; Column view in the agenda
@ -1564,6 +1586,7 @@ PARAMS is a property list of parameters:
(move-marker org-columns-begin-marker (point)) (move-marker org-columns-begin-marker (point))
(setq org-columns-begin-marker (point-marker))) (setq org-columns-begin-marker (point-marker)))
(let* ((org-columns--time (float-time)) (let* ((org-columns--time (float-time))
(org-done-keywords org-done-keywords-for-agenda)
(fmt (fmt
(cond (cond
((bound-and-true-p org-overriding-columns-format)) ((bound-and-true-p org-overriding-columns-format))
@ -1613,6 +1636,7 @@ PARAMS is a property list of parameters:
(dolist (entry cache) (dolist (entry cache)
(goto-char (car entry)) (goto-char (car entry))
(org-columns--display-here (cdr entry))) (org-columns--display-here (cdr entry)))
(setq-local org-agenda-columns-active t)
(when org-agenda-columns-show-summaries (when org-agenda-columns-show-summaries
(org-agenda-colview-summarize cache))))))) (org-agenda-colview-summarize cache)))))))
@ -1677,8 +1701,7 @@ This will add overlays to the date lines, to show the summary for each day."
'face 'bold final)) 'face 'bold final))
(list spec final final))))) (list spec final final)))))
fmt) fmt)
'dateline) 'dateline))))
(setq-local org-agenda-columns-active t))))
(if (bobp) (throw :complete t) (forward-line -1))))))) (if (bobp) (throw :complete t) (forward-line -1)))))))
(defun org-agenda-colview-compute (fmt) (defun org-agenda-colview-compute (fmt)
@ -1704,4 +1727,8 @@ This will add overlays to the date lines, to show the summary for each day."
(provide 'org-colview) (provide 'org-colview)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-colview.el ends here ;;; org-colview.el ends here

View file

@ -46,11 +46,13 @@
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading)) (declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
(declare-function org-get-heading "org" (&optional no-tags no-todo no-priority no-comment)) (declare-function org-get-heading "org" (&optional no-tags no-todo no-priority no-comment))
(declare-function org-get-tags "org" (&optional pos local)) (declare-function org-get-tags "org" (&optional pos local))
(declare-function org-hide-block-toggle "org" (&optional force no-error element))
(declare-function org-link-display-format "ol" (s)) (declare-function org-link-display-format "ol" (s))
(declare-function org-link-set-parameters "ol" (type &rest rest)) (declare-function org-link-set-parameters "ol" (type &rest rest))
(declare-function org-log-into-drawer "org" ()) (declare-function org-log-into-drawer "org" ())
(declare-function org-make-tag-string "org" (tags)) (declare-function org-make-tag-string "org" (tags))
(declare-function org-reduced-level "org" (l)) (declare-function org-reduced-level "org" (l))
(declare-function org-return "org" (&optional indent arg interactive))
(declare-function org-show-context "org" (&optional key)) (declare-function org-show-context "org" (&optional key))
(declare-function org-table-end "org-table" (&optional table-type)) (declare-function org-table-end "org-table" (&optional table-type))
(declare-function outline-next-heading "outline" ()) (declare-function outline-next-heading "outline" ())
@ -101,6 +103,20 @@ is nil)."
(defun org-time-convert-to-list (time) (defun org-time-convert-to-list (time)
(seconds-to-time (float-time time)))) (seconds-to-time (float-time time))))
;; `newline-and-indent' did not take a numeric argument before 27.1.
(if (version< emacs-version "27")
(defsubst org-newline-and-indent (&optional _arg)
(newline-and-indent))
(defalias 'org-newline-and-indent #'newline-and-indent))
(defun org--set-faces-extend (faces extend-p)
"Set the :extend attribute of FACES to EXTEND-P.
This is a no-op for Emacs versions lower than 27, since face
extension beyond end of line was not controllable."
(when (fboundp 'set-face-extend)
(mapc (lambda (f) (set-face-extend f extend-p)) faces)))
;;; Emacs < 26.1 compatibility ;;; Emacs < 26.1 compatibility
@ -314,6 +330,8 @@ Counting starts at 1."
(define-obsolete-variable-alias 'org-attach-directory (define-obsolete-variable-alias 'org-attach-directory
'org-attach-id-dir "Org 9.3") 'org-attach-id-dir "Org 9.3")
(make-obsolete 'org-attach-store-link "No longer used" "Org 9.4")
(make-obsolete 'org-attach-expand-link "No longer used" "Org 9.4")
(defun org-in-fixed-width-region-p () (defun org-in-fixed-width-region-p ()
"Non-nil if point in a fixed-width region." "Non-nil if point in a fixed-width region."
@ -556,6 +574,11 @@ use of this function is for the stuck project list."
(define-obsolete-function-alias 'org-make-link-regexps (define-obsolete-function-alias 'org-make-link-regexps
'org-link-make-regexps "Org 9.3") 'org-link-make-regexps "Org 9.3")
(define-obsolete-function-alias 'org-property-global-value
'org-property-global-or-keyword-value "Org 9.3")
(make-obsolete-variable 'org-file-properties 'org-keyword-properties "Org 9.3")
(define-obsolete-variable-alias 'org-angle-link-re (define-obsolete-variable-alias 'org-angle-link-re
'org-link-angle-re "Org 9.3") 'org-link-angle-re "Org 9.3")
@ -616,6 +639,72 @@ use of this function is for the stuck project list."
(declare (obsolete "use `org-align-tags' instead." "Org 9.2")) (declare (obsolete "use `org-align-tags' instead." "Org 9.2"))
(org-align-tags t)) (org-align-tags t))
(define-obsolete-function-alias
'org-at-property-block-p 'org-at-property-drawer-p "Org 9.4")
(defun org-flag-drawer (flag &optional element beg end)
"When FLAG is non-nil, hide the drawer we are at.
Otherwise make it visible.
When optional argument ELEMENT is a parsed drawer, as returned by
`org-element-at-point', hide or show that drawer instead.
When buffer positions BEG and END are provided, hide or show that
region as a drawer without further ado."
(declare (obsolete "use `org-hide-drawer-toggle' instead." "Org 9.4"))
(if (and beg end) (org-flag-region beg end flag 'outline)
(let ((drawer
(or element
(and (save-excursion
(beginning-of-line)
(looking-at-p "^[ \t]*:\\(\\(?:\\w\\|[-_]\\)+\\):[ \t]*$"))
(org-element-at-point)))))
(when (memq (org-element-type drawer) '(drawer property-drawer))
(let ((post (org-element-property :post-affiliated drawer)))
(org-flag-region
(save-excursion (goto-char post) (line-end-position))
(save-excursion (goto-char (org-element-property :end drawer))
(skip-chars-backward " \t\n")
(line-end-position))
flag 'outline)
;; When the drawer is hidden away, make sure point lies in
;; a visible part of the buffer.
(when (invisible-p (max (1- (point)) (point-min)))
(goto-char post)))))))
(defun org-hide-block-toggle-maybe ()
"Toggle visibility of block at point.
Unlike to `org-hide-block-toggle', this function does not throw
an error. Return a non-nil value when toggling is successful."
(declare (obsolete "use `org-hide-block-toggle' instead." "Org 9.4"))
(interactive)
(org-hide-block-toggle nil t))
(defun org-hide-block-toggle-all ()
"Toggle the visibility of all blocks in the current buffer."
(declare (obsolete "please notify Org mailing list if you use this function."
"Org 9.4"))
(let ((start (point-min))
(end (point-max)))
(save-excursion
(goto-char start)
(while (and (< (point) end)
(re-search-forward "^[ \t]*#\\+begin_?\
\\([^ \n]+\\)\\(\\([^\n]+\\)\\)?\n\\([^\000]+?\\)#\\+end_?\\1[ \t]*$" end t))
(save-excursion
(save-match-data
(goto-char (match-beginning 0))
(org-hide-block-toggle)))))))
(defun org-return-indent ()
"Goto next table row or insert a newline and indent.
Calls `org-table-next-row' or `newline-and-indent', depending on
context. See the individual commands for more information."
(declare (obsolete "use `org-return' with INDENT set to t instead."
"Org 9.4"))
(interactive)
(org-return t))
(defmacro org-with-silent-modifications (&rest body) (defmacro org-with-silent-modifications (&rest body)
(declare (obsolete "use `with-silent-modifications' instead." "Org 9.2") (declare (obsolete "use `with-silent-modifications' instead." "Org 9.2")
(debug (body))) (debug (body)))
@ -624,6 +713,23 @@ use of this function is for the stuck project list."
(define-obsolete-function-alias 'org-babel-strip-quotes (define-obsolete-function-alias 'org-babel-strip-quotes
'org-strip-quotes "Org 9.2") 'org-strip-quotes "Org 9.2")
(define-obsolete-variable-alias 'org-sort-agenda-notime-is-late
'org-agenda-sort-notime-is-late "9.4")
(define-obsolete-variable-alias 'org-sort-agenda-noeffort-is-high
'org-agenda-sort-noeffort-is-high "9.4")
(defconst org-maybe-keyword-time-regexp
(concat "\\(\\<\\(\\(?:CLO\\(?:CK\\|SED\\)\\|DEADLINE\\|SCHEDULED\\):\\)\\)?"
" *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^]\r\n>]*[]>]"
"\\|"
"<%%([^\r\n>]*>\\)")
"Matches a timestamp, possibly preceded by a keyword.")
(make-obsolete-variable
'org-maybe-keyword-time-regexp
"use `org-planning-line-re', followed by `org-ts-regexp-both' instead."
"Org 9.4")
;;;; Obsolete link types ;;;; Obsolete link types
(eval-after-load 'ol (eval-after-load 'ol
@ -808,7 +914,7 @@ This also applied for speedbar access."
(setq last-level level))))) (setq last-level level)))))
(aref subs 1)))) (aref subs 1))))
(eval-after-load "imenu" (eval-after-load 'imenu
'(progn '(progn
(add-hook 'imenu-after-jump-hook (add-hook 'imenu-after-jump-hook
(lambda () (lambda ()
@ -870,7 +976,7 @@ To get rid of the restriction, use `\\[org-agenda-remove-restriction-lock]'."
(defvar speedbar-file-key-map) (defvar speedbar-file-key-map)
(declare-function speedbar-add-supported-extension "speedbar" (extension)) (declare-function speedbar-add-supported-extension "speedbar" (extension))
(eval-after-load "speedbar" (eval-after-load 'speedbar
'(progn '(progn
(speedbar-add-supported-extension ".org") (speedbar-add-supported-extension ".org")
(define-key speedbar-file-key-map "<" 'org-speedbar-set-agenda-restriction) (define-key speedbar-file-key-map "<" 'org-speedbar-set-agenda-restriction)
@ -980,7 +1086,7 @@ ELEMENT is the element at point."
(flyspell-delete-region-overlays beg end))) (flyspell-delete-region-overlays beg end)))
(defvar flyspell-delayed-commands) (defvar flyspell-delayed-commands)
(eval-after-load "flyspell" (eval-after-load 'flyspell
'(add-to-list 'flyspell-delayed-commands 'org-self-insert-command)) '(add-to-list 'flyspell-delayed-commands 'org-self-insert-command))
;;;; Bookmark ;;;; Bookmark
@ -994,7 +1100,7 @@ ELEMENT is the element at point."
(org-show-context 'bookmark-jump))) (org-show-context 'bookmark-jump)))
;; Make `bookmark-jump' shows the jump location if it was hidden. ;; Make `bookmark-jump' shows the jump location if it was hidden.
(eval-after-load "bookmark" (eval-after-load 'bookmark
'(if (boundp 'bookmark-after-jump-hook) '(if (boundp 'bookmark-after-jump-hook)
;; We can use the hook ;; We can use the hook
(add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide) (add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide)
@ -1043,17 +1149,18 @@ key."
((guard (not (lookup-key calendar-mode-map "c"))) ((guard (not (lookup-key calendar-mode-map "c")))
(local-set-key "c" #'org-calendar-goto-agenda)) (local-set-key "c" #'org-calendar-goto-agenda))
(_ nil)) (_ nil))
(unless (eq org-agenda-diary-file 'diary-file) (unless (and (boundp 'org-agenda-diary-file)
(eq org-agenda-diary-file 'diary-file))
(local-set-key org-calendar-insert-diary-entry-key (local-set-key org-calendar-insert-diary-entry-key
#'org-agenda-diary-entry))) #'org-agenda-diary-entry)))
(eval-after-load "calendar" (eval-after-load 'calendar
'(add-hook 'calendar-mode-hook #'org--setup-calendar-bindings)) '(add-hook 'calendar-mode-hook #'org--setup-calendar-bindings))
;;;; Saveplace ;;;; Saveplace
;; Make sure saveplace shows the location if it was hidden ;; Make sure saveplace shows the location if it was hidden
(eval-after-load "saveplace" (eval-after-load 'saveplace
'(defadvice save-place-find-file-hook (after org-make-visible activate) '(defadvice save-place-find-file-hook (after org-make-visible activate)
"Make the position visible." "Make the position visible."
(org-bookmark-jump-unhide))) (org-bookmark-jump-unhide)))
@ -1061,7 +1168,7 @@ key."
;;;; Ecb ;;;; Ecb
;; Make sure ecb shows the location if it was hidden ;; Make sure ecb shows the location if it was hidden
(eval-after-load "ecb" (eval-after-load 'ecb
'(defadvice ecb-method-clicked (after esf/org-show-context activate) '(defadvice ecb-method-clicked (after esf/org-show-context activate)
"Make hierarchy visible when jumping into location from ECB tree buffer." "Make hierarchy visible when jumping into location from ECB tree buffer."
(when (derived-mode-p 'org-mode) (when (derived-mode-p 'org-mode)
@ -1075,17 +1182,17 @@ key."
(org-invisible-p)) (org-invisible-p))
(org-show-context 'mark-goto))) (org-show-context 'mark-goto)))
(eval-after-load "simple" (eval-after-load 'simple
'(defadvice pop-to-mark-command (after org-make-visible activate) '(defadvice pop-to-mark-command (after org-make-visible activate)
"Make the point visible with `org-show-context'." "Make the point visible with `org-show-context'."
(org-mark-jump-unhide))) (org-mark-jump-unhide)))
(eval-after-load "simple" (eval-after-load 'simple
'(defadvice exchange-point-and-mark (after org-make-visible activate) '(defadvice exchange-point-and-mark (after org-make-visible activate)
"Make the point visible with `org-show-context'." "Make the point visible with `org-show-context'."
(org-mark-jump-unhide))) (org-mark-jump-unhide)))
(eval-after-load "simple" (eval-after-load 'simple
'(defadvice pop-global-mark (after org-make-visible activate) '(defadvice pop-global-mark (after org-make-visible activate)
"Make the point visible with `org-show-context'." "Make the point visible with `org-show-context'."
(org-mark-jump-unhide))) (org-mark-jump-unhide)))
@ -1094,9 +1201,13 @@ key."
;; Make "session.el" ignore our circular variable. ;; Make "session.el" ignore our circular variable.
(defvar session-globals-exclude) (defvar session-globals-exclude)
(eval-after-load "session" (eval-after-load 'session
'(add-to-list 'session-globals-exclude 'org-mark-ring)) '(add-to-list 'session-globals-exclude 'org-mark-ring))
(provide 'org-compat) (provide 'org-compat)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-compat.el ends here ;;; org-compat.el ends here

View file

@ -1,14 +1,8 @@
;;; org-crypt.el --- Public Key Encryption for Org Entries -*- lexical-binding: t; -*- ;;; org-crypt.el --- Public Key Encryption for Org Entries -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2007-2020 Free Software Foundation, Inc. ;; Copyright (C) 2007-2020 Free Software Foundation, Inc.
;; Emacs Lisp Archive Entry
;; Filename: org-crypt.el
;; Keywords: org-mode
;; Author: John Wiegley <johnw@gnu.org> ;; Author: John Wiegley <johnw@gnu.org>
;; Maintainer: Peter Jones <pjones@pmade.com>
;; Description: Adds public key encryption to Org buffers
;; URL: http://www.newartisans.com/software/emacs.html
;; Compatibility: Emacs22
;; This file is part of GNU Emacs. ;; This file is part of GNU Emacs.
;; ;;
@ -47,9 +41,7 @@
;; ;;
;; 3. To later decrypt an entry, use `org-decrypt-entries' or ;; 3. To later decrypt an entry, use `org-decrypt-entries' or
;; `org-decrypt-entry'. It might be useful to bind this to a key, ;; `org-decrypt-entry'. It might be useful to bind this to a key,
;; like C-c C-/. I hope that in the future, C-c C-r can be might ;; like C-c C-/.
;; overloaded to also decrypt an entry if it's encrypted, since
;; that fits nicely with the meaning of "reveal".
;; ;;
;; 4. To automatically encrypt all necessary entries when saving a ;; 4. To automatically encrypt all necessary entries when saving a
;; file, call `org-crypt-use-before-save-magic' after loading ;; file, call `org-crypt-use-before-save-magic' after loading
@ -60,10 +52,11 @@
;; - Carsten Dominik ;; - Carsten Dominik
;; - Vitaly Ostanin ;; - Vitaly Ostanin
(require 'org)
;;; Code: ;;; Code:
(require 'org-macs)
(require 'org-compat)
(declare-function epg-decrypt-string "epg" (context cipher)) (declare-function epg-decrypt-string "epg" (context cipher))
(declare-function epg-list-keys "epg" (context &optional name mode)) (declare-function epg-list-keys "epg" (context &optional name mode))
(declare-function epg-make-context "epg" (declare-function epg-make-context "epg"
@ -74,6 +67,17 @@
(context plain recipients &optional sign always-trust)) (context plain recipients &optional sign always-trust))
(defvar epg-context) (defvar epg-context)
(declare-function org-back-over-empty-lines "org" ())
(declare-function org-back-to-heading "org" (&optional invisible-ok))
(declare-function org-before-first-heading-p "org" ())
(declare-function org-end-of-meta-data "org" (&optional full))
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
(declare-function org-flag-subtree "org" (flag))
(declare-function org-make-tags-matcher "org" (match))
(declare-function org-previous-visible-heading "org" (arg))
(declare-function org-scan-tags "org" (action matcher todo-only &optional start-level))
(declare-function org-set-property "org" (property value))
(defgroup org-crypt nil (defgroup org-crypt nil
"Org Crypt." "Org Crypt."
@ -90,9 +94,18 @@ See the \"Match syntax\" section of the org manual for more details."
(defcustom org-crypt-key "" (defcustom org-crypt-key ""
"The default key to use when encrypting the contents of a heading. "The default key to use when encrypting the contents of a heading.
This setting can also be overridden in the CRYPTKEY property." If this variable is nil, always use symmetric encryption, unconditionally.
:type 'string
:group 'org-crypt) Otherwise, The string is matched against all keys in the key ring.
In particular, the empty string matches no key. If no key is found,
look for the `epa-file-encrypt-to' local variable. Ultimately fall back
to symmetric encryption.
This setting can be overridden in the CRYPTKEY property."
:group 'org-crypt
:type '(choice
(string :tag "Public key(s) matching")
(const :tag "Symmetric encryption" nil)))
(defcustom org-crypt-disable-auto-save 'ask (defcustom org-crypt-disable-auto-save 'ask
"What org-decrypt should do if `auto-save-mode' is enabled. "What org-decrypt should do if `auto-save-mode' is enabled.
@ -118,6 +131,36 @@ nil : Leave auto-save-mode enabled.
(const :tag "Ask" ask) (const :tag "Ask" ask)
(const :tag "Encrypt" encrypt))) (const :tag "Encrypt" encrypt)))
(defun org-crypt--encrypted-text (beg end)
"Return encrypted text in between BEG and END."
;; Ignore indentation.
(replace-regexp-in-string
"^[ \t]*" ""
(buffer-substring-no-properties beg end)))
(defun org-at-encrypted-entry-p ()
"Is the current entry encrypted?
When the entry is encrypted, return a pair (BEG . END) where BEG
and END are buffer positions delimiting the encrypted area."
(org-with-wide-buffer
(unless (org-before-first-heading-p)
(org-back-to-heading t)
(org-end-of-meta-data 'standard)
(let ((case-fold-search nil)
(banner-start (rx (seq bol
(zero-or-more (any "\t "))
"-----BEGIN PGP MESSAGE-----"
eol))))
(when (looking-at banner-start)
(let ((start (point))
(banner-end (rx (seq bol
(or (group (zero-or-more (any "\t "))
"-----END PGP MESSAGE-----"
eol)
(seq (one-or-more "*") " "))))))
(when (and (re-search-forward banner-end nil t) (match-string 1))
(cons start (line-beginning-position 2)))))))))
(defun org-crypt-check-auto-save () (defun org-crypt-check-auto-save ()
"Check whether auto-save-mode is enabled for the current buffer. "Check whether auto-save-mode is enabled for the current buffer.
@ -149,93 +192,99 @@ See `org-crypt-disable-auto-save'."
(t nil)))) (t nil))))
(defun org-crypt-key-for-heading () (defun org-crypt-key-for-heading ()
"Return the encryption key for the current heading." "Return the encryption key(s) for the current heading.
(save-excursion Assume `epg-context' is set."
(org-back-to-heading t) (and org-crypt-key
(or (org-entry-get nil "CRYPTKEY" 'selective) (or (epg-list-keys epg-context
org-crypt-key (or (org-entry-get nil "CRYPTKEY" 'selective)
(and (boundp 'epa-file-encrypt-to) epa-file-encrypt-to) org-crypt-key))
(message "No crypt key set, using symmetric encryption.")))) (bound-and-true-p epa-file-encrypt-to)
(progn
(defun org-encrypt-string (str crypt-key) (message "No crypt key set, using symmetric encryption.")
"Return STR encrypted with CRYPT-KEY." nil))))
;; Text and key have to be identical, otherwise we re-crypt.
(if (and (string= crypt-key (get-text-property 0 'org-crypt-key str))
(string= (sha1 str) (get-text-property 0 'org-crypt-checksum str)))
(get-text-property 0 'org-crypt-text str)
(setq-local epg-context (epg-make-context nil t t))
(epg-encrypt-string epg-context str (epg-list-keys epg-context crypt-key))))
;;;###autoload
(defun org-encrypt-entry () (defun org-encrypt-entry ()
"Encrypt the content of the current headline." "Encrypt the content of the current headline."
(interactive) (interactive)
(require 'epg) (unless (org-at-encrypted-entry-p)
(org-with-wide-buffer (require 'epg)
(org-back-to-heading t) (setq-local epg-context (epg-make-context nil t t))
(setq-local epg-context (epg-make-context nil t t)) (org-with-wide-buffer
(let ((start-heading (point))) (org-back-to-heading t)
(org-end-of-meta-data) (let ((start-heading (point))
(unless (looking-at-p "-----BEGIN PGP MESSAGE-----") (crypt-key (org-crypt-key-for-heading))
(let ((folded (org-invisible-p)) (folded? (org-invisible-p (line-beginning-position))))
(crypt-key (org-crypt-key-for-heading)) (org-end-of-meta-data 'standard)
(beg (point))) (let ((beg (point))
(folded-heading
(and folded?
(save-excursion
(org-previous-visible-heading 1)
(point)))))
(goto-char start-heading) (goto-char start-heading)
(org-end-of-subtree t t) (org-end-of-subtree t t)
(org-back-over-empty-lines) (org-back-over-empty-lines)
(let ((contents (delete-and-extract-region beg (point)))) (let* ((contents (delete-and-extract-region beg (point)))
(key (get-text-property 0 'org-crypt-key contents))
(checksum (get-text-property 0 'org-crypt-checksum contents)))
(condition-case err (condition-case err
(insert (org-encrypt-string contents crypt-key)) (insert
;; Text and key have to be identical, otherwise we
;; re-crypt.
(if (and (equal crypt-key key)
(string= checksum (sha1 contents)))
(get-text-property 0 'org-crypt-text contents)
(epg-encrypt-string epg-context contents crypt-key)))
;; If encryption failed, make sure to insert back entry ;; If encryption failed, make sure to insert back entry
;; contents in the buffer. ;; contents in the buffer.
(error (insert contents) (error (nth 1 err))))) (error
(when folded (insert contents)
(goto-char start-heading) (error (error-message-string err)))))
(when folded-heading
(goto-char folded-heading)
(org-flag-subtree t)) (org-flag-subtree t))
nil))))) nil)))))
;;;###autoload
(defun org-decrypt-entry () (defun org-decrypt-entry ()
"Decrypt the content of the current headline." "Decrypt the content of the current headline."
(interactive) (interactive)
(require 'epg) (pcase (org-at-encrypted-entry-p)
(unless (org-before-first-heading-p) (`(,beg . ,end)
(org-with-wide-buffer (require 'epg)
(org-back-to-heading t) (setq-local epg-context (epg-make-context nil t t))
(let ((heading-point (point)) (org-with-point-at beg
(heading-was-invisible-p (org-crypt-check-auto-save)
(save-excursion (let* ((folded-heading
(outline-end-of-heading) (and (org-invisible-p)
(org-invisible-p)))) (save-excursion
(org-end-of-meta-data) (org-previous-visible-heading 1)
(when (looking-at "-----BEGIN PGP MESSAGE-----") (point))))
(org-crypt-check-auto-save) (encrypted-text (org-crypt--encrypted-text beg end))
(setq-local epg-context (epg-make-context nil t t)) (decrypted-text
(let* ((end (save-excursion (decode-coding-string
(search-forward "-----END PGP MESSAGE-----") (epg-decrypt-string epg-context encrypted-text)
(forward-line) 'utf-8)))
(point))) ;; Delete region starting just before point, because the
(encrypted-text (buffer-substring-no-properties (point) end)) ;; outline property starts at the \n of the heading.
(decrypted-text (delete-region (1- (point)) end)
(decode-coding-string ;; Store a checksum of the decrypted and the encrypted text
(epg-decrypt-string ;; value. This allows reusing the same encrypted text if the
epg-context ;; text does not change, and therefore avoid a re-encryption
encrypted-text) ;; process.
'utf-8))) (insert "\n"
;; Delete region starting just before point, because the (propertize decrypted-text
;; outline property starts at the \n of the heading. 'org-crypt-checksum (sha1 decrypted-text)
(delete-region (1- (point)) end) 'org-crypt-key (org-crypt-key-for-heading)
;; Store a checksum of the decrypted and the encrypted 'org-crypt-text encrypted-text))
;; text value. This allows reusing the same encrypted text (when folded-heading
;; if the text does not change, and therefore avoid a (goto-char folded-heading)
;; re-encryption process. (org-flag-subtree t))
(insert "\n" (propertize decrypted-text nil)))
'org-crypt-checksum (sha1 decrypted-text) (_ nil)))
'org-crypt-key (org-crypt-key-for-heading)
'org-crypt-text encrypted-text))
(when heading-was-invisible-p
(goto-char heading-point)
(org-flag-subtree t))
nil))))))
;;;###autoload
(defun org-encrypt-entries () (defun org-encrypt-entries ()
"Encrypt all top-level entries in the current buffer." "Encrypt all top-level entries in the current buffer."
(interactive) (interactive)
@ -245,6 +294,7 @@ See `org-crypt-disable-auto-save'."
(cdr (org-make-tags-matcher org-crypt-tag-matcher)) (cdr (org-make-tags-matcher org-crypt-tag-matcher))
org--matcher-tags-todo-only))) org--matcher-tags-todo-only)))
;;;###autoload
(defun org-decrypt-entries () (defun org-decrypt-entries ()
"Decrypt all entries in the current buffer." "Decrypt all entries in the current buffer."
(interactive) (interactive)
@ -254,14 +304,7 @@ See `org-crypt-disable-auto-save'."
(cdr (org-make-tags-matcher org-crypt-tag-matcher)) (cdr (org-make-tags-matcher org-crypt-tag-matcher))
org--matcher-tags-todo-only))) org--matcher-tags-todo-only)))
(defun org-at-encrypted-entry-p () ;;;###autoload
"Is the current entry encrypted?"
(unless (org-before-first-heading-p)
(save-excursion
(org-back-to-heading t)
(search-forward "-----BEGIN PGP MESSAGE-----"
(save-excursion (outline-next-heading)) t))))
(defun org-crypt-use-before-save-magic () (defun org-crypt-use-before-save-magic ()
"Add a hook to automatically encrypt entries before a file is saved to disk." "Add a hook to automatically encrypt entries before a file is saved to disk."
(add-hook (add-hook

View file

@ -51,11 +51,29 @@ Added time stamp is active unless value is `inactive'."
;;;###autoload ;;;###autoload
(defun org-datetree-find-date-create (d &optional keep-restriction) (defun org-datetree-find-date-create (d &optional keep-restriction)
"Find or create an entry for date D. "Find or create a day entry for date D.
If KEEP-RESTRICTION is non-nil, do not widen the buffer. If KEEP-RESTRICTION is non-nil, do not widen the buffer.
When it is nil, the buffer will be widened to make sure an existing date When it is nil, the buffer will be widened to make sure an existing date
tree can be found. If it is the symbol `subtree-at-point', then the tree tree can be found. If it is the symbol `subtree-at-point', then the tree
will be built under the headline at point." will be built under the headline at point."
(org-datetree--find-create-group d 'day keep-restriction))
;;;###autoload
(defun org-datetree-find-month-create (d &optional keep-restriction)
"Find or create a month entry for date D.
Compared to `org-datetree-find-date-create' this function creates
entries grouped by month instead of days.
If KEEP-RESTRICTION is non-nil, do not widen the buffer.
When it is nil, the buffer will be widened to make sure an existing date
tree can be found. If it is the symbol `subtree-at-point', then the tree
will be built under the headline at point."
(org-datetree--find-create-group d 'month keep-restriction))
(defun org-datetree--find-create-group
(d time-grouping &optional keep-restriction)
"Find or create an entry for date D.
If time-period is day, group entries by day. If time-period is
month, then group entries by month."
(setq-local org-datetree-base-level 1) (setq-local org-datetree-base-level 1)
(save-restriction (save-restriction
(if (eq keep-restriction 'subtree-at-point) (if (eq keep-restriction 'subtree-at-point)
@ -84,9 +102,10 @@ will be built under the headline at point."
(org-datetree--find-create (org-datetree--find-create
"^\\*+[ \t]+%d-\\([01][0-9]\\) \\w+$" "^\\*+[ \t]+%d-\\([01][0-9]\\) \\w+$"
year month) year month)
(org-datetree--find-create (when (eq time-grouping 'day)
"^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$" (org-datetree--find-create
year month day)))) "^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$"
year month day)))))
;;;###autoload ;;;###autoload
(defun org-datetree-find-iso-week-create (d &optional keep-restriction) (defun org-datetree-find-iso-week-create (d &optional keep-restriction)
@ -166,6 +185,8 @@ inserted into the buffer."
(defun org-datetree-insert-line (year &optional month day text) (defun org-datetree-insert-line (year &optional month day text)
(delete-region (save-excursion (skip-chars-backward " \t\n") (point)) (point)) (delete-region (save-excursion (skip-chars-backward " \t\n") (point)) (point))
(when (assq 'heading org-blank-before-new-entry)
(insert "\n"))
(insert "\n" (make-string org-datetree-base-level ?*) " \n") (insert "\n" (make-string org-datetree-base-level ?*) " \n")
(backward-char) (backward-char)
(when month (org-do-demote)) (when month (org-do-demote))

View file

@ -28,14 +28,16 @@
;; - 3:12 ;; - 3:12
;; - 1:23:45 ;; - 1:23:45
;; - 1y 3d 3h 4min ;; - 1y 3d 3h 4min
;; - 1d3h5min
;; - 3d 13:35 ;; - 3d 13:35
;; - 2.35h ;; - 2.35h
;; ;;
;; More accurately, it consists of numbers and units, as defined in ;; More accurately, it consists of numbers and units, as defined in
;; variable `org-duration-units', separated with white spaces, and ;; variable `org-duration-units', possibly separated with white
;; a "H:MM" or "H:MM:SS" part. White spaces are tolerated between the ;; spaces, and an optional "H:MM" or "H:MM:SS" part, which always
;; number and its relative unit. Variable `org-duration-format' ;; comes last. White spaces are tolerated between the number and its
;; controls durations default representation. ;; relative unit. Variable `org-duration-format' controls durations
;; default representation.
;; ;;
;; The library provides functions allowing to convert a duration to, ;; The library provides functions allowing to convert a duration to,
;; and from, a number of minutes: `org-duration-to-minutes' and ;; and from, a number of minutes: `org-duration-to-minutes' and
@ -122,8 +124,7 @@ are specified here.
Units with a zero value are skipped, unless REQUIRED? is non-nil. Units with a zero value are skipped, unless REQUIRED? is non-nil.
In that case, the unit is always used. In that case, the unit is always used.
Eventually, the list can contain one of the following special The list can also contain one of the following special entries:
entries:
(special . h:mm) (special . h:mm)
(special . h:mm:ss) (special . h:mm:ss)
@ -139,6 +140,10 @@ entries:
first one required or with a non-zero integer part. If there first one required or with a non-zero integer part. If there
is no such unit, the smallest one is used. is no such unit, the smallest one is used.
Eventually, if the list contains the symbol `compact', the
duration is expressed in a compact form, without any white space
between units.
For example, For example,
((\"d\" . nil) (\"h\" . t) (\"min\" . t)) ((\"d\" . nil) (\"h\" . t) (\"min\" . t))
@ -172,7 +177,6 @@ a 2-digits fractional part, of \"d\" unit. A duration shorter
than a day uses \"h\" unit instead." than a day uses \"h\" unit instead."
:group 'org-time :group 'org-time
:group 'org-clock :group 'org-clock
:version "26.1"
:package-version '(Org . "9.1") :package-version '(Org . "9.1")
:type '(choice :type '(choice
(const :tag "Use H:MM" h:mm) (const :tag "Use H:MM" h:mm)
@ -191,7 +195,8 @@ than a day uses \"h\" unit instead."
(const h:mm)) (const h:mm))
(cons :tag "Use both units and H:MM:SS" (cons :tag "Use both units and H:MM:SS"
(const special) (const special)
(const h:mm:ss)))))) (const h:mm:ss))
(const :tag "Use compact form" compact)))))
;;; Internal variables and functions ;;; Internal variables and functions
@ -249,13 +254,10 @@ When optional argument CANONICAL is non-nil, refer to
org-duration-units)) org-duration-units))
t))) t)))
(setq org-duration--full-re (setq org-duration--full-re
(format "\\`[ \t]*%s\\(?:[ \t]+%s\\)*[ \t]*\\'" (format "\\`\\(?:[ \t]*%s\\)+[ \t]*\\'" org-duration--unit-re))
org-duration--unit-re
org-duration--unit-re))
(setq org-duration--mixed-re (setq org-duration--mixed-re
(format "\\`[ \t]*\\(?1:%s\\(?:[ \t]+%s\\)*\\)[ \t]+\ (format "\\`\\(?1:\\([ \t]*%s\\)+\\)[ \t]*\
\\(?2:[0-9]+\\(?::[0-9][0-9]\\)\\{1,2\\}\\)[ \t]*\\'" \\(?2:[0-9]+\\(?::[0-9][0-9]\\)\\{1,2\\}\\)[ \t]*\\'"
org-duration--unit-re
org-duration--unit-re))) org-duration--unit-re)))
;;;###autoload ;;;###autoload
@ -353,10 +355,11 @@ Raise an error if expected format is unknown."
;; Represent minutes above hour using provided units and H:MM ;; Represent minutes above hour using provided units and H:MM
;; or H:MM:SS below. ;; or H:MM:SS below.
(let* ((units-part (* min-modifier (/ (floor minutes) min-modifier))) (let* ((units-part (* min-modifier (/ (floor minutes) min-modifier)))
(minutes-part (- minutes units-part))) (minutes-part (- minutes units-part))
(compact (memq 'compact duration-format)))
(concat (concat
(org-duration-from-minutes units-part truncated-format canonical) (org-duration-from-minutes units-part truncated-format canonical)
" " (and (not compact) " ")
(org-duration-from-minutes minutes-part mode)))))) (org-duration-from-minutes minutes-part mode))))))
;; Units format. ;; Units format.
(duration-format (duration-format
@ -368,12 +371,16 @@ Raise an error if expected format is unknown."
(format "%%.%df" digits)))) (format "%%.%df" digits))))
(selected-units (selected-units
(sort (cl-remove-if (sort (cl-remove-if
;; Ignore special format cells. ;; Ignore special format cells and compact option.
(lambda (pair) (pcase pair (`(special . ,_) t) (_ nil))) (lambda (pair)
(pcase pair
((or `compact `(special . ,_)) t)
(_ nil)))
duration-format) duration-format)
(lambda (a b) (lambda (a b)
(> (org-duration--modifier (car a) canonical) (> (org-duration--modifier (car a) canonical)
(org-duration--modifier (car b) canonical)))))) (org-duration--modifier (car b) canonical)))))
(separator (if (memq 'compact duration-format) "" " ")))
(cond (cond
;; Fractional duration: use first unit that is either required ;; Fractional duration: use first unit that is either required
;; or smaller than MINUTES. ;; or smaller than MINUTES.
@ -402,8 +409,8 @@ Raise an error if expected format is unknown."
(cond ((<= modifier minutes) (cond ((<= modifier minutes)
(let ((value (floor minutes modifier))) (let ((value (floor minutes modifier)))
(cl-decf minutes (* value modifier)) (cl-decf minutes (* value modifier))
(format " %d%s" value unit))) (format "%s%d%s" separator value unit)))
(required? (concat " 0" unit)) (required? (concat separator "0" unit))
(t "")))) (t ""))))
selected-units selected-units
"")))) ""))))
@ -441,4 +448,9 @@ with \"H:MM:SS\" format, return `h:mm:ss'. Otherwise, return
(org-duration-set-regexps) (org-duration-set-regexps)
(provide 'org-duration) (provide 'org-duration)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-duration.el ends here ;;; org-duration.el ends here

View file

@ -72,7 +72,6 @@
(declare-function org-at-heading-p "org" (&optional _)) (declare-function org-at-heading-p "org" (&optional _))
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading)) (declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
(declare-function org-escape-code-in-string "org-src" (s)) (declare-function org-escape-code-in-string "org-src" (s))
(declare-function org-find-visible "org" ())
(declare-function org-macro-escape-arguments "org-macro" (&rest args)) (declare-function org-macro-escape-arguments "org-macro" (&rest args))
(declare-function org-macro-extract-arguments "org-macro" (s)) (declare-function org-macro-extract-arguments "org-macro" (s))
(declare-function org-reduced-level "org" (l)) (declare-function org-reduced-level "org" (l))
@ -330,7 +329,9 @@ match group 2.
Don't modify it, set `org-element-affiliated-keywords' instead.") Don't modify it, set `org-element-affiliated-keywords' instead.")
(defconst org-element-object-restrictions (defconst org-element-object-restrictions
(let* ((standard-set (remq 'table-cell org-element-all-objects)) (let* ((minimal-set '(bold code entity italic latex-fragment strike-through
subscript superscript underline verbatim))
(standard-set (remq 'table-cell org-element-all-objects))
(standard-set-no-line-break (remq 'line-break standard-set))) (standard-set-no-line-break (remq 'line-break standard-set)))
`((bold ,@standard-set) `((bold ,@standard-set)
(footnote-reference ,@standard-set) (footnote-reference ,@standard-set)
@ -341,23 +342,20 @@ Don't modify it, set `org-element-affiliated-keywords' instead.")
(keyword ,@(remq 'footnote-reference standard-set)) (keyword ,@(remq 'footnote-reference standard-set))
;; Ignore all links in a link description. Also ignore ;; Ignore all links in a link description. Also ignore
;; radio-targets and line breaks. ;; radio-targets and line breaks.
(link bold code entity export-snippet inline-babel-call inline-src-block (link export-snippet inline-babel-call inline-src-block macro
italic latex-fragment macro statistics-cookie strike-through statistics-cookie ,@minimal-set)
subscript superscript underline verbatim)
(paragraph ,@standard-set) (paragraph ,@standard-set)
;; Remove any variable object from radio target as it would ;; Remove any variable object from radio target as it would
;; prevent it from being properly recognized. ;; prevent it from being properly recognized.
(radio-target bold code entity italic latex-fragment strike-through (radio-target ,@minimal-set)
subscript superscript underline superscript)
(strike-through ,@standard-set) (strike-through ,@standard-set)
(subscript ,@standard-set) (subscript ,@standard-set)
(superscript ,@standard-set) (superscript ,@standard-set)
;; Ignore inline babel call and inline source block as formulas ;; Ignore inline babel call and inline source block as formulas
;; are possible. Also ignore line breaks and statistics ;; are possible. Also ignore line breaks and statistics
;; cookies. ;; cookies.
(table-cell bold code entity export-snippet footnote-reference italic (table-cell export-snippet footnote-reference link macro radio-target
latex-fragment link macro radio-target strike-through target timestamp ,@minimal-set)
subscript superscript target timestamp underline verbatim)
(table-row table-cell) (table-row table-cell)
(underline ,@standard-set) (underline ,@standard-set)
(verse-block ,@standard-set))) (verse-block ,@standard-set)))
@ -367,10 +365,6 @@ key is an element or object type containing objects and value is
a list of types that can be contained within an element or object a list of types that can be contained within an element or object
of such type. of such type.
For example, in a `radio-target' object, one can only find
entities, latex-fragments, subscript, superscript and text
markup.
This alist also applies to secondary string. For example, an This alist also applies to secondary string. For example, an
`headline' type element doesn't directly contain objects, but `headline' type element doesn't directly contain objects, but
still has an entry since one of its properties (`:title') does.") still has an entry since one of its properties (`:title') does.")
@ -1806,13 +1800,10 @@ Return a list whose CAR is `clock' and CDR is a plist containing
;;;; Comment ;;;; Comment
(defun org-element-comment-parser (limit affiliated) (defun org-element-comment-parser (limit)
"Parse a comment. "Parse a comment.
LIMIT bounds the search. AFFILIATED is a list of which CAR is LIMIT bounds the search.
the buffer position at the beginning of the first affiliated
keyword and CDR is a plist of affiliated keywords along with
their value.
Return a list whose CAR is `comment' and CDR is a plist Return a list whose CAR is `comment' and CDR is a plist
containing `:begin', `:end', `:value', `:post-blank', containing `:begin', `:end', `:value', `:post-blank',
@ -1820,8 +1811,7 @@ containing `:begin', `:end', `:value', `:post-blank',
Assume point is at comment beginning." Assume point is at comment beginning."
(save-excursion (save-excursion
(let* ((begin (car affiliated)) (let* ((begin (point))
(post-affiliated (point))
(value (prog2 (looking-at "[ \t]*# ?") (value (prog2 (looking-at "[ \t]*# ?")
(buffer-substring-no-properties (buffer-substring-no-properties
(match-end 0) (line-end-position)) (match-end 0) (line-end-position))
@ -1843,13 +1833,11 @@ Assume point is at comment beginning."
(skip-chars-forward " \r\t\n" limit) (skip-chars-forward " \r\t\n" limit)
(if (eobp) (point) (line-beginning-position))))) (if (eobp) (point) (line-beginning-position)))))
(list 'comment (list 'comment
(nconc (list :begin begin
(list :begin begin :end end
:end end :value value
:value value :post-blank (count-lines com-end end)
:post-blank (count-lines com-end end) :post-affiliated begin)))))
:post-affiliated post-affiliated)
(cdr affiliated))))))
(defun org-element-comment-interpreter (comment _) (defun org-element-comment-interpreter (comment _)
"Interpret COMMENT element as Org syntax. "Interpret COMMENT element as Org syntax.
@ -2186,9 +2174,9 @@ the buffer position at the beginning of the first affiliated
keyword and CDR is a plist of affiliated keywords along with keyword and CDR is a plist of affiliated keywords along with
their value. their value.
Return a list whose CAR is `keyword' and CDR is a plist Return a list whose CAR is a normalized `keyword' (uppercase) and
containing `:key', `:value', `:begin', `:end', `:post-blank' and CDR is a plist containing `:key', `:value', `:begin', `:end',
`:post-affiliated' keywords." `:post-blank' and `:post-affiliated' keywords."
(save-excursion (save-excursion
;; An orphaned affiliated keyword is considered as a regular ;; An orphaned affiliated keyword is considered as a regular
;; keyword. In this case AFFILIATED is nil, so we take care of ;; keyword. In this case AFFILIATED is nil, so we take care of
@ -3217,10 +3205,11 @@ Assume point is at the beginning of the link."
(setq post-blank (setq post-blank
(progn (goto-char link-end) (skip-chars-forward " \t"))) (progn (goto-char link-end) (skip-chars-forward " \t")))
(setq end (point))) (setq end (point)))
;; Special "file" type link processing. Extract opening ;; Special "file"-type link processing. Extract opening
;; application and search option, if any. Also normalize URI. ;; application and search option, if any. Also normalize URI.
(when (string-match "\\`file\\(?:\\+\\(.+\\)\\)?\\'" type) (when (string-match "\\`file\\(?:\\+\\(.+\\)\\)?\\'" type)
(setq application (match-string 1 type) type "file") (setq application (match-string 1 type))
(setq type "file")
(when (string-match "::\\(.*\\)\\'" path) (when (string-match "::\\(.*\\)\\'" path)
(setq search-option (match-string 1 path)) (setq search-option (match-string 1 path))
(setq path (replace-match "" nil nil path))) (setq path (replace-match "" nil nil path)))
@ -3823,12 +3812,6 @@ Assume point is at the first equal sign marker."
;; `org-element--current-element' is the core function of this section. ;; `org-element--current-element' is the core function of this section.
;; It returns the Lisp representation of the element starting at ;; It returns the Lisp representation of the element starting at
;; point. ;; point.
;;
;; `org-element--current-element' makes use of special modes. They
;; are activated for fixed element chaining (e.g., `plain-list' >
;; `item') or fixed conditional element chaining (e.g., `headline' >
;; `section'). Special modes are: `first-section', `item',
;; `node-property', `section' and `table-row'.
(defun org-element--current-element (limit &optional granularity mode structure) (defun org-element--current-element (limit &optional granularity mode structure)
"Parse the element starting at point. "Parse the element starting at point.
@ -3848,8 +3831,9 @@ nil), secondary values will not be parsed, since they only
contain objects. contain objects.
Optional argument MODE, when non-nil, can be either Optional argument MODE, when non-nil, can be either
`first-section', `section', `planning', `item', `node-property' `first-section', `item', `node-property', `planning',
and `table-row'. `property-drawer', `section', `table-row', or `top-comment'.
If STRUCTURE isn't provided but MODE is set to `item', it will be If STRUCTURE isn't provided but MODE is set to `item', it will be
computed. computed.
@ -3879,15 +3863,22 @@ element it has to parse."
(org-element-section-parser (org-element-section-parser
(or (save-excursion (org-with-limited-levels (outline-next-heading))) (or (save-excursion (org-with-limited-levels (outline-next-heading)))
limit))) limit)))
;; Comments.
((looking-at "^[ \t]*#\\(?: \\|$\\)")
(org-element-comment-parser limit))
;; Planning. ;; Planning.
((and (eq mode 'planning) ((and (eq mode 'planning)
(eq ?* (char-after (line-beginning-position 0))) (eq ?* (char-after (line-beginning-position 0)))
(looking-at org-planning-line-re)) (looking-at org-planning-line-re))
(org-element-planning-parser limit)) (org-element-planning-parser limit))
;; Property drawer. ;; Property drawer.
((and (memq mode '(planning property-drawer)) ((and (pcase mode
(eq ?* (char-after (line-beginning-position (`planning (eq ?* (char-after (line-beginning-position 0))))
(if (eq mode 'planning) 0 -1)))) ((or `property-drawer `top-comment)
(save-excursion
(beginning-of-line 0)
(not (looking-at "[[:blank:]]*$"))))
(_ nil))
(looking-at org-property-drawer-re)) (looking-at org-property-drawer-re))
(org-element-property-drawer-parser limit)) (org-element-property-drawer-parser limit))
;; When not at bol, point is at the beginning of an item or ;; When not at bol, point is at the beginning of an item or
@ -3896,7 +3887,7 @@ element it has to parse."
;; Clock. ;; Clock.
((looking-at org-clock-line-re) (org-element-clock-parser limit)) ((looking-at org-clock-line-re) (org-element-clock-parser limit))
;; Inlinetask. ;; Inlinetask.
((org-at-heading-p) ((looking-at "^\\*+ ")
(org-element-inlinetask-parser limit raw-secondary-p)) (org-element-inlinetask-parser limit raw-secondary-p))
;; From there, elements can have affiliated keywords. ;; From there, elements can have affiliated keywords.
(t (let ((affiliated (org-element--collect-affiliated-keywords (t (let ((affiliated (org-element--collect-affiliated-keywords
@ -3910,7 +3901,7 @@ element it has to parse."
;; LaTeX Environment. ;; LaTeX Environment.
((looking-at org-element--latex-begin-environment) ((looking-at org-element--latex-begin-environment)
(org-element-latex-environment-parser limit affiliated)) (org-element-latex-environment-parser limit affiliated))
;; Drawer and Property Drawer. ;; Drawer.
((looking-at org-drawer-regexp) ((looking-at org-drawer-regexp)
(org-element-drawer-parser limit affiliated)) (org-element-drawer-parser limit affiliated))
;; Fixed Width ;; Fixed Width
@ -3918,13 +3909,10 @@ element it has to parse."
(org-element-fixed-width-parser limit affiliated)) (org-element-fixed-width-parser limit affiliated))
;; Inline Comments, Blocks, Babel Calls, Dynamic Blocks and ;; Inline Comments, Blocks, Babel Calls, Dynamic Blocks and
;; Keywords. ;; Keywords.
((looking-at "[ \t]*#") ((looking-at "[ \t]*#\\+")
(goto-char (match-end 0)) (goto-char (match-end 0))
(cond (cond
((looking-at "\\(?: \\|$\\)") ((looking-at "BEGIN_\\(\\S-+\\)")
(beginning-of-line)
(org-element-comment-parser limit affiliated))
((looking-at "\\+BEGIN_\\(\\S-+\\)")
(beginning-of-line) (beginning-of-line)
(funcall (pcase (upcase (match-string 1)) (funcall (pcase (upcase (match-string 1))
("CENTER" #'org-element-center-block-parser) ("CENTER" #'org-element-center-block-parser)
@ -3937,13 +3925,13 @@ element it has to parse."
(_ #'org-element-special-block-parser)) (_ #'org-element-special-block-parser))
limit limit
affiliated)) affiliated))
((looking-at "\\+CALL:") ((looking-at "CALL:")
(beginning-of-line) (beginning-of-line)
(org-element-babel-call-parser limit affiliated)) (org-element-babel-call-parser limit affiliated))
((looking-at "\\+BEGIN:? ") ((looking-at "BEGIN:? ")
(beginning-of-line) (beginning-of-line)
(org-element-dynamic-block-parser limit affiliated)) (org-element-dynamic-block-parser limit affiliated))
((looking-at "\\+\\S-+:") ((looking-at "\\S-+:")
(beginning-of-line) (beginning-of-line)
(org-element-keyword-parser limit affiliated)) (org-element-keyword-parser limit affiliated))
(t (t
@ -4024,7 +4012,8 @@ When PARSE is non-nil, values from keywords belonging to
(skip-chars-backward " \t") (skip-chars-backward " \t")
(point)))) (point))))
(if parsed? (if parsed?
(org-element--parse-objects beg end nil restrict) (save-match-data
(org-element--parse-objects beg end nil restrict))
(org-trim (buffer-substring-no-properties beg end))))) (org-trim (buffer-substring-no-properties beg end)))))
;; If KWD is a dual keyword, find its secondary value. ;; If KWD is a dual keyword, find its secondary value.
;; Maybe parse it. ;; Maybe parse it.
@ -4144,7 +4133,9 @@ If STRING is the empty string or nil, return nil."
(dolist (v local-variables) (dolist (v local-variables)
(ignore-errors (ignore-errors
(if (symbolp v) (makunbound v) (if (symbolp v) (makunbound v)
(set (make-local-variable (car v)) (cdr v))))) ;; Don't set file name to avoid mishandling hooks (bug#44524)
(unless (memq (car v) '(buffer-file-name buffer-file-truename))
(set (make-local-variable (car v)) (cdr v))))))
;; Transferring local variables may put the temporary buffer ;; Transferring local variables may put the temporary buffer
;; into a read-only state. Make sure we can insert STRING. ;; into a read-only state. Make sure we can insert STRING.
(let ((inhibit-read-only t)) (insert string)) (let ((inhibit-read-only t)) (insert string))
@ -4320,34 +4311,41 @@ looking into captions:
;; `org-element--object-lex' to find the next object in the current ;; `org-element--object-lex' to find the next object in the current
;; container. ;; container.
(defsubst org-element--next-mode (type parentp) (defsubst org-element--next-mode (mode type parent?)
"Return next special mode according to TYPE, or nil. "Return next mode according to current one.
TYPE is a symbol representing the type of an element or object
containing next element if PARENTP is non-nil, or before it MODE is a symbol representing the expectation about the next
otherwise. Modes can be either `first-section', `item', element or object. Meaningful values are `first-section',
`node-property', `planning', `property-drawer', `section', `item', `node-property', `planning', `property-drawer',
`table-row' or nil." `section', `table-row', `top-comment', and nil.
(if parentp
TYPE is the type of the current element or object.
If PARENT? is non-nil, assume the next element or object will be
located inside the current one. "
(if parent?
(pcase type (pcase type
(`headline 'section) (`headline 'section)
((and (guard (eq mode 'first-section)) `section) 'top-comment)
(`inlinetask 'planning) (`inlinetask 'planning)
(`plain-list 'item) (`plain-list 'item)
(`property-drawer 'node-property) (`property-drawer 'node-property)
(`section 'planning) (`section 'planning)
(`table 'table-row)) (`table 'table-row))
(pcase type (pcase mode
(`item 'item) (`item 'item)
(`node-property 'node-property) (`node-property 'node-property)
(`planning 'property-drawer) ((and `planning (guard (eq type 'planning))) 'property-drawer)
(`table-row 'table-row)))) (`table-row 'table-row)
((and `top-comment (guard (eq type 'comment))) 'property-drawer))))
(defun org-element--parse-elements (defun org-element--parse-elements
(beg end mode structure granularity visible-only acc) (beg end mode structure granularity visible-only acc)
"Parse elements between BEG and END positions. "Parse elements between BEG and END positions.
MODE prioritizes some elements over the others. It can be set to MODE prioritizes some elements over the others. It can be set to
`first-section', `section', `planning', `item', `node-property' `first-section', `item', `node-property', `planning',
or `table-row'. `property-drawer', `section', `table-row', `top-comment', or nil.
When value is `item', STRUCTURE will be used as the current list When value is `item', STRUCTURE will be used as the current list
structure. structure.
@ -4361,54 +4359,52 @@ elements.
Elements are accumulated into ACC." Elements are accumulated into ACC."
(save-excursion (save-excursion
(goto-char beg) (goto-char beg)
;; Visible only: skip invisible parts at the beginning of the
;; element.
(when (and visible-only (org-invisible-p2))
(goto-char (min (1+ (org-find-visible)) end)))
;; When parsing only headlines, skip any text before first one. ;; When parsing only headlines, skip any text before first one.
(when (and (eq granularity 'headline) (not (org-at-heading-p))) (when (and (eq granularity 'headline) (not (org-at-heading-p)))
(org-with-limited-levels (outline-next-heading))) (org-with-limited-levels (outline-next-heading)))
(let (elements) (let (elements)
(while (< (point) end) (while (< (point) end)
;; Find current element's type and parse it accordingly to ;; Visible only: skip invisible parts due to folding.
;; its category. (if (and visible-only (org-invisible-p nil t))
(let* ((element (org-element--current-element (progn
end granularity mode structure)) (goto-char (org-find-visible))
(type (org-element-type element)) (when (and (eolp) (not (eobp))) (forward-char)))
(cbeg (org-element-property :contents-begin element))) ;; Find current element's type and parse it accordingly to
(goto-char (org-element-property :end element)) ;; its category.
;; Visible only: skip invisible parts between siblings. (let* ((element (org-element--current-element
(when (and visible-only (org-invisible-p2)) end granularity mode structure))
(goto-char (min (1+ (org-find-visible)) end))) (type (org-element-type element))
;; Fill ELEMENT contents by side-effect. (cbeg (org-element-property :contents-begin element)))
(cond (goto-char (org-element-property :end element))
;; If element has no contents, don't modify it. ;; Fill ELEMENT contents by side-effect.
((not cbeg)) (cond
;; Greater element: parse it between `contents-begin' and ;; If element has no contents, don't modify it.
;; `contents-end'. Make sure GRANULARITY allows the ((not cbeg))
;; recursion, or ELEMENT is a headline, in which case going ;; Greater element: parse it between `contents-begin' and
;; inside is mandatory, in order to get sub-level headings. ;; `contents-end'. Ensure GRANULARITY allows recursion,
((and (memq type org-element-greater-elements) ;; or ELEMENT is a headline, in which case going inside
(or (memq granularity '(element object nil)) ;; is mandatory, in order to get sub-level headings.
(and (eq granularity 'greater-element) ((and (memq type org-element-greater-elements)
(eq type 'section)) (or (memq granularity '(element object nil))
(eq type 'headline))) (and (eq granularity 'greater-element)
(org-element--parse-elements (eq type 'section))
cbeg (org-element-property :contents-end element) (eq type 'headline)))
;; Possibly switch to a special mode. (org-element--parse-elements
(org-element--next-mode type t) cbeg (org-element-property :contents-end element)
(and (memq type '(item plain-list)) ;; Possibly switch to a special mode.
(org-element-property :structure element)) (org-element--next-mode mode type t)
granularity visible-only element)) (and (memq type '(item plain-list))
;; ELEMENT has contents. Parse objects inside, if (org-element-property :structure element))
;; GRANULARITY allows it. granularity visible-only element))
((memq granularity '(object nil)) ;; ELEMENT has contents. Parse objects inside, if
(org-element--parse-objects ;; GRANULARITY allows it.
cbeg (org-element-property :contents-end element) element ((memq granularity '(object nil))
(org-element-restriction type)))) (org-element--parse-objects
(push (org-element-put-property element :parent acc) elements) cbeg (org-element-property :contents-end element) element
;; Update mode. (org-element-restriction type))))
(setq mode (org-element--next-mode type nil)))) (push (org-element-put-property element :parent acc) elements)
;; Update mode.
(setq mode (org-element--next-mode mode type nil)))))
;; Return result. ;; Return result.
(apply #'org-element-set-contents acc (nreverse elements))))) (apply #'org-element-set-contents acc (nreverse elements)))))
@ -4498,15 +4494,21 @@ to an appropriate container (e.g., a paragraph)."
(and (memq 'latex-fragment restriction) (and (memq 'latex-fragment restriction)
(org-element-latex-fragment-parser))))) (org-element-latex-fragment-parser)))))
(?\[ (?\[
(if (eq (aref result 1) ?\[) (pcase (aref result 1)
(and (memq 'link restriction) ((and ?\[
(org-element-link-parser)) (guard (memq 'link restriction)))
(or (and (memq 'footnote-reference restriction) (org-element-link-parser))
(org-element-footnote-reference-parser)) ((and ?f
(and (memq 'timestamp restriction) (guard (memq 'footnote-reference restriction)))
(org-element-timestamp-parser)) (org-element-footnote-reference-parser))
(and (memq 'statistics-cookie restriction) ((and (or ?% ?/)
(org-element-statistics-cookie-parser))))) (guard (memq 'statistics-cookie restriction)))
(org-element-statistics-cookie-parser))
(_
(or (and (memq 'timestamp restriction)
(org-element-timestamp-parser))
(and (memq 'statistics-cookie restriction)
(org-element-statistics-cookie-parser))))))
;; This is probably a plain link. ;; This is probably a plain link.
(_ (and (memq 'link restriction) (_ (and (memq 'link restriction)
(org-element-link-parser))))))) (org-element-link-parser)))))))
@ -4821,10 +4823,12 @@ indentation removed from its contents."
;; ;;
;; A single public function is provided: `org-element-cache-reset'. ;; A single public function is provided: `org-element-cache-reset'.
;; ;;
;; Cache is enabled by default, but can be disabled globally with ;; Cache is disabled by default for now because it sometimes triggers
;; freezes, but it can be enabled globally with
;; `org-element-use-cache'. `org-element-cache-sync-idle-time', ;; `org-element-use-cache'. `org-element-cache-sync-idle-time',
;; org-element-cache-sync-duration' and `org-element-cache-sync-break' ;; `org-element-cache-sync-duration' and
;; can be tweaked to control caching behavior. ;; `org-element-cache-sync-break' can be tweaked to control caching
;; behavior.
;; ;;
;; Internally, parsed elements are stored in an AVL tree, ;; Internally, parsed elements are stored in an AVL tree,
;; `org-element--cache'. This tree is updated lazily: whenever ;; `org-element--cache'. This tree is updated lazily: whenever
@ -4892,7 +4896,7 @@ with `org-element--cache-compare'. This cache is used in
A request is a vector with the following pattern: A request is a vector with the following pattern:
\[NEXT BEG END OFFSET PARENT PHASE] [NEXT BEG END OFFSET PARENT PHASE]
Processing a synchronization request consists of three phases: Processing a synchronization request consists of three phases:
@ -5450,9 +5454,11 @@ the process stopped before finding the expected result."
;; element following headline above, or first element in ;; element following headline above, or first element in
;; buffer. ;; buffer.
((not cached) ((not cached)
(when (org-with-limited-levels (outline-previous-heading)) (if (org-with-limited-levels (outline-previous-heading))
(setq mode 'planning) (progn
(forward-line)) (setq mode 'planning)
(forward-line))
(setq mode 'top-comment))
(skip-chars-forward " \r\t\n") (skip-chars-forward " \r\t\n")
(beginning-of-line)) (beginning-of-line))
;; Cache returned exact match: return it. ;; Cache returned exact match: return it.
@ -5521,7 +5527,7 @@ the process stopped before finding the expected result."
;; after it. ;; after it.
((and (<= elem-end pos) (/= (point-max) elem-end)) ((and (<= elem-end pos) (/= (point-max) elem-end))
(goto-char elem-end) (goto-char elem-end)
(setq mode (org-element--next-mode type nil))) (setq mode (org-element--next-mode mode type nil)))
;; A non-greater element contains point: return it. ;; A non-greater element contains point: return it.
((not (memq type org-element-greater-elements)) ((not (memq type org-element-greater-elements))
(throw 'exit element)) (throw 'exit element))
@ -5549,7 +5555,7 @@ the process stopped before finding the expected result."
(and (= cend pos) (= (point-max) pos))))) (and (= cend pos) (= (point-max) pos)))))
(goto-char (or next cbeg)) (goto-char (or next cbeg))
(setq next nil (setq next nil
mode (org-element--next-mode type t) mode (org-element--next-mode mode type t)
parent element parent element
end cend)))) end cend))))
;; Otherwise, return ELEMENT as it is the smallest ;; Otherwise, return ELEMENT as it is the smallest
@ -5813,7 +5819,7 @@ element.
Possible types are defined in `org-element-all-elements'. Possible types are defined in `org-element-all-elements'.
Properties depend on element or object type, but always include Properties depend on element or object type, but always include
`:begin', `:end', `:parent' and `:post-blank' properties. `:begin', `:end', and `:post-blank' properties.
As a special case, if point is at the very beginning of the first As a special case, if point is at the very beginning of the first
item in a list or sub-list, returned element will be that list item in a list or sub-list, returned element will be that list

View file

@ -226,7 +226,7 @@ packages to be loaded, add these packages to `org-latex-packages-alist'."
("beth" "\\beth" t "&beth;" "beth" "beth" "ב") ("beth" "\\beth" t "&beth;" "beth" "beth" "ב")
("dalet" "\\daleth" t "&daleth;" "dalet" "dalet" "ד") ("dalet" "\\daleth" t "&daleth;" "dalet" "dalet" "ד")
"** Dead languages" "** Icelandic"
("ETH" "\\DH{}" nil "&ETH;" "D" "Ð" "Ð") ("ETH" "\\DH{}" nil "&ETH;" "D" "Ð" "Ð")
("eth" "\\dh{}" nil "&eth;" "dh" "ð" "ð") ("eth" "\\dh{}" nil "&eth;" "dh" "ð" "ð")
("THORN" "\\TH{}" nil "&THORN;" "TH" "Þ" "Þ") ("THORN" "\\TH{}" nil "&THORN;" "TH" "Þ" "Þ")
@ -386,7 +386,7 @@ packages to be loaded, add these packages to `org-latex-packages-alist'."
("exists" "\\exists" t "&exist;" "[there exists]" "[there exists]" "") ("exists" "\\exists" t "&exist;" "[there exists]" "[there exists]" "")
("nexist" "\\nexists" t "&exist;" "[there does not exists]" "[there does not exists]" "") ("nexist" "\\nexists" t "&exist;" "[there does not exists]" "[there does not exists]" "")
("nexists" "\\nexists" t "&exist;" "[there does not exists]" "[there does not exists]" "") ("nexists" "\\nexists" t "&exist;" "[there does not exists]" "[there does not exists]" "")
("empty" "\\empty" t "&empty;" "[empty set]" "[empty set]" "") ("empty" "\\emptyset" t "&empty;" "[empty set]" "[empty set]" "")
("emptyset" "\\emptyset" t "&empty;" "[empty set]" "[empty set]" "") ("emptyset" "\\emptyset" t "&empty;" "[empty set]" "[empty set]" "")
("isin" "\\in" t "&isin;" "[element of]" "[element of]" "") ("isin" "\\in" t "&isin;" "[element of]" "[element of]" "")
("in" "\\in" t "&isin;" "[element of]" "[element of]" "") ("in" "\\in" t "&isin;" "[element of]" "[element of]" "")

View file

@ -243,6 +243,15 @@ is of course immediately visible, but for example a passed deadline is
of the frame, for example." of the frame, for example."
:group 'org-faces) :group 'org-faces)
(defface org-headline-todo ;Copied from `font-lock-string-face'
'((((class color) (min-colors 16) (background light)) (:foreground "Red4"))
(((class color) (min-colors 16) (background dark)) (:foreground "Pink2"))
(((class color) (min-colors 8) (background light)) (:bold t)))
"Face used to indicate that a headline is marked as TODO.
This face is only used if `org-fontify-todo-headline' is set. If applies
to the part of the headline after the TODO keyword."
:group 'org-faces)
(defface org-headline-done ;Copied from `font-lock-string-face' (defface org-headline-done ;Copied from `font-lock-string-face'
'((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown")) '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
(((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon")) (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
@ -355,6 +364,12 @@ changes."
"Face used for tables." "Face used for tables."
:group 'org-faces) :group 'org-faces)
(defface org-table-header '((t :inherit org-table
:background "LightGray"
:foreground "Black"))
"Face for table header."
:group 'org-faces)
(defface org-formula (defface org-formula
'((((class color) (min-colors 88) (background light)) (:foreground "Firebrick")) '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
(((class color) (min-colors 88) (background dark)) (:foreground "chocolate1")) (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
@ -393,9 +408,17 @@ follows a #+DATE:, #+AUTHOR: or #+EMAIL: keyword."
"Face for #+TITLE:, #+AUTHOR:, #+EMAIL: and #+DATE: keywords." "Face for #+TITLE:, #+AUTHOR:, #+EMAIL: and #+DATE: keywords."
:group 'org-faces) :group 'org-faces)
(defface org-block '((t :inherit shadow)) (defface org-block `((t :inherit shadow
"Face text in #+begin ... #+end blocks. ,@(and (>= emacs-major-version 27) '(:extend t))))
For source-blocks `org-src-block-faces' takes precedence." "Face used for text inside various blocks.
It is always used for source blocks. You can refine what face
should be used depending on the source block language by setting,
`org-src-block-faces', which takes precedence.
When `org-fontify-quote-and-verse-blocks' is not nil, text inside
verse and quote blocks are fontified using the `org-verse' and
`org-quote' faces, which inherit from `org-block'."
:group 'org-faces :group 'org-faces
:version "26.1") :version "26.1")

View file

@ -22,27 +22,8 @@
;;; Code: ;;; Code:
(require 'org-macs) (require 'org)
(require 'org-compat) (require 'org-refile)
(declare-function org-at-heading-p "org" (&optional ignored))
(declare-function org-beginning-of-line "org" (&optional n))
(declare-function org-defkey "org" (keymap key def))
(declare-function org-mark-ring-push "org" (&optional pos buffer))
(declare-function org-overview "org" ())
(declare-function org-refile-check-position "org" (refile-pointer))
(declare-function org-refile-get-location "org" (&optional prompt default-buffer new-nodes))
(declare-function org-show-context "org" (&optional key))
(declare-function org-show-set-visibility "org" (detail))
(defvar org-complex-heading-regexp)
(defvar org-startup-align-all-tables)
(defvar org-startup-folded)
(defvar org-startup-truncated)
(defvar org-special-ctrl-a/e)
(defvar org-refile-target-verify-function)
(defvar org-refile-use-outline-path)
(defvar org-refile-targets)
(defvar org-goto-exit-command nil) (defvar org-goto-exit-command nil)
(defvar org-goto-map nil) (defvar org-goto-map nil)
@ -234,20 +215,15 @@ position or nil."
(and (get-buffer "*org-goto*") (kill-buffer "*org-goto*")) (and (get-buffer "*org-goto*") (kill-buffer "*org-goto*"))
(pop-to-buffer-same-window (pop-to-buffer-same-window
(condition-case nil (condition-case nil
(make-indirect-buffer (current-buffer) "*org-goto*") (make-indirect-buffer (current-buffer) "*org-goto*" t)
(error (make-indirect-buffer (current-buffer) "*org-goto*")))) (error (make-indirect-buffer (current-buffer) "*org-goto*" t))))
(let (temp-buffer-show-function temp-buffer-show-hook) (let (temp-buffer-show-function temp-buffer-show-hook)
(with-output-to-temp-buffer "*Org Help*" (with-output-to-temp-buffer "*Org Help*"
(princ (format help (if org-goto-auto-isearch (princ (format help (if org-goto-auto-isearch
" Just type for auto-isearch." " Just type for auto-isearch."
" n/p/f/b/u to navigate, q to quit."))))) " n/p/f/b/u to navigate, q to quit.")))))
(org-fit-window-to-buffer (get-buffer-window "*Org Help*")) (org-fit-window-to-buffer (get-buffer-window "*Org Help*"))
(setq buffer-read-only nil) (org-overview)
(let ((org-startup-truncated t)
(org-startup-folded nil)
(org-startup-align-all-tables nil))
(org-mode)
(org-overview))
(setq buffer-read-only t) (setq buffer-read-only t)
(if (and (boundp 'org-goto-start-pos) (if (and (boundp 'org-goto-start-pos)
(integer-or-marker-p org-goto-start-pos)) (integer-or-marker-p org-goto-start-pos))
@ -309,4 +285,8 @@ With a prefix argument, use the alternative interface: e.g., if
(provide 'org-goto) (provide 'org-goto)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-goto.el ends here ;;; org-goto.el ends here

View file

@ -90,7 +90,7 @@ It will be green even if it was done after the deadline."
:type 'boolean) :type 'boolean)
(defcustom org-habit-scheduled-past-days nil (defcustom org-habit-scheduled-past-days nil
"Value to use instead of `org-scheduled-past-days', for habits only. "Value to use instead of `org-scheduled-past-days', for habits only.
If nil, `org-scheduled-past-days' is used. If nil, `org-scheduled-past-days' is used.
@ -343,7 +343,10 @@ current time."
(if (and in-the-past-p (if (and in-the-past-p
(not last-done-date) (not last-done-date)
(not (< scheduled now))) (not (< scheduled now)))
'(org-habit-clear-face . org-habit-clear-future-face) (if (and all-done-dates (= (car all-done-dates) start))
;; This is the very first done of this habit.
'(org-habit-ready-face . org-habit-ready-future-face)
'(org-habit-clear-face . org-habit-clear-future-face))
(org-habit-get-faces (org-habit-get-faces
habit start habit start
(and in-the-past-p (and in-the-past-p
@ -409,7 +412,7 @@ current time."
'help-echo 'help-echo
(concat (format-time-string (concat (format-time-string
(org-time-stamp-format) (org-time-stamp-format)
(time-add starting (days-to-time (- start (time-to-days starting))))) (time-add starting (days-to-time (- start (time-to-days starting)))))
(if donep " DONE" "")) (if donep " DONE" ""))
graph)) graph))
(setq start (1+ start) (setq start (1+ start)
@ -436,7 +439,7 @@ current time."
habit habit
(time-subtract moment (days-to-time org-habit-preceding-days)) (time-subtract moment (days-to-time org-habit-preceding-days))
moment moment
(time-add moment (days-to-time org-habit-following-days)))))) (time-add moment (days-to-time org-habit-following-days))))))
(forward-line))))) (forward-line)))))
(defun org-habit-toggle-habits () (defun org-habit-toggle-habits ()

View file

@ -71,11 +71,11 @@
;;; Code: ;;; Code:
(require 'org) (require 'org)
(require 'org-refile)
(require 'ol) (require 'ol)
(declare-function message-make-fqdn "message" ()) (declare-function message-make-fqdn "message" ())
(declare-function org-goto-location "org-goto" (&optional _buf help)) (declare-function org-goto-location "org-goto" (&optional _buf help))
(declare-function org-link-set-parameters "ol" (type &rest rest))
;;; Customization ;;; Customization
@ -259,6 +259,11 @@ Create an ID if necessary."
(interactive) (interactive)
(org-kill-new (org-id-get nil 'create))) (org-kill-new (org-id-get nil 'create)))
(defvar org-id-overriding-file-name nil
"Tell `org-id-get' to use this as the file name when creating an ID.
This is useful when working with contents in a temporary buffer
that will be copied back to the original.")
;;;###autoload ;;;###autoload
(defun org-id-get (&optional pom create prefix) (defun org-id-get (&optional pom create prefix)
"Get the ID property of the entry at point-or-marker POM. "Get the ID property of the entry at point-or-marker POM.
@ -275,7 +280,9 @@ In any case, the ID of the entry is returned."
(create (create
(setq id (org-id-new prefix)) (setq id (org-id-new prefix))
(org-entry-put pom "ID" id) (org-entry-put pom "ID" id)
(org-id-add-location id (buffer-file-name (buffer-base-buffer))) (org-id-add-location id
(or org-id-overriding-file-name
(buffer-file-name (buffer-base-buffer))))
id))))) id)))))
;;;###autoload ;;;###autoload
@ -478,55 +485,64 @@ This will scan all agenda files, all associated archives, and all
files currently mentioned in `org-id-locations'. files currently mentioned in `org-id-locations'.
When FILES is given, scan also these files." When FILES is given, scan also these files."
(interactive) (interactive)
(if (not org-id-track-globally) (unless org-id-track-globally
(error "Please turn on `org-id-track-globally' if you want to track IDs") (error "Please turn on `org-id-track-globally' if you want to track IDs"))
(let* ((files (delete-dups (setq org-id-locations nil)
(mapcar #'file-truename (let* ((files
(append (delete-dups
;; Agenda files and all associated archives (mapcar #'file-truename
(org-agenda-files t org-id-search-archives) (cl-remove-if-not
;; Explicit extra files ;; Default `org-id-extra-files' value contains
(unless (symbolp org-id-extra-files) ;; `agenda-archives' symbol.
org-id-extra-files) #'stringp
;; All files known to have IDs (append
org-id-files ;; Agenda files and all associated archives.
;; function input (org-agenda-files t org-id-search-archives)
files)))) ;; Explicit extra files.
(nfiles (length files)) (if (symbolp org-id-extra-files)
ids seen-ids (ndup 0) (i 0) file-id-alist) (symbol-value org-id-extra-files)
(with-temp-buffer org-id-extra-files)
(delay-mode-hooks ;; All files known to have IDs.
(org-mode) org-id-files
(dolist (file files) ;; Additional files from function call.
(unless silent files)))))
(setq i (1+ i)) (nfiles (length files))
(message "Finding ID locations (%d/%d files): %s" (id-regexp
i nfiles file)) (rx (seq bol (0+ (any "\t ")) ":ID:" (1+ " ") (not (any " ")))))
(when (file-exists-p file) (seen-ids nil)
(insert-file-contents file nil nil nil 'replace) (ndup 0)
(setq ids (org-map-entries (i 0))
(lambda () (dolist (file files)
(org-entry-get (point) "ID")) (when (file-exists-p file)
"ID<>\"\"")) (unless silent
(dolist (id ids) (cl-incf i)
(if (member id seen-ids) (message "Finding ID locations (%d/%d files): %s" i nfiles file))
(progn (with-current-buffer (find-file-noselect file t)
(message "Duplicate ID \"%s\"" id) (let ((ids nil)
(setq ndup (1+ ndup))) (case-fold-search t))
(push id seen-ids))) (org-with-point-at 1
(while (re-search-forward id-regexp nil t)
(when (org-at-property-p)
(push (org-entry-get (point) "ID") ids)))
(when ids (when ids
(setq file-id-alist (cons (cons (abbreviate-file-name file) ids) (push (cons (abbreviate-file-name file) ids)
file-id-alist))))))) org-id-locations)
(setq org-id-locations file-id-alist) (dolist (id ids)
(setq org-id-files (mapcar 'car org-id-locations)) (cond
(org-id-locations-save) ((not (member id seen-ids)) (push id seen-ids))
;; now convert to a hash (silent nil)
(setq org-id-locations (org-id-alist-to-hash org-id-locations)) (t
(when (> ndup 0) (message "Duplicate ID %S" id)
(warn "WARNING: %d duplicate IDs found, check *Messages* buffer" ndup)) (cl-incf ndup))))))))))
(message "%d files scanned, %d files contains IDs and in total %d IDs found." (setq org-id-files (mapcar #'car org-id-locations))
nfiles (length org-id-files) (hash-table-count org-id-locations)) (org-id-locations-save)
org-id-locations))) ;; Now convert to a hash table.
(setq org-id-locations (org-id-alist-to-hash org-id-locations))
(when (and (not silent) (> ndup 0))
(warn "WARNING: %d duplicate IDs found, check *Messages* buffer" ndup))
(message "%d files scanned, %d files contains IDs, and %d IDs found."
nfiles (length org-id-files) (hash-table-count org-id-locations))
org-id-locations))
(defun org-id-locations-save () (defun org-id-locations-save ()
"Save `org-id-locations' in `org-id-locations-file'." "Save `org-id-locations' in `org-id-locations-file'."
@ -572,8 +588,10 @@ When FILES is given, scan also these files."
(defun org-id-add-location (id file) (defun org-id-add-location (id file)
"Add the ID with location FILE to the database of ID locations." "Add the ID with location FILE to the database of ID locations."
;; Only if global tracking is on, and when the buffer has a file ;; Only if global tracking is on, and when the buffer has a file
(unless file
(error "bug: org-id-get expects a file-visiting buffer"))
(let ((afile (abbreviate-file-name file))) (let ((afile (abbreviate-file-name file)))
(when (and org-id-track-globally id file) (when (and org-id-track-globally id)
(unless org-id-locations (org-id-locations-load)) (unless org-id-locations (org-id-locations-load))
(puthash id afile org-id-locations) (puthash id afile org-id-locations)
(unless (member afile org-id-files) (unless (member afile org-id-files)
@ -631,7 +649,7 @@ When FILES is given, scan also these files."
(or (and org-id-locations (or (and org-id-locations
(hash-table-p org-id-locations) (hash-table-p org-id-locations)
(gethash id org-id-locations)) (gethash id org-id-locations))
;; ball back on current buffer ;; Fall back on current buffer
(buffer-file-name (or (buffer-base-buffer (current-buffer)) (buffer-file-name (or (buffer-base-buffer (current-buffer))
(current-buffer))))) (current-buffer)))))
@ -665,8 +683,11 @@ optional argument MARKERP, return the position as a new marker."
(let* ((link (concat "id:" (org-id-get-create))) (let* ((link (concat "id:" (org-id-get-create)))
(case-fold-search nil) (case-fold-search nil)
(desc (save-excursion (desc (save-excursion
(org-back-to-heading t) (org-back-to-heading-or-point-min t)
(or (and (looking-at org-complex-heading-regexp) (or (and (org-before-first-heading-p)
(file-name-nondirectory
(buffer-file-name (buffer-base-buffer))))
(and (looking-at org-complex-heading-regexp)
(if (match-end 4) (if (match-end 4)
(match-string 4) (match-string 4)
(match-string 0))) (match-string 0)))
@ -674,7 +695,7 @@ optional argument MARKERP, return the position as a new marker."
(org-link-store-props :link link :description desc :type "id") (org-link-store-props :link link :description desc :type "id")
link))) link)))
(defun org-id-open (id) (defun org-id-open (id _)
"Go to the entry with id ID." "Go to the entry with id ID."
(org-mark-ring-push) (org-mark-ring-push)
(let ((m (org-id-find id 'marker)) (let ((m (org-id-find id 'marker))

View file

@ -71,8 +71,6 @@ Delay used when the buffer to initialize isn't current.")
(defvar org-indent--initial-marker nil (defvar org-indent--initial-marker nil
"Position of initialization before interrupt. "Position of initialization before interrupt.
This is used locally in each buffer being initialized.") This is used locally in each buffer being initialized.")
(defvar org-hide-leading-stars-before-indent-mode nil
"Used locally.")
(defvar org-indent-modified-headline-flag nil (defvar org-indent-modified-headline-flag nil
"Non-nil means the last deletion operated on a headline. "Non-nil means the last deletion operated on a headline.
It is modified by `org-indent-notify-modified-headline'.") It is modified by `org-indent-notify-modified-headline'.")
@ -178,10 +176,11 @@ during idle time."
(setq-local indent-tabs-mode nil) (setq-local indent-tabs-mode nil)
(setq-local org-indent--initial-marker (copy-marker 1)) (setq-local org-indent--initial-marker (copy-marker 1))
(when org-indent-mode-turns-off-org-adapt-indentation (when org-indent-mode-turns-off-org-adapt-indentation
(setq-local org-adapt-indentation nil)) ;; Don't turn off `org-adapt-indentation' when its value is
;; 'headline-data, just indent headline data specially.
(or (eq org-adapt-indentation 'headline-data)
(setq-local org-adapt-indentation nil)))
(when org-indent-mode-turns-on-hiding-stars (when org-indent-mode-turns-on-hiding-stars
(setq-local org-hide-leading-stars-before-indent-mode
org-hide-leading-stars)
(setq-local org-hide-leading-stars t)) (setq-local org-hide-leading-stars t))
(org-indent--compute-prefixes) (org-indent--compute-prefixes)
(if (boundp 'filter-buffer-substring-functions) (if (boundp 'filter-buffer-substring-functions)
@ -207,15 +206,14 @@ during idle time."
(setq org-indent-agent-timer (setq org-indent-agent-timer
(run-with-idle-timer 0.2 t #'org-indent-initialize-agent)))) (run-with-idle-timer 0.2 t #'org-indent-initialize-agent))))
(t (t
;; mode was turned off (or we refused to turn it on) ;; Mode was turned off (or we refused to turn it on)
(kill-local-variable 'org-adapt-indentation) (kill-local-variable 'org-adapt-indentation)
(setq org-indent-agentized-buffers (setq org-indent-agentized-buffers
(delq (current-buffer) org-indent-agentized-buffers)) (delq (current-buffer) org-indent-agentized-buffers))
(when (markerp org-indent--initial-marker) (when (markerp org-indent--initial-marker)
(set-marker org-indent--initial-marker nil)) (set-marker org-indent--initial-marker nil))
(when (boundp 'org-hide-leading-stars-before-indent-mode) (when (local-variable-p 'org-hide-leading-stars)
(setq-local org-hide-leading-stars (kill-local-variable 'org-hide-leading-stars))
org-hide-leading-stars-before-indent-mode))
(if (boundp 'filter-buffer-substring-functions) (if (boundp 'filter-buffer-substring-functions)
(remove-hook 'filter-buffer-substring-functions (remove-hook 'filter-buffer-substring-functions
(lambda (fun start end delete) (lambda (fun start end delete)
@ -365,7 +363,18 @@ stopped."
level (org-list-item-body-column (point)))) level (org-list-item-body-column (point))))
;; Regular line. ;; Regular line.
(t (t
(org-indent-set-line-properties level (current-indentation)))))))))) (org-indent-set-line-properties
level
(current-indentation)
;; When adapt indentation is 'headline-data, use
;; `org-indent--heading-line-prefixes' for setting
;; headline data indentation.
(and (eq org-adapt-indentation 'headline-data)
(or (org-at-planning-p)
(org-at-clock-log-p)
(looking-at-p org-property-start-re)
(looking-at-p org-property-end-re)
(looking-at-p org-property-re))))))))))))
(defun org-indent-notify-modified-headline (beg end) (defun org-indent-notify-modified-headline (beg end)
"Set `org-indent-modified-headline-flag' depending on context. "Set `org-indent-modified-headline-flag' depending on context.

View file

@ -56,7 +56,7 @@
(declare-function org-clone-subtree-with-time-shift "org" (n &optional shift)) (declare-function org-clone-subtree-with-time-shift "org" (n &optional shift))
(declare-function org-columns "org" (&optional global columns-fmt-string)) (declare-function org-columns "org" (&optional global columns-fmt-string))
(declare-function org-comment-dwim "org" (arg)) (declare-function org-comment-dwim "org" (arg))
(declare-function org-copy "org" ()) (declare-function org-refile-copy "org" ())
(declare-function org-copy-special "org" ()) (declare-function org-copy-special "org" ())
(declare-function org-copy-visible "org" (beg end)) (declare-function org-copy-visible "org" (beg end))
(declare-function org-ctrl-c-ctrl-c "org" (&optional arg)) (declare-function org-ctrl-c-ctrl-c "org" (&optional arg))
@ -148,7 +148,7 @@
(declare-function org-remove-file "org" (&optional file)) (declare-function org-remove-file "org" (&optional file))
(declare-function org-resolve-clocks "org" (&optional only-dangling-p prompt-fn last-valid)) (declare-function org-resolve-clocks "org" (&optional only-dangling-p prompt-fn last-valid))
(declare-function org-return "org" (&optional indent)) (declare-function org-return "org" (&optional indent))
(declare-function org-return-indent "org" ()) (declare-function org-return-and-maybe-indent "org" ())
(declare-function org-reveal "org" (&optional siblings)) (declare-function org-reveal "org" (&optional siblings))
(declare-function org-schedule "org" (arg &optional time)) (declare-function org-schedule "org" (arg &optional time))
(declare-function org-self-insert-command "org" (N)) (declare-function org-self-insert-command "org" (N))
@ -196,6 +196,7 @@
(declare-function org-todo "org" (&optional arg1)) (declare-function org-todo "org" (&optional arg1))
(declare-function org-toggle-archive-tag "org" (&optional find-done)) (declare-function org-toggle-archive-tag "org" (&optional find-done))
(declare-function org-toggle-checkbox "org" (&optional toggle-presence)) (declare-function org-toggle-checkbox "org" (&optional toggle-presence))
(declare-function org-toggle-radio-button "org" (&optional arg))
(declare-function org-toggle-comment "org" ()) (declare-function org-toggle-comment "org" ())
(declare-function org-toggle-fixed-width "org" ()) (declare-function org-toggle-fixed-width "org" ())
(declare-function org-toggle-inline-images "org" (&optional include-linked)) (declare-function org-toggle-inline-images "org" (&optional include-linked))
@ -218,7 +219,7 @@
;;; Variables ;;; Variables
(defvar org-mode-map (make-sparse-keymap) (defvar org-mode-map (make-sparse-keymap)
"Keymap fo Org mode.") "Keymap for Org mode.")
(defvaralias 'org-CUA-compatible 'org-replace-disputed-keys) (defvaralias 'org-CUA-compatible 'org-replace-disputed-keys)
@ -444,7 +445,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
;;;; TAB key with modifiers ;;;; TAB key with modifiers
(org-defkey org-mode-map (kbd "C-i") #'org-cycle) (org-defkey org-mode-map (kbd "C-i") #'org-cycle)
(org-defkey org-mode-map (kbd "<tab>") #'org-cycle) (org-defkey org-mode-map (kbd "<tab>") #'org-cycle)
(org-defkey org-mode-map (kbd "C-<tab>") #'org-force-cycle-archived) (org-defkey org-mode-map (kbd "C-c C-<tab>") #'org-force-cycle-archived)
;; Override text-mode binding to expose `complete-symbol' for ;; Override text-mode binding to expose `complete-symbol' for
;; pcomplete functionality. ;; pcomplete functionality.
(org-defkey org-mode-map (kbd "M-<tab>") nil) (org-defkey org-mode-map (kbd "M-<tab>") nil)
@ -580,7 +581,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
(org-defkey org-mode-map (kbd "C-c C-d") #'org-deadline) (org-defkey org-mode-map (kbd "C-c C-d") #'org-deadline)
(org-defkey org-mode-map (kbd "C-c ;") #'org-toggle-comment) (org-defkey org-mode-map (kbd "C-c ;") #'org-toggle-comment)
(org-defkey org-mode-map (kbd "C-c C-w") #'org-refile) (org-defkey org-mode-map (kbd "C-c C-w") #'org-refile)
(org-defkey org-mode-map (kbd "C-c M-w") #'org-copy) (org-defkey org-mode-map (kbd "C-c M-w") #'org-refile-copy)
(org-defkey org-mode-map (kbd "C-c /") #'org-sparse-tree) ;minor-mode reserved (org-defkey org-mode-map (kbd "C-c /") #'org-sparse-tree) ;minor-mode reserved
(org-defkey org-mode-map (kbd "C-c \\") #'org-match-sparse-tree) ;minor-mode r. (org-defkey org-mode-map (kbd "C-c \\") #'org-match-sparse-tree) ;minor-mode r.
(org-defkey org-mode-map (kbd "C-c RET") #'org-ctrl-c-ret) (org-defkey org-mode-map (kbd "C-c RET") #'org-ctrl-c-ret)
@ -617,7 +618,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
(org-defkey org-mode-map (kbd "C-c C-k") #'org-kill-note-or-show-branches) (org-defkey org-mode-map (kbd "C-c C-k") #'org-kill-note-or-show-branches)
(org-defkey org-mode-map (kbd "C-c #") #'org-update-statistics-cookies) (org-defkey org-mode-map (kbd "C-c #") #'org-update-statistics-cookies)
(org-defkey org-mode-map (kbd "RET") #'org-return) (org-defkey org-mode-map (kbd "RET") #'org-return)
(org-defkey org-mode-map (kbd "C-j") #'org-return-indent) (org-defkey org-mode-map (kbd "C-j") #'org-return-and-maybe-indent)
(org-defkey org-mode-map (kbd "C-c ?") #'org-table-field-info) (org-defkey org-mode-map (kbd "C-c ?") #'org-table-field-info)
(org-defkey org-mode-map (kbd "C-c SPC") #'org-table-blank-field) (org-defkey org-mode-map (kbd "C-c SPC") #'org-table-blank-field)
(org-defkey org-mode-map (kbd "C-c +") #'org-table-sum) (org-defkey org-mode-map (kbd "C-c +") #'org-table-sum)
@ -658,6 +659,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
(org-defkey org-mode-map (kbd "C-c C-x C-M-v") #'org-redisplay-inline-images) (org-defkey org-mode-map (kbd "C-c C-x C-M-v") #'org-redisplay-inline-images)
(org-defkey org-mode-map (kbd "C-c C-x \\") #'org-toggle-pretty-entities) (org-defkey org-mode-map (kbd "C-c C-x \\") #'org-toggle-pretty-entities)
(org-defkey org-mode-map (kbd "C-c C-x C-b") #'org-toggle-checkbox) (org-defkey org-mode-map (kbd "C-c C-x C-b") #'org-toggle-checkbox)
(org-defkey org-mode-map (kbd "C-c C-x C-r") #'org-toggle-radio-button)
(org-defkey org-mode-map (kbd "C-c C-x p") #'org-set-property) (org-defkey org-mode-map (kbd "C-c C-x p") #'org-set-property)
(org-defkey org-mode-map (kbd "C-c C-x P") #'org-set-property-and-value) (org-defkey org-mode-map (kbd "C-c C-x P") #'org-set-property-and-value)
(org-defkey org-mode-map (kbd "C-c C-x e") #'org-set-effort) (org-defkey org-mode-map (kbd "C-c C-x e") #'org-set-effort)
@ -923,6 +925,10 @@ a-list placed behind the generic `org-babel-key-prefix'.")
(interactive) (interactive)
(describe-bindings org-babel-key-prefix)) (describe-bindings org-babel-key-prefix))
(provide 'org-keys) (provide 'org-keys)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-keys.el ends here ;;; org-keys.el ends here

View file

@ -108,6 +108,7 @@
(require 'cl-lib) (require 'cl-lib)
(require 'ob) (require 'ob)
(require 'ol) (require 'ol)
(require 'org-attach)
(require 'org-macro) (require 'org-macro)
(require 'ox) (require 'ox)
@ -423,8 +424,10 @@ instead"
(defun org-lint-deprecated-header-syntax (ast) (defun org-lint-deprecated-header-syntax (ast)
(let* ((deprecated-babel-properties (let* ((deprecated-babel-properties
(mapcar (lambda (arg) (symbol-name (car arg))) ;; DIR is also used for attachments.
org-babel-common-header-args-w-values)) (delete "dir"
(mapcar (lambda (arg) (downcase (symbol-name (car arg))))
org-babel-common-header-args-w-values)))
(deprecated-re (deprecated-re
(format "\\`%s[ \t]" (regexp-opt deprecated-babel-properties t)))) (format "\\`%s[ \t]" (regexp-opt deprecated-babel-properties t))))
(org-element-map ast '(keyword node-property) (org-element-map ast '(keyword node-property)
@ -541,15 +544,16 @@ Use :header-args: instead"
(org-element-map ast 'drawer (org-element-map ast 'drawer
(lambda (d) (lambda (d)
(when (equal (org-element-property :drawer-name d) "PROPERTIES") (when (equal (org-element-property :drawer-name d) "PROPERTIES")
(let ((section (org-element-lineage d '(section)))) (let ((headline? (org-element-lineage d '(headline)))
(unless (org-element-map section 'property-drawer #'identity nil t) (before
(list (org-element-property :post-affiliated d) (mapcar #'org-element-type
(if (save-excursion (assq d (reverse (org-element-contents
(goto-char (org-element-property :post-affiliated d)) (org-element-property :parent d)))))))
(forward-line -1) (list (org-element-property :post-affiliated d)
(or (org-at-heading-p) (org-at-planning-p))) (if (or (and headline? (member before '(nil (planning))))
"Incorrect contents for PROPERTIES drawer" (and (null headline?) (member before '(nil (comment)))))
"Incorrect location for PROPERTIES drawer")))))))) "Incorrect contents for PROPERTIES drawer"
"Incorrect location for PROPERTIES drawer")))))))
(defun org-lint-invalid-effort-property (ast) (defun org-lint-invalid-effort-property (ast)
(org-element-map ast 'node-property (org-element-map ast 'node-property
@ -564,16 +568,23 @@ Use :header-args: instead"
(defun org-lint-link-to-local-file (ast) (defun org-lint-link-to-local-file (ast)
(org-element-map ast 'link (org-element-map ast 'link
(lambda (l) (lambda (l)
(when (equal "file" (org-element-property :type l)) (let ((type (org-element-property :type l)))
(let ((file (org-element-property :path l))) (pcase type
(and (not (file-remote-p file)) ((or "attachment" "file")
(not (file-exists-p file)) (let* ((path (org-element-property :path l))
(list (org-element-property :begin l) (file (if (string= type "file")
(format (if (org-element-lineage l '(link)) path
"Link to non-existent image file \"%s\"\ (org-with-point-at (org-element-property :begin l)
in link description" (org-attach-expand path)))))
"Link to non-existent local file \"%s\"") (and (not (file-remote-p file))
file)))))))) (not (file-exists-p file))
(list (org-element-property :begin l)
(format (if (org-element-lineage l '(link))
"Link to non-existent image file %S \
in description"
"Link to non-existent local file %S")
file)))))
(_ nil))))))
(defun org-lint-non-existent-setupfile-parameter (ast) (defun org-lint-non-existent-setupfile-parameter (ast)
(org-element-map ast 'keyword (org-element-map ast 'keyword
@ -793,15 +804,25 @@ Use \"export %s\" instead"
(let ((name (org-trim (match-string-no-properties 0))) (let ((name (org-trim (match-string-no-properties 0)))
(element (org-element-at-point))) (element (org-element-at-point)))
(pcase (org-element-type element) (pcase (org-element-type element)
((or `drawer `property-drawer) (`drawer
(goto-char (org-element-property :end element)) ;; Find drawer opening lines within non-empty drawers.
nil) (let ((end (org-element-property :contents-end element)))
(when end
(while (re-search-forward org-drawer-regexp end t)
(let ((n (org-trim (match-string-no-properties 0))))
(push (list (line-beginning-position)
(format "Possible misleading drawer entry %S" n))
reports))))
(goto-char (org-element-property :end element))))
(`property-drawer
(goto-char (org-element-property :end element)))
((or `comment-block `example-block `export-block `src-block ((or `comment-block `example-block `export-block `src-block
`verse-block) `verse-block)
nil) nil)
(_ (_
;; Find drawer opening lines outside of any drawer.
(push (list (line-beginning-position) (push (list (line-beginning-position)
(format "Possible incomplete drawer \"%s\"" name)) (format "Possible incomplete drawer %S" name))
reports))))) reports)))))
reports)) reports))
@ -1257,6 +1278,10 @@ ARG can also be a list of checker names, as symbols, to run."
(org-lint--display-reports (current-buffer) checkers) (org-lint--display-reports (current-buffer) checkers)
(message "Org linting process completed")))) (message "Org linting process completed"))))
(provide 'org-lint) (provide 'org-lint)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-lint.el ends here ;;; org-lint.el ends here

View file

@ -81,12 +81,12 @@
(require 'org-compat) (require 'org-compat)
(defvar org-M-RET-may-split-line) (defvar org-M-RET-may-split-line)
(defvar org-adapt-indentation)
(defvar org-auto-align-tags) (defvar org-auto-align-tags)
(defvar org-blank-before-new-entry) (defvar org-blank-before-new-entry)
(defvar org-clock-string) (defvar org-clock-string)
(defvar org-closed-string) (defvar org-closed-string)
(defvar org-deadline-string) (defvar org-deadline-string)
(defvar org-description-max-indent)
(defvar org-done-keywords) (defvar org-done-keywords)
(defvar org-drawer-regexp) (defvar org-drawer-regexp)
(defvar org-element-all-objects) (defvar org-element-all-objects)
@ -911,13 +911,13 @@ items, as returned by `org-list-prevs-alist'."
STRUCT is the list structure." STRUCT is the list structure."
(let* ((item-end (org-list-get-item-end item struct)) (let* ((item-end (org-list-get-item-end item struct))
(sub-struct (cdr (member (assq item struct) struct))) (sub-struct (cdr (member (assq item struct) struct)))
subtree) items)
(catch 'exit (catch :exit
(mapc (lambda (e) (pcase-dolist (`(,pos . ,_) sub-struct)
(let ((pos (car e))) (if (< pos item-end)
(if (< pos item-end) (push pos subtree) (throw 'exit nil)))) (push pos items)
sub-struct)) (throw :exit nil))))
(nreverse subtree))) (nreverse items)))
(defun org-list-get-all-items (item struct prevs) (defun org-list-get-all-items (item struct prevs)
"List all items in the same sub-list as ITEM. "List all items in the same sub-list as ITEM.
@ -1234,125 +1234,127 @@ after the bullet. Cursor will be after this text once the
function ends. function ends.
This function modifies STRUCT." This function modifies STRUCT."
(let ((case-fold-search t)) (let* ((case-fold-search t)
;; 1. Get information about list: ITEM containing POS, position of ;; Get information about list: ITEM containing POS, position
;; point with regards to item start (BEFOREP), blank lines ;; of point with regards to item start (BEFOREP), blank lines
;; number separating items (BLANK-NB), if we're allowed to ;; number separating items (BLANK-NB), if we're allowed to
;; (SPLIT-LINE-P). ;; (SPLIT-LINE-P).
(let* ((item (goto-char (catch :exit (item
(let ((inner-item 0)) (catch :exit
(pcase-dolist (`(,i . ,_) struct) (let ((i nil))
(cond (pcase-dolist (`(,start ,_ ,_ ,_ ,_ ,_ ,end) struct)
((= i pos) (throw :exit i)) (cond
((< i pos) (setq inner-item i)) ((> start pos) (throw :exit i))
(t (throw :exit inner-item)))) ((< end pos) nil) ;skip sub-lists before point
inner-item)))) (t (setq i start))))
(item-end (org-list-get-item-end item struct)) ;; If no suitable item is found, insert a sibling of the
(item-end-no-blank (org-list-get-item-end-before-blank item struct)) ;; last item in buffer.
(beforep (or i (caar (reverse struct))))))
(progn (item-end (org-list-get-item-end item struct))
(looking-at org-list-full-item-re) (item-end-no-blank (org-list-get-item-end-before-blank item struct))
(<= pos (beforep
(cond (progn
((not (match-beginning 4)) (match-end 0)) (goto-char item)
;; Ignore tag in a non-descriptive list. (looking-at org-list-full-item-re)
((save-match-data (string-match "[.)]" (match-string 1))) (<= pos
(match-beginning 4)) (cond
(t (save-excursion ((not (match-beginning 4)) (match-end 0))
(goto-char (match-end 4)) ;; Ignore tag in a non-descriptive list.
(skip-chars-forward " \t") ((save-match-data (string-match "[.)]" (match-string 1)))
(point))))))) (match-beginning 4))
(split-line-p (org-get-alist-option org-M-RET-may-split-line 'item)) (t (save-excursion
(blank-nb (org-list-separating-blank-lines-number (goto-char (match-end 4))
pos struct prevs)) (skip-chars-forward " \t")
;; 2. Build the new item to be created. Concatenate same (point)))))))
;; bullet as item, checkbox, text AFTER-BULLET if (split-line-p (org-get-alist-option org-M-RET-may-split-line 'item))
;; provided, and text cut from point to end of item (blank-nb (org-list-separating-blank-lines-number pos struct prevs))
;; (TEXT-CUT) to form item's BODY. TEXT-CUT depends on ;; Build the new item to be created. Concatenate same bullet
;; BEFOREP and SPLIT-LINE-P. The difference of size ;; as item, checkbox, text AFTER-BULLET if provided, and text
;; between what was cut and what was inserted in buffer ;; cut from point to end of item (TEXT-CUT) to form item's
;; is stored in SIZE-OFFSET. ;; BODY. TEXT-CUT depends on BEFOREP and SPLIT-LINE-P. The
(ind (org-list-get-ind item struct)) ;; difference of size between what was cut and what was
(ind-size (if indent-tabs-mode ;; inserted in buffer is stored in SIZE-OFFSET.
(+ (/ ind tab-width) (mod ind tab-width)) (ind (org-list-get-ind item struct))
ind)) (ind-size (if indent-tabs-mode
(bullet (org-list-bullet-string (org-list-get-bullet item struct))) (+ (/ ind tab-width) (mod ind tab-width))
(box (when checkbox "[ ]")) ind))
(text-cut (bullet (org-list-bullet-string (org-list-get-bullet item struct)))
(and (not beforep) split-line-p (box (and checkbox "[ ]"))
(progn (text-cut
(goto-char pos) (and (not beforep)
;; If POS is greater than ITEM-END, then point is split-line-p
;; in some white lines after the end of the list. (progn
;; Those must be removed, or they will be left, (goto-char pos)
;; stacking up after the list. ;; If POS is greater than ITEM-END, then point is in
(when (< item-end pos) ;; some white lines after the end of the list. Those
(delete-region (1- item-end) (point-at-eol))) ;; must be removed, or they will be left, stacking up
(skip-chars-backward " \r\t\n") ;; after the list.
(setq pos (point)) (when (< item-end pos)
(delete-and-extract-region pos item-end-no-blank)))) (delete-region (1- item-end) (point-at-eol)))
(body (concat bullet (when box (concat box " ")) after-bullet (skip-chars-backward " \r\t\n")
(and text-cut ;; Cut position is after any blank on the line.
(if (string-match "\\`[ \t]+" text-cut) (save-excursion
(replace-match "" t t text-cut) (skip-chars-forward " \t")
text-cut)))) (setq pos (point)))
(item-sep (make-string (1+ blank-nb) ?\n)) (delete-and-extract-region (point) item-end-no-blank))))
(item-size (+ ind-size (length body) (length item-sep))) (body
(size-offset (- item-size (length text-cut)))) (concat bullet
;; 4. Insert effectively item into buffer. (and box (concat box " "))
(goto-char item) after-bullet
(indent-to-column ind) (and text-cut
(insert body item-sep) (if (string-match "\\`[ \t]+" text-cut)
;; 5. Add new item to STRUCT. (replace-match "" t t text-cut)
(mapc (lambda (e) text-cut))))
(let ((p (car e)) (end (nth 6 e))) (item-sep (make-string (1+ blank-nb) ?\n))
(cond (item-size (+ ind-size (length body) (length item-sep)))
;; Before inserted item, positions don't change but (size-offset (- item-size (length text-cut))))
;; an item ending after insertion has its end shifted ;; Insert effectively item into buffer.
;; by SIZE-OFFSET. (goto-char item)
((< p item) (indent-to-column ind)
(when (> end item) (setcar (nthcdr 6 e) (+ end size-offset)))) (insert body item-sep)
;; Trivial cases where current item isn't split in ;; Add new item to STRUCT.
;; two. Just shift every item after new one by (dolist (e struct)
;; ITEM-SIZE. (let ((p (car e)) (end (nth 6 e)))
((or beforep (not split-line-p)) (cond
(setcar e (+ p item-size)) ;; Before inserted item, positions don't change but an item
(setcar (nthcdr 6 e) (+ end item-size))) ;; ending after insertion has its end shifted by SIZE-OFFSET.
;; Item is split in two: elements before POS are just ((< p item)
;; shifted by ITEM-SIZE. In the case item would end (when (> end item)
;; after split POS, ending is only shifted by (setcar (nthcdr 6 e) (+ end size-offset))))
;; SIZE-OFFSET. ;; Item where insertion happens may be split in two parts.
((< p pos) ;; In this case, move start by ITEM-SIZE and end by
(setcar e (+ p item-size)) ;; SIZE-OFFSET.
(if (< end pos) ((and (= p item) (not beforep) split-line-p)
(setcar (nthcdr 6 e) (+ end item-size)) (setcar e (+ p item-size))
(setcar (nthcdr 6 e) (+ end size-offset)))) (setcar (nthcdr 6 e) (+ end size-offset)))
;; Elements after POS are moved into new item. ;; Items starting after modified item fall into two
;; Length of ITEM-SEP has to be removed as ITEM-SEP ;; categories.
;; doesn't appear in buffer yet. ;;
((< p item-end) ;; If modified item was split, and current sub-item was
(setcar e (+ p size-offset (- item pos (length item-sep)))) ;; located after split point, it was moved to the new item:
(if (= end item-end) ;; the part between body start and split point (POS) was
(setcar (nthcdr 6 e) (+ item item-size)) ;; removed. So we compute the length of that part and shift
(setcar (nthcdr 6 e) ;; item's positions accordingly.
(+ end size-offset ;;
(- item pos (length item-sep)))))) ;; Otherwise, the item was simply shifted by SIZE-OFFSET.
;; Elements at ITEM-END or after are only shifted by ((and split-line-p (not beforep) (>= p pos) (<= p item-end-no-blank))
;; SIZE-OFFSET. (let ((offset (- pos item ind (length bullet) (length after-bullet))))
(t (setcar e (+ p size-offset)) (setcar e (- p offset))
(setcar (nthcdr 6 e) (+ end size-offset)))))) (setcar (nthcdr 6 e) (- end offset))))
struct) (t
(push (list item ind bullet nil box nil (+ item item-size)) struct) (setcar e (+ p size-offset))
(setq struct (sort struct (lambda (e1 e2) (< (car e1) (car e2))))) (setcar (nthcdr 6 e) (+ end size-offset))))))
;; 6. If not BEFOREP, new item must appear after ITEM, so (push (list item ind bullet nil box nil (+ item item-size)) struct)
;; exchange ITEM with the next item in list. Position cursor (setq struct (sort struct #'car-less-than-car))
;; after bullet, counter, checkbox, and label. ;; If not BEFOREP, new item must appear after ITEM, so exchange
(if beforep ;; ITEM with the next item in list. Position cursor after bullet,
(goto-char item) ;; counter, checkbox, and label.
(setq struct (org-list-swap-items item (+ item item-size) struct)) (if beforep
(goto-char (org-list-get-next-item (goto-char item)
item struct (org-list-prevs-alist struct)))) (setq struct (org-list-swap-items item (+ item item-size) struct))
struct))) (goto-char (org-list-get-next-item
item struct (org-list-prevs-alist struct))))
struct))
(defun org-list-delete-item (item struct) (defun org-list-delete-item (item struct)
"Remove ITEM from the list and return the new structure. "Remove ITEM from the list and return the new structure.
@ -1793,10 +1795,9 @@ This function modifies STRUCT."
;; There are boxes checked after an unchecked one: fix that. ;; There are boxes checked after an unchecked one: fix that.
(when (member "[X]" after-unchecked) (when (member "[X]" after-unchecked)
(let ((index (- (length struct) (length after-unchecked)))) (let ((index (- (length struct) (length after-unchecked))))
(mapc (lambda (e) (dolist (e (nthcdr index all-items))
(when (org-list-get-checkbox e struct) (when (org-list-get-checkbox e struct)
(org-list-set-checkbox e struct "[ ]"))) (org-list-set-checkbox e struct "[ ]")))
(nthcdr index all-items))
;; Verify once again the structure, without ORDERED. ;; Verify once again the structure, without ORDERED.
(org-list-struct-fix-box struct parents prevs nil) (org-list-struct-fix-box struct parents prevs nil)
;; Return blocking item. ;; Return blocking item.
@ -1807,24 +1808,22 @@ This function modifies STRUCT."
This function modifies STRUCT." This function modifies STRUCT."
(let (end-list acc-end) (let (end-list acc-end)
(mapc (lambda (e) (pcase-dolist (`(,pos . ,_) struct)
(let* ((pos (car e)) (let ((ind-pos (org-list-get-ind pos struct))
(ind-pos (org-list-get-ind pos struct)) (end-pos (org-list-get-item-end pos struct)))
(end-pos (org-list-get-item-end pos struct))) (unless (assq end-pos struct)
(unless (assq end-pos struct) ;; To determine real ind of an ending position that is not
;; To determine real ind of an ending position that is ;; at an item, we have to find the item it belongs to: it is
;; not at an item, we have to find the item it belongs ;; the last item (ITEM-UP), whose ending is further than the
;; to: it is the last item (ITEM-UP), whose ending is ;; position we're interested in.
;; further than the position we're interested in. (let ((item-up (assoc-default end-pos acc-end #'>)))
(let ((item-up (assoc-default end-pos acc-end '>))) (push (cons
(push (cons ;; Else part is for the bottom point.
;; Else part is for the bottom point. (if item-up (+ (org-list-get-ind item-up struct) 2) 0)
(if item-up (+ (org-list-get-ind item-up struct) 2) 0) end-pos)
end-pos) end-list)))
end-list))) (push (cons ind-pos pos) end-list)
(push (cons ind-pos pos) end-list) (push (cons end-pos pos) acc-end)))
(push (cons end-pos pos) acc-end)))
struct)
(setq end-list (sort end-list (lambda (e1 e2) (< (cdr e1) (cdr e2))))) (setq end-list (sort end-list (lambda (e1 e2) (< (cdr e1) (cdr e2)))))
(org-list-struct-assoc-end struct end-list))) (org-list-struct-assoc-end struct end-list)))
@ -2021,10 +2020,9 @@ beginning of the item."
(item (copy-marker (point-at-bol))) (item (copy-marker (point-at-bol)))
(all (org-list-get-all-items (marker-position item) struct prevs)) (all (org-list-get-all-items (marker-position item) struct prevs))
(value init-value)) (value init-value))
(mapc (lambda (e) (dolist (e (nreverse all))
(goto-char e) (goto-char e)
(setq value (apply function value args))) (setq value (apply function value args)))
(nreverse all))
(goto-char item) (goto-char item)
(move-marker item nil) (move-marker item nil)
value)) value))
@ -2046,9 +2044,8 @@ Possible values are: `folded', `children' or `subtree'. See
;; Then fold every child. ;; Then fold every child.
(let* ((parents (org-list-parents-alist struct)) (let* ((parents (org-list-parents-alist struct))
(children (org-list-get-children item struct parents))) (children (org-list-get-children item struct parents)))
(mapc (lambda (e) (dolist (child children)
(org-list-set-item-visibility e struct 'folded)) (org-list-set-item-visibility child struct 'folded))))
children)))
((eq view 'subtree) ((eq view 'subtree)
;; Show everything ;; Show everything
(let ((item-end (org-list-get-item-end item struct))) (let ((item-end (org-list-get-item-end item struct)))
@ -2303,6 +2300,56 @@ is an integer, 0 means `-', 1 means `+' etc. If WHICH is
(org-list-struct-fix-ind struct parents) (org-list-struct-fix-ind struct parents)
(org-list-struct-apply-struct struct old-struct))))) (org-list-struct-apply-struct struct old-struct)))))
;;;###autoload
(define-minor-mode org-list-checkbox-radio-mode
"When turned on, use list checkboxes as radio buttons."
nil " CheckBoxRadio" nil
(unless (eq major-mode 'org-mode)
(user-error "Cannot turn this mode outside org-mode buffers")))
(defun org-toggle-radio-button (&optional arg)
"Toggle off all checkboxes and toggle on the one at point."
(interactive "P")
(if (not (org-at-item-p))
(user-error "Cannot toggle checkbox outside of a list")
(let* ((cpos (org-in-item-p))
(struct (org-list-struct))
(orderedp (org-entry-get nil "ORDERED"))
(parents (org-list-parents-alist struct))
(old-struct (copy-tree struct))
(cbox (org-list-get-checkbox cpos struct))
(prevs (org-list-prevs-alist struct))
(start (org-list-get-list-begin (point-at-bol) struct prevs))
(new (unless (and cbox (equal arg '(4)) (equal start cpos))
"[ ]")))
(dolist (pos (org-list-get-all-items
start struct (org-list-prevs-alist struct)))
(org-list-set-checkbox pos struct new))
(when new
(org-list-set-checkbox
cpos struct
(cond ((equal arg '(4)) (unless cbox "[ ]"))
((equal arg '(16)) (unless cbox "[-]"))
(t (if (equal cbox "[X]") "[ ]" "[X]")))))
(org-list-struct-fix-box struct parents prevs orderedp)
(org-list-struct-apply-struct struct old-struct)
(org-update-checkbox-count-maybe))))
(defun org-at-radio-list-p ()
"Is point at a list item with radio buttons?"
(when (org-match-line (org-item-re)) ;short-circuit
(let* ((e (save-excursion (beginning-of-line) (org-element-at-point))))
;; Check we're really on a line with a bullet.
(when (memq (org-element-type e) '(item plain-list))
;; Look for ATTR_ORG attribute in the current plain list.
(let ((plain-list (org-element-lineage e '(plain-list) t)))
(org-with-point-at (org-element-property :post-affiliated plain-list)
(let ((case-fold-search t)
(regexp "^[ \t]*#\\+attr_org:.* :radio \\(\\S-+\\)")
(begin (org-element-property :begin plain-list)))
(and (re-search-backward regexp begin t)
(not (string-equal "nil" (match-string 1)))))))))))
(defun org-toggle-checkbox (&optional toggle-presence) (defun org-toggle-checkbox (&optional toggle-presence)
"Toggle the checkbox in the current line. "Toggle the checkbox in the current line.
@ -2317,92 +2364,94 @@ If point is on a headline, apply this to all checkbox items in
the text below the heading, taking as reference the first item in the text below the heading, taking as reference the first item in
subtree, ignoring planning line and any drawer following it." subtree, ignoring planning line and any drawer following it."
(interactive "P") (interactive "P")
(save-excursion (if (org-at-radio-list-p)
(let* (singlep (org-toggle-radio-button toggle-presence)
block-item (save-excursion
lim-up (let* (singlep
lim-down block-item
(orderedp (org-entry-get nil "ORDERED")) lim-up
(_bounds lim-down
;; In a region, start at first item in region. (orderedp (org-entry-get nil "ORDERED"))
(_bounds
;; In a region, start at first item in region.
(cond
((org-region-active-p)
(let ((limit (region-end)))
(goto-char (region-beginning))
(if (org-list-search-forward (org-item-beginning-re) limit t)
(setq lim-up (point-at-bol))
(error "No item in region"))
(setq lim-down (copy-marker limit))))
((org-at-heading-p)
;; On a heading, start at first item after drawers and
;; time-stamps (scheduled, etc.).
(let ((limit (save-excursion (outline-next-heading) (point))))
(org-end-of-meta-data t)
(if (org-list-search-forward (org-item-beginning-re) limit t)
(setq lim-up (point-at-bol))
(error "No item in subtree"))
(setq lim-down (copy-marker limit))))
;; Just one item: set SINGLEP flag.
((org-at-item-p)
(setq singlep t)
(setq lim-up (point-at-bol)
lim-down (copy-marker (point-at-eol))))
(t (error "Not at an item or heading, and no active region"))))
;; Determine the checkbox going to be applied to all items
;; within bounds.
(ref-checkbox
(progn
(goto-char lim-up)
(let ((cbox (and (org-at-item-checkbox-p) (match-string 1))))
(cond
((equal toggle-presence '(16)) "[-]")
((equal toggle-presence '(4))
(unless cbox "[ ]"))
((equal "[X]" cbox) "[ ]")
(t "[X]"))))))
;; When an item is found within bounds, grab the full list at
;; point structure, then: (1) set check-box of all its items
;; within bounds to REF-CHECKBOX, (2) fix check-boxes of the
;; whole list, (3) move point after the list.
(goto-char lim-up)
(while (and (< (point) lim-down)
(org-list-search-forward (org-item-beginning-re)
lim-down 'move))
(let* ((struct (org-list-struct))
(struct-copy (copy-tree struct))
(parents (org-list-parents-alist struct))
(prevs (org-list-prevs-alist struct))
(bottom (copy-marker (org-list-get-bottom-point struct)))
(items-to-toggle (cl-remove-if
(lambda (e) (or (< e lim-up) (> e lim-down)))
(mapcar #'car struct))))
(dolist (e items-to-toggle)
(org-list-set-checkbox
e struct
;; If there is no box at item, leave as-is unless
;; function was called with C-u prefix.
(let ((cur-box (org-list-get-checkbox e struct)))
(if (or cur-box (equal toggle-presence '(4)))
ref-checkbox
cur-box))))
(setq block-item (org-list-struct-fix-box
struct parents prevs orderedp))
;; Report some problems due to ORDERED status of subtree.
;; If only one box was being checked, throw an error, else,
;; only signal problems.
(cond (cond
((org-region-active-p) ((and singlep block-item (> lim-up block-item))
(let ((limit (region-end))) (error
(goto-char (region-beginning)) "Checkbox blocked because of unchecked box at line %d"
(if (org-list-search-forward (org-item-beginning-re) limit t) (org-current-line block-item)))
(setq lim-up (point-at-bol)) (block-item
(error "No item in region")) (message
(setq lim-down (copy-marker limit)))) "Checkboxes were removed due to unchecked box at line %d"
((org-at-heading-p) (org-current-line block-item))))
;; On a heading, start at first item after drawers and (goto-char bottom)
;; time-stamps (scheduled, etc.). (move-marker bottom nil)
(let ((limit (save-excursion (outline-next-heading) (point)))) (org-list-struct-apply-struct struct struct-copy)))
(org-end-of-meta-data t) (move-marker lim-down nil))))
(if (org-list-search-forward (org-item-beginning-re) limit t)
(setq lim-up (point-at-bol))
(error "No item in subtree"))
(setq lim-down (copy-marker limit))))
;; Just one item: set SINGLEP flag.
((org-at-item-p)
(setq singlep t)
(setq lim-up (point-at-bol)
lim-down (copy-marker (point-at-eol))))
(t (error "Not at an item or heading, and no active region"))))
;; Determine the checkbox going to be applied to all items
;; within bounds.
(ref-checkbox
(progn
(goto-char lim-up)
(let ((cbox (and (org-at-item-checkbox-p) (match-string 1))))
(cond
((equal toggle-presence '(16)) "[-]")
((equal toggle-presence '(4))
(unless cbox "[ ]"))
((equal "[X]" cbox) "[ ]")
(t "[X]"))))))
;; When an item is found within bounds, grab the full list at
;; point structure, then: (1) set check-box of all its items
;; within bounds to REF-CHECKBOX, (2) fix check-boxes of the
;; whole list, (3) move point after the list.
(goto-char lim-up)
(while (and (< (point) lim-down)
(org-list-search-forward (org-item-beginning-re)
lim-down 'move))
(let* ((struct (org-list-struct))
(struct-copy (copy-tree struct))
(parents (org-list-parents-alist struct))
(prevs (org-list-prevs-alist struct))
(bottom (copy-marker (org-list-get-bottom-point struct)))
(items-to-toggle (cl-remove-if
(lambda (e) (or (< e lim-up) (> e lim-down)))
(mapcar #'car struct))))
(mapc (lambda (e) (org-list-set-checkbox
e struct
;; If there is no box at item, leave as-is
;; unless function was called with C-u prefix.
(let ((cur-box (org-list-get-checkbox e struct)))
(if (or cur-box (equal toggle-presence '(4)))
ref-checkbox
cur-box))))
items-to-toggle)
(setq block-item (org-list-struct-fix-box
struct parents prevs orderedp))
;; Report some problems due to ORDERED status of subtree.
;; If only one box was being checked, throw an error, else,
;; only signal problems.
(cond
((and singlep block-item (> lim-up block-item))
(error
"Checkbox blocked because of unchecked box at line %d"
(org-current-line block-item)))
(block-item
(message
"Checkboxes were removed due to unchecked box at line %d"
(org-current-line block-item))))
(goto-char bottom)
(move-marker bottom nil)
(org-list-struct-apply-struct struct struct-copy)))
(move-marker lim-down nil)))
(org-update-checkbox-count-maybe)) (org-update-checkbox-count-maybe))
(defun org-reset-checkbox-state-subtree () (defun org-reset-checkbox-state-subtree ()
@ -2632,10 +2681,9 @@ Return t if successful."
(org-list-bullet-string "-"))) (org-list-bullet-string "-")))
;; Shift every item by OFFSET and fix bullets. Then ;; Shift every item by OFFSET and fix bullets. Then
;; apply changes to buffer. ;; apply changes to buffer.
(mapc (lambda (e) (pcase-dolist (`(,pos . ,_) struct)
(let ((ind (org-list-get-ind (car e) struct))) (let ((ind (org-list-get-ind pos struct)))
(org-list-set-ind (car e) struct (+ ind offset)))) (org-list-set-ind pos struct (+ ind offset))))
struct)
(org-list-struct-fix-bul struct prevs) (org-list-struct-fix-bul struct prevs)
(org-list-struct-apply-struct struct old-struct)))) (org-list-struct-apply-struct struct old-struct))))
;; Forbidden move: ;; Forbidden move:
@ -2733,51 +2781,83 @@ If a region is active, all items inside will be moved."
(t (error "Not at an item"))))) (t (error "Not at an item")))))
(defvar org-tab-ind-state) (defvar org-tab-ind-state)
(defvar org-adapt-indentation)
(defun org-cycle-item-indentation () (defun org-cycle-item-indentation ()
"Cycle levels of indentation of an empty item. "Cycle levels of indentation of an empty item.
The first run indents the item, if applicable. Subsequent runs The first run indents the item, if applicable. Subsequent runs
outdent it at meaningful levels in the list. When done, item is outdent it at meaningful levels in the list. When done, item is
put back at its original position with its original bullet. put back at its original position with its original bullet.
Return t at each successful move." Return t at each successful move."
(when (org-at-item-p) (when (org-at-item-p)
(let* ((org-adapt-indentation nil) (let* ((struct (org-list-struct))
(struct (org-list-struct)) (item (line-beginning-position))
(ind (org-list-get-ind (point-at-bol) struct)) (ind (org-list-get-ind item struct)))
(bullet (org-trim (buffer-substring (point-at-bol) (point-at-eol)))))
;; Accept empty items or if cycle has already started. ;; Accept empty items or if cycle has already started.
(when (or (eq last-command 'org-cycle-item-indentation) (when (or (eq last-command 'org-cycle-item-indentation)
(and (save-excursion (and (org-match-line org-list-full-item-re)
(beginning-of-line) (>= (match-end 0)
(looking-at org-list-full-item-re)) (save-excursion
(>= (match-end 0) (save-excursion (goto-char (org-list-get-item-end item struct))
(goto-char (org-list-get-item-end (skip-chars-backward " \t\n")
(point-at-bol) struct)) (point)))))
(skip-chars-backward " \r\t\n")
(point)))))
(setq this-command 'org-cycle-item-indentation) (setq this-command 'org-cycle-item-indentation)
;; When in the middle of the cycle, try to outdent first. If (let ((prevs (org-list-prevs-alist struct))
;; it fails, and point is still at initial position, indent. (parents (org-list-parents-alist struct)))
;; Else, re-create it at its original position. (if (eq last-command 'org-cycle-item-indentation)
(if (eq last-command 'org-cycle-item-indentation) ;; When in the middle of the cycle, try to outdent. If
;; it fails, move point back to its initial position and
;; reset cycle.
(pcase-let ((`(,old-ind . ,old-bul) org-tab-ind-state)
(allow-outdent
(lambda (struct prevs parents)
;; Non-nil if current item can be
;; outdented.
(and (not (org-list-get-next-item item nil prevs))
(not (org-list-has-child-p item struct))
(org-list-get-parent item struct parents)))))
(cond
((and (> ind old-ind)
(org-list-get-prev-item item nil prevs))
(org-list-indent-item-generic 1 t struct))
((and (< ind old-ind)
(funcall allow-outdent struct prevs parents))
(org-list-indent-item-generic -1 t struct))
(t
(delete-region (line-beginning-position) (line-end-position))
(indent-to-column old-ind)
(insert old-bul " ")
(let* ((struct (org-list-struct))
(parents (org-list-parents-alist struct)))
(if (and (> ind old-ind)
;; We were previously indenting item. It
;; is no longer possible. Try to outdent
;; from initial position.
(funcall allow-outdent
struct
(org-list-prevs-alist struct)
parents))
(org-list-indent-item-generic -1 t struct)
(org-list-write-struct struct parents)
;; Start cycle over.
(setq this-command 'identity)
t)))))
;; If a cycle is starting, remember initial indentation
;; and bullet, then try to indent. If it fails, try to
;; outdent.
(setq org-tab-ind-state
(cons ind (org-trim (org-current-line-string))))
(cond (cond
((ignore-errors (org-list-indent-item-generic -1 t struct))) ((org-list-get-prev-item item nil prevs)
((and (= ind (car org-tab-ind-state)) (org-list-indent-item-generic 1 t struct))
(ignore-errors (org-list-indent-item-generic 1 t struct)))) ((and (not (org-list-get-next-item item nil prevs))
(t (delete-region (point-at-bol) (point-at-eol)) (org-list-get-parent item struct parents))
(indent-to-column (car org-tab-ind-state)) (org-list-indent-item-generic -1 t struct))
(insert (cdr org-tab-ind-state) " ") (t
;; Break cycle ;; This command failed. So will the following one.
(setq this-command 'identity))) ;; There's no point in starting the cycle.
;; If a cycle is starting, remember indentation and bullet, (setq this-command 'identity)
;; then try to indent. If it fails, try to outdent. (user-error "Cannot move item")))))))))
(setq org-tab-ind-state (cons ind bullet))
(cond
((ignore-errors (org-list-indent-item-generic 1 t struct)))
((ignore-errors (org-list-indent-item-generic -1 t struct)))
(t (user-error "Cannot move item"))))
t))))
(defun org-sort-list (defun org-sort-list
(&optional with-case sorting-type getkey-func compare-func interactive?) (&optional with-case sorting-type getkey-func compare-func interactive?)
@ -2794,8 +2874,8 @@ if the current locale allows for it.
The command prompts for the sorting type unless it has been given The command prompts for the sorting type unless it has been given
to the function through the SORTING-TYPE argument, which needs to to the function through the SORTING-TYPE argument, which needs to
be a character, \(?n ?N ?a ?A ?t ?T ?f ?F ?x ?X). Here is the be a character, among ?n ?N ?a ?A ?t ?T ?f ?F ?x or ?X. Here is
detailed meaning of each character: the detailed meaning of each character:
n Numerically, by converting the beginning of the item to a number. n Numerically, by converting the beginning of the item to a number.
a Alphabetically. Only the first line of item is checked. a Alphabetically. Only the first line of item is checked.
@ -2958,7 +3038,7 @@ With a prefix argument ARG, change the region in a single item."
(if (org-region-active-p) (if (org-region-active-p)
(setq beg (funcall skip-blanks (region-beginning)) (setq beg (funcall skip-blanks (region-beginning))
end (copy-marker (region-end))) end (copy-marker (region-end)))
(setq beg (funcall skip-blanks (point-at-bol)) (setq beg (point-at-bol)
end (copy-marker (point-at-eol)))) end (copy-marker (point-at-eol))))
;; Depending on the starting line, choose an action on the text ;; Depending on the starting line, choose an action on the text
;; between BEG and END. ;; between BEG and END.
@ -3501,4 +3581,8 @@ overruling parameters for `org-list-to-generic'."
(provide 'org-list) (provide 'org-list)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-list.el ends here ;;; org-list.el ends here

View file

@ -50,6 +50,7 @@
(require 'org-macs) (require 'org-macs)
(require 'org-compat) (require 'org-compat)
(declare-function org-collect-keywords "org" (keywords &optional unique directory))
(declare-function org-element-at-point "org-element" ()) (declare-function org-element-at-point "org-element" ())
(declare-function org-element-context "org-element" (&optional element)) (declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-copy "org-element" (datum)) (declare-function org-element-copy "org-element" (datum))
@ -88,49 +89,24 @@ directly, use instead:
VALUE is the template of the macro. The new value override the VALUE is the template of the macro. The new value override the
previous one, unless VALUE is nil. TEMPLATES is the list of previous one, unless VALUE is nil. TEMPLATES is the list of
templates. Return the updated list." templates. Return the updated list."
(when value (let ((old-definition (assoc name templates)))
(let ((old-definition (assoc name templates))) (cond ((and value old-definition) (setcdr old-definition value))
(if old-definition (old-definition)
(setcdr old-definition value) (t (push (cons name (or value "")) templates))))
(push (cons name value) templates))))
templates) templates)
(defun org-macro--collect-macros (&optional files templates) (defun org-macro--collect-macros ()
"Collect macro definitions in current buffer and setup files. "Collect macro definitions in current buffer and setup files.
Return an alist containing all macro templates found. Return an alist containing all macro templates found."
(let ((templates nil))
FILES is a list of setup files names read so far, used to avoid (pcase (org-collect-keywords '("MACRO"))
circular dependencies. TEMPLATES is the alist collected so far. (`(("MACRO" . ,values))
The two arguments are used in recursive calls." (dolist (value values)
(let ((case-fold-search t)) (when (string-match "^\\(\\S-+\\)[ \t]*" value)
(org-with-point-at 1 (let ((name (match-string 1 value))
(while (re-search-forward "^[ \t]*#\\+\\(MACRO\\|SETUPFILE\\):" nil t) (definition (substring value (match-end 0))))
(let ((element (org-element-at-point))) (setq templates
(when (eq (org-element-type element) 'keyword) (org-macro--set-template name definition templates)))))))
(let ((val (org-element-property :value element)))
(if (equal "MACRO" (org-element-property :key element))
;; Install macro in TEMPLATES.
(when (string-match "^\\(\\S-+\\)[ \t]*" val)
(let ((name (match-string 1 val))
(value (substring val (match-end 0))))
(setq templates
(org-macro--set-template name value templates))))
;; Enter setup file.
(let* ((uri (org-strip-quotes val))
(uri-is-url (org-file-url-p uri))
(uri (if uri-is-url
uri
(expand-file-name uri))))
;; Avoid circular dependencies.
(unless (member uri files)
(with-temp-buffer
(unless uri-is-url
(setq default-directory (file-name-directory uri)))
(org-mode)
(insert (org-file-contents uri 'noerror))
(setq templates
(org-macro--collect-macros
(cons uri files) templates)))))))))))
(let ((macros `(("author" . ,(org-macro--find-keyword-value "AUTHOR")) (let ((macros `(("author" . ,(org-macro--find-keyword-value "AUTHOR"))
("email" . ,(org-macro--find-keyword-value "EMAIL")) ("email" . ,(org-macro--find-keyword-value "EMAIL"))
("title" . ,(org-macro--find-keyword-value "TITLE" t)) ("title" . ,(org-macro--find-keyword-value "TITLE" t))
@ -417,6 +393,6 @@ Any other non-empty string resets the counter to 1."
(t 1)) (t 1))
org-macro--counter-table))) org-macro--counter-table)))
(provide 'org-macro) (provide 'org-macro)
;;; org-macro.el ends here ;;; org-macro.el ends here

View file

@ -34,6 +34,7 @@
(require 'cl-lib) (require 'cl-lib)
(require 'format-spec) (require 'format-spec)
(declare-function org-show-context "org" (&optional key))
(declare-function org-string-collate-lessp "org-compat" (s1 s2 &optional locale ignore-case)) (declare-function org-string-collate-lessp "org-compat" (s1 s2 &optional locale ignore-case))
(defvar org-ts-regexp0) (defvar org-ts-regexp0)
@ -122,7 +123,7 @@ means that the buffer should stay alive during the operation,
because otherwise all these markers will point to nowhere." because otherwise all these markers will point to nowhere."
(declare (debug (form body)) (indent 1)) (declare (debug (form body)) (indent 1))
(org-with-gensyms (data invisible-types markers?) (org-with-gensyms (data invisible-types markers?)
`(let* ((,invisible-types '(org-hide-block org-hide-drawer outline)) `(let* ((,invisible-types '(org-hide-block outline))
(,markers? ,use-markers) (,markers? ,use-markers)
(,data (,data
(mapcar (lambda (o) (mapcar (lambda (o)
@ -416,6 +417,7 @@ is selected, only the bare key is returned."
(let ((inhibit-quit t) (let ((inhibit-quit t)
(buffer (org-switch-to-buffer-other-window "*Org Select*")) (buffer (org-switch-to-buffer-other-window "*Org Select*"))
(prompt (or prompt "Select: ")) (prompt (or prompt "Select: "))
case-fold-search
current) current)
(unwind-protect (unwind-protect
(catch 'exit (catch 'exit
@ -644,6 +646,25 @@ The number of levels is controlled by `org-inlinetask-min-level'."
limit-level))) limit-level)))
(format "\\*\\{1,%d\\} " nstars))))) (format "\\*\\{1,%d\\} " nstars)))))
(defun org--line-empty-p (n)
"Is the Nth next line empty?
Counts the current line as N = 1 and the previous line as N = 0;
see `beginning-of-line'."
(and (not (bobp))
(save-excursion
(beginning-of-line n)
(looking-at-p "[ \t]*$"))))
(defun org-previous-line-empty-p ()
"Is the previous line a blank line?
When NEXT is non-nil, check the next line instead."
(org--line-empty-p 0))
(defun org-next-line-empty-p ()
"Is the previous line a blank line?
When NEXT is non-nil, check the next line instead."
(org--line-empty-p 2))
;;; Motion ;;; Motion
@ -695,7 +716,9 @@ SPEC is the invisibility spec, as a symbol."
(let ((o (make-overlay from to nil 'front-advance))) (let ((o (make-overlay from to nil 'front-advance)))
(overlay-put o 'evaporate t) (overlay-put o 'evaporate t)
(overlay-put o 'invisible spec) (overlay-put o 'invisible spec)
(overlay-put o 'isearch-open-invisible #'delete-overlay)))) (overlay-put o
'isearch-open-invisible
(lambda (&rest _) (org-show-context 'isearch))))))
@ -920,7 +943,8 @@ if necessary."
(if (<= (length s) maxlength) (if (<= (length s) maxlength)
s s
(let* ((n (max (- maxlength 4) 1)) (let* ((n (max (- maxlength 4) 1))
(re (concat "\\`\\(.\\{1," (int-to-string n) "\\}[^ ]\\)\\([ ]\\|\\'\\)"))) (re (concat "\\`\\(.\\{1," (number-to-string n)
"\\}[^ ]\\)\\([ ]\\|\\'\\)")))
(if (string-match re s) (if (string-match re s)
(concat (match-string 1 s) "...") (concat (match-string 1 s) "...")
(concat (substring s 0 (max (- maxlength 3) 0)) "..."))))) (concat (substring s 0 (max (- maxlength 3) 0)) "...")))))
@ -1065,10 +1089,16 @@ the value in cdr."
(get-text-property (or (next-single-property-change 0 prop s) 0) (get-text-property (or (next-single-property-change 0 prop s) 0)
prop s))) prop s)))
(defun org-invisible-p (&optional pos) (defun org-invisible-p (&optional pos folding-only)
"Non-nil if the character after POS is invisible. "Non-nil if the character after POS is invisible.
If POS is nil, use `point' instead." If POS is nil, use `point' instead. When optional argument
(get-char-property (or pos (point)) 'invisible)) FOLDING-ONLY is non-nil, only consider invisible parts due to
folding of a headline, a block or a drawer, i.e., not because of
fontification."
(let ((value (get-char-property (or pos (point)) 'invisible)))
(cond ((not value) nil)
(folding-only (memq value '(org-hide-block outline)))
(t value))))
(defun org-truely-invisible-p () (defun org-truely-invisible-p ()
"Check if point is at a character currently not visible. "Check if point is at a character currently not visible.
@ -1086,6 +1116,18 @@ move it back by one char before doing this check."
(backward-char 1)) (backward-char 1))
(org-invisible-p))) (org-invisible-p)))
(defun org-find-visible ()
"Return closest visible buffer position, or `point-max'"
(if (org-invisible-p)
(next-single-char-property-change (point) 'invisible)
(point)))
(defun org-find-invisible ()
"Return closest invisible buffer position, or `point-max'"
(if (org-invisible-p)
(point)
(next-single-char-property-change (point) 'invisible)))
;;; Time ;;; Time
@ -1182,8 +1224,41 @@ Return 0. if S is not recognized as a valid value."
((string-match org-ts-regexp0 s) (org-2ft s)) ((string-match org-ts-regexp0 s) (org-2ft s))
(t 0.))))) (t 0.)))))
(defun org-scroll (key &optional additional-keys)
"Receive KEY and scroll the current window accordingly.
When ADDITIONAL-KEYS is not nil, also include SPC and DEL in the
allowed keys for scrolling, as expected in the export dispatch
window."
(let ((scrlup (if additional-keys '(?\s 22) 22))
(scrldn (if additional-keys `(?\d 134217846) 134217846)))
(eval
`(cl-case ,key
;; C-n
(14 (if (not (pos-visible-in-window-p (point-max)))
(ignore-errors (scroll-up 1))
(message "End of buffer")
(sit-for 1)))
;; C-p
(16 (if (not (pos-visible-in-window-p (point-min)))
(ignore-errors (scroll-down 1))
(message "Beginning of buffer")
(sit-for 1)))
;; SPC or
(,scrlup
(if (not (pos-visible-in-window-p (point-max)))
(scroll-up nil)
(message "End of buffer")
(sit-for 1)))
;; DEL
(,scrldn (if (not (pos-visible-in-window-p (point-min)))
(scroll-down nil)
(message "Beginning of buffer")
(sit-for 1)))))))
(provide 'org-macs) (provide 'org-macs)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-macs.el ends here ;;; org-macs.el ends here

View file

@ -258,6 +258,17 @@ the old and new values for the entry.")
(defvar org-mobile-files-alist nil) (defvar org-mobile-files-alist nil)
(defvar org-mobile-checksum-files nil) (defvar org-mobile-checksum-files nil)
;; Add org mobile commands to the main org menu
(easy-menu-add-item
org-org-menu
nil
'("MobileOrg"
["Push Files and Views" org-mobile-push t]
["Get Captured and Flagged" org-mobile-pull t]
["Find FLAGGED Tasks" (org-agenda nil "?") :active t :keys "\\[org-agenda] ?"]
"--"
["Setup" (customize-group 'org-mobile) t]))
(defun org-mobile-prepare-file-lists () (defun org-mobile-prepare-file-lists ()
(setq org-mobile-files-alist (org-mobile-files-alist)) (setq org-mobile-files-alist (org-mobile-files-alist))
(setq org-mobile-checksum-files nil)) (setq org-mobile-checksum-files nil))

View file

@ -386,7 +386,7 @@ DEFAULT is returned if no priority is given in the headline."
(save-excursion (save-excursion
(if (org-mouse-re-search-line org-mouse-priority-regexp) (if (org-mouse-re-search-line org-mouse-priority-regexp)
(match-string 1) (match-string 1)
(when default (char-to-string org-default-priority))))) (when default (char-to-string org-priority-default)))))
(defun org-mouse-delete-timestamp () (defun org-mouse-delete-timestamp ()
"Deletes the current timestamp as well as the preceding keyword. "Deletes the current timestamp as well as the preceding keyword.
@ -407,7 +407,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
(> (match-end 0) point)))))) (> (match-end 0) point))))))
(defun org-mouse-priority-list () (defun org-mouse-priority-list ()
(cl-loop for priority from ?A to org-lowest-priority (cl-loop for priority from ?A to org-priority-lowest
collect (char-to-string priority))) collect (char-to-string priority)))
(defun org-mouse-todo-menu (state) (defun org-mouse-todo-menu (state)
@ -495,7 +495,8 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
["Check Deadlines" ["Check Deadlines"
(if (functionp 'org-check-deadlines-and-todos) (if (functionp 'org-check-deadlines-and-todos)
(org-check-deadlines-and-todos org-deadline-warning-days) (org-check-deadlines-and-todos org-deadline-warning-days)
(org-check-deadlines org-deadline-warning-days)) t] (org-check-deadlines org-deadline-warning-days))
t]
["Check TODOs" org-show-todo-tree t] ["Check TODOs" org-show-todo-tree t]
("Check Tags" ("Check Tags"
,@(org-mouse-keyword-menu ,@(org-mouse-keyword-menu
@ -741,7 +742,8 @@ This means, between the beginning of line and the point."
(?$ "($) Formula Parameters") (?$ "($) Formula Parameters")
(?# "(#) Recalculation: Auto") (?# "(#) Recalculation: Auto")
(?* "(*) Recalculation: Manual") (?* "(*) Recalculation: Manual")
(?' "(') Recalculation: None"))) t)))) (?' "(') Recalculation: None")))
t))))
((assq :table contextlist) ((assq :table contextlist)
(popup-menu (popup-menu
'(nil '(nil

View file

@ -254,6 +254,7 @@ otherwise."
org-footnote-section org-footnote-section
(equal title org-footnote-section)) (equal title org-footnote-section))
(and org-num-skip-commented (and org-num-skip-commented
title
(let ((case-fold-search nil)) (let ((case-fold-search nil))
(string-match org-num--comment-re title)) (string-match org-num--comment-re title))
t) t)
@ -466,6 +467,10 @@ NUMBERING is a list of numbers."
(remove-hook 'after-change-functions #'org-num--verify t) (remove-hook 'after-change-functions #'org-num--verify t)
(remove-hook 'change-major-mode-hook #'org-num--clear t)))) (remove-hook 'change-major-mode-hook #'org-num--clear t))))
(provide 'org-num) (provide 'org-num)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-num.el ends here ;;; org-num.el ends here

View file

@ -32,6 +32,8 @@
(require 'pcomplete) (require 'pcomplete)
(declare-function org-at-heading-p "org" (&optional ignored)) (declare-function org-at-heading-p "org" (&optional ignored))
(declare-function org-babel-combine-header-arg-lists "ob-core" (original &rest others))
(declare-function org-babel-get-src-block-info "ob-core" (&optional light datum))
(declare-function org-before-first-heading-p "org" ()) (declare-function org-before-first-heading-p "org" ())
(declare-function org-buffer-property-keys "org" (&optional specials defaults columns)) (declare-function org-buffer-property-keys "org" (&optional specials defaults columns))
(declare-function org-element-at-point "org-element" ()) (declare-function org-element-at-point "org-element" ())
@ -47,8 +49,9 @@
(declare-function org-link-heading-search-string "ol" (&optional string)) (declare-function org-link-heading-search-string "ol" (&optional string))
(declare-function org-tag-alist-to-string "org" (alist &optional skip-key)) (declare-function org-tag-alist-to-string "org" (alist &optional skip-key))
(defvar org-babel-common-header-args-w-values)
(defvar org-current-tag-alist) (defvar org-current-tag-alist)
(defvar org-default-priority) (defvar org-priority-default)
(defvar org-drawer-regexp) (defvar org-drawer-regexp)
(defvar org-element-affiliated-keywords) (defvar org-element-affiliated-keywords)
(defvar org-entities) (defvar org-entities)
@ -56,10 +59,10 @@
(defvar org-export-exclude-tags) (defvar org-export-exclude-tags)
(defvar org-export-select-tags) (defvar org-export-select-tags)
(defvar org-file-tags) (defvar org-file-tags)
(defvar org-highest-priority) (defvar org-priority-highest)
(defvar org-link-abbrev-alist) (defvar org-link-abbrev-alist)
(defvar org-link-abbrev-alist-local) (defvar org-link-abbrev-alist-local)
(defvar org-lowest-priority) (defvar org-priority-lowest)
(defvar org-options-keywords) (defvar org-options-keywords)
(defvar org-outline-regexp) (defvar org-outline-regexp)
(defvar org-property-re) (defvar org-property-re)
@ -252,9 +255,9 @@ When completing for #+STARTUP, for example, this function returns
(defun pcomplete/org-mode/file-option/priorities () (defun pcomplete/org-mode/file-option/priorities ()
"Complete arguments for the #+PRIORITIES file option." "Complete arguments for the #+PRIORITIES file option."
(pcomplete-here (list (format "%c %c %c" (pcomplete-here (list (format "%c %c %c"
org-highest-priority org-priority-highest
org-lowest-priority org-priority-lowest
org-default-priority)))) org-priority-default))))
(defun pcomplete/org-mode/file-option/select_tags () (defun pcomplete/org-mode/file-option/select_tags ()
"Complete arguments for the #+SELECT_TAGS file option." "Complete arguments for the #+SELECT_TAGS file option."
@ -352,8 +355,9 @@ This needs more work, to handle headings with lots of spaces in them."
(goto-char (point-min)) (goto-char (point-min))
(let (tbl) (let (tbl)
(while (re-search-forward org-outline-regexp nil t) (while (re-search-forward org-outline-regexp nil t)
(push (org-link-heading-search-string (org-get-heading t t t t)) ;; Remove the leading asterisk from
tbl)) ;; `org-link-heading-search-string' result.
(push (substring (org-link-heading-search-string) 1) tbl))
(pcomplete-uniquify-list tbl))) (pcomplete-uniquify-list tbl)))
;; When completing a bracketed link, i.e., "[[*", argument ;; When completing a bracketed link, i.e., "[[*", argument
;; starts at the star, so remove this character. ;; starts at the star, so remove this character.
@ -417,11 +421,17 @@ switches."
(symbol-plist (symbol-plist
'org-babel-load-languages) 'org-babel-load-languages)
'custom-type))))))) 'custom-type)))))))
(while (pcomplete-here (let* ((info (org-babel-get-src-block-info 'light))
'("-n" "-r" "-l" (lang (car info))
":cache" ":colnames" ":comments" ":dir" ":eval" ":exports" (lang-headers (intern (concat "org-babel-header-args:" lang)))
":file" ":hlines" ":no-expand" ":noweb" ":results" ":rownames" (headers (org-babel-combine-header-arg-lists
":session" ":shebang" ":tangle" ":tangle-mode" ":var")))) org-babel-common-header-args-w-values
(and (boundp lang-headers) (eval lang-headers t)))))
(while (pcomplete-here
(append (mapcar
(lambda (arg) (format ":%s" (symbol-name (car arg))))
headers)
'("-n" "-r" "-l"))))))
(defun pcomplete/org-mode/block-option/clocktable () (defun pcomplete/org-mode/block-option/clocktable ()
"Complete keywords in a clocktable line." "Complete keywords in a clocktable line."

View file

@ -3,6 +3,7 @@
;; Copyright (C) 2008-2020 Free Software Foundation, Inc. ;; Copyright (C) 2008-2020 Free Software Foundation, Inc.
;; ;;
;; Author: Eric Schulte <schulte dot eric at gmail dot com> ;; Author: Eric Schulte <schulte dot eric at gmail dot com>
;; Maintainer: TEC <tecosaur@gmail.com>
;; Keywords: tables, plotting ;; Keywords: tables, plotting
;; Homepage: https://orgmode.org ;; Homepage: https://orgmode.org
;; ;;
@ -144,7 +145,8 @@ and dependent variables."
row-vals) row-vals)
(when (>= ind 0) ;; collect values of ind col (when (>= ind 0) ;; collect values of ind col
(setf row-vals (mapcar (lambda (row) (setf counter (+ 1 counter)) (setf row-vals (mapcar (lambda (row) (setf counter (+ 1 counter))
(cons counter (nth ind row))) table))) (cons counter (nth ind row)))
table)))
(when (or deps (>= ind 0)) ;; remove non-plotting columns (when (or deps (>= ind 0)) ;; remove non-plotting columns
(setf deps (delq ind deps)) (setf deps (delq ind deps))
(setf table (mapcar (lambda (row) (setf table (mapcar (lambda (row)
@ -288,14 +290,12 @@ line directly before or after the table."
(setf params (plist-put params (car pair) (cdr pair))))) (setf params (plist-put params (car pair) (cdr pair)))))
;; collect table and table information ;; collect table and table information
(let* ((data-file (make-temp-file "org-plot")) (let* ((data-file (make-temp-file "org-plot"))
(table (org-table-to-lisp)) (table (org-table-collapse-header (org-table-to-lisp)))
(num-cols (length (if (eq (nth 0 table) 'hline) (nth 1 table) (num-cols (length (car table))))
(nth 0 table)))))
(run-with-idle-timer 0.1 nil #'delete-file data-file) (run-with-idle-timer 0.1 nil #'delete-file data-file)
(while (eq 'hline (car table)) (setf table (cdr table)))
(when (eq (cadr table) 'hline) (when (eq (cadr table) 'hline)
(setf params (setf params
(plist-put params :labels (nth 0 table))) ; headers to labels (plist-put params :labels (car table))) ; headers to labels
(setf table (delq 'hline (cdr table)))) ; clean non-data from table (setf table (delq 'hline (cdr table)))) ; clean non-data from table
;; Collect options. ;; Collect options.
(save-excursion (while (and (equal 0 (forward-line -1)) (save-excursion (while (and (equal 0 (forward-line -1))
@ -308,26 +308,20 @@ line directly before or after the table."
(`grid (let ((y-labels (org-plot/gnuplot-to-grid-data (`grid (let ((y-labels (org-plot/gnuplot-to-grid-data
table data-file params))) table data-file params)))
(when y-labels (plist-put params :ylabels y-labels))))) (when y-labels (plist-put params :ylabels y-labels)))))
;; Check for timestamp ind column. ;; Check type of ind column (timestamp? text?)
(let ((ind (1- (plist-get params :ind)))) (when (eq `2d (plist-get params :plot-type))
(when (and (>= ind 0) (eq '2d (plist-get params :plot-type))) (let* ((ind (1- (plist-get params :ind)))
(if (= (length (ind-column (mapcar (lambda (row) (nth ind row)) table)))
(delq 0 (mapcar (cond ((< ind 0) nil) ; ind is implicit
(lambda (el) ((cl-every (lambda (el)
(if (string-match org-ts-regexp3 el) 0 1)) (string-match org-ts-regexp3 el))
(mapcar (lambda (row) (nth ind row)) table)))) ind-column)
0) (plist-put params :timeind t)) ; ind holds timestamps
(plist-put params :timeind t) ((or (string= (plist-get params :with) "hist")
;; Check for text ind column. (cl-notevery (lambda (el)
(if (or (string= (plist-get params :with) "hist") (string-match org-table-number-regexp el))
(> (length ind-column))
(delq 0 (mapcar (plist-put params :textind t))))) ; ind holds text
(lambda (el)
(if (string-match org-table-number-regexp el)
0 1))
(mapcar (lambda (row) (nth ind row)) table))))
0))
(plist-put params :textind t)))))
;; Write script. ;; Write script.
(with-temp-buffer (with-temp-buffer
(if (plist-get params :script) ; user script (if (plist-get params :script) ; user script

View file

@ -191,7 +191,7 @@ Example:
:working-suffix \".org\" :working-suffix \".org\"
:base-url \"https://orgmode.org/worg/\" :base-url \"https://orgmode.org/worg/\"
:working-directory \"/home/user/org/Worg/\") :working-directory \"/home/user/org/Worg/\")
(\"http://localhost/org-notes/\" (\"localhost org-notes/\"
:online-suffix \".html\" :online-suffix \".html\"
:working-suffix \".org\" :working-suffix \".org\"
:base-url \"http://localhost/org/\" :base-url \"http://localhost/org/\"
@ -202,12 +202,17 @@ Example:
:working-directory \"~/site/content/post/\" :working-directory \"~/site/content/post/\"
:online-suffix \".html\" :online-suffix \".html\"
:working-suffix \".md\" :working-suffix \".md\"
:rewrites ((\"\\(https://site.com/[0-9]+/[0-9]+/[0-9]+/\\)\" . \".md\"))))) :rewrites ((\"\\(https://site.com/[0-9]+/[0-9]+/[0-9]+/\\)\" . \".md\")))
(\"GNU emacs OpenGrok\"
:base-url \"https://opengrok.housegordon.com/source/xref/emacs/\"
:working-directory \"~/dev/gnu-emacs/\")))
The :rewrites line of \"localhost org-notes\" entry tells
The last line tells `org-protocol-open-source' to open `org-protocol-open-source' to open /home/user/org/index.php,
/home/user/org/index.php, if the URL cannot be mapped to an existing if the URL cannot be mapped to an existing file, and ends with
file, and ends with either \"org\" or \"org/\". either \"org\" or \"org/\". The \"GNU emacs OpenGrok\" entry
does not include any suffix properties, allowing local source
file to be opened as found by OpenGrok.
Consider using the interactive functions `org-protocol-create' and Consider using the interactive functions `org-protocol-create' and
`org-protocol-create-for-org' to help you filling this variable with valid contents." `org-protocol-create-for-org' to help you filling this variable with valid contents."
@ -278,7 +283,7 @@ This should be a single regexp string."
:group 'org-protocol :group 'org-protocol
:version "24.4" :version "24.4"
:package-version '(Org . "8.0") :package-version '(Org . "8.0")
:type 'string) :type 'regexp)
;;; Helper functions: ;;; Helper functions:
@ -545,11 +550,12 @@ The location for a browser's bookmark should look like this:
;; ending than strip-suffix here: ;; ending than strip-suffix here:
(f1 (substring f 0 (string-match "\\([\\?#].*\\)?$" f))) (f1 (substring f 0 (string-match "\\([\\?#].*\\)?$" f)))
(start-pos (+ (string-match wsearch f1) (length base-url))) (start-pos (+ (string-match wsearch f1) (length base-url)))
(end-pos (string-match (end-pos (if strip-suffix
(regexp-quote strip-suffix) f1)) (string-match (regexp-quote strip-suffix) f1)
(length f1)))
;; We have to compare redirects without suffix below: ;; We have to compare redirects without suffix below:
(f2 (concat wdir (substring f1 start-pos end-pos))) (f2 (concat wdir (substring f1 start-pos end-pos)))
(the-file (concat f2 add-suffix))) (the-file (if add-suffix (concat f2 add-suffix) f2)))
;; Note: the-file may still contain `%C3' et al here because browsers ;; Note: the-file may still contain `%C3' et al here because browsers
;; tend to encode `&auml;' in URLs to `%25C3' - `%25' being `%'. ;; tend to encode `&auml;' in URLs to `%25C3' - `%25' being `%'.
@ -617,13 +623,13 @@ CLIENT is ignored."
(let ((proto (let ((proto
(concat the-protocol (concat the-protocol
(regexp-quote (plist-get (cdr prolist) :protocol)) (regexp-quote (plist-get (cdr prolist) :protocol))
"\\(:/+\\|\\?\\)"))) "\\(:/+\\|/*\\?\\)")))
(when (string-match proto fname) (when (string-match proto fname)
(let* ((func (plist-get (cdr prolist) :function)) (let* ((func (plist-get (cdr prolist) :function))
(greedy (plist-get (cdr prolist) :greedy)) (greedy (plist-get (cdr prolist) :greedy))
(split (split-string fname proto)) (split (split-string fname proto))
(result (if greedy restoffiles (cadr split))) (result (if greedy restoffiles (cadr split)))
(new-style (string= (match-string 1 fname) "?"))) (new-style (string-match "/*?" (match-string 1 fname))))
(when (plist-get (cdr prolist) :kill-client) (when (plist-get (cdr prolist) :kill-client)
(message "Greedy org-protocol handler. Killing client.") (message "Greedy org-protocol handler. Killing client.")
(server-edit)) (server-edit))

742
lisp/org/org-refile.el Normal file
View file

@ -0,0 +1,742 @@
;;; org-refile.el --- Refile Org Subtrees -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2020 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
;;
;; This file is part of GNU Emacs.
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Org Refile allows you to refile subtrees to various locations.
;;; Code:
(require 'org)
(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
(defgroup org-refile nil
"Options concerning refiling entries in Org mode."
:tag "Org Refile"
:group 'org)
(defcustom org-log-refile nil
"Information to record when a task is refiled.
Possible values are:
nil Don't add anything
time Add a time stamp to the task
note Prompt for a note and add it with template `org-log-note-headings'
This option can also be set with on a per-file-basis with
#+STARTUP: nologrefile
#+STARTUP: logrefile
#+STARTUP: lognoterefile
You can have local logging settings for a subtree by setting the LOGGING
property to one or more of these keywords.
When bulk-refiling, e.g., from the agenda, the value `note' is
forbidden and will temporarily be changed to `time'."
:group 'org-refile
:group 'org-progress
:version "24.1"
:type '(choice
(const :tag "No logging" nil)
(const :tag "Record timestamp" time)
(const :tag "Record timestamp with note." note)))
(defcustom org-refile-targets nil
"Targets for refiling entries with `\\[org-refile]'.
This is a list of cons cells. Each cell contains:
- a specification of the files to be considered, either a list of files,
or a symbol whose function or variable value will be used to retrieve
a file name or a list of file names. If you use `org-agenda-files' for
that, all agenda files will be scanned for targets. Nil means consider
headings in the current buffer.
- A specification of how to find candidate refile targets. This may be
any of:
- a cons cell (:tag . \"TAG\") to identify refile targets by a tag.
This tag has to be present in all target headlines, inheritance will
not be considered.
- a cons cell (:todo . \"KEYWORD\") to identify refile targets by
todo keyword.
- a cons cell (:regexp . \"REGEXP\") with a regular expression matching
headlines that are refiling targets.
- a cons cell (:level . N). Any headline of level N is considered a target.
Note that, when `org-odd-levels-only' is set, level corresponds to
order in hierarchy, not to the number of stars.
- a cons cell (:maxlevel . N). Any headline with level <= N is a target.
Note that, when `org-odd-levels-only' is set, level corresponds to
order in hierarchy, not to the number of stars.
Each element of this list generates a set of possible targets.
The union of these sets is presented (with completion) to
the user by `org-refile'.
You can set the variable `org-refile-target-verify-function' to a function
to verify each headline found by the simple criteria above.
When this variable is nil, all top-level headlines in the current buffer
are used, equivalent to the value `((nil . (:level . 1))'."
:group 'org-refile
:type '(repeat
(cons
(choice :value org-agenda-files
(const :tag "All agenda files" org-agenda-files)
(const :tag "Current buffer" nil)
(function) (variable) (file))
(choice :tag "Identify target headline by"
(cons :tag "Specific tag" (const :value :tag) (string))
(cons :tag "TODO keyword" (const :value :todo) (string))
(cons :tag "Regular expression" (const :value :regexp) (regexp))
(cons :tag "Level number" (const :value :level) (integer))
(cons :tag "Max Level number" (const :value :maxlevel) (integer))))))
(defcustom org-refile-target-verify-function nil
"Function to verify if the headline at point should be a refile target.
The function will be called without arguments, with point at the
beginning of the headline. It should return t and leave point
where it is if the headline is a valid target for refiling.
If the target should not be selected, the function must return nil.
In addition to this, it may move point to a place from where the search
should be continued. For example, the function may decide that the entire
subtree of the current entry should be excluded and move point to the end
of the subtree."
:group 'org-refile
:type '(choice
(const nil)
(function)))
(defcustom org-refile-use-cache nil
"Non-nil means cache refile targets to speed up the process.
\\<org-mode-map>\
The cache for a particular file will be updated automatically when
the buffer has been killed, or when any of the marker used for flagging
refile targets no longer points at a live buffer.
If you have added new entries to a buffer that might themselves be targets,
you need to clear the cache manually by pressing `C-0 \\[org-refile]' or,
if you find that easier, \
`\\[universal-argument] \\[universal-argument] \\[universal-argument] \
\\[org-refile]'."
:group 'org-refile
:version "24.1"
:type 'boolean)
(defcustom org-refile-use-outline-path nil
"Non-nil means provide refile targets as paths.
So a level 3 headline will be available as level1/level2/level3.
When the value is `file', also include the file name (without directory)
into the path. In this case, you can also stop the completion after
the file name, to get entries inserted as top level in the file.
When `full-file-path', include the full file path.
When `buffer-name', use the buffer name."
:group 'org-refile
:type '(choice
(const :tag "Not" nil)
(const :tag "Yes" t)
(const :tag "Start with file name" file)
(const :tag "Start with full file path" full-file-path)
(const :tag "Start with buffer name" buffer-name)))
(defcustom org-outline-path-complete-in-steps t
"Non-nil means complete the outline path in hierarchical steps.
When Org uses the refile interface to select an outline path (see
`org-refile-use-outline-path'), the completion of the path can be
done in a single go, or it can be done in steps down the headline
hierarchy. Going in steps is probably the best if you do not use
a special completion package like `ido' or `icicles'. However,
when using these packages, going in one step can be very fast,
while still showing the whole path to the entry."
:group 'org-refile
:type 'boolean)
(defcustom org-refile-allow-creating-parent-nodes nil
"Non-nil means allow the creation of new nodes as refile targets.
New nodes are then created by adding \"/new node name\" to the completion
of an existing node. When the value of this variable is `confirm',
new node creation must be confirmed by the user (recommended).
When nil, the completion must match an existing entry.
Note that, if the new heading is not seen by the criteria
listed in `org-refile-targets', multiple instances of the same
heading would be created by trying again to file under the new
heading."
:group 'org-refile
:type '(choice
(const :tag "Never" nil)
(const :tag "Always" t)
(const :tag "Prompt for confirmation" confirm)))
(defcustom org-refile-active-region-within-subtree nil
"Non-nil means also refile active region within a subtree.
By default `org-refile' doesn't allow refiling regions if they
don't contain a set of subtrees, but it might be convenient to
do so sometimes: in that case, the first line of the region is
converted to a headline before refiling."
:group 'org-refile
:version "24.1"
:type 'boolean)
(defvar org-refile-target-table nil
"The list of refile targets, created by `org-refile'.")
(defvar org-refile-cache nil
"Cache for refile targets.")
(defvar org-refile-markers nil
"All the markers used for caching refile locations.")
;; Add org refile commands to the main org menu
(mapc (lambda (i) (easy-menu-add-item
org-org-menu
'("Edit Structure") i))
'(["Refile Subtree" org-refile (org-in-subtree-not-table-p)]
["Refile and copy Subtree" org-copy (org-in-subtree-not-table-p)]))
(defun org-refile-marker (pos)
"Get a new refile marker, but only if caching is in use."
(if (not org-refile-use-cache)
pos
(let ((m (make-marker)))
(move-marker m pos)
(push m org-refile-markers)
m)))
(defun org-refile-cache-clear ()
"Clear the refile cache and disable all the markers."
(dolist (m org-refile-markers) (move-marker m nil))
(setq org-refile-markers nil)
(setq org-refile-cache nil)
(message "Refile cache has been cleared"))
(defun org-refile-cache-check-set (set)
"Check if all the markers in the cache still have live buffers."
(let (marker)
(catch 'exit
(while (and set (setq marker (nth 3 (pop set))))
;; If `org-refile-use-outline-path' is 'file, marker may be nil
(when (and marker (null (marker-buffer marker)))
(message "Please regenerate the refile cache with `C-0 C-c C-w'")
(sit-for 3)
(throw 'exit nil)))
t)))
(defun org-refile-cache-put (set &rest identifiers)
"Push the refile targets SET into the cache, under IDENTIFIERS."
(let* ((key (sha1 (prin1-to-string identifiers)))
(entry (assoc key org-refile-cache)))
(if entry
(setcdr entry set)
(push (cons key set) org-refile-cache))))
(defun org-refile-cache-get (&rest identifiers)
"Retrieve the cached value for refile targets given by IDENTIFIERS."
(cond
((not org-refile-cache) nil)
((not org-refile-use-cache) (org-refile-cache-clear) nil)
(t
(let ((set (cdr (assoc (sha1 (prin1-to-string identifiers))
org-refile-cache))))
(and set (org-refile-cache-check-set set) set)))))
(defun org-refile-get-targets (&optional default-buffer)
"Produce a table with refile targets."
(let ((case-fold-search nil)
;; otherwise org confuses "TODO" as a kw and "Todo" as a word
(entries (or org-refile-targets '((nil . (:level . 1)))))
targets tgs files desc descre)
(message "Getting targets...")
(with-current-buffer (or default-buffer (current-buffer))
(dolist (entry entries)
(setq files (car entry) desc (cdr entry))
(cond
((null files) (setq files (list (current-buffer))))
((eq files 'org-agenda-files)
(setq files (org-agenda-files 'unrestricted)))
((and (symbolp files) (fboundp files))
(setq files (funcall files)))
((and (symbolp files) (boundp files))
(setq files (symbol-value files))))
(when (stringp files) (setq files (list files)))
(cond
((eq (car desc) :tag)
(setq descre (concat "^\\*+[ \t]+.*?:" (regexp-quote (cdr desc)) ":")))
((eq (car desc) :todo)
(setq descre (concat "^\\*+[ \t]+" (regexp-quote (cdr desc)) "[ \t]")))
((eq (car desc) :regexp)
(setq descre (cdr desc)))
((eq (car desc) :level)
(setq descre (concat "^\\*\\{" (number-to-string
(if org-odd-levels-only
(1- (* 2 (cdr desc)))
(cdr desc)))
"\\}[ \t]")))
((eq (car desc) :maxlevel)
(setq descre (concat "^\\*\\{1," (number-to-string
(if org-odd-levels-only
(1- (* 2 (cdr desc)))
(cdr desc)))
"\\}[ \t]")))
(t (error "Bad refiling target description %s" desc)))
(dolist (f files)
(with-current-buffer (if (bufferp f) f (org-get-agenda-file-buffer f))
(or
(setq tgs (org-refile-cache-get (buffer-file-name) descre))
(progn
(when (bufferp f)
(setq f (buffer-file-name (buffer-base-buffer f))))
(setq f (and f (expand-file-name f)))
(when (eq org-refile-use-outline-path 'file)
(push (list (file-name-nondirectory f) f nil nil) tgs))
(when (eq org-refile-use-outline-path 'buffer-name)
(push (list (buffer-name (buffer-base-buffer)) f nil nil) tgs))
(when (eq org-refile-use-outline-path 'full-file-path)
(push (list (file-truename (buffer-file-name (buffer-base-buffer))) f nil nil) tgs))
(org-with-wide-buffer
(goto-char (point-min))
(setq org-outline-path-cache nil)
(while (re-search-forward descre nil t)
(beginning-of-line)
(let ((case-fold-search nil))
(looking-at org-complex-heading-regexp))
(let ((begin (point))
(heading (match-string-no-properties 4)))
(unless (or (and
org-refile-target-verify-function
(not
(funcall org-refile-target-verify-function)))
(not heading))
(let ((re (format org-complex-heading-regexp-format
(regexp-quote heading)))
(target
(if (not org-refile-use-outline-path) heading
(mapconcat
#'identity
(append
(pcase org-refile-use-outline-path
(`file (list (file-name-nondirectory
(buffer-file-name
(buffer-base-buffer)))))
(`full-file-path
(list (buffer-file-name
(buffer-base-buffer))))
(`buffer-name
(list (buffer-name
(buffer-base-buffer))))
(_ nil))
(mapcar (lambda (s) (replace-regexp-in-string
"/" "\\/" s nil t))
(org-get-outline-path t t)))
"/"))))
(push (list target f re (org-refile-marker (point)))
tgs)))
(when (= (point) begin)
;; Verification function has not moved point.
(end-of-line)))))))
(when org-refile-use-cache
(org-refile-cache-put tgs (buffer-file-name) descre))
(setq targets (append tgs targets))))))
(message "Getting targets...done")
(delete-dups (nreverse targets))))
(defvar org-refile-history nil
"History for refiling operations.")
(defvar org-after-refile-insert-hook nil
"Hook run after `org-refile' has inserted its stuff at the new location.
Note that this is still *before* the stuff will be removed from
the *old* location.")
(defvar org-refile-keep nil
"Non-nil means `org-refile' will copy instead of refile.")
(define-obsolete-function-alias 'org-copy 'org-refile-copy)
;;;###autoload
(defun org-refile-copy ()
"Like `org-refile', but preserve the refiled subtree."
(interactive)
(let ((org-refile-keep t))
(org-refile nil nil nil "Copy")))
(defvar org-capture-last-stored-marker)
;;;###autoload
(defun org-refile (&optional arg default-buffer rfloc msg)
"Move the entry or entries at point to another heading.
The list of target headings is compiled using the information in
`org-refile-targets', which see.
At the target location, the entry is filed as a subitem of the
target heading. Depending on `org-reverse-note-order', the new
subitem will either be the first or the last subitem.
If there is an active region, all entries in that region will be
refiled. However, the region must fulfill the requirement that
the first heading sets the top-level of the moved text.
With a `\\[universal-argument]' ARG, the command will only visit the target \
location
and not actually move anything.
With a prefix `\\[universal-argument] \\[universal-argument]', go to the \
location where the last
refiling operation has put the subtree.
With a numeric prefix argument of `2', refile to the running clock.
With a numeric prefix argument of `3', emulate `org-refile-keep'
being set to t and copy to the target location, don't move it.
Beware that keeping refiled entries may result in duplicated ID
properties.
RFLOC can be a refile location obtained in a different way. It
should be a list with the following 4 elements:
1. Name - an identifier for the refile location, typically the
headline text
2. File - the file the refile location is in
3. nil - used for generating refile location candidates, not
needed when passing RFLOC
4. Position - the position in the specified file of the
headline to refile under
MSG is a string to replace \"Refile\" in the default prompt with
another verb. E.g. `org-copy' sets this parameter to \"Copy\".
See also `org-refile-use-outline-path'.
If you are using target caching (see `org-refile-use-cache'), you
have to clear the target cache in order to find new targets.
This can be done with a `0' prefix (`C-0 C-c C-w') or a triple
prefix argument (`C-u C-u C-u C-c C-w')."
(interactive "P")
(if (member arg '(0 (64)))
(org-refile-cache-clear)
(let* ((actionmsg (cond (msg msg)
((equal arg 3) "Refile (and keep)")
(t "Refile")))
(regionp (org-region-active-p))
(region-start (and regionp (region-beginning)))
(region-end (and regionp (region-end)))
(org-refile-keep (if (equal arg 3) t org-refile-keep))
pos it nbuf file level reversed)
(setq last-command nil)
(when regionp
(goto-char region-start)
(beginning-of-line)
(setq region-start (point))
(unless (or (org-kill-is-subtree-p
(buffer-substring region-start region-end))
(prog1 org-refile-active-region-within-subtree
(let ((s (point-at-eol)))
(org-toggle-heading)
(setq region-end (+ (- (point-at-eol) s) region-end)))))
(user-error "The region is not a (sequence of) subtree(s)")))
(if (equal arg '(16))
(org-refile-goto-last-stored)
(when (or
(and (equal arg 2)
org-clock-hd-marker (marker-buffer org-clock-hd-marker)
(prog1
(setq it (list (or org-clock-heading "running clock")
(buffer-file-name
(marker-buffer org-clock-hd-marker))
""
(marker-position org-clock-hd-marker)))
(setq arg nil)))
(setq it
(or rfloc
(let (heading-text)
(save-excursion
(unless (and arg (listp arg))
(org-back-to-heading t)
(setq heading-text
(replace-regexp-in-string
org-link-bracket-re
"\\2"
(or (nth 4 (org-heading-components))
""))))
(org-refile-get-location
(cond ((and arg (listp arg)) "Goto")
(regionp (concat actionmsg " region to"))
(t (concat actionmsg " subtree \""
heading-text "\" to")))
default-buffer
(and (not (equal '(4) arg))
org-refile-allow-creating-parent-nodes)))))))
(setq file (nth 1 it)
pos (nth 3 it))
(when (and (not arg)
pos
(equal (buffer-file-name) file)
(if regionp
(and (>= pos region-start)
(<= pos region-end))
(and (>= pos (point))
(< pos (save-excursion
(org-end-of-subtree t t))))))
(error "Cannot refile to position inside the tree or region"))
(setq nbuf (or (find-buffer-visiting file)
(find-file-noselect file)))
(if (and arg (not (equal arg 3)))
(progn
(pop-to-buffer-same-window nbuf)
(goto-char (cond (pos)
((org-notes-order-reversed-p) (point-min))
(t (point-max))))
(org-show-context 'org-goto))
(if regionp
(progn
(org-kill-new (buffer-substring region-start region-end))
(org-save-markers-in-region region-start region-end))
(org-copy-subtree 1 nil t))
(with-current-buffer (setq nbuf (or (find-buffer-visiting file)
(find-file-noselect file)))
(setq reversed (org-notes-order-reversed-p))
(org-with-wide-buffer
(if pos
(progn
(goto-char pos)
(setq level (org-get-valid-level (funcall outline-level) 1))
(goto-char
(if reversed
(or (outline-next-heading) (point-max))
(or (save-excursion (org-get-next-sibling))
(org-end-of-subtree t t)
(point-max)))))
(setq level 1)
(if (not reversed)
(goto-char (point-max))
(goto-char (point-min))
(or (outline-next-heading) (goto-char (point-max)))))
(unless (bolp) (newline))
(org-paste-subtree level nil nil t)
;; Record information, according to `org-log-refile'.
;; Do not prompt for a note when refiling multiple
;; headlines, however. Simply add a time stamp.
(cond
((not org-log-refile))
(regionp
(org-map-region
(lambda () (org-add-log-setup 'refile nil nil 'time))
(point)
(+ (point) (- region-end region-start))))
(t
(org-add-log-setup 'refile nil nil org-log-refile)))
(and org-auto-align-tags
(let ((org-loop-over-headlines-in-active-region nil))
(org-align-tags)))
(let ((bookmark-name (plist-get org-bookmark-names-plist
:last-refile)))
(when bookmark-name
(with-demoted-errors
(bookmark-set bookmark-name))))
;; If we are refiling for capture, make sure that the
;; last-capture pointers point here
(when (bound-and-true-p org-capture-is-refiling)
(let ((bookmark-name (plist-get org-bookmark-names-plist
:last-capture-marker)))
(when bookmark-name
(with-demoted-errors
(bookmark-set bookmark-name))))
(move-marker org-capture-last-stored-marker (point)))
(when (fboundp 'deactivate-mark) (deactivate-mark))
(run-hooks 'org-after-refile-insert-hook)))
(unless org-refile-keep
(if regionp
(delete-region (point) (+ (point) (- region-end region-start)))
(org-preserve-local-variables
(delete-region
(and (org-back-to-heading t) (point))
(min (1+ (buffer-size)) (org-end-of-subtree t t) (point))))))
(when (featurep 'org-inlinetask)
(org-inlinetask-remove-END-maybe))
(setq org-markers-to-move nil)
(message "%s to \"%s\" in file %s: done" actionmsg
(car it) file)))))))
(defun org-refile-goto-last-stored ()
"Go to the location where the last refile was stored."
(interactive)
(bookmark-jump (plist-get org-bookmark-names-plist :last-refile))
(message "This is the location of the last refile"))
(defun org-refile--get-location (refloc tbl)
"When user refile to REFLOC, find the associated target in TBL.
Also check `org-refile-target-table'."
(car (delq
nil
(mapcar
(lambda (r) (or (assoc r tbl)
(assoc r org-refile-target-table)))
(list (replace-regexp-in-string "/$" "" refloc)
(replace-regexp-in-string "\\([^/]\\)$" "\\1/" refloc))))))
(defun org-refile-get-location (&optional prompt default-buffer new-nodes)
"Prompt the user for a refile location, using PROMPT.
PROMPT should not be suffixed with a colon and a space, because
this function appends the default value from
`org-refile-history' automatically, if that is not empty."
(let ((org-refile-targets org-refile-targets)
(org-refile-use-outline-path org-refile-use-outline-path))
(setq org-refile-target-table (org-refile-get-targets default-buffer)))
(unless org-refile-target-table
(user-error "No refile targets"))
(let* ((cbuf (current-buffer))
(cfn (buffer-file-name (buffer-base-buffer cbuf)))
(cfunc (if (and org-refile-use-outline-path
org-outline-path-complete-in-steps)
#'org-olpath-completing-read
#'completing-read))
(extra (if org-refile-use-outline-path "/" ""))
(cbnex (concat (buffer-name) extra))
(filename (and cfn (expand-file-name cfn)))
(tbl (mapcar
(lambda (x)
(if (and (not (member org-refile-use-outline-path
'(file full-file-path)))
(not (equal filename (nth 1 x))))
(cons (concat (car x) extra " ("
(file-name-nondirectory (nth 1 x)) ")")
(cdr x))
(cons (concat (car x) extra) (cdr x))))
org-refile-target-table))
(completion-ignore-case t)
cdef
(prompt (concat prompt
(or (and (car org-refile-history)
(concat " (default " (car org-refile-history) ")"))
(and (assoc cbnex tbl) (setq cdef cbnex)
(concat " (default " cbnex ")"))) ": "))
pa answ parent-target child parent old-hist)
(setq old-hist org-refile-history)
(setq answ (funcall cfunc prompt tbl nil (not new-nodes)
nil 'org-refile-history
(or cdef (concat (car org-refile-history) extra))))
(if (setq pa (org-refile--get-location answ tbl))
(let* ((last-refile-loc (car org-refile-history))
(last-refile-loc-path (concat last-refile-loc extra)))
(org-refile-check-position pa)
(when (or (not org-refile-history)
(not (eq old-hist org-refile-history))
(not (equal (car pa) last-refile-loc-path)))
(setq org-refile-history
(cons (car pa) (if (assoc last-refile-loc tbl)
org-refile-history
(cdr org-refile-history))))
(when (or (equal last-refile-loc-path (nth 1 org-refile-history))
(equal last-refile-loc (nth 1 org-refile-history)))
(pop org-refile-history)))
pa)
(if (string-match "\\`\\(.*\\)/\\([^/]+\\)\\'" answ)
(progn
(setq parent (match-string 1 answ)
child (match-string 2 answ))
(setq parent-target (org-refile--get-location parent tbl))
(when (and parent-target
(or (eq new-nodes t)
(and (eq new-nodes 'confirm)
(y-or-n-p (format "Create new node \"%s\"? "
child)))))
(org-refile-new-child parent-target child)))
(user-error "Invalid target location")))))
(defun org-refile-check-position (refile-pointer)
"Check if the refile pointer matches the headline to which it points."
(let* ((file (nth 1 refile-pointer))
(re (nth 2 refile-pointer))
(pos (nth 3 refile-pointer))
buffer)
(if (and (not (markerp pos)) (not file))
(user-error "Please indicate a target file in the refile path")
(when (org-string-nw-p re)
(setq buffer (if (markerp pos)
(marker-buffer pos)
(or (find-buffer-visiting file)
(find-file-noselect file))))
(with-current-buffer buffer
(org-with-wide-buffer
(goto-char pos)
(beginning-of-line 1)
(unless (looking-at-p re)
(user-error "Invalid refile position, please clear the cache with `C-0 C-c C-w' before refiling"))))))))
(defun org-refile-new-child (parent-target child)
"Use refile target PARENT-TARGET to add new CHILD below it."
(unless parent-target
(error "Cannot find parent for new node"))
(let ((file (nth 1 parent-target))
(pos (nth 3 parent-target))
level)
(with-current-buffer (or (find-buffer-visiting file)
(find-file-noselect file))
(org-with-wide-buffer
(if pos
(goto-char pos)
(goto-char (point-max))
(unless (bolp) (newline)))
(when (looking-at org-outline-regexp)
(setq level (funcall outline-level))
(org-end-of-subtree t t))
(org-back-over-empty-lines)
(insert "\n" (make-string
(if pos (org-get-valid-level level 1) 1) ?*)
" " child "\n")
(beginning-of-line 0)
(list (concat (car parent-target) "/" child) file "" (point))))))
(defun org-olpath-completing-read (prompt collection &rest args)
"Read an outline path like a file name."
(let ((thetable collection))
(apply #'completing-read
prompt
(lambda (string predicate &optional flag)
(cond
((eq flag nil) (try-completion string thetable))
((eq flag t)
(let ((l (length string)))
(mapcar (lambda (x)
(let ((r (substring x l))
(f (if (string-match " ([^)]*)$" x)
(match-string 0 x)
"")))
(if (string-match "/" r)
(concat string (substring r 0 (match-end 0)) f)
x)))
(all-completions string thetable predicate))))
;; Exact match?
((eq flag 'lambda) (assoc string thetable))))
args)))
(provide 'org-refile)
;; Local variables:
;; generated-autoload-file: "org-loaddefs.el"
;; End:
;;; org-refile.el ends here

Some files were not shown because too many files have changed in this diff Show more