mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2026-09-10 07:46:51 -04:00
Update to Org 9.8.1
This commit is contained in:
parent
0a62e6c304
commit
6c22780955
|
|
@ -29,9 +29,9 @@
|
|||
|
||||
# Contact Info
|
||||
#+texinfo_header: @set MAINTAINERSITE @uref{https://orgmode.org,maintainers webpage}
|
||||
#+texinfo_header: @set MAINTAINER Bastien Guerry
|
||||
#+texinfo_header: @set MAINTAINEREMAIL @email{bzg@gnu.org}
|
||||
#+texinfo_header: @set MAINTAINERCONTACT @uref{mailto:bzg@gnu.org,contact the maintainer}
|
||||
#+texinfo_header: @set MAINTAINER Ihor Radchenko
|
||||
#+texinfo_header: @set MAINTAINEREMAIL @email{yantar92@posteo.net}
|
||||
#+texinfo_header: @set MAINTAINERCONTACT @uref{mailto:yantar92@posteo.net,contact the maintainer}
|
||||
|
||||
#+options: H:4 num:t toc:t author:t \n:nil ::t |:t ^:nil -:t f:t *:t <:t e:t ':t
|
||||
#+options: d:nil todo:nil pri:nil tags:not-in-toc stat:nil broken-links:mark
|
||||
|
|
|
|||
1642
doc/misc/org.org
1642
doc/misc/org.org
File diff suppressed because it is too large
Load diff
928
etc/ORG-NEWS
928
etc/ORG-NEWS
|
|
@ -4,13 +4,930 @@ ORG NEWS -- history of user-visible changes. -*- mode: org; coding: utf-8 -*-
|
|||
|
||||
#+LINK: doc https://orgmode.org/worg/doc.html#%s
|
||||
#+LINK: msg https://list.orgmode.org/%s/
|
||||
#+LINK: git https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=%s
|
||||
#+LINK: git https://git.savannah.nongnu.org/cgit/org-mode.git/commit/?id=%s
|
||||
#+macro: kbd (eval (org-texinfo-kbd-macro $1))
|
||||
|
||||
Copyright (C) 2012-2026 Free Software Foundation, Inc.
|
||||
See the end of the file for license conditions.
|
||||
|
||||
Please send Org bug reports to mailto:emacs-orgmode@gnu.org.
|
||||
|
||||
* Version 9.8
|
||||
** Important announcements and breaking changes
|
||||
|
||||
# Here, we list the *most important* changes and changes that _likely_
|
||||
# require user action for most Org mode users.
|
||||
# Sorted from most important to least important.
|
||||
|
||||
*** You may need to update =org-protocol= bookmarklets for browsers
|
||||
|
||||
In Firefox 133 and Firefox 128.5 ESR, the previously suggested
|
||||
JavaScript bookmarklets replace the current page with the bookmarklet URL
|
||||
text. We have updated the manual with new bookmarklets that do not
|
||||
have this problem.
|
||||
|
||||
The new bookmarklets have ~void(0);~ appended at the end, so that they
|
||||
do not return anything.
|
||||
|
||||
Example:
|
||||
|
||||
#+begin_example
|
||||
javascript:location.href='org-protocol://store-link?url='+
|
||||
encodeURIComponent(location.href);void(0);
|
||||
#+end_example
|
||||
|
||||
*** =C-c C-x C-v= command toggling inline image display has been reworked
|
||||
|
||||
Previously, =C-c C-x C-v= always toggled image display in the whole
|
||||
buffer (or narrowed part of the buffer). With prefix argument, it
|
||||
also forced displaying image links with description.
|
||||
|
||||
Now, =C-c C-x C-v= is bound to a new command ~org-link-preview~, which
|
||||
uses different defaults:
|
||||
|
||||
1. When the region is active, images in the region are previewed
|
||||
|
||||
2. Otherwise, if there is an image at point, it is toggled. If there
|
||||
is no image at point, images in the current entry are previewed
|
||||
|
||||
3. With the =C-u= argument, image previews in the active region or at
|
||||
point are cleared instead
|
||||
|
||||
4. The =C-u C-u= argument unconditionally shows all images in the
|
||||
accessible portion of the buffer
|
||||
|
||||
5. The =C-u C-u C-u= argument unconditionally clears all images in the
|
||||
accessible portion of the buffer
|
||||
|
||||
6. Displaying images over links with description can be forced using
|
||||
numeric argument:
|
||||
- ~C-u 1~ for toggling all images at point/current entry
|
||||
- ~C-u 11~ for toggling all images in buffer
|
||||
|
||||
(The first five of these prefix argument behaviors are the same as that of
|
||||
the ~org-latex-preview~ command.)
|
||||
|
||||
In addition to images, ~org-link-preview~ can also be used to preview
|
||||
Org links of all types for which preview behavior is defined, see
|
||||
[[#link-preview][previews for arbitrary link types]].
|
||||
|
||||
The old ~org-toggle-inline-images~ command is obsolete but still
|
||||
available. You can bind it back to =C-c C-x C-v= by adding the
|
||||
following to your config:
|
||||
#+begin_src emacs-lisp
|
||||
(eval-after-load 'org-keys
|
||||
(org-defkey org-mode-map (kbd "C-c C-x C-v") #'org-toggle-inline-images))
|
||||
#+end_src
|
||||
|
||||
*** Org mode no longer treats =:results drawer= as verbatim output
|
||||
|
||||
Previously, =:results drawer= left the code block results verbatim in
|
||||
some scenarios. This is no longer the case, in line with the manual
|
||||
and the intended purpose of this option. However, the fix may have
|
||||
brought subtle changes in the code block output for users who made use
|
||||
of the previous erroneous behavior. If you use =:results drawer= in your
|
||||
Org documents, please watch out for potential changes in the code evaluation.
|
||||
|
||||
*** Diary-style timestamps are exported together with active timestamps
|
||||
|
||||
~org-export-with-timestamps~ and ~org-icalendar-with-timestamps~ now
|
||||
treat diary-style timestamps as a type of active timestamp for
|
||||
purposes of export.
|
||||
|
||||
This mainly affects iCalendar export, where diary timestamps will now
|
||||
be included when only active timestamps are exported (the default).
|
||||
|
||||
This should have minimal impact on non-iCalendar exporters, since
|
||||
~org-export-with-timestamps~ was already ~t~ by default. However,
|
||||
users who manually set ~org-export-with-timestamps~ to ~active~ will
|
||||
now have diary timestamps included as well.
|
||||
|
||||
To use the old behavior and export active timestamps only without
|
||||
diary timestamps, users can set ~org-export-with-timestamps~ and
|
||||
~org-icalendar-with-timestamps~ to ~active-exclude-diary~.
|
||||
|
||||
*** ~org-element-drawer-parser~ assigns ~:pre-blank~ property
|
||||
|
||||
Previously, the whole contents of drawer, including blank lines at the beginning were
|
||||
parsed as paragraph. Now, the blank lines at the beginning are stored in ~:pre-blank~
|
||||
property, just as in other greater elements.
|
||||
|
||||
*** ~org-element-org-data-parser~ now returns syntax node with ~:pre-blank~ property
|
||||
|
||||
Previously, parsing ~org-data~ syntax node did not record information
|
||||
about blank lines at the beginning of the document. Now, the number
|
||||
of blank lines is recorded in ~:pre-blank~ property.
|
||||
|
||||
~org-element-org-data-interpreter~ takes into account this information.
|
||||
|
||||
*** Emacs 26 and Emacs 27 support has been dropped
|
||||
|
||||
We maintain compatibility with the latest Emacs release, and two
|
||||
versions prior the latest. The latest is Emacs 30, so we drop
|
||||
everything before Emacs 28.
|
||||
|
||||
** New features
|
||||
|
||||
# We list the most important features, and the features that may
|
||||
# require user action to be used.
|
||||
|
||||
*** Some navigation commands can now be repeated
|
||||
|
||||
When ~repeat-mode~ is turned on, the following navigation commands can
|
||||
be repeated:
|
||||
|
||||
| Command | Key binding | Repeat key |
|
||||
|-----------------------------------+------------------------+--------------|
|
||||
| ~org-next-visible-heading~ | {{{kbd(C-c C-n)}}} | {{{kbd(n)}}} |
|
||||
| ~org-previous-visible-heading~ | {{{kbd(C-c C-p)}}} | {{{kbd(p)}}} |
|
||||
| ~org-forward-heading-same-level~ | {{{kbd(C-c C-f)}}} | {{{kbd(f)}}} |
|
||||
| ~org-backward-heading-same-level~ | {{{kbd(C-c C-b)}}} | {{{kbd(b)}}} |
|
||||
| ~org-up-heading~ | {{{kbd(C-c C-u)}}} | {{{kbd(u)}}} |
|
||||
| ~org-next-block~ | {{{kbd(C-c M-f)}}} | {{{kbd(f)}}} |
|
||||
| ~org-previous-block~ | {{{kbd(C-c M-b)}}} | {{{kbd(b)}}} |
|
||||
| ~org-next-link~ | {{{kbd(C-c C-x C-n)}}} | {{{kbd(n)}}} |
|
||||
| ~org-previous-link~ | {{{kbd(C-c C-x C-p)}}} | {{{kbd(p)}}} |
|
||||
|
||||
The keybindings in the repeat-maps can be changed by customizing
|
||||
~org-navigation-repeat-map~, ~org-link-navigation-repeat-map~, and
|
||||
~org-block-navigation-repeat-map~.
|
||||
|
||||
See the new [[info:org#Repeating commands]["Repeating commands"]] section in Org mode manual.
|
||||
|
||||
*** New babel backend for C# code blocks
|
||||
|
||||
Org now officially enables C# code block evaluation based on the .NET SDK.
|
||||
The old backend that does not use .NET SDK remains in org-contrib
|
||||
and will be removed in a future release. The built-in =ob-csharp.el= should be
|
||||
considered the official successor.
|
||||
|
||||
*** All Org link types can be previewed
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: link-preview
|
||||
:END:
|
||||
|
||||
Org links support a new parameter =:preview= that can be used to
|
||||
preview arbitrary link types. The value of this parameter should be a
|
||||
function that is called to preview links of the corresponding type
|
||||
(see ~org-link-parameters~).
|
||||
|
||||
The new preview system does not bring any brand-new link previews, but
|
||||
open the possibility for third-party packages to implement custom previews
|
||||
without having to use non-ideal hacks.
|
||||
|
||||
On the user side, the existing image link previews should now run
|
||||
smoother, especially in Org buffers that have a lot of image links to
|
||||
preview. The new previews are less blocking, previewing link in
|
||||
batches, without fully blocking Emacs. See the new
|
||||
~org-link-preview-batch-size~ and ~org-link-preview-delay~ options.
|
||||
|
||||
*** New =%\*N= placeholder in ~org-capture-templates~
|
||||
|
||||
The new placeholder is like =%\N=, but gives access not only to the
|
||||
=%^{prompt}= values, but also to =%^{prompt}X= values.
|
||||
|
||||
*** Alignment of image previews can be customized
|
||||
|
||||
This feature was added in Org 9.7 but was not documented in the release notes. See [[https://orgmode.org/worg/org-release-notes.html#preview-align][retrospectively added news entry]].
|
||||
|
||||
*** ~org-open-at-point-global~ now accepts prefix argument
|
||||
|
||||
The argument is passed through to ~org-link-open~, allowing alternative
|
||||
way to open links, if link ~:follow~ function supports it.
|
||||
|
||||
*** ox-latex: Table of contents generation has been fixed and augmented
|
||||
|
||||
The LaTeX exporter differs from other exporters in that it does not
|
||||
include unnumbered sections in the table of contents by default. To
|
||||
include an unnumbered section, set the property =:UNNUMBERED: toc= on
|
||||
the section.
|
||||
|
||||
Alternatively, you can set the new custom variable
|
||||
~org-latex-toc-include-unnumbered~ to include unnumbered sections by
|
||||
default, aligning with other exporters' behavior. In that case, to
|
||||
exclude a section from the table of contents, mark it as =:UNNUMBERED:
|
||||
notoc= in its properties.
|
||||
|
||||
*** Tables copied from LibreOffice Calc documents can be pasted as Org tables
|
||||
|
||||
Tables copied into the clipboard from LibreOffice Calc documents can
|
||||
now be pasted as an Org table using ~yank-media~.
|
||||
|
||||
*** Ditaa code blocks can use ditaa executable, and can produce SVG output
|
||||
|
||||
In order to use a ditaa executable instead of a JAR file, you can set
|
||||
~org-ditaa-default-exec-mode~ to ~'ditaa~. The location of the
|
||||
executable can be configured via ~org-ditaa-exec~.
|
||||
|
||||
SVG output can now be generated; note, however, that this requires a
|
||||
ditaa version of at least 0.11.0.
|
||||
|
||||
*** New datetree capture ~:tree-type~ options
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: 9.8-datetree-treetype
|
||||
:END:
|
||||
|
||||
For datetree capture, ~:tree-type~ can now be any subset of ~(year
|
||||
quarter month week day)~ to construct a datetree with the specified
|
||||
levels. For back-compatibility, the default value of ~nil~ is an
|
||||
alias for ~(year month day)~, ~month~ is an alias for ~(year month)~,
|
||||
and ~week~ is an alias for ~(year week day)~.
|
||||
|
||||
If ~:tree-type~ is a superset of ~(month week)~, then weeks are
|
||||
assigned to the month containing Thursday, to be consistent with the
|
||||
ISO-8601 year-week rule. If ~:tree-type~ contains ~(quarter week)~
|
||||
but does not contain ~month~, then quarters are defined as 13-week
|
||||
periods (the final quarter of a 53-week year has 14-weeks).
|
||||
Otherwise, quarters are defined as 3-month periods.
|
||||
|
||||
Additionally, ~:tree-type~ can be a function, in which case it should
|
||||
take the date as an argument, and generate a list of pairs for
|
||||
~org-datetree-find-create-hierarchy~. This allows for creating new
|
||||
types of datetrees (e.g. for lunar calendars, academic calendars,
|
||||
retail 4-4-5 calendars, etc).
|
||||
|
||||
*** New =shortdoc= link type
|
||||
|
||||
You can now create links to =shortdoc= documentation groups for Emacs
|
||||
Lisp functions (see =M-x shortdoc-display-group=). Requires Emacs 28
|
||||
or newer.
|
||||
|
||||
*** Beamer export supports setting frame subtitles
|
||||
|
||||
If a headline is exported as a frame, and has its =BEAMER_SUBTITLE=
|
||||
property set, the value is used as the subtitle.
|
||||
|
||||
*** =:wrap= header argument can now be explicitly disabled
|
||||
|
||||
Previously, presence of =:wrap= argument (inherited or not) in code
|
||||
block headers always made the block results wrapped. There was no way
|
||||
to disable wrapping if =:wrap= was specified in the inherited header
|
||||
arguments. Now, =:wrap no= or =:wrap nil= will explicitly disable
|
||||
wrapping.
|
||||
|
||||
*** =ob-sqlite=: Added ability to open a database in readonly mode
|
||||
|
||||
Added option ~:readonly~ to =ob-sqlite=.
|
||||
|
||||
With ~:readonly yes~, the database is opened in readonly mode. For
|
||||
example:
|
||||
|
||||
#+begin_example
|
||||
,#+begin_src sqlite :db /tmp/rip.db :readonly yes :exports both
|
||||
create table rip(a,b);
|
||||
,#+end_src
|
||||
#+end_example
|
||||
|
||||
This results in an error such as:
|
||||
|
||||
#+begin_example
|
||||
Runtime error near line 2: attempt to write a readonly database (8)
|
||||
[ Babel evaluation exited with code 1 ]
|
||||
#+end_example
|
||||
|
||||
** New and changed options
|
||||
|
||||
# Changes dealing with changing default values of customizations,
|
||||
# adding new customizations, or changing the interpretation of the
|
||||
# existing customizations.
|
||||
|
||||
*** New option ~org-edit-keep-region~
|
||||
|
||||
Since Org 9.7, structure editing commands do not deactivate region
|
||||
after editing. Now, this is configurable via the new option.
|
||||
|
||||
*** =xelatex= can be used for LaTeX previews
|
||||
|
||||
A new process =xelatex= is added to ~org-preview-process-alist~ to
|
||||
allow generating LaTeX fragment preview through =xdv= file produced by
|
||||
XeLaTeX, which has better support for Unicode.
|
||||
|
||||
You can now set ~org-preview-latex-default-process~ to ~'xelatex~.
|
||||
|
||||
*** New link preview system
|
||||
**** New option ~org-link-preview-batch-size~
|
||||
|
||||
Org link previews are generated asynchronously and a few at a time, in
|
||||
batches. This option controls the number of links that are previewed
|
||||
in each batch.
|
||||
|
||||
**** New option ~org-link-preview-delay~
|
||||
|
||||
Org link previews are generated asynchronously. This option controls
|
||||
the minimum idle time in seconds between previews of batches of links.
|
||||
|
||||
*** New and changed export options
|
||||
**** ~org-html-style-default~ now highlights =#+begin_src c= (lowercase) blocks
|
||||
|
||||
The default value has been changed, adding ~pre.src-c:before {
|
||||
content: 'C'; }~ (lowercase =c=) that parallels ~pre.src-C:before {
|
||||
content: 'C'; }~ (uppercase =C=).
|
||||
|
||||
**** ~org-odt-with-latex~ accepts any method from ~org-preview-latex-process-alist~
|
||||
|
||||
Previously, only a few conversion methods (~dvipng~, ~imagemagick~,
|
||||
~dvisvgm~) could be used to render LaTeX fragments as images when
|
||||
exporting to ODT. Now any method in ~org-preview-latex-process-alist~
|
||||
can be used.
|
||||
|
||||
**** New environment =onlyenv= in ~org-beamer-environments-default~
|
||||
|
||||
The =onlyenv= environment limits showing parts of an animated Beamer
|
||||
slide to specific animation steps.
|
||||
|
||||
#+begin_example
|
||||
,***** Comment
|
||||
:PROPERTIES:
|
||||
:BEAMER_env: onlyenv
|
||||
:BEAMER_act: <2->
|
||||
:END:
|
||||
This text will be displayed on animation step 2 and later.
|
||||
#+end_example
|
||||
|
||||
**** =ox-html=: Headline self links can be enabled from an Org mode file
|
||||
|
||||
Previously HTML export could add, to each headline, a link to itself.
|
||||
To enable it, you had to use the variable
|
||||
~org-html-self-link-headlines~.
|
||||
|
||||
Now, it's also possible to enable it per Org mode file by adding:
|
||||
: #+OPTIONS: html-self-link-headlines:t
|
||||
|
||||
**** Allow disabling macro replacement during export
|
||||
|
||||
New custom option ~org-export-replace-macros~ controls whether Org
|
||||
mode replaces macros in the buffer before export. Set it to nil to
|
||||
disable macro replacement.
|
||||
|
||||
This variable has no effect on the ={{{results...}}}= macros for inline
|
||||
code block results.
|
||||
|
||||
**** New option ~org-cite-bibtex-bibliography-style~
|
||||
|
||||
This option adds a fallback bibliography style for BibTeX when none is
|
||||
provided in the =#+CITE_EXPORT= options. The default style is
|
||||
"plain".
|
||||
|
||||
**** New option ~org-cite-csl-bibtex-titles-to-sentence-case~
|
||||
|
||||
When this option is non-nil then title fields in BibTeX bibliography
|
||||
entries are converted to sentence-case before being formatted
|
||||
according to a CSL style, except for entries with a =langid= field
|
||||
specifying a non-English language. When nil, this conversion is
|
||||
limited to entries having a =langid= field specifying a variant of
|
||||
English. The default value is ~t~ as the CSL standard assumes that
|
||||
English titles are specified in sentence-case but the BibTeX
|
||||
bibliography format requires them to be written in title-case.
|
||||
|
||||
**** New option ~org-latex-mathml-directory~
|
||||
|
||||
This option specifies the path where MathML files generated from LaTeX
|
||||
fragments are stored.
|
||||
|
||||
**** New option ~org-latex-use-sans~
|
||||
|
||||
This option specifies the PDF should be typeset using the Sans font
|
||||
specified in the document class (or the user) instead of the default
|
||||
font (i.e. the Roman font).
|
||||
|
||||
**** New option ~#+LATEX_CLASS_PRE~
|
||||
|
||||
This option prepends LaTeX code before the LaTeX preamble.
|
||||
|
||||
**** New option ~org-odt-with-forbidden-chars~
|
||||
|
||||
The new export option controls how to deal with characters that are forbidden
|
||||
inside ODT documents during export.
|
||||
|
||||
The ODT documents must follow XML1.0 specification and cannot contain
|
||||
certain Unicode characters. For example, form feed characters like ^L
|
||||
are disallowed.
|
||||
|
||||
By default, =ox-odt= will strip such characters and display warning.
|
||||
You may return to the previous behavior by setting
|
||||
~org-odt-with-forbidden-chars~ to t.
|
||||
|
||||
Note that Emacs warnings can always be suppressed by clicking on ⛔
|
||||
symbol or by customizing ~warning-suppress-types~.
|
||||
|
||||
**** New option ~org-md-link-org-files-as-md~
|
||||
|
||||
This option makes it possible to disable mapping of linked org files
|
||||
to markdown during export to Markdown. This is analogous to how
|
||||
~org-html-link-org-files-as-html~ works in export to HTML.
|
||||
|
||||
*** New context available to save in archived headings
|
||||
|
||||
~org-archive-save-context-info~ can now contain ~olid~ symbol to save
|
||||
parent heading ID in the archived heading.
|
||||
|
||||
*** New hook ~org-archive-finalize-hook~
|
||||
|
||||
Hook run after successfully archiving a subtree in final location.
|
||||
Unlike ~org-archive-hook~, which runs in the source Org buffer, the
|
||||
new hook is called with point on the subtree in the destination file.
|
||||
|
||||
*** Headline/olp target in ~org-capture-templates~ can be a function/variable
|
||||
|
||||
The variable ~org-capture-templates~ accepts a target specification as
|
||||
function or symbol for headline (~file+headline~) and olp (~file+olp~
|
||||
and ~file+olp+datetree~).
|
||||
|
||||
*** The default value of ~org-babel-latex-process-alist~ is no longer taken from ~org-preview-latex-process-alist~
|
||||
|
||||
The default value used to be pulled from =dvipng= process type from
|
||||
~org-preview-latex-process-alist~. Now, it defaults to using
|
||||
=latexmk= (when available), or running =latex= multiple times, so that
|
||||
all the references are resolved in the generated PNG.
|
||||
|
||||
*** ~org-tags-sort-function~ can now be a list of functions
|
||||
|
||||
~org-tags-sort-function~ can now be set to a list of functions.
|
||||
Subsequent sorting functions will be used if two tags are found to be
|
||||
equivalent. See docstring for more information.
|
||||
|
||||
*** New tags sorting function ~org-tags-sort-hierarchy~
|
||||
|
||||
By setting ~org-tags-sort-function~ to ~org-tags-sort-hierarchy~, tags
|
||||
are sorted taking their hierarchy into account. See
|
||||
[[info:org#Tag Hierarchy][Tag Hierarchy]] for how to set up a tag
|
||||
hierarchy.
|
||||
|
||||
*** New option ~org-cite-basic-complete-key-crm-separator~
|
||||
|
||||
This option makes ~org-cite~'s ~basic~ insert processor use
|
||||
~completing-read-multiple~ instead of the default consecutive prompts.
|
||||
It can also be set to dynamically compute ~crm-separator~ so that the
|
||||
separator does not appear in completion candidates.
|
||||
|
||||
*** ~org-yank-image-save-method~ can be a function producing directory name
|
||||
|
||||
In previous versions, ~org-yank-image-save-method~ could be either a
|
||||
symbol ~attach~ or a string -- directory name. Now it can also be a
|
||||
function, which will be called with no arguments and its return value
|
||||
will be used as a directory to save the image to.
|
||||
|
||||
*** ~org-refile-targets~ can now match all headlines in the target file(s)
|
||||
|
||||
Candidate refile targets may now be specified with the symbol ~t~ to
|
||||
indicate that all headlines within the specified file are to be
|
||||
considered. For example, setting ~org-refile-targets~ to ~((nil . t))~
|
||||
will allow one to refile to any heading within the current buffer.
|
||||
|
||||
*** In =ob-ditaa=, the output type is now controlled consistently with other babel backends
|
||||
|
||||
Output file type is determined as specified in Babel documentation:
|
||||
the suffix of =:file= is the primary determinant, and =:file-ext=
|
||||
secondary. Header arguments =:pdf= and =:eps= are supported for
|
||||
backwards compatibility. Default output type is still PNG.
|
||||
|
||||
** New functions and changes in function arguments
|
||||
|
||||
# This also includes changes in function behavior from Elisp perspective.
|
||||
|
||||
*** The deprecated =show= parameter to =org-priority= has been removed
|
||||
|
||||
The =show= parameter for the =org-priority= function was deprecated in
|
||||
Org 9.2 (released in 2017). Sufficient time has passed, and it is being
|
||||
removed as part of refactoring for numeric priorities.
|
||||
|
||||
*** ~org-attach-attach~ now returns a link to file stored
|
||||
|
||||
Previously, ~org-attach-attach~ did not have any specified default value.
|
||||
Now, it returns a list =(LINK DESCRIPTION)= to the file stored.
|
||||
The link obeys non-nil ~org-attach-store-link-p~ setting.
|
||||
When ~org-attach-store-link-p~ is nil, an =attachment:= link is returned.
|
||||
|
||||
*** New functions exposing link formatting done by ~org-insert-link~
|
||||
|
||||
New function ~org-link-get-description~ exposes handling ~:insert-description~
|
||||
link parameter and ~org-link-make-description-function~.
|
||||
|
||||
New function ~org-link-make-string-for-buffer~ exposes link and description
|
||||
cleanups performed by ~org-insert-link~, including cleaning up =<...>= brackets,
|
||||
stripping current buffer file path from the link, and adjusting =file:= links
|
||||
according to ~org-link-file-path-type~.
|
||||
|
||||
*** ob-comint: New optional arguments controlling prompt handling
|
||||
|
||||
The new argument ~prompt-handling~ in ~org-babel-comint-with-output~
|
||||
and ~org-babel-comint-async-register~ allows Babel languages to
|
||||
specify how prompts should be handled in comint output. If equal to
|
||||
~filter-prompts~, prompts are removed from output before it is passed
|
||||
on to language-specific processing. If equal to
|
||||
~disable-prompt-filtering~, then the prompt filtering is skipped. If
|
||||
unset, then the default behavior is the same as ~filter-prompts~ for
|
||||
backwards compatibility.
|
||||
|
||||
Prompt filtering is needed for some Babel languages, such as ob-shell,
|
||||
which leave extra prompts in the output as a side effect of
|
||||
evaluation. However, other Babel languages, like ob-python, don't
|
||||
leave extra prompts after evaluation, and skipping the prompt
|
||||
filtering can be more robust for such languages (as this avoids
|
||||
removing false positive prompts).
|
||||
|
||||
*** Elisp functions for new datetree tree-types
|
||||
|
||||
Accompanying the [[#9.8-datetree-treetype][new datetree capture ~:tree-type~ options]], on the
|
||||
elisp level ~org-datetree-find-create-entry~ and
|
||||
~org-datetree-find-create-hierarchy~ generalize
|
||||
~org-datetree-find-date-create~, ~org-datetree-find-month-create~, and
|
||||
~org-datetree-find-iso-week-create~ to new datetree types.
|
||||
|
||||
*** New function ~org-src-get-lang-mode-if-bound~
|
||||
|
||||
The new function is like ~org-src-get-lang-mode~, except that it
|
||||
ensures the returned major mode for the given language is bound, and
|
||||
so available to the user. If the mode is not bound, the function can
|
||||
optionally return a fallback mode and display a message when doing so.
|
||||
The function was added so that Org can fall back to Fundamental mode
|
||||
for source blocks where the appropriate major mode is unavailable.
|
||||
|
||||
*** New function ~org-gnus-no-new-news-other-frame~ (to be used in ~org-link-frame-setup~)
|
||||
|
||||
The new function is like ~org-gnus-no-new-news~, but always opens the
|
||||
link in other frame.
|
||||
|
||||
*** New function ~org-string-width-invisibility-spec~
|
||||
|
||||
The new function constructs an invisibility spec without folds and
|
||||
ellipses, suitable for ~org-string-width~. This can be helpful for
|
||||
performance if ~org-string-width~ is called multiple times.
|
||||
|
||||
*** New command ~org-link-preview~ to preview Org links
|
||||
|
||||
This command replaces ~org-toggle-inline-images~, which is now
|
||||
obsolete.
|
||||
|
||||
*** New command ~org-link-preview-region~ to preview Org links in a region or the buffer
|
||||
|
||||
This command replaces ~org-display-inline-images~, which is now
|
||||
obsolete.
|
||||
|
||||
*** New command ~org-link-preview-clear~ to clear Org link previews in a region or the buffer
|
||||
|
||||
This command replaces ~org-remove-inline-images~, which is now
|
||||
obsolete.
|
||||
|
||||
*** New command ~org-link-preview-refresh~ to refresh Org link previews in the buffer
|
||||
|
||||
This command replaces ~org-redisplay-inline-images~, which is now
|
||||
obsolete.
|
||||
|
||||
*** ~org-html-head~ and ~org-html-head-extra~ can now be specified as functions
|
||||
|
||||
Previously, ~org-html-head~ and ~org-html-head-extra~ could only be
|
||||
specified directly as strings. Now, they can be set to functions that
|
||||
accept the INFO channel and return a string. This makes it possible
|
||||
to dynamically generate the content of the resulting ~<head>~ tag in
|
||||
the resulting HTML document.
|
||||
|
||||
*** ~org-element-create~ now ignores ~nil~s in CHILDREN argument
|
||||
|
||||
When CHILDREN contains ~nil~ elements, they are skipped. This way,
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(let ((children nil))
|
||||
(org-element-create 'section nil children)) ; => (section nil)
|
||||
#+end_src
|
||||
|
||||
will yield expected results rather than assigning literal ~nil~ as a child.
|
||||
|
||||
*** ~org-clock-get-clock-string~ now takes an optional ~max-length~ argument
|
||||
|
||||
When a ~max-length~ is passed to ~org-clock-get-clock-string~, it will first
|
||||
attempt to truncate the headline and add an ellipsis in order to make the entire
|
||||
clock string fit under the length limit. If the length limit is too small to
|
||||
accommodate even a single character of the headline, after accounting for spaces
|
||||
and the surrounding parentheses, it will omit the headline entirely and just
|
||||
show as much of the clock as fits under the limit.
|
||||
|
||||
*** ~org-string-width~ now takes an optional ~invisibility-spec~ argument
|
||||
|
||||
For performance, if the invisibility spec has been constructed, it can
|
||||
be passed in as ~invisibility-spec~ instead of having it be
|
||||
constructed again.
|
||||
|
||||
** Removed or renamed functions and variables
|
||||
|
||||
*** Obsolete functions and variables removed from ~org-datetree~
|
||||
|
||||
Due to the refactoring of ~org-datetree~ to support the [[#9.8-datetree-treetype][new datetree
|
||||
capture ~:tree-type~ options]], the internal variable
|
||||
~org-datetree-base-level~ has been removed, as well as the
|
||||
undocumented helper function ~org-datetree-insert-line~.
|
||||
|
||||
*** Obsolete functions ~org-let~ and ~org-let2~ are removed
|
||||
|
||||
If any code is still using these ancient functions, it should move to ~cl-progv~.
|
||||
|
||||
*** ~org-show-empty-lines-in-parent~ is now obsolete
|
||||
|
||||
This function is unused in Org code and does not appear to be used in third-party code.
|
||||
To be removed in future releases.
|
||||
|
||||
*** ~org-edit-src-content-indentation~ is renamed to ~org-src-content-indentation~
|
||||
|
||||
The new name highlights that the customization affects more than
|
||||
editing. ~org-src-content-indentation~ also affects detangling,
|
||||
printing Org syntax tree (for example, during export to Org), and
|
||||
indentation of src and example blocks in Org buffers.
|
||||
|
||||
*** ~org-cycle-display-inline-images~ is renamed to ~org-cycle-display-link-previews~
|
||||
|
||||
Inline image previews in Org mode are now provided by the more general
|
||||
link previews feature. The behavior with regard to image links is
|
||||
unchanged.
|
||||
|
||||
*** ~org-cycle-inline-images-display~ is renamed to ~org-cycle-link-previews-display~
|
||||
|
||||
The behavior is unchanged, except in that the new variable now affects
|
||||
previews of supported link types besides image links.
|
||||
|
||||
*** ~org-startup-with-inline-images~ is renamed to ~org-startup-with-link-previews~
|
||||
|
||||
The behavior is unchanged, except in that the new variable now affects
|
||||
previews of supported link types besides image links.
|
||||
|
||||
*** =ob-ditaa=: =org-babel-ditaa-java-cmd= renamed and =org-ditaa-jar-option= made obsolete
|
||||
|
||||
To align with other customizable variable names, which do not contain
|
||||
the word =babel=, variable =org-babel-ditaa-java-cmd= has been renamed
|
||||
to =org-ditaa-java-exec=. The old variable =org-babel-ditaa-java-cmd=
|
||||
is still available as an obsolete alias.
|
||||
|
||||
Variable =org-ditaa-jar-option= did not serve any sensible purpose and
|
||||
has been made obsolete. Its value is still used in place of default
|
||||
parameter -jar if the variable is defined.
|
||||
|
||||
** Miscellaneous
|
||||
*** =ob-calc.el=: Vector and matrix are now inserted as Org tables by default
|
||||
|
||||
~ob-calc~ now formats vector and matrix results as Org tables. This
|
||||
conversion can be overridden using the ~:results verbatim~ keyword on
|
||||
a per source block basis.
|
||||
|
||||
To get back the old behavior, add
|
||||
|
||||
#+begin_example
|
||||
(with-eval-after-load 'ob-calc
|
||||
(setq org-babel-header-args:calc
|
||||
(append '(:results . "verbatim") org-babel-header-args:calc)))
|
||||
#+end_example
|
||||
|
||||
to your configuration.
|
||||
|
||||
The new behavior follows general babel backend rules (auto-detecting
|
||||
result type), but may affect the existing usage.
|
||||
|
||||
*** ~orgtbl-to-generic~ retains special rows when exporting to Org
|
||||
|
||||
Previously, special table rows were unconditionally removed when
|
||||
export to Org. Now, the defaults follow what ox-org does - to retain
|
||||
special rows by default. See [[https://orgmode.org/worg/org-release-notes.html#ox-org-special-table-rows][previous change]].
|
||||
|
||||
To retain the old behavior, add ~:with-special-rows nil~ to PARAMS argument:
|
||||
|
||||
: (orgtbl-to-generic table '(:with-special-rows nil)
|
||||
|
||||
*** ~org-babel-lob-ingest~ no longer performs noweb expansion when ingesting blocks
|
||||
|
||||
Previously, ~org-babel-lob-ingest~ would expand noweb references when
|
||||
adding source blocks to the Library of Babel. Now, blocks are stored
|
||||
with unexpanded noweb references.
|
||||
|
||||
Noweb expansion is handled appropriately when blocks are actually used
|
||||
via ~org-babel-execute-src-block~ or ~org-babel-exp-do-export~, with
|
||||
the correct context (~:tangle~, ~:export~, or ~:eval~).
|
||||
|
||||
This change is unlikely to affect most users, but code that directly
|
||||
accesses ~org-babel-library-of-babel~ may observe the difference.
|
||||
|
||||
*** Trailing =-= is now allowed in plain links
|
||||
|
||||
Previously, plain links like
|
||||
|
||||
: https://domain/test-
|
||||
|
||||
did not include the trailing =-= punctuation.
|
||||
|
||||
Now, the =-= is allowed at the end, and is considered a part of the plain link.
|
||||
|
||||
#+begin_quote
|
||||
These types of links will likely be encountered for sites where anchor
|
||||
targets are automatically generated from documentation headings which
|
||||
are questions.
|
||||
https://list.orgmode.org/orgmode/87sexh9ddv.fsf@ice9.digital/
|
||||
#+end_quote
|
||||
|
||||
*** Update of statistics cookies now respects narrowing
|
||||
|
||||
Calling ~org-update-statistics-cookies~ with a prefix argument will
|
||||
now only update cookies in the accessible portion of the buffer.
|
||||
|
||||
*** ox-man: Support specifying =#+DATE:= and ~org-export-with-date~
|
||||
|
||||
Previously, ox-man ignored =#+DATE:= keyword even when
|
||||
~org-export-with-date~ is set to non-nil. Now, the date is exported
|
||||
and specified in the =footer-middle= argument of =.TH= macro (see ~man
|
||||
7 man~).
|
||||
|
||||
*** ox-man: Support specifying =:release= and =:header= in =#+MAN_CLASS_OPTIONS:= in addition to =:section-id=
|
||||
|
||||
The newly added =:release= and =:header= options of =#+MAN_CLASS_OPTIONS=
|
||||
are respectively mapped to the =footer-inside= and =header-middle=
|
||||
arguments of the =.TH= macro (see ~man 7 groff_man~).
|
||||
|
||||
*** ~org-capture~ target pointing to headline is now handled uniformly for =plain= entry type
|
||||
|
||||
Previously, when using ~file+regexp~, ~file+function~ or ~function~, =plain= entries
|
||||
were inserted right at the point according to regexp/function, even when point is
|
||||
on an existing headline.
|
||||
|
||||
Now, when target points to an existing headline, =plain= entries are
|
||||
inserted inside its body, honoring ~:prepend~ property. This is more
|
||||
consistent with how ~item~, ~checkitem~, and ~table-line~ templates
|
||||
are handled.
|
||||
|
||||
*** ~org-lint~ now checks priorities
|
||||
|
||||
Warnings are raised on headlines containing out-of-bounds, invalid
|
||||
(e.g., =[#-1]=, =[#AA]=), or malformed (e.g., =[#1=, =[#A=)
|
||||
priorities.
|
||||
|
||||
*** In Dot code blocks, ~graphviz-dot-mode~ is used if available
|
||||
|
||||
Previously, when editing Dot code blocks with =M-x org-edit-special=,
|
||||
Dot code would open in Fundamental mode, even when specialized mode is
|
||||
installed. The new behavior is more DWIM.
|
||||
|
||||
*** Source blocks fall back to Fundamental mode
|
||||
|
||||
Org now falls back to Fundamental mode for source blocks when the
|
||||
appropriate major mode is unavailable.
|
||||
|
||||
*** Priority speed commands adapt to user options
|
||||
|
||||
Previously, =1=, =2=, and =3= would insert priorities =A=, =B=, and
|
||||
=C=, which causes errors when using numeric priorities. These now
|
||||
insert ~org-priority-highest~, ~org-priority-default~, and
|
||||
~org-priority-lowest~, respectively.
|
||||
|
||||
*** ~org-store-link~ no longer asks to select store function when called noninteractively
|
||||
|
||||
Previously, when multiple store functions are available to store link
|
||||
at point, ~org-store-link~ would always ask user which store function
|
||||
to use.
|
||||
|
||||
Now, when ~org-store-link~ is called noninteractively (~interactive?~
|
||||
argument is nil), the first matching store function is used.
|
||||
Interactively, the previous behavior is retained.
|
||||
|
||||
*** Org mode may throw an error when attempting to include remote unsafe resource noninteractively
|
||||
|
||||
Previously, when ~org-resource-download-policy~ is ~ask~ (default),
|
||||
and Emacs is running in batch mode, Org mode simply skipped unsafe
|
||||
remote resources in the =#+include:='s. Now, an error is thrown to
|
||||
avoid seemingly ignored =#+include= statements when publishing via
|
||||
batch scripts.
|
||||
|
||||
*** HTML export wraps ~<code>~ around all the exported src blocks
|
||||
|
||||
HTML export always uses ~<pre>~ tag around exported src blocks.
|
||||
In addition, previously, HTML export used ~<code>~ tag around src
|
||||
blocks when ~org-html-klipsify-src~ is non-nil.
|
||||
|
||||
Now, both ~<pre>~ and ~<code>~ tags are *always* wrapped around the
|
||||
export src blocks.
|
||||
|
||||
*** ~yank-media~ and DND handlers now honor the user option ~org-file-link-type~
|
||||
|
||||
When inserting file: links, ~yank-media~ and DND handlers now respect
|
||||
the user option ~org-file-link-type~.
|
||||
|
||||
*** ~org-timer-done-hook~ is now run before the timer is stopped
|
||||
|
||||
Previously, ~org-timer-countdown-timer~ and ~org-timer-start-time~
|
||||
were unset when the hook is run. Now, they still hold the timer info.
|
||||
|
||||
*** ox-latex: LaTeX images are now stored alongside the exported =.html= file
|
||||
|
||||
Previously, LaTeX images (when HTML export does use images for LaTeX)
|
||||
were stored alongside the original =.org= file. Now, they are stored
|
||||
alongside the =.html= file.
|
||||
|
||||
This change will make links to LaTeX images point to the folder
|
||||
containing =.html= file, not the =.org= file.
|
||||
|
||||
*** Org mode no longer prevents =flyspell= from spell-checking inside =LOGBOOK= drawers
|
||||
|
||||
Previously, spell-checking via =flyspell= was disabled inside
|
||||
=LOGBOOK= (or ~org-log-into-drawer~) drawers. Now, it is no longer
|
||||
the case. It can be useful to see spelling mistakes inside notes
|
||||
added via ~org-add-note~ command.
|
||||
|
||||
*** ~ob-R~ and ~ob-julia~ no longer use ESS settings for working directory
|
||||
|
||||
Previously, without =:dir= parameter, R and Julia code blocks could
|
||||
query for working directory during evaluation. This was because
|
||||
~ess-ask-for-ess-directory~ setting was obeyed.
|
||||
|
||||
Now, ~ess-ask-for-ess-directory~, ~ess-directory-function~, and
|
||||
~ess-directory~ are all ignored during code block evaluation (except
|
||||
when session is already running). In other words, R and Julia code
|
||||
blocks now conform to the "16.4 Environment of a Code Block" section
|
||||
of Org mode manual that prescribes Org buffer directory or ~:dir~
|
||||
value to be used as working dir to run the code blocks.
|
||||
|
||||
*** ~org-cancel-repeater~ now cancels all the repeaters inside entry
|
||||
|
||||
Previously, ~org-cancel-repeater~ only canceled repeater in the first
|
||||
active timestamp inside heading. Now, all the repeaters are
|
||||
canceled.
|
||||
|
||||
The function is renamed to ~org-cancel-repeaters~ accordingly (the old
|
||||
name is still kept as an alias).
|
||||
|
||||
*** ~org-refile~ now saves current position to Org mark ring when jumping to heading
|
||||
|
||||
When ~org-refile~ is called with =C-u= or =C-u C-u= prefix argument
|
||||
(to jump to heading or to jump to the last refiled heading), it saves
|
||||
point to Org mark ring before jumping. Then, the user can return back
|
||||
via ~org-mark-ring-goto~.
|
||||
|
||||
*** =org-attach= now considers symlinked files when searching pre-existing attach dirs
|
||||
|
||||
When Org buffer is opened from a symlink, Org mode looks into the
|
||||
original file directory when searching if an attachment directory already exists.
|
||||
This way, attachments will remain accessible when opening symlinked Org file.
|
||||
|
||||
When no attach dir exists, Org mode will still prefer creating it in
|
||||
the "default" directory - where the symlink is located.
|
||||
|
||||
*** Texinfo exporter now supports links in headings
|
||||
|
||||
The Texinfo exporter no longer removes links from headings. This
|
||||
applies to all headings, below and above the =H= and =toc= export
|
||||
=#+OPTIONS:=.
|
||||
|
||||
*** Texinfo exporter now considers numeric =toc= values in =#+OPTIONS:=
|
||||
|
||||
For example, given =H:3= and =toc:2= in =#+OPTIONS:=, all headings at
|
||||
the 1st and 2nd level appear in the table of contents and those at the
|
||||
3rd level do not.
|
||||
|
||||
*** =ob-tangle= now tangles source blocks that do not specify a =language= if an inherited property sets a tangle filename
|
||||
|
||||
Previously, all source blocks that did not specify a =language= where
|
||||
ignored by ~org-babel-tangle-collect-blocks~. Now, if it inherits a
|
||||
:tangle header argument with a value other than =no= or =yes= (that is, a
|
||||
filename), a source block without =language= will get tangled to that
|
||||
file.
|
||||
|
||||
*** BibTeX is tangled with the standard =.bib= file extension
|
||||
|
||||
Previously, =bibtex= source blocks located in a file named =NAME.org=
|
||||
were tangled into a file named =NAME.bibtex=. Now, they are tangled
|
||||
into a file named =FILE.bib=, using the standard extension =.bib=,
|
||||
matching the rest of the ecosystem, including BibTeX and LaTeX.
|
||||
|
||||
*** LaTeX export now respects ~org-latex-with...~ options in the PDF metadata
|
||||
|
||||
Previously, the LaTeX exporter handled the PDF metadata =pdfcreator=,
|
||||
=pdfauthor= and =pdftitle= as defined in
|
||||
~org-latex-hyperref-template~. This has changed, and these three fields
|
||||
will be defined as empty and not produce any metadata if their
|
||||
corresponding ~org-latex-with-author~, ~org-latex-with-title~, or
|
||||
~org-latex-with-creator~ option is set to ~nil~.
|
||||
|
||||
*** Fancy HTML5 export uses ~<time>~ element for timestamps
|
||||
Previously, timestamps would always be rendered inside a ~<span
|
||||
class="timestamp">~. Now, if both ~org-html-doctype~ is ~html5~ and
|
||||
~org-html-html5-fancy~ is enabled, org will use the semantic
|
||||
~<time>~ element. This will also have the ~timestamp~ class, but
|
||||
additionally set the ~datetime~ attribute with a machine-readable
|
||||
variant of the timestamp. The format used for the attribute can be
|
||||
customized using ~org-html-datetime-formats~.
|
||||
|
||||
*** Export dispatcher supports arrow keys and mouse wheel
|
||||
|
||||
Previously, the arrow keys and the mouse wheel were ignored in the
|
||||
export dispatcher, ~org-export-dispatch~ bound to =C-c C-e=. Now,
|
||||
they scroll the text in the export dispatcher window.
|
||||
|
||||
*** Add completion for ID links
|
||||
|
||||
Completion is enabled for ID links inserted with ~org-insert-link~.
|
||||
Completion candidates, by default, will be sourced from all files
|
||||
known to contain headlines with IDs. You can use new option
|
||||
~org-id-completion-targets~ to change where the candidates are
|
||||
searched.
|
||||
|
||||
*** Pre-populate the description for BBDB links
|
||||
|
||||
When inserting BBDB links, use the full name as the default link
|
||||
description, instead of nothing.
|
||||
|
||||
* Version 9.7
|
||||
|
||||
** Important announcements and breaking changes
|
||||
|
|
@ -285,6 +1202,9 @@ Images dropped also respect the value of ~org-yank-image-save-method~
|
|||
when ~org-yank-dnd-method~ is =attach=.
|
||||
|
||||
*** Alignment of image previews can be customized
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: preview-align
|
||||
:END:
|
||||
|
||||
Previously, all the image previews were always left-aligned.
|
||||
|
||||
|
|
@ -1634,6 +2554,9 @@ Previously, all the header arguments where stripped from src blocks
|
|||
during export. Now, header arguments are preserved.
|
||||
|
||||
*** =ox-org= now exports special table rows by default
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: ox-org-special-table-rows
|
||||
:END:
|
||||
|
||||
Previously, when exporting to Org, special table rows (for example,
|
||||
width cookies) were not exported. Now, they are exported by default.
|
||||
|
|
@ -4205,10 +5128,13 @@ wget -c "https://ben.akrin.com/crackzor/crackzor_1.0.c.gz"
|
|||
#+end_example
|
||||
|
||||
*** Add ~:session~ support of ob-js for js-comint
|
||||
|
||||
#+begin_src js :session "*Javascript REPL*"
|
||||
console.log("stardiviner")
|
||||
#+end_src
|
||||
|
||||
# SIC, JavaScript miscapitalized in `js-comint.el'.
|
||||
|
||||
*** Add ~:session~ support of ob-js for Indium
|
||||
#+begin_src js :session "*JS REPL*"
|
||||
console.log("stardiviner")
|
||||
|
|
|
|||
|
|
@ -404,9 +404,6 @@
|
|||
<style:style style:name="OrgTags" style:family="text"/>
|
||||
|
||||
<style:style style:name="OrgPriority" style:family="text"/>
|
||||
<style:style style:name="OrgPriority-A" style:family="text" style:parent-style-name="OrgPriority"/>
|
||||
<style:style style:name="OrgPriority-B" style:family="text" style:parent-style-name="OrgPriority"/>
|
||||
<style:style style:name="OrgPriority-C" style:family="text" style:parent-style-name="OrgPriority"/>
|
||||
|
||||
<style:style style:name="OrgTimestamp" style:display-name="OrgTimestamp" style:family="text">
|
||||
<style:text-properties style:font-name="Courier New" fo:background-color="transparent" style:font-name-asian="NSimSun" style:font-name-complex="Courier New"/>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
% Reference Card for Org Mode
|
||||
\def\orgversionnumber{9.7.11}
|
||||
\def\versionyear{2024} % latest update
|
||||
\def\orgversionnumber{9.8.1}
|
||||
\def\versionyear{2026} % latest update
|
||||
\input emacsver.tex
|
||||
|
||||
%**start of header
|
||||
|
|
@ -401,7 +401,7 @@ \section{Tables}
|
|||
formula, \kbd{:=} a field formula.
|
||||
|
||||
\key{Example: Add Col1 and Col2}{|=\$1+\$2 |}
|
||||
\key{... with printf format specification}{|=\$1+\$2;\%.2f|}
|
||||
\key{... with printf-style format specification}{|=\$1+\$2;\%.2f|}
|
||||
\key{... with constants from constants.el}{|=\$1/\$c/\$cm |}
|
||||
\metax{sum from 2nd to 3rd hline}{|:=vsum(@II..@III)|}
|
||||
\key{apply current column formula}{| = |}
|
||||
|
|
|
|||
|
|
@ -482,7 +482,6 @@ int get_column_num (int nbcols, const char** header, const char* column)
|
|||
(defun org-babel-C-header-to-C (head type)
|
||||
"Convert an elisp list of header table into a C or D vector
|
||||
specifying a variable with the name of the table."
|
||||
(unless noninteractive (message "%S" type))
|
||||
(let ((table (car head))
|
||||
(headers (cdr head))
|
||||
(typename (pcase type
|
||||
|
|
|
|||
|
|
@ -35,13 +35,24 @@
|
|||
(require 'cl-lib)
|
||||
(require 'ob)
|
||||
|
||||
(require 'subr-x) ; For `string-trim-right', Emacs < 28
|
||||
|
||||
(declare-function orgtbl-to-tsv "org-table" (table params))
|
||||
(declare-function run-ess-r "ext:ess-r-mode" (&optional start-args))
|
||||
(declare-function inferior-ess-send-input "ext:ess-inf" ())
|
||||
(declare-function ess-make-buffer-current "ext:ess-inf" ())
|
||||
(declare-function ess-eval-buffer "ext:ess-inf" (vis))
|
||||
(declare-function ess-wait-for-process "ext:ess-inf"
|
||||
(&optional proc sec-prompt wait force-redisplay))
|
||||
(declare-function ess-send-string "ext:ess-inf"
|
||||
(process string &optional visibly message type))
|
||||
|
||||
(defvar ess-current-process-name) ; ess-custom.el
|
||||
(defvar ess-local-process-name) ; ess-custom.el
|
||||
(defvar ess-ask-for-ess-directory) ; ess-custom.el
|
||||
(defvar ess-directory-function) ; ess-custom.el
|
||||
(defvar ess-directory) ; ess-custom.el
|
||||
(defvar ess-gen-proc-buffer-name-function) ; ess-custom.el
|
||||
(defvar ess-eval-visibly) ; ess-custom.el
|
||||
|
||||
(defconst org-babel-header-args:R
|
||||
'((width . :any)
|
||||
|
|
@ -239,7 +250,10 @@ Retrieve variables from PARAMS."
|
|||
(min (if lengths (apply 'min lengths) 0)))
|
||||
;; Ensure VALUE has an orgtbl structure (depth of at least 2).
|
||||
(unless (listp (car value)) (setq value (mapcar 'list value)))
|
||||
(let ((file (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field)))
|
||||
(let ((file (orgtbl-to-tsv
|
||||
value
|
||||
'( :fmt org-babel-R-quote-tsv-field
|
||||
:with-special-rows nil)))
|
||||
(header (if (or (eq (nth 1 value) 'hline) colnames-p)
|
||||
"TRUE" "FALSE"))
|
||||
(row-names (if rownames-p "1" "NULL")))
|
||||
|
|
@ -254,19 +268,17 @@ Retrieve variables from PARAMS."
|
|||
(t (format "%s <- %S" name (prin1-to-string value))))))
|
||||
|
||||
|
||||
(defvar ess-current-process-name) ; dynamically scoped
|
||||
(defvar ess-local-process-name) ; dynamically scoped
|
||||
(defvar ess-ask-for-ess-directory) ; dynamically scoped
|
||||
(defvar ess-gen-proc-buffer-name-function) ; defined in ess-inf.el
|
||||
(defun org-babel-R-initiate-session (session params)
|
||||
"Create or return the current R SESSION buffer.
|
||||
Use PARAMS to set default directory when creating a new session."
|
||||
(defun org-babel-R-initiate-session (session _params)
|
||||
"Create or return the current R SESSION buffer."
|
||||
(unless (string= session "none")
|
||||
(let* ((session (or session "*R*"))
|
||||
(ess-ask-for-ess-directory
|
||||
(and (boundp 'ess-ask-for-ess-directory)
|
||||
ess-ask-for-ess-directory
|
||||
(not (cdr (assq :dir params)))))
|
||||
;; Force using `default-directory', as we promise in the
|
||||
;; manual. The caller should have taken care about setting
|
||||
;; it according to :dir if necessary.
|
||||
;; https://ess.r-project.org/Manual/ess.html#Changing-the-startup-actions
|
||||
(ess-ask-for-ess-directory nil)
|
||||
(ess-directory-function nil)
|
||||
(ess-directory nil)
|
||||
;; Make ESS name the process buffer as SESSION.
|
||||
(ess-gen-proc-buffer-name-function
|
||||
(lambda (_) session)))
|
||||
|
|
@ -442,26 +454,20 @@ last statement in BODY, as elisp."
|
|||
(org-babel-import-elisp-from-file tmp-file '(16)))
|
||||
column-names-p)))
|
||||
(output
|
||||
(mapconcat
|
||||
'org-babel-chomp
|
||||
(butlast
|
||||
(delq nil
|
||||
(mapcar
|
||||
(lambda (line) (when (> (length line) 0) line))
|
||||
(mapcar
|
||||
(lambda (line) ;; cleanup extra prompts left in output
|
||||
(if (string-match
|
||||
"^\\([>+.]\\([ ][>.+]\\)*[ ]\\)"
|
||||
(car (split-string line "\n")))
|
||||
(substring line (match-end 1))
|
||||
line))
|
||||
(let ((tmp-src-file (org-babel-temp-file "R-")))
|
||||
(with-temp-file tmp-src-file
|
||||
(insert (concat
|
||||
(org-babel-chomp body) "\n" org-babel-R-eoe-indicator)))
|
||||
(with-current-buffer session
|
||||
(let ((comint-prompt-regexp (concat "^" comint-prompt-regexp)))
|
||||
(org-babel-comint-with-output (session org-babel-R-eoe-output)
|
||||
(insert (mapconcat 'org-babel-chomp
|
||||
(list body org-babel-R-eoe-indicator)
|
||||
"\n"))
|
||||
(inferior-ess-send-input)))))))) "\n"))))
|
||||
(org-babel-chomp
|
||||
(string-trim-right
|
||||
(org-babel-comint-with-output
|
||||
(session org-babel-R-eoe-output nil nil 'disable-prompt-filtering)
|
||||
(ess-send-string (get-buffer-process (current-buffer))
|
||||
(format "source('%s', echo=F, print.eval=T)"
|
||||
(org-babel-process-file-name
|
||||
tmp-src-file 'noquote))))
|
||||
(rx (literal org-babel-R-eoe-output) (zero-or-more anychar)))))))))
|
||||
|
||||
(defun org-babel-R-process-value-result (result column-names-p)
|
||||
"R-specific processing of return value.
|
||||
|
|
@ -486,7 +492,8 @@ by `org-babel-comint-async-filter'."
|
|||
session (current-buffer)
|
||||
"^\\(?:[>.+] \\)*\\[1\\] \"ob_comint_async_R_\\(start\\|end\\|file\\)_\\(.+\\)\"$"
|
||||
'org-babel-chomp
|
||||
'ob-session-async-R-value-callback)
|
||||
'ob-session-async-R-value-callback
|
||||
'disable-prompt-filtering)
|
||||
(cl-case result-type
|
||||
(value
|
||||
(let ((tmp-file (org-babel-temp-file "R-")))
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@
|
|||
"Execute a block of Awk code BODY with org-babel.
|
||||
PARAMS is a plist of src block parameters .
|
||||
This function is called by `org-babel-execute-src-block'."
|
||||
(unless noninteractive (message "Executing Awk source code block"))
|
||||
(let* ((result-params (cdr (assq :result-params params)))
|
||||
(cmd-line (cdr (assq :cmd-line params)))
|
||||
(in-file (cdr (assq :in-file params)))
|
||||
|
|
@ -112,7 +111,11 @@ table."
|
|||
(let ((echo-var (lambda (v) (if (stringp v) v (format "%S" v)))))
|
||||
(cond
|
||||
((and (listp var) (listp (car var)))
|
||||
(orgtbl-to-generic var (list :sep (or sep "\t") :fmt echo-var)))
|
||||
(orgtbl-to-generic
|
||||
var
|
||||
(list :sep (or sep "\t")
|
||||
:fmt echo-var
|
||||
:with-special-rows nil)))
|
||||
((listp var)
|
||||
(mapconcat echo-var var "\n"))
|
||||
(t (funcall echo-var var)))))
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@
|
|||
(require 'calc-trail)
|
||||
(require 'calc-store)
|
||||
|
||||
(declare-function calc-store-into "calc-store" (&optional var))
|
||||
(declare-function calc-recall "calc-store" (&optional var))
|
||||
(declare-function math-evaluate-expr "calc-ext" (x))
|
||||
|
||||
(defvar org-babel-default-header-args:calc nil
|
||||
|
|
@ -114,11 +112,30 @@
|
|||
))))))
|
||||
(mapcar #'org-trim
|
||||
(split-string (org-babel-expand-body:calc body params) "[\n\r]"))))
|
||||
(save-excursion
|
||||
(with-current-buffer "*Calculator*"
|
||||
(prog1
|
||||
(calc-eval (calc-top 1))
|
||||
(calc-pop 1)))))
|
||||
(let ((result (prog1
|
||||
;; Cannot use 'top' as SEPARATOR reliably when the
|
||||
;; top of the stack has a vector.
|
||||
(calc-eval (calc-top 1) 'raw)
|
||||
(calc-eval 1 'pop)))
|
||||
(calc-line-numbering)
|
||||
lisp-table)
|
||||
(org-babel-reassemble-table
|
||||
(org-babel-result-cond (cdr (assq :result-params params))
|
||||
(calc-eval result)
|
||||
(if (Math-vectorp result)
|
||||
(progn
|
||||
(dolist (r (if (math-matrixp result)
|
||||
(cdr result) ; Ignore the 'vec item.
|
||||
(list result)))
|
||||
(setq r (cdr r)) ; Ignore the 'vec item.
|
||||
(push (mapcar (lambda (x) (math-format-stack-value (list x 1 nil))) r)
|
||||
lisp-table))
|
||||
(setq lisp-table (nreverse lisp-table)))
|
||||
(calc-eval result)))
|
||||
(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-calc-maybe-resolve-var (el)
|
||||
"Resolve user variables in EL.
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@
|
|||
(require 'ob)
|
||||
|
||||
(declare-function cider-current-connection "ext:cider-client" (&optional type))
|
||||
(declare-function cider-current-ns "ext:cider-client" ())
|
||||
(declare-function inf-clojure "ext:inf-clojure" (cmd))
|
||||
(declare-function inf-clojure-cmd "ext:inf-clojure" (project-type))
|
||||
(declare-function inf-clojure-eval-string "ext:inf-clojure" (code))
|
||||
|
|
@ -155,21 +154,21 @@ or set the `:backend' header argument"))))
|
|||
(result-params (cdr (assq :result-params params)))
|
||||
(print-level nil)
|
||||
(print-length nil)
|
||||
;; Remove comments, they break (let [...] ...) bindings
|
||||
(body (replace-regexp-in-string "^[ ]*;+.*$" "" body))
|
||||
(body (org-trim
|
||||
(concat
|
||||
;; Source block specified namespace :ns.
|
||||
(and (cdr (assq :ns params)) (format "(ns %s)\n" ns))
|
||||
;; Variables binding.
|
||||
(if (null vars) (org-trim body)
|
||||
;; Remove comments, they break (let [...] ...) bindings
|
||||
(let ((body (replace-regexp-in-string "^[ ]*;+.*$" "" body)))
|
||||
(format "(let [%s]\n%s)"
|
||||
(mapconcat
|
||||
(lambda (var)
|
||||
(format "%S '%S" (car var) (cdr var)))
|
||||
vars
|
||||
"\n ")
|
||||
body))))))
|
||||
body)))))))
|
||||
;; If the result param is set to "output" we don't have to do
|
||||
;; anything special and just let the backend handle everything
|
||||
(if (member "output" result-params)
|
||||
|
|
@ -237,8 +236,8 @@ or set the `:backend' header argument"))))
|
|||
"clojure" (format "clojure -A%s" alias)
|
||||
cmd0)
|
||||
cmd0)))
|
||||
(setq
|
||||
org-babel-comint-prompt-regexp-old comint-prompt-regexp
|
||||
(setq-local
|
||||
org-babel-comint-prompt-regexp-fallback comint-prompt-regexp
|
||||
comint-prompt-regexp inf-clojure-comint-prompt-regexp)
|
||||
(funcall-interactively #'inf-clojure cmd)
|
||||
(goto-char (point-max))))
|
||||
|
|
|
|||
|
|
@ -36,8 +36,13 @@
|
|||
|
||||
(require 'ob-core)
|
||||
(require 'org-compat)
|
||||
(require 'org-element-ast)
|
||||
|
||||
(require 'comint)
|
||||
|
||||
(declare-function org-element-context "org-element" (&optional element))
|
||||
(defvar org-element-inline-src-block-regexp)
|
||||
|
||||
(defun org-babel-comint-buffer-livep (buffer)
|
||||
"Check if BUFFER is a comint buffer with a live process."
|
||||
(let ((buffer (when buffer (get-buffer buffer))))
|
||||
|
|
@ -58,7 +63,8 @@ executed inside the protection of `save-excursion' and
|
|||
(let ((comint-input-filter (lambda (_input) nil)))
|
||||
,@body))))))
|
||||
|
||||
(defvar-local org-babel-comint-prompt-regexp-old nil
|
||||
(defvaralias 'org-babel-comint-prompt-regexp-old 'org-babel-comint-prompt-regexp-fallback)
|
||||
(defvar org-babel-comint-prompt-regexp-fallback nil
|
||||
"Fallback regexp used to detect prompt.")
|
||||
|
||||
(defcustom org-babel-comint-fallback-regexp-threshold 5.0
|
||||
|
|
@ -69,11 +75,11 @@ This is useful when prompt unexpectedly changes."
|
|||
:package-version '(Org . "9.7"))
|
||||
|
||||
(defun org-babel-comint--set-fallback-prompt ()
|
||||
"Swap `comint-prompt-regexp' and `org-babel-comint-prompt-regexp-old'."
|
||||
(when org-babel-comint-prompt-regexp-old
|
||||
"Swap `comint-prompt-regexp' and `org-babel-comint-prompt-regexp-fallback'."
|
||||
(when org-babel-comint-prompt-regexp-fallback
|
||||
(let ((tmp comint-prompt-regexp))
|
||||
(setq comint-prompt-regexp org-babel-comint-prompt-regexp-old
|
||||
org-babel-comint-prompt-regexp-old tmp))))
|
||||
(setq comint-prompt-regexp org-babel-comint-prompt-regexp-fallback
|
||||
org-babel-comint-prompt-regexp-fallback tmp))))
|
||||
|
||||
(defun org-babel-comint--prompt-filter (string &optional prompt-regexp)
|
||||
"Remove PROMPT-REGEXP from STRING.
|
||||
|
|
@ -100,15 +106,33 @@ PROMPT-REGEXP defaults to `comint-prompt-regexp'."
|
|||
(setq string (substring string (match-end 0))))
|
||||
string)
|
||||
|
||||
(defun org-babel-comint--remove-prompts-p (prompt-handling)
|
||||
"Helper to decide whether to remove prompts from comint output.
|
||||
Parses the symbol in PROMPT-HANDLING, which can be
|
||||
`filter-prompts', in which case prompts should be removed; or
|
||||
`disable-prompt-filtering', in which case prompt filtering is
|
||||
skipped. For backward-compatibility, the default value of `nil'
|
||||
is equivalent to `filter-prompts'."
|
||||
(cond
|
||||
((eq prompt-handling 'disable-prompt-filtering) nil)
|
||||
((eq prompt-handling 'filter-prompts) t)
|
||||
((eq prompt-handling nil) t)
|
||||
(t (error (format "Unrecognized prompt handling behavior %s"
|
||||
prompt-handling)))))
|
||||
|
||||
(defmacro org-babel-comint-with-output (meta &rest body)
|
||||
"Evaluate BODY in BUFFER and return process output.
|
||||
Will wait until EOE-INDICATOR appears in the output, then return
|
||||
all process output. If REMOVE-ECHO and FULL-BODY are present and
|
||||
non-nil, then strip echo'd body from the returned output. META
|
||||
should be a list containing the following where the last two
|
||||
elements are optional.
|
||||
non-nil, then strip echo'd body from the returned output.
|
||||
PROMPT-HANDLING may be either of the symbols `filter-prompts', in
|
||||
which case the output is split by `comint-prompt-regexp' and
|
||||
returned as a list; or, `disable-prompt-filtering', which
|
||||
suppresses this behavior and returns the full output as a string.
|
||||
META should be a list containing the following where the last
|
||||
three elements are optional.
|
||||
|
||||
(BUFFER EOE-INDICATOR REMOVE-ECHO FULL-BODY)
|
||||
(BUFFER EOE-INDICATOR REMOVE-ECHO FULL-BODY PROMPT-HANDLING)
|
||||
|
||||
This macro ensures that the filter is removed in case of an error
|
||||
or user `keyboard-quit' during execution of body."
|
||||
|
|
@ -116,7 +140,8 @@ or user `keyboard-quit' during execution of body."
|
|||
(let ((buffer (nth 0 meta))
|
||||
(eoe-indicator (nth 1 meta))
|
||||
(remove-echo (nth 2 meta))
|
||||
(full-body (nth 3 meta)))
|
||||
(full-body (nth 3 meta))
|
||||
(prompt-handling (nth 4 meta)))
|
||||
`(org-babel-comint-in-buffer ,buffer
|
||||
(let* ((string-buffer "")
|
||||
(comint-output-filter-functions
|
||||
|
|
@ -134,27 +159,25 @@ or user `keyboard-quit' during execution of body."
|
|||
,@body
|
||||
;; wait for end-of-evaluation indicator
|
||||
(let ((start-time (current-time)))
|
||||
(while (progn
|
||||
(goto-char comint-last-input-end)
|
||||
(not (save-excursion
|
||||
(and (re-search-forward
|
||||
(regexp-quote ,eoe-indicator) nil t)
|
||||
(re-search-forward
|
||||
comint-prompt-regexp nil t)))))
|
||||
(while (not (save-excursion
|
||||
(and (string-match
|
||||
(regexp-quote ,eoe-indicator) string-buffer)
|
||||
(string-match
|
||||
comint-prompt-regexp string-buffer))))
|
||||
(accept-process-output
|
||||
(get-buffer-process (current-buffer))
|
||||
org-babel-comint-fallback-regexp-threshold)
|
||||
(when (and org-babel-comint-prompt-regexp-old
|
||||
(when (and org-babel-comint-prompt-regexp-fallback
|
||||
(> (float-time (time-since start-time))
|
||||
org-babel-comint-fallback-regexp-threshold)
|
||||
(progn
|
||||
(goto-char comint-last-input-end)
|
||||
(save-excursion
|
||||
(and
|
||||
(re-search-forward
|
||||
(regexp-quote ,eoe-indicator) nil t)
|
||||
(re-search-forward
|
||||
org-babel-comint-prompt-regexp-old nil t)))))
|
||||
(string-match
|
||||
(regexp-quote ,eoe-indicator) string-buffer)
|
||||
(string-match
|
||||
org-babel-comint-prompt-regexp-fallback string-buffer)))))
|
||||
(org-babel-comint--set-fallback-prompt))))
|
||||
;; replace cut dangling text
|
||||
(goto-char (process-mark (get-buffer-process (current-buffer))))
|
||||
|
|
@ -164,8 +187,9 @@ or user `keyboard-quit' during execution of body."
|
|||
(and ,remove-echo ,full-body
|
||||
(setq string-buffer (org-babel-comint--echo-filter string-buffer ,full-body)))
|
||||
|
||||
;; Filter out prompts.
|
||||
(org-babel-comint--prompt-filter string-buffer)))))
|
||||
(if (org-babel-comint--remove-prompts-p ,prompt-handling)
|
||||
(org-babel-comint--prompt-filter string-buffer)
|
||||
string-buffer)))))
|
||||
|
||||
(defun org-babel-comint-input-command (buffer cmd)
|
||||
"Pass CMD to BUFFER.
|
||||
|
|
@ -189,14 +213,14 @@ statement (not large blocks of code)."
|
|||
(accept-process-output
|
||||
(get-buffer-process buffer)
|
||||
org-babel-comint-fallback-regexp-threshold)
|
||||
(when (and org-babel-comint-prompt-regexp-old
|
||||
(when (and org-babel-comint-prompt-regexp-fallback
|
||||
(> (float-time (time-since start-time))
|
||||
org-babel-comint-fallback-regexp-threshold)
|
||||
(progn
|
||||
(goto-char comint-last-input-end)
|
||||
(save-excursion
|
||||
(re-search-forward
|
||||
org-babel-comint-prompt-regexp-old nil t))))
|
||||
org-babel-comint-prompt-regexp-fallback nil t))))
|
||||
(org-babel-comint--set-fallback-prompt))))))
|
||||
|
||||
(defun org-babel-comint-eval-invisibly-and-wait-for-file
|
||||
|
|
@ -239,6 +263,9 @@ Its single argument is a string consisting of output from the
|
|||
comint process. It should return a string that will be passed
|
||||
to `org-babel-insert-result'.")
|
||||
|
||||
(defvar-local org-babel-comint-async-remove-prompts-p t
|
||||
"Whether prompts should be detected and removed from async output.")
|
||||
|
||||
(defvar-local org-babel-comint-async-dangling nil
|
||||
"Dangling piece of the last process output, as a string.
|
||||
Used when `org-babel-comint-async-indicator' is spread across multiple
|
||||
|
|
@ -290,8 +317,7 @@ STRING contains the output originally inserted into the comint buffer."
|
|||
(with-current-buffer buf
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(when (search-forward tmp-file nil t)
|
||||
(org-babel-previous-src-block)
|
||||
(when (org-babel-comint-async--find-src tmp-file)
|
||||
(let* ((info (org-babel-get-src-block-info))
|
||||
(params (nth 2 info))
|
||||
(result-params
|
||||
|
|
@ -326,17 +352,22 @@ STRING contains the output originally inserted into the comint buffer."
|
|||
until (and (equal (match-string 1) "start")
|
||||
(equal (match-string 2) uuid))
|
||||
finally return (+ 1 (match-end 0)))))
|
||||
;; Remove prompt
|
||||
(res-promptless (org-trim (string-join (mapcar #'org-trim (org-babel-comint--prompt-filter res-str-raw)) "\n") "\n"))
|
||||
;; Apply user callback
|
||||
(res-str (funcall org-babel-comint-async-chunk-callback res-promptless)))
|
||||
(res-str (funcall org-babel-comint-async-chunk-callback
|
||||
(if org-babel-comint-async-remove-prompts-p
|
||||
(org-trim (string-join
|
||||
(mapcar #'org-trim
|
||||
(org-babel-comint--prompt-filter
|
||||
res-str-raw))
|
||||
"\n")
|
||||
t)
|
||||
res-str-raw))))
|
||||
;; Search for uuid in associated org-buffers to insert results
|
||||
(cl-loop for buf in org-buffers
|
||||
until (with-current-buffer buf
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(when (search-forward uuid nil t)
|
||||
(org-babel-previous-src-block)
|
||||
(when (org-babel-comint-async--find-src uuid)
|
||||
(let* ((info (org-babel-get-src-block-info))
|
||||
(params (nth 2 info))
|
||||
(result-params
|
||||
|
|
@ -348,20 +379,63 @@ STRING contains the output originally inserted into the comint buffer."
|
|||
;; Remove uuid from the list to search for
|
||||
(setq uuid-list (delete uuid uuid-list)))))))))
|
||||
|
||||
(defun org-babel-comint-async--find-src (uuid-or-tmpfile)
|
||||
"Find source block associated with an async comint result.
|
||||
UUID-OR-TMPFILE is the uuid or tmpfile associated with the result.
|
||||
Returns non-nil if the source block is succesfully found, and moves
|
||||
point there.
|
||||
|
||||
This function assumes that UUID-OR-TMPFILE was previously inserted as
|
||||
the source block's result, as a placeholder until the true result
|
||||
becomes ready. It may fail to find the source block if the buffer was
|
||||
modified so that UUID-OR-TMPFILE is no longer the result of the source
|
||||
block, or if it has been copied elsewhere into the buffer (this is a
|
||||
limitation of the current async implementation)."
|
||||
(goto-char (point-min))
|
||||
(when (search-forward uuid-or-tmpfile nil t)
|
||||
(let ((uuid-pos (point)))
|
||||
(and (re-search-backward
|
||||
;; find the nearest preceding src or inline-src block
|
||||
(rx (or (regexp org-babel-src-block-regexp)
|
||||
(regexp org-element-inline-src-block-regexp)))
|
||||
nil t)
|
||||
;; check it's actually a src block and not verbatim text
|
||||
(org-element-type-p (org-element-context)
|
||||
'(inline-src-block src-block))
|
||||
;; Check result contains the uuid. There isn't a simple way
|
||||
;; to extract the result value that works in all cases
|
||||
;; (e.g. inline blocks or results drawers), so instead
|
||||
;; check the result region contains the found uuid position
|
||||
(let ((result-where (org-babel-where-is-src-block-result)))
|
||||
(when result-where
|
||||
(save-excursion
|
||||
(goto-char result-where)
|
||||
(and
|
||||
(>= uuid-pos (org-element-property :begin (org-element-context)))
|
||||
(< uuid-pos (org-element-property :end (org-element-context)))))))))))
|
||||
|
||||
(defun org-babel-comint-async-register
|
||||
(session-buffer org-buffer indicator-regexp
|
||||
chunk-callback file-callback)
|
||||
chunk-callback file-callback
|
||||
&optional prompt-handling)
|
||||
"Set local org-babel-comint-async variables in SESSION-BUFFER.
|
||||
ORG-BUFFER is added to `org-babel-comint-async-buffers' if not
|
||||
present. `org-babel-comint-async-indicator',
|
||||
`org-babel-comint-async-chunk-callback', and
|
||||
`org-babel-comint-async-file-callback' are set to
|
||||
INDICATOR-REGEXP, CHUNK-CALLBACK, and FILE-CALLBACK
|
||||
respectively."
|
||||
INDICATOR-REGEXP, CHUNK-CALLBACK, and FILE-CALLBACK respectively.
|
||||
PROMPT-HANDLING may be either of the symbols `filter-prompts', in
|
||||
which case prompts matching `comint-prompt-regexp' are filtered
|
||||
from output before it is passed to CHUNK-CALLBACK, or
|
||||
`disable-prompt-filtering', in which case this behavior is
|
||||
disabled. For backward-compatibility, the default value of `nil'
|
||||
is equivalent to `filter-prompts'."
|
||||
(org-babel-comint-in-buffer session-buffer
|
||||
(setq org-babel-comint-async-indicator indicator-regexp
|
||||
org-babel-comint-async-chunk-callback chunk-callback
|
||||
org-babel-comint-async-file-callback file-callback)
|
||||
(setq org-babel-comint-async-remove-prompts-p
|
||||
(org-babel-comint--remove-prompts-p prompt-handling))
|
||||
(unless (memq org-buffer org-babel-comint-async-buffers)
|
||||
(setq org-babel-comint-async-buffers
|
||||
(cons org-buffer org-babel-comint-async-buffers)))
|
||||
|
|
|
|||
|
|
@ -42,30 +42,26 @@
|
|||
nil))
|
||||
|
||||
(defvar org-babel-library-of-babel)
|
||||
(defvar org-edit-src-content-indentation)
|
||||
(defvar org-src-content-indentation)
|
||||
(defvar org-link-file-path-type)
|
||||
(defvar org-src-lang-modes)
|
||||
(defvar org-babel-tangle-uncomment-comments)
|
||||
|
||||
(declare-function org-attach-dir "org-attach" (&optional create-if-not-exists-p no-fs-check))
|
||||
(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-table" (&optional table-type))
|
||||
(declare-function org-babel-lob-execute-maybe "ob-lob" ())
|
||||
(declare-function org-babel-ref-goto-headline-id "ob-ref" (id))
|
||||
(declare-function org-babel-ref-headline-body "ob-ref" ())
|
||||
(declare-function org-babel-ref-parse "ob-ref" (assignment))
|
||||
(declare-function org-babel-ref-resolve "ob-ref" (ref))
|
||||
(declare-function org-babel-ref-split-args "ob-ref" (arg-string))
|
||||
(declare-function org-babel-tangle-comment-links "ob-tangle" (&optional info))
|
||||
(declare-function org-current-level "org" ())
|
||||
(declare-function org-cycle "org-cycle" (&optional arg))
|
||||
(declare-function org-edit-src-code "org-src" (&optional code edit-buffer-name))
|
||||
(declare-function org-edit-src-exit "org-src" ())
|
||||
(declare-function org-src-preserve-indentation-p "org-src" (node))
|
||||
(declare-function org-src-preserve-indentation-p "org-src" (&optional node))
|
||||
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
|
||||
(declare-function org-element-at-point-no-context "org-element" (&optional pom))
|
||||
(declare-function org-element-context "org-element" (&optional element))
|
||||
(declare-function org-element-normalize-string "org-element" (s))
|
||||
(declare-function org-element-normalize-string "org-element" (s &optional keep-newlines))
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
(declare-function org-element-begin "org-element" (node))
|
||||
(declare-function org-element-end "org-element" (node))
|
||||
|
|
@ -79,34 +75,26 @@
|
|||
(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-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 element))
|
||||
(declare-function org-indent-block "org" ())
|
||||
(declare-function org-indent-line "org" ())
|
||||
(declare-function org-list-get-list-end "org-list" (item struct prevs))
|
||||
(declare-function org-list-prevs-alist "org-list" (struct))
|
||||
(declare-function org-list-struct "org-list" ())
|
||||
(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-org "org-list" (list &optional params))
|
||||
(declare-function org-macro-escape-arguments "org-macro" (&rest args))
|
||||
(declare-function org-mark-ring-push "org" (&optional pos buffer))
|
||||
(declare-function org-narrow-to-subtree "org" (&optional element))
|
||||
(declare-function org-next-block "org" (arg &optional backward block-regexp))
|
||||
(declare-function org-open-at-point "org" (&optional in-emacs reference-buffer))
|
||||
(declare-function org-open-at-point "org" (&optional arg))
|
||||
(declare-function org-previous-block "org" (arg &optional block-regexp))
|
||||
(declare-function org-fold-show-context "org-fold" (&optional key))
|
||||
(declare-function org-src-coderef-format "org-src" (&optional element))
|
||||
(declare-function org-src-coderef-regexp "org-src" (fmt &optional label))
|
||||
(declare-function org-src-get-lang-mode "org-src" (lang))
|
||||
(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-import "org-table" (file arg))
|
||||
(declare-function org-table-to-lisp "org-table" (&optional txt))
|
||||
(declare-function org-unescape-code-in-string "org-src" (s))
|
||||
(declare-function orgtbl-to-generic "org-table" (table params))
|
||||
(declare-function orgtbl-to-orgtbl "org-table" (table params))
|
||||
(declare-function tramp-compat-make-temp-file "tramp-compat" (filename &optional dir-flag))
|
||||
|
||||
(defgroup org-babel nil
|
||||
"Code block evaluation and management in `org-mode' documents."
|
||||
|
|
@ -217,7 +205,7 @@ When matching, reference is stored in match group 1."
|
|||
(defvar org-babel-src-block-regexp
|
||||
(concat
|
||||
;; (1) indentation (2) lang
|
||||
"^\\([ \t]*\\)#\\+begin_src[ \t]+\\([^ \f\t\n\r\v]+\\)[ \t]*"
|
||||
"^\\([ \t]*\\)#\\+begin_src\\(?:[ \t]+\\([^ \f\t\n\r\v]*\\)\\)?[ \t]*"
|
||||
;; (3) switches
|
||||
"\\([^\":\n]*\"[^\"\n*]*\"[^\":\n]*\\|[^\":\n]*\\)"
|
||||
;; (4) header arguments
|
||||
|
|
@ -358,18 +346,27 @@ a window into the `org-babel-get-src-block-info' function."
|
|||
(full (lambda (it) (> (length it) 0)))
|
||||
(printf (lambda (fmt &rest args) (princ (apply #'format fmt args)))))
|
||||
(when info
|
||||
(with-help-window (help-buffer)
|
||||
(let ((name (nth 4 info))
|
||||
(lang (nth 0 info))
|
||||
(let* ((name (nth 4 info))
|
||||
(language (nth 0 info))
|
||||
(switches (nth 3 info))
|
||||
(header-args (nth 2 info)))
|
||||
(header-args (nth 2 info))
|
||||
(property-header-args
|
||||
(org-entry-get (point) "header-args" t))
|
||||
(property-header-args-language
|
||||
(org-entry-get (point) (concat "header-args:" language) t)))
|
||||
(with-help-window (help-buffer)
|
||||
(when name (funcall printf "Name: %s\n" name))
|
||||
(when lang (funcall printf "Lang: %s\n" lang))
|
||||
(when language (funcall printf "Language: %s\n" language))
|
||||
;; Show header arguments that have been set through
|
||||
;; properties (i.e. in property drawers or through
|
||||
;; #+PROPERTY)
|
||||
(funcall printf "Properties:\n")
|
||||
(funcall printf "\t:header-args \t%s\n" (org-entry-get (point) "header-args" t))
|
||||
(funcall printf "\t:header-args:%s \t%s\n" lang (org-entry-get (point) (concat "header-args:" lang) t))
|
||||
|
||||
(funcall printf "\t:header-args \t%s\n" property-header-args)
|
||||
(funcall printf "\t:header-args:%s \t%s\n" language property-header-args-language)
|
||||
;; Show switches
|
||||
(when (funcall full switches) (funcall printf "Switches: %s\n" switches))
|
||||
;; Show default header arguments and header arguments that
|
||||
;; have been explicitly set in the current code block.
|
||||
(funcall printf "Header Arguments:\n")
|
||||
(dolist (pair (sort header-args
|
||||
(lambda (a b) (string< (symbol-name (car a))
|
||||
|
|
@ -722,9 +719,17 @@ Otherwise, return a list with the following pattern:
|
|||
lang
|
||||
(org-babel--normalize-body datum)
|
||||
(apply #'org-babel-merge-params
|
||||
;; Use `copy-tree' to avoid creating shared structure
|
||||
;; with the `org-babel-default-header-args-*' variables:
|
||||
;; modifications by `org-babel-generate-file-param'
|
||||
;; below would modify the shared structure, thereby
|
||||
;; modifying the variables.
|
||||
(copy-tree
|
||||
(if inline org-babel-default-inline-header-args
|
||||
org-babel-default-header-args)
|
||||
(and (boundp lang-headers) (eval lang-headers t))
|
||||
t)
|
||||
(and (boundp lang-headers)
|
||||
(copy-tree (eval lang-headers t) t))
|
||||
(append
|
||||
;; If DATUM is provided, make sure we get node
|
||||
;; properties applicable to its location within
|
||||
|
|
@ -748,11 +753,19 @@ Otherwise, return a list with the following pattern:
|
|||
(defun org-babel--expand-body (info)
|
||||
"Expand noweb references in src block and remove any coderefs.
|
||||
The src block is defined by its INFO, as returned by
|
||||
`org-babel-get-src-block-info'."
|
||||
`org-babel-get-src-block-info'.
|
||||
|
||||
This function uses the :eval context for noweb expansion because it is
|
||||
called when code needs to be evaluated, either by
|
||||
`org-babel-execute-src-block' or `org-babel-confirm-evaluate'. The :eval
|
||||
context is appropriate even during export or tangling when the code block
|
||||
needs to be evaluated to generate results. It is distinct from the :export
|
||||
and :tangle contexts which are used when generating the source code body for
|
||||
display in exported documents or tangled files."
|
||||
(let ((coderef (nth 6 info))
|
||||
(expand
|
||||
(if (org-babel-noweb-p (nth 2 info) :eval)
|
||||
(org-babel-expand-noweb-references info)
|
||||
(org-babel-expand-noweb-references info nil :eval)
|
||||
(nth 1 info))))
|
||||
(if (not coderef) expand
|
||||
(replace-regexp-in-string
|
||||
|
|
@ -986,7 +999,7 @@ arguments and pop open the results in a preview buffer."
|
|||
(symbol-name (car el2)))))))
|
||||
(body (setf (nth 1 info)
|
||||
(if (org-babel-noweb-p params :eval)
|
||||
(org-babel-expand-noweb-references info) (nth 1 info))))
|
||||
(org-babel-expand-noweb-references info nil :eval) (nth 1 info))))
|
||||
(expand-cmd (intern (concat "org-babel-expand-body:" lang)))
|
||||
(assignments-cmd (intern (concat "org-babel-variable-assignments:"
|
||||
lang)))
|
||||
|
|
@ -1076,10 +1089,19 @@ completion from lists of common args and values."
|
|||
(unless (= (char-before (point)) ?\ ) (insert " "))
|
||||
(insert ":" header-arg) (when value (insert " " value)))))
|
||||
|
||||
(defun org-babel-in-src-block-header-p ()
|
||||
"Return non-nil when `point' is in the header line of the source block."
|
||||
(let ((beg (org-babel-where-is-src-block-head)))
|
||||
(when beg
|
||||
(let ((end (save-excursion (goto-char beg) (end-of-line) (point))))
|
||||
(and (>= (point) beg) (<= (point) end))))))
|
||||
|
||||
;; Add support for completing-read insertion of header arguments after ":"
|
||||
(defun org-babel-header-arg-expand ()
|
||||
"Call `org-babel-enter-header-arg-w-completion' in appropriate contexts."
|
||||
(when (and (equal (char-before) ?\:) (org-babel-where-is-src-block-head))
|
||||
"Call `org-babel-enter-header-arg-w-completion' in appropriate contexts
|
||||
(the header line of a source block)."
|
||||
(when (and (equal (char-before) ?\:)
|
||||
(org-babel-in-src-block-header-p))
|
||||
(org-babel-enter-header-arg-w-completion (match-string 2))))
|
||||
|
||||
(defun org-babel-enter-header-arg-w-completion (&optional lang)
|
||||
|
|
@ -1117,7 +1139,7 @@ session."
|
|||
(user-error "No src code block at point")
|
||||
(setf (nth 1 info)
|
||||
(if (org-babel-noweb-p params :eval)
|
||||
(org-babel-expand-noweb-references info)
|
||||
(org-babel-expand-noweb-references info nil :eval)
|
||||
(nth 1 info)))))
|
||||
(session (cdr (assq :session params)))
|
||||
(dir (cdr (assq :dir params)))
|
||||
|
|
@ -1240,6 +1262,9 @@ evaluation mechanisms."
|
|||
(save-match-data (org-element-context))
|
||||
'(babel-call inline-babel-call inline-src-block src-block)))
|
||||
|
||||
(defvar org-babel-results-buffer-name "*Org Babel Results*"
|
||||
"The buffer name of Org Babel evaluate results.")
|
||||
|
||||
;;;###autoload
|
||||
(defun org-babel-open-src-block-result (&optional re-run)
|
||||
"Open results of source block at point.
|
||||
|
|
@ -1263,7 +1288,7 @@ exist."
|
|||
(if (looking-at org-link-bracket-re) (org-open-at-point)
|
||||
(let ((r (org-babel-format-result (org-babel-read-result)
|
||||
(cdr (assq :sep arguments)))))
|
||||
(pop-to-buffer (get-buffer-create "*Org Babel Results*"))
|
||||
(pop-to-buffer (get-buffer-create org-babel-results-buffer-name))
|
||||
(erase-buffer)
|
||||
(insert r)))
|
||||
t))
|
||||
|
|
@ -1379,8 +1404,8 @@ buffer."
|
|||
(while (re-search-forward "call_\\S-\\|^[ \t]*#\\+CALL:" nil t)
|
||||
(let ((,datum (org-element-context)))
|
||||
(when (org-element-type-p ,datum '(babel-call inline-babel-call))
|
||||
(goto-char (or (org-element-post-affiliated datum)
|
||||
(org-element-begin datum)))
|
||||
(goto-char (or (org-element-post-affiliated ,datum)
|
||||
(org-element-begin ,datum)))
|
||||
(let ((,end (copy-marker (org-element-end ,datum))))
|
||||
,@body
|
||||
(goto-char ,end)
|
||||
|
|
@ -1484,7 +1509,7 @@ CONTEXT specifies the context of evaluation. It can be `:eval',
|
|||
(lang (nth 0 info))
|
||||
(params (nth 2 info))
|
||||
(body (if (org-babel-noweb-p params context)
|
||||
(org-babel-expand-noweb-references info)
|
||||
(org-babel-expand-noweb-references info nil context)
|
||||
(nth 1 info)))
|
||||
(expand-cmd (intern (concat "org-babel-expand-body:" lang)))
|
||||
(assignments-cmd (intern (concat "org-babel-variable-assignments:"
|
||||
|
|
@ -2136,7 +2161,14 @@ block of the same language as the previous."
|
|||
(list (point))))
|
||||
(n (- (length parts) 2)) ;; 1 or 2 parts in `dolist' below.
|
||||
;; `post-blank' caches the property before setting it to 0.
|
||||
(post-blank (org-element-property :post-blank copy)))
|
||||
(post-blank (org-element-property :post-blank copy))
|
||||
(to-uppercase
|
||||
(lambda (str)
|
||||
(string-match "^[ \t]*#\\+\\(begin_src\\)" str)
|
||||
(setq str (replace-match "BEGIN_SRC" t t str 1))
|
||||
(string-match "^[ \t]*#\\+\\(end_src\\)" str)
|
||||
(setq str (replace-match "END_SRC" t t str 1))
|
||||
str)))
|
||||
;; Point or region are within body when parts is in increasing order.
|
||||
(unless (apply #'<= parts)
|
||||
(user-error "Select within the source block body to split it"))
|
||||
|
|
@ -2156,7 +2188,12 @@ block of the same language as the previous."
|
|||
;; Set `:post-blank' to 0. We take care of spacing between blocks.
|
||||
(org-element-put-property copy :post-blank 0)
|
||||
(org-element-put-property copy :value (car parts))
|
||||
(insert (org-element-interpret-data copy))
|
||||
(let ((copy-str (org-element-interpret-data copy)))
|
||||
;; `org-element-interpret-data' produces lower-case
|
||||
;; #+begin_src .. #+end_src
|
||||
(when upper-case-p
|
||||
(setq copy-str (funcall to-uppercase copy-str)))
|
||||
(insert copy-str))
|
||||
;; `org-indent-block' may see another `org-element' (e.g. paragraph)
|
||||
;; immediately after the block. Ensure to indent the inserted block
|
||||
;; and move point to its end.
|
||||
|
|
@ -2173,7 +2210,12 @@ block of the same language as the previous."
|
|||
(when (= n 0)
|
||||
;; Use `post-blank' to reset the property of the last block.
|
||||
(org-element-put-property copy :post-blank post-blank))
|
||||
(insert (org-element-interpret-data copy))
|
||||
(let ((copy-str (org-element-interpret-data copy)))
|
||||
;; `org-element-interpret-data' produces lower-case
|
||||
;; #+begin_src .. #+end_src
|
||||
(when upper-case-p
|
||||
(setq copy-str (funcall to-uppercase copy-str)))
|
||||
(insert copy-str))
|
||||
;; Ensure to indent the inserted block and move point to its end.
|
||||
(org-babel-previous-src-block 1)
|
||||
(org-indent-block)
|
||||
|
|
@ -2683,6 +2725,10 @@ result:
|
|||
(opening-line (concat "#+begin_" full))
|
||||
(closing-line (concat "#+end_" type)))
|
||||
(cond
|
||||
;; Do nothing if type is "no" or "nil"
|
||||
((or (org-string-equal-ignore-case type "nil")
|
||||
(org-string-equal-ignore-case type "no"))
|
||||
nil)
|
||||
;; Escape contents from "export" wrap. Wrap
|
||||
;; inline results within an export snippet with
|
||||
;; appropriate value.
|
||||
|
|
@ -2835,7 +2881,9 @@ If called with prefix argument ARG, remove all result blocks in the
|
|||
buffer."
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(progn
|
||||
(org-babel-map-src-blocks nil (org-babel-remove-result))
|
||||
(org-babel-map-call-lines nil (org-babel-remove-result)))
|
||||
(org-babel-remove-result)))
|
||||
|
||||
(defun org-babel-result-end ()
|
||||
|
|
@ -2953,7 +3001,7 @@ used as a string to be appended to #+begin_example line."
|
|||
(indent-rigidly
|
||||
(point-min)
|
||||
(point-max)
|
||||
(+ ind org-edit-src-content-indentation))
|
||||
(+ ind org-src-content-indentation))
|
||||
(buffer-string))))))
|
||||
(delete-region body-start
|
||||
(org-with-wide-buffer
|
||||
|
|
@ -3025,6 +3073,8 @@ parameters when merging lists."
|
|||
(setf (cddr (nth variable-index vars))
|
||||
(concat (symbol-name name) "=" value))
|
||||
(cl-incf variable-index)))
|
||||
((null (cdr pair)) ;; Empty :var, ignore
|
||||
nil)
|
||||
(t (error "Variable \"%s\" must be assigned a default value"
|
||||
(cdr pair))))))
|
||||
(`(:results . ,value)
|
||||
|
|
@ -3089,7 +3139,7 @@ CONTEXT may be one of :tangle, :export or :eval."
|
|||
(defvar org-babel-expand-noweb-references--cache-buffer nil
|
||||
"Cons (BUFFER . MODIFIED-TICK) for cached noweb references.
|
||||
See `org-babel-expand-noweb-references--cache'.")
|
||||
(defun org-babel-expand-noweb-references (&optional info parent-buffer)
|
||||
(defun org-babel-expand-noweb-references (&optional info parent-buffer context)
|
||||
"Expand Noweb references in the body of the current source code block.
|
||||
|
||||
When optional argument INFO is non-nil, use the block defined by INFO
|
||||
|
|
@ -3098,6 +3148,24 @@ instead.
|
|||
The block is assumed to be located in PARENT-BUFFER or current buffer
|
||||
\(when PARENT-BUFFER is nil).
|
||||
|
||||
CONTEXT specifies the context of expansion and can be one of :tangle,
|
||||
:export, or :eval. When CONTEXT is nil, it defaults to :eval.
|
||||
|
||||
Note: CONTEXT does not affect whether the top-level block is expanded -
|
||||
that is determined by the caller and the block's own :noweb setting.
|
||||
The context only determines which noweb header arguments are honored when
|
||||
recursively expanding nested references within referenced blocks.
|
||||
|
||||
For recursive expansion:
|
||||
- :tangle context: expands blocks with :noweb tangle, :noweb yes, etc.
|
||||
- :export context: expands blocks with :noweb export, :noweb yes, etc.
|
||||
- :eval context: expands blocks with :noweb eval, :noweb yes, etc.
|
||||
|
||||
This is important for recursive expansion: when a block with :noweb tangle
|
||||
references another block that also contains noweb references, those nested
|
||||
references should only be expanded if the referenced block's :noweb setting
|
||||
permits expansion in the tangle context.
|
||||
|
||||
For example the following reference would be replaced with the
|
||||
body of the source-code block named `example-block'.
|
||||
|
||||
|
|
@ -3125,7 +3193,8 @@ defined by `org-babel-lob'. For example
|
|||
would set the value of argument \"a\" equal to \"9\". Note that
|
||||
these arguments are not evaluated in the current source-code
|
||||
block but are passed literally to the \"example-block\"."
|
||||
(let* ((parent-buffer (or parent-buffer (current-buffer)))
|
||||
(let* ((context (or context :eval))
|
||||
(parent-buffer (or parent-buffer (current-buffer)))
|
||||
(info (or info (org-babel-get-src-block-info 'no-eval)))
|
||||
(lang (nth 0 info))
|
||||
(body (nth 1 info))
|
||||
|
|
@ -3159,8 +3228,9 @@ block but are passed literally to the \"example-block\"."
|
|||
(expand-body
|
||||
(i)
|
||||
;; Expand body of code represented by block info I.
|
||||
`(let ((b (if (org-babel-noweb-p (nth 2 ,i) :eval)
|
||||
(org-babel-expand-noweb-references ,i)
|
||||
`(let ((b (if (org-babel-noweb-p (nth 2 ,i) context)
|
||||
(org-babel-expand-noweb-references
|
||||
,i parent-buffer context)
|
||||
(nth 1 ,i))))
|
||||
(if (not comment) b
|
||||
(let ((cs (org-babel-tangle-comment-links ,i)))
|
||||
|
|
@ -3501,8 +3571,7 @@ Execute TABLE-FORMS when result should be considered sexp and parsed."
|
|||
(member "file" ,params)
|
||||
(and (or (member "output" ,params)
|
||||
(member "raw" ,params)
|
||||
(member "org" ,params)
|
||||
(member "drawer" ,params))
|
||||
(member "org" ,params))
|
||||
(not (member "table" ,params))))
|
||||
,scalar-form
|
||||
,@table-forms)))))
|
||||
|
|
|
|||
304
lisp/org/ob-csharp.el
Normal file
304
lisp/org/ob-csharp.el
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
;;; ob-csharp.el --- org-babel functions for csharp evaluation -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2024-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Maximilian Kueffner
|
||||
;; Maintainer: Maximilian Kueffner <poverobuosodonati@gmail.com>
|
||||
;; Keywords: literate programming, reproducible research
|
||||
;; Homepage: https://orgmode.org
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;;; Requirements:
|
||||
|
||||
;; Some .NET runtime environment should be installed.
|
||||
;; The `dotnet' command should be available to the system's environment
|
||||
;; (PATH discoverable for example).
|
||||
|
||||
;;; Code:
|
||||
(require 'ob)
|
||||
|
||||
;; file extension for C#
|
||||
(add-to-list 'org-babel-tangle-lang-exts '("csharp" . "cs"))
|
||||
|
||||
;; default header arguments for C#
|
||||
(defvar org-babel-default-header-args:csharp
|
||||
'((main . ((no)))
|
||||
(nugetconfig . :any)
|
||||
(framework . :any)
|
||||
(class . ((no nil :any)))
|
||||
(references . :any)
|
||||
(usings . :any)
|
||||
(cmdline . :any))
|
||||
"Csharp specific header arguments.")
|
||||
|
||||
(defcustom org-babel-csharp-compiler "dotnet"
|
||||
"The program to call for compiling a csharp project."
|
||||
:group 'org-babel
|
||||
:package-version '(Org. "9.8")
|
||||
:type 'string
|
||||
:risky t)
|
||||
|
||||
(defun org-babel-csharp--default-compile-command (dir-proj-sln bin-dir)
|
||||
"Construct the default compilation command for C#.
|
||||
|
||||
DIR-PROJ-SLN is either a directory containing a \".csproj\" or \".sln\" file
|
||||
or a full path to either of these.
|
||||
BIN-DIR is the directory for the compiled output."
|
||||
(format "%s build --output %S %S"
|
||||
org-babel-csharp-compiler bin-dir dir-proj-sln))
|
||||
|
||||
(defun org-babel-csharp--default-restore-command (project-file)
|
||||
"Construct the default restore command for C# projects.
|
||||
|
||||
PROJECT-FILE is a path to a \".csproj\" file on which the restore command
|
||||
takes effect."
|
||||
(format "%s restore %S" org-babel-csharp-compiler project-file))
|
||||
|
||||
(defun org-babel-csharp--find-dotnet-version ()
|
||||
"Get a list of dotnet major versions from a list of dotnet sdks."
|
||||
(cl-delete-if #'(lambda (v) (= 0 v))
|
||||
(delete-dups
|
||||
(mapcar #'(lambda (n)
|
||||
(let ((fr (string-match "^[0-9.]+\\." n))
|
||||
(to (string-match "\\." n)))
|
||||
(string-to-number (substring n fr to))))
|
||||
(split-string
|
||||
(shell-command-to-string
|
||||
(format "%s --list-sdks" org-babel-csharp-compiler))
|
||||
"\n")))))
|
||||
|
||||
(defcustom org-babel-csharp-default-target-framework
|
||||
(format "net%s.0"
|
||||
(let ((net-sdks (org-babel-csharp--find-dotnet-version)))
|
||||
(when net-sdks
|
||||
(apply #'max net-sdks))))
|
||||
"The desired target framework to use."
|
||||
:group 'org-babel
|
||||
:package-version '(Org. "9.8")
|
||||
:type 'string
|
||||
:safe #'stringp)
|
||||
|
||||
(defcustom org-babel-csharp-generate-compile-command
|
||||
#'org-babel-csharp--default-compile-command
|
||||
"A function creating the compile command.
|
||||
|
||||
It must take two parameters intended for the target binary directory and
|
||||
a .sln file, .csproj file, or a base directory where either can be found."
|
||||
:group 'org-babel
|
||||
:package-version '(Org. "9.8")
|
||||
:type 'function
|
||||
:risky t)
|
||||
|
||||
(defcustom org-babel-csharp-generate-restore-command
|
||||
#'org-babel-csharp--default-restore-command
|
||||
"A function creating a project restore command.
|
||||
|
||||
It must take one parameter defining the project to perform a restore on."
|
||||
:group 'org-babel
|
||||
:package-version '(Org. "9.8")
|
||||
:type 'function
|
||||
:risky t)
|
||||
|
||||
(defcustom org-babel-csharp-additional-project-flags nil
|
||||
"Will be passed in the \"PropertyGroup\" defining the project.
|
||||
|
||||
This is taken as-is. It should be a string in XML-format."
|
||||
:group 'org-babel
|
||||
:package-version '(Org. "9.8")
|
||||
:type '(choice string (const nil))
|
||||
:safe (lambda (x) (or (eq x nil) (stringp x))))
|
||||
|
||||
(defun org-babel-csharp--generate-project-file (refs framework)
|
||||
"Generate the file content to be used in a csproj-file.
|
||||
|
||||
REFS is a list of references. Check `org-babel-csharp--format-refs' for
|
||||
the allowed semantics.
|
||||
FRAMEWORK is the target framework."
|
||||
(unless framework
|
||||
(error "framework cannot be nil"))
|
||||
(concat "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n "
|
||||
(when refs
|
||||
(org-babel-csharp--format-refs refs))
|
||||
"\n\n <PropertyGroup>"
|
||||
"\n <OutputType>Exe</OutputType>\n"
|
||||
(format "\n <TargetFramework>%s</TargetFramework>" framework)
|
||||
"\n <ImplicitUsings>enable</ImplicitUsings>"
|
||||
"\n <Nullable>enable</Nullable>"
|
||||
(when org-babel-csharp-additional-project-flags
|
||||
(format "\n %s" org-babel-csharp-additional-project-flags))
|
||||
"\n </PropertyGroup>"
|
||||
"\n</Project>"))
|
||||
|
||||
(defun org-babel-csharp--format-usings (usings)
|
||||
"Format USINGS into a string suitable for inclusion in a C# source file.
|
||||
|
||||
USINGS should be a list of strings, each representing a using directive.
|
||||
Returns a string with each using directive on a new line."
|
||||
(mapconcat
|
||||
(lambda (u)
|
||||
(unless (stringp u) (error "Usings must be of type string."))
|
||||
(format "using %s;" u))
|
||||
usings "\n"))
|
||||
|
||||
(defun org-babel-expand-body:csharp (body params)
|
||||
"Expand a block of C# code in BODY according to PARAMS.
|
||||
|
||||
See `org-babel-default-header-args:csharp' for available parameters."
|
||||
(let* ((main-p (not (string= (cdr (assq :main params)) "no")))
|
||||
(class (pcase (alist-get :class params)
|
||||
("no" nil)
|
||||
(`nil "Program")
|
||||
(_ (alist-get :class params))))
|
||||
(namespace "org.babel.autogen")
|
||||
(usings (alist-get :usings params)))
|
||||
(with-temp-buffer
|
||||
(when (alist-get :prologue params)
|
||||
(insert (alist-get :prologue params) "\n"))
|
||||
(insert "namespace " namespace ";\n")
|
||||
(when usings
|
||||
(insert (format "\n%s\n" (org-babel-csharp--format-usings usings))))
|
||||
(when class
|
||||
(insert "\nclass " class "\n{\n"))
|
||||
(when main-p
|
||||
(insert "static void Main(string[] args)\n{\n"))
|
||||
(insert (if (alist-get :var params)
|
||||
(mapconcat #'identity (org-babel-variable-assignments:csharp params) "\n")
|
||||
"")
|
||||
"\n")
|
||||
(insert body)
|
||||
(when main-p
|
||||
(insert "\n}"))
|
||||
(when class
|
||||
(insert "\n}"))
|
||||
(when (alist-get :epilogue params)
|
||||
(insert "\n" (alist-get :epilogue params)))
|
||||
(buffer-string))))
|
||||
|
||||
(defun org-babel-csharp--format-refs (refs)
|
||||
"Format REFS into a string suitable for inclusion in a .csproj file.
|
||||
|
||||
REFS should be a list of strings or cons cells, each representing a reference.
|
||||
If an entry is a cons cell, the car denotes the reference name and
|
||||
the cdr is the version.
|
||||
|
||||
Returns a formatted string representing the references, categorized into
|
||||
project reference, assembly reference, and package reference.
|
||||
Reference types are distinguished by their file extension.
|
||||
'.csproj' is interpreted as a project reference,
|
||||
'.dll' as an assembly reference.
|
||||
When a version is present, it will be treated as a package reference."
|
||||
(let ((projectref)
|
||||
(assemblyref)
|
||||
(systemref))
|
||||
(dolist (ref refs)
|
||||
(let* ((version (if (consp ref)
|
||||
(cdr ref)
|
||||
nil))
|
||||
(ref-string (if (consp ref)
|
||||
(car ref)
|
||||
ref))
|
||||
(full-ref (if version
|
||||
(file-truename (car ref))
|
||||
(file-truename ref))))
|
||||
(cond
|
||||
((string= "csproj" (file-name-extension full-ref))
|
||||
(setf projectref
|
||||
(concat projectref
|
||||
(format "\n <ProjectReference Include=\"%s\" />"
|
||||
full-ref))))
|
||||
((string= "dll" (file-name-extension full-ref))
|
||||
(setf assemblyref
|
||||
(concat assemblyref
|
||||
(format "\n <Reference Include=%S>\n <HintPath>%s</HintPath>\n </Reference>"
|
||||
(file-name-base full-ref) full-ref))))
|
||||
(t (setf systemref
|
||||
(concat systemref
|
||||
(format "\n <PackageReference Include=%s />"
|
||||
(if version
|
||||
(format "%S Version=%S" ref-string version)
|
||||
(format "%S" ref-string)))))))))
|
||||
(format "%s\n\n %s\n\n %s"
|
||||
(if projectref
|
||||
(format "<ItemGroup>%s\n </ItemGroup>" projectref)
|
||||
"")
|
||||
(if assemblyref
|
||||
(format "<ItemGroup>%s\n </ItemGroup>" assemblyref)
|
||||
"")
|
||||
(if systemref
|
||||
(format "<ItemGroup>%s\n </ItemGroup>" systemref)
|
||||
""))))
|
||||
|
||||
(defun org-babel-execute:csharp (body params)
|
||||
"Execute a block of Csharp code with org-babel.
|
||||
This function is called by `org-babel-execute-src-block'"
|
||||
(let* ((full-body (org-babel-expand-body:csharp body params))
|
||||
(base-dir (make-temp-name (file-name-concat org-babel-temporary-directory "obcs")))
|
||||
(project-name (file-name-base base-dir))
|
||||
(bin-dir (file-name-concat base-dir "bin"))
|
||||
(framework (or (alist-get :framework params) org-babel-csharp-default-target-framework))
|
||||
(program-file (file-name-concat base-dir "Program.cs"))
|
||||
(project-file (file-name-concat base-dir (concat project-name ".csproj")))
|
||||
(nuget-file (alist-get :nugetconfig params))
|
||||
(cmdline (alist-get :cmdline params))
|
||||
(cmdline (if cmdline cmdline ""))
|
||||
(restore-cmd (funcall org-babel-csharp-generate-restore-command project-file))
|
||||
(compile-cmd (funcall org-babel-csharp-generate-compile-command
|
||||
(file-truename project-file)
|
||||
(file-truename bin-dir)))
|
||||
(run-cmd (format "%S %S" (file-truename (file-name-concat bin-dir project-name)) cmdline)))
|
||||
(unless (org-babel-csharp--find-dotnet-version)
|
||||
(error "Could not find a .NET SDK for compiling."))
|
||||
(unless (file-exists-p base-dir)
|
||||
(make-directory base-dir))
|
||||
(with-temp-file program-file
|
||||
(insert full-body))
|
||||
(with-temp-file project-file
|
||||
(insert
|
||||
(let ((refs (alist-get :references params)))
|
||||
(org-babel-csharp--generate-project-file refs framework))))
|
||||
(when (and nuget-file (file-exists-p (file-truename nuget-file)))
|
||||
(copy-file nuget-file (file-name-concat base-dir (file-name-nondirectory (file-truename nuget-file)))))
|
||||
;; nuget restore
|
||||
(org-babel-eval restore-cmd "")
|
||||
(let ((compile-result (org-babel-eval compile-cmd "")))
|
||||
(when (string-match ": error" compile-result)
|
||||
(org-babel-eval-error-notify 1 compile-result)))
|
||||
(let ((results (org-babel-eval run-cmd "")))
|
||||
(when results
|
||||
(setq results (org-remove-indentation results))
|
||||
;; results
|
||||
(org-babel-reassemble-table
|
||||
(org-babel-result-cond (cdr (assq :result-params params))
|
||||
results
|
||||
(let ((tmp-file (org-babel-temp-file "c-")))
|
||||
(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-variable-assignments:csharp (params)
|
||||
"Return a list of C# variable assignments from header arguments."
|
||||
(mapcar
|
||||
#'(lambda (pair) (format "var %s = %S;" (car pair) (cdr pair)))
|
||||
(org-babel--get-vars params)))
|
||||
|
||||
(provide 'ob-csharp)
|
||||
;;; ob-csharp.el ends here
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
;; Copyright (C) 2009-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Eric Schulte
|
||||
;; Authors: Eric Schulte, Jarmo Hurri
|
||||
;; Keywords: literate programming, reproducible research
|
||||
;; URL: https://orgmode.org
|
||||
|
||||
|
|
@ -25,15 +25,52 @@
|
|||
|
||||
;; Org-Babel support for evaluating ditaa source code.
|
||||
;;
|
||||
;; This differs from most standard languages in that
|
||||
;; Source code blocks of type ditaa have some special features:
|
||||
;;
|
||||
;; 1) there is no such thing as a "session" in ditaa
|
||||
;; - there is no such thing as a "session"
|
||||
;;
|
||||
;; 2) we are generally only going to return results of type "file"
|
||||
;; - :export results is the default
|
||||
;;
|
||||
;; 3) we are adding the "file" and "cmdline" header arguments
|
||||
;; - only results of type "file" are returned
|
||||
;;
|
||||
;; 4) there are no variables (at least for now)
|
||||
;; - there are no variables
|
||||
;;
|
||||
;; - three different variants of "ditaa" exist: a ditaa executable
|
||||
;; (shell script), ditaa.jar Java archive and DitaaEPS.jar Java
|
||||
;; archive; the third one is a fork generating eps output, and is
|
||||
;; also a prerequisite for producing pdf output; ob-ditaa supports
|
||||
;; all three of these; if ditaa.jar or DitaaEPS.jar is used, paths
|
||||
;; to file(s) must be set; the following table summarizes which
|
||||
;; variant is used in which case; column mode refers to
|
||||
;; `org-ditaa-default-exec-mode'
|
||||
;;
|
||||
;; | mode | output | command |
|
||||
;; |----------------+----------+-----------------------------------------------------|
|
||||
;; | `ditaa' | png, svg | `org-ditaa-exec' |
|
||||
;; | `jar' | png, svg | `org-ditaa-java-exec' -jar `org-ditaa-jar-path' |
|
||||
;; | `ditaa', `jar' | eps | `org-ditaa-java-exec' -jar `org-ditaa-eps-jar-path' |
|
||||
;; | `ditaa', `jar' | pdf | `org-ditaa-java-exec' -jar `org-ditaa-eps-jar-path' |
|
||||
;;
|
||||
;; - standard header argument "cmdline" controls command line parameters passed to ditaa
|
||||
;; - the following header arguments are added:
|
||||
;; "java" : additional parameters passed to java if ditaa run via a jar
|
||||
;;
|
||||
|
||||
;;; Requirements:
|
||||
|
||||
;; at least one of the following:
|
||||
;;
|
||||
;; ditaa (executable)
|
||||
;; - packaged in some distributions
|
||||
;; - configurable via `org-ditaa-exec'
|
||||
;;
|
||||
;; ditaa.jar | when exec mode is `jar'
|
||||
;; - `org-ditaa-jar-path' must point to this jar file
|
||||
;; - see https://github.com/stathissideris/ditaa
|
||||
;;
|
||||
;; DitaaEps.jar | when generating eps or pdf output
|
||||
;; - `org-ditaa-eps-jar-path' must point to this jar file
|
||||
;; - see https://sourceforge.net/projects/ditaa-addons/files/DitaaEps/
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
|
@ -44,11 +81,39 @@
|
|||
(require 'org-compat)
|
||||
|
||||
(defvar org-babel-default-header-args:ditaa
|
||||
'((:results . "file")
|
||||
'((:results . "file graphics")
|
||||
(:exports . "results")
|
||||
(:java . "-Dfile.encoding=UTF-8"))
|
||||
(:file-ext . "png"))
|
||||
"Default arguments for evaluating a ditaa source block.")
|
||||
|
||||
(defcustom org-ditaa-default-exec-mode 'jar
|
||||
"Method to use for ditaa diagram generation when generating png or svg output.
|
||||
`jar' means to use java together with a JAR.
|
||||
The JAR must be set via `org-ditaa-jar-path'.
|
||||
|
||||
`ditaa' means to use the ditaa executable.
|
||||
The executable can be configured via `org-ditaa-exec'."
|
||||
|
||||
:group 'org-babel
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(choice (const :tag "Use java together with a JAR file." jar)
|
||||
(const :tag "Use ditaa executable." ditaa))
|
||||
:safe (lambda (x) (memq x '(jar ditaa))))
|
||||
|
||||
(defcustom org-ditaa-exec "ditaa"
|
||||
"File name of the ditaa executable."
|
||||
:group 'org-babel
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'string
|
||||
:risky t)
|
||||
|
||||
(define-obsolete-variable-alias 'org-babel-ditaa-java-cmd 'org-ditaa-java-exec "9.8")
|
||||
(defcustom org-ditaa-java-exec "java"
|
||||
"Java executable to use when evaluating ditaa blocks using a JAR."
|
||||
:group 'org-babel
|
||||
:type 'string
|
||||
:risky t)
|
||||
|
||||
(defcustom org-ditaa-jar-path (expand-file-name
|
||||
"ditaa.jar"
|
||||
(file-name-as-directory
|
||||
|
|
@ -58,65 +123,82 @@
|
|||
(expand-file-name
|
||||
"../contrib"
|
||||
(file-name-directory (org-find-library-dir "org")))))))
|
||||
"Path to the ditaa jar executable."
|
||||
:group 'org-babel
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-babel-ditaa-java-cmd "java"
|
||||
"Java executable to use when evaluating ditaa blocks."
|
||||
"Path to the ditaa.jar file."
|
||||
:group 'org-babel
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-ditaa-eps-jar-path
|
||||
(expand-file-name "DitaaEps.jar" (file-name-directory org-ditaa-jar-path))
|
||||
"Path to the DitaaEps.jar executable."
|
||||
"Path to the DitaaEps.jar executable.
|
||||
Used when generating eps or pdf output."
|
||||
:group 'org-babel
|
||||
:version "24.4"
|
||||
:package-version '(Org . "8.0")
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-ditaa-jar-option "-jar"
|
||||
"Option for the ditaa jar file.
|
||||
Do not leave leading or trailing spaces in this string."
|
||||
:group 'org-babel
|
||||
:version "24.1"
|
||||
:type 'string)
|
||||
(make-obsolete-variable 'org-ditaa-jar-option
|
||||
"(ob-ditaa) variable org-ditaa-jar-option is obsolete"
|
||||
"9.8")
|
||||
|
||||
(defun ob-ditaa--ensure-jar-file (file)
|
||||
"Return FILE if it exists, signal error otherwise."
|
||||
(if (file-exists-p file)
|
||||
file
|
||||
(error "(ob-ditaa) Could not find jar file %s" file)))
|
||||
|
||||
(defun org-babel-execute:ditaa (body params)
|
||||
"Execute BODY of Ditaa code with org-babel according to PARAMS.
|
||||
"Execute BODY of ditaa code with org-babel according to PARAMS.
|
||||
This function is called by `org-babel-execute-src-block'."
|
||||
(let* ((out-file (or (cdr (assq :file params))
|
||||
(error
|
||||
"Ditaa code block requires :file header argument")))
|
||||
(cmdline (cdr (assq :cmdline params)))
|
||||
(java (cdr (assq :java params)))
|
||||
(in-file (org-babel-temp-file "ditaa-"))
|
||||
(eps (cdr (assq :eps params)))
|
||||
(eps-file (when eps
|
||||
(org-babel-process-file-name (concat in-file ".eps"))))
|
||||
(pdf-cmd (when (and (or (string= (file-name-extension out-file) "pdf")
|
||||
(cdr (assq :pdf params))))
|
||||
(concat
|
||||
"epstopdf"
|
||||
" " eps-file
|
||||
" -o=" (org-babel-process-file-name out-file))))
|
||||
(cmd (concat org-babel-ditaa-java-cmd
|
||||
" " java " " org-ditaa-jar-option " "
|
||||
(let* ((out-file (org-babel-graphical-output-file params))
|
||||
(out-file-suffix (file-name-extension out-file))
|
||||
;; backwards-compatibility of :eps and :pdf header arguments
|
||||
;; notice that these take precedence over file type (suffix)
|
||||
(legacy-eps (cdr (assq :eps params)))
|
||||
(legacy-pdf (cdr (assq :pdf params))))
|
||||
(when (and legacy-eps legacy-pdf)
|
||||
(error "(ob-ditaa) Both :eps and :pdf legacy output types specified"))
|
||||
(let* ((legacy-output-type (or legacy-eps legacy-pdf))
|
||||
(eps (or legacy-eps (string= out-file-suffix "eps")))
|
||||
(pdf (or legacy-pdf (string= out-file-suffix "pdf")))
|
||||
(svg (and (not legacy-output-type) (string= out-file-suffix "svg")))
|
||||
(png (and (not legacy-output-type)
|
||||
(or (string= out-file-suffix "png")
|
||||
(not (or svg pdf eps))))) ;; default output type is png
|
||||
(ditaa-options (cdr (assq :cmdline params)))
|
||||
(java-options (cdr (assq :java params)))
|
||||
(use-eps-jar (or eps pdf))
|
||||
(exec-form (if (or (equal org-ditaa-default-exec-mode 'jar) use-eps-jar)
|
||||
(concat org-ditaa-java-exec
|
||||
(when java-options (concat " " java-options))
|
||||
" "
|
||||
;; use obsolete variable instead of default param if defined
|
||||
(if (boundp 'org-ditaa-jar-option) org-ditaa-jar-option "-jar")
|
||||
" "
|
||||
(shell-quote-argument
|
||||
(expand-file-name
|
||||
(if eps org-ditaa-eps-jar-path org-ditaa-jar-path)))
|
||||
" " cmdline
|
||||
" " (org-babel-process-file-name in-file)
|
||||
" " (if pdf-cmd
|
||||
eps-file
|
||||
(org-babel-process-file-name out-file)))))
|
||||
(unless (file-exists-p org-ditaa-jar-path)
|
||||
(error "Could not find ditaa.jar at %s" org-ditaa-jar-path))
|
||||
(with-temp-file in-file (insert body))
|
||||
(unless noninteractive (message cmd))
|
||||
(ob-ditaa--ensure-jar-file (if use-eps-jar org-ditaa-eps-jar-path
|
||||
org-ditaa-jar-path))))
|
||||
org-ditaa-exec))
|
||||
(in-file (org-babel-temp-file "ditaa-"))
|
||||
(ditaa-out-file (org-babel-process-file-name (if pdf (concat in-file ".eps") out-file)))
|
||||
(ditaa-coding-system 'utf-8)
|
||||
(cmd (concat exec-form
|
||||
(when ditaa-options (concat " " ditaa-options))
|
||||
(when svg (concat " " "--svg"))
|
||||
" " "-e" " " (symbol-name ditaa-coding-system)
|
||||
" " in-file " " ditaa-out-file)))
|
||||
;; verify that output file type is specified - note that this
|
||||
;; error should in fact never happen, since default png type is
|
||||
;; set above if no other supported type is specified
|
||||
(unless (or eps pdf svg png)
|
||||
(error (concat "(ob-ditaa) Unknown output file extension: " out-file-suffix)))
|
||||
(with-temp-file in-file
|
||||
(set-buffer-file-coding-system ditaa-coding-system)
|
||||
(insert body))
|
||||
(shell-command cmd)
|
||||
(when pdf-cmd (unless noninteractive (message pdf-cmd)) (shell-command pdf-cmd))
|
||||
nil)) ;; signal that output has already been written to file
|
||||
(when pdf
|
||||
(shell-command (concat "epstopdf" " " ditaa-out-file " "
|
||||
"-o=" (org-babel-process-file-name out-file))))
|
||||
nil))) ;; signal that output has already been written to file
|
||||
|
||||
(defun org-babel-prep-session:ditaa (_session _params)
|
||||
"Return an error because ditaa does not support sessions."
|
||||
|
|
|
|||
|
|
@ -32,11 +32,6 @@
|
|||
|
||||
(require 'ob-core)
|
||||
|
||||
(declare-function org-babel--get-vars "ob" (params))
|
||||
(declare-function org-babel-result-cond "ob" (result-params scalar-form &rest table-forms))
|
||||
(declare-function org-babel-reassemble-table "ob" (table colnames rownames))
|
||||
(declare-function org-babel-pick-name "ob" (names selector))
|
||||
|
||||
(defconst org-babel-header-args:emacs-lisp '((lexical . :any))
|
||||
"Emacs-lisp specific header arguments.")
|
||||
|
||||
|
|
@ -77,7 +72,7 @@ by `org-edit-src-code'.")
|
|||
(org-babel-expand-body:emacs-lisp body params)))
|
||||
(result (eval (read (if (or (member "code" result-params)
|
||||
(member "pp" result-params))
|
||||
(concat "(pp " body ")")
|
||||
(concat "(pp-to-string " body ")")
|
||||
body))
|
||||
(org-babel-emacs-lisp-lexical lexical))))
|
||||
(when (and session (not (equal session "none")))
|
||||
|
|
@ -102,7 +97,7 @@ Convert LEXICAL into the form appropriate for `lexical-binding'
|
|||
and the LEXICAL argument to `eval'."
|
||||
(if (listp lexical)
|
||||
lexical
|
||||
(not (null (member lexical '("yes" "t"))))))
|
||||
(not (null (member lexical '("yes" "t" t))))))
|
||||
|
||||
(defun org-babel-edit-prep:emacs-lisp (info)
|
||||
"Set `lexical-binding' in Org edit buffer.
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@
|
|||
|
||||
(eval-when-compile (require 'subr-x)) ; For `string-empty-p', Emacs < 29
|
||||
|
||||
(defvar org-babel-error-buffer-name "*Org-Babel Error Output*")
|
||||
(defvar org-babel-error-buffer-name "*Org-Babel Error Output*"
|
||||
"The buffer name Org Babel evaluate error output.")
|
||||
(declare-function org-babel-temp-file "ob-core" (prefix &optional suffix))
|
||||
|
||||
(defun org-babel-eval-error-notify (exit-code stderr)
|
||||
|
|
@ -160,15 +161,8 @@ This buffer is named by `org-babel-error-buffer-name'."
|
|||
"Return system `shell-file-name', defaulting to /bin/sh.
|
||||
Unfortunately, `executable-find' does not support file name
|
||||
handlers. Therefore, we could use it in the local case only."
|
||||
;; FIXME: Since Emacs 27, `executable-find' accepts optional second
|
||||
;; argument supporting remote hosts.
|
||||
(cond ((and (not (file-remote-p default-directory))
|
||||
(executable-find shell-file-name))
|
||||
shell-file-name)
|
||||
((file-executable-p
|
||||
(concat (file-remote-p default-directory) shell-file-name))
|
||||
shell-file-name)
|
||||
("/bin/sh")))
|
||||
(if (executable-find shell-file-name 'respect-remote)
|
||||
shell-file-name "/bin/sh"))
|
||||
|
||||
(provide 'ob-eval)
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
drop-locals))
|
||||
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance element))
|
||||
(declare-function org-in-archived-heading-p "org" (&optional no-inheritance element))
|
||||
(declare-function org-src-preserve-indentation-p "org-src" (node))
|
||||
(declare-function org-src-preserve-indentation-p "org-src" (&optional node))
|
||||
|
||||
(defcustom org-export-use-babel t
|
||||
"Switch controlling code evaluation and header processing during export.
|
||||
|
|
@ -215,7 +215,7 @@ this template."
|
|||
(string= "yes"
|
||||
(cdr (assq :noweb params))))
|
||||
(org-babel-expand-noweb-references
|
||||
info org-babel-exp-reference-buffer)
|
||||
info org-babel-exp-reference-buffer :export)
|
||||
(nth 1 info)))
|
||||
(goto-char begin)
|
||||
(let ((replacement
|
||||
|
|
@ -306,10 +306,7 @@ this template."
|
|||
;; Do not use tabs for block
|
||||
;; indentation.
|
||||
(when (fboundp 'indent-tabs-mode)
|
||||
(indent-tabs-mode -1)
|
||||
;; FIXME: Emacs 26
|
||||
;; compatibility.
|
||||
(setq-local indent-tabs-mode nil))
|
||||
(indent-tabs-mode -1))
|
||||
(insert replacement)
|
||||
(skip-chars-backward " \r\t\n")
|
||||
(indent-line-to ind)
|
||||
|
|
@ -321,10 +318,7 @@ this template."
|
|||
;; Do not use tabs for block
|
||||
;; indentation.
|
||||
(when (fboundp 'indent-tabs-mode)
|
||||
(indent-tabs-mode -1)
|
||||
;; FIXME: Emacs 26
|
||||
;; compatibility.
|
||||
(setq-local indent-tabs-mode nil))
|
||||
(indent-tabs-mode -1))
|
||||
(insert replacement)
|
||||
(indent-rigidly
|
||||
1 (point) ind)
|
||||
|
|
@ -423,7 +417,7 @@ replaced with its value."
|
|||
(org-babel-noweb-wrap) "" (nth 1 info))
|
||||
(if (org-babel-noweb-p (nth 2 info) :export)
|
||||
(org-babel-expand-noweb-references
|
||||
info org-babel-exp-reference-buffer)
|
||||
info org-babel-exp-reference-buffer :export)
|
||||
(nth 1 info))))
|
||||
(org-fill-template
|
||||
(if (eq type 'inline)
|
||||
|
|
@ -462,7 +456,7 @@ inhibit insertion of results into the buffer."
|
|||
(let ((lang (nth 0 info))
|
||||
(body (if (org-babel-noweb-p (nth 2 info) :eval)
|
||||
(org-babel-expand-noweb-references
|
||||
info org-babel-exp-reference-buffer)
|
||||
info org-babel-exp-reference-buffer :eval)
|
||||
(nth 1 info)))
|
||||
(info (copy-sequence info))
|
||||
(org-babel-current-src-block-location (point-marker)))
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
;; Authors: Sergey Litvinov
|
||||
;; Eric Schulte
|
||||
;; Maintainer: Ken Mankoff <km@kenmankoff.com>
|
||||
;; Keywords: literate programming, reproducible research, fortran
|
||||
;; URL: https://orgmode.org
|
||||
|
||||
|
|
|
|||
|
|
@ -209,7 +209,6 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(let ((script-file (org-babel-temp-file "gnuplot-script-")))
|
||||
(with-temp-file script-file
|
||||
(insert (concat body "\n")))
|
||||
(unless noninteractive (message "gnuplot \"%s\"" script-file))
|
||||
(setq output
|
||||
(shell-command-to-string
|
||||
(format
|
||||
|
|
@ -217,8 +216,7 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(org-babel-process-file-name
|
||||
script-file
|
||||
(if (member system-type '(cygwin windows-nt ms-dos))
|
||||
t nil)))))
|
||||
(unless noninteractive (message "%s" output)))
|
||||
t nil))))))
|
||||
(with-temp-buffer
|
||||
(insert (concat body "\n"))
|
||||
(gnuplot-mode)
|
||||
|
|
@ -231,7 +229,6 @@ This function is called by `org-babel-execute-src-block'."
|
|||
"Prepare SESSION according to the header arguments in PARAMS."
|
||||
(let* ((session (org-babel-gnuplot-initiate-session session))
|
||||
(var-lines (org-babel-variable-assignments:gnuplot params)))
|
||||
(unless noninteractive (message "%S" session))
|
||||
(org-babel-comint-in-buffer session
|
||||
(dolist (var-line var-lines)
|
||||
(insert var-line)
|
||||
|
|
@ -320,6 +317,7 @@ Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE."
|
|||
`( :sep "\t" :fmt org-babel-gnuplot-quote-tsv-field
|
||||
;; Two setting below are needed to make :fmt work.
|
||||
:raw t
|
||||
:with-special-rows nil
|
||||
:backend ,ob-gnuplot-data)
|
||||
params)))))
|
||||
data-file)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ parameters may be used, like groovy -v"
|
|||
(defun org-babel-execute:groovy (body params)
|
||||
"Execute Groovy BODY according to PARAMS.
|
||||
This function is called by `org-babel-execute-src-block'."
|
||||
(unless noninteractive (message "Executing Groovy source code block"))
|
||||
(let* ((processed-params (org-babel-process-params params))
|
||||
(session (org-babel-groovy-initiate-session (nth 0 processed-params)))
|
||||
(result-params (nth 2 processed-params))
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
(add-to-list 'org-babel-tangle-lang-exts '("haskell" . "hs"))
|
||||
|
||||
(defvar org-babel-default-header-args:haskell
|
||||
'((:padlines . "no")))
|
||||
'((:padline . "no")))
|
||||
|
||||
(defvar org-babel-haskell-lhs2tex-command "lhs2tex")
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ This function should only be called by `org-babel-execute:haskell'."
|
|||
(add-hook 'inferior-haskell-hook
|
||||
(lambda ()
|
||||
(setq-local
|
||||
org-babel-comint-prompt-regexp-old comint-prompt-regexp
|
||||
org-babel-comint-prompt-regexp-fallback comint-prompt-regexp
|
||||
comint-prompt-regexp
|
||||
(concat haskell-prompt-regexp "\\|^λ?> "))))
|
||||
(org-babel-haskell-with-session session params
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;;; ob-js.el --- Babel Functions for Javascript -*- lexical-binding: t; -*-
|
||||
;;; ob-js.el --- Babel Functions for JavaScript -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2010-2026 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -73,10 +73,10 @@
|
|||
;; parenthesis are not shadowed if the last line of the body is a
|
||||
;; line comment.
|
||||
"require('process').stdout.write(require('util').inspect(function(){%s\n}()));"
|
||||
"Javascript code to print value of body.")
|
||||
"JavaScript code to print value of body.")
|
||||
|
||||
(defun org-babel-execute:js (body params)
|
||||
"Execute Javascript BODY according to PARAMS.
|
||||
"Execute JavaScript BODY according to PARAMS.
|
||||
This function is called by `org-babel-execute-src-block'."
|
||||
(let* ((org-babel-js-cmd (or (cdr (assq :cmd params)) org-babel-js-cmd))
|
||||
(session (cdr (assq :session params)))
|
||||
|
|
@ -158,7 +158,7 @@ specifying a variable of the same value."
|
|||
session))
|
||||
|
||||
(defun org-babel-variable-assignments:js (params)
|
||||
"Return list of Javascript statements assigning the block's variables.
|
||||
"Return list of JavaScript statements assigning the block's variables.
|
||||
The variables are defined in PARAMS."
|
||||
(mapcar
|
||||
(lambda (pair) (format "var %s=%s;"
|
||||
|
|
@ -183,6 +183,7 @@ Return the initialized session."
|
|||
(run-skewer)
|
||||
(skewer-repl)
|
||||
session-buffer)))
|
||||
;; SIC, JavaScript miscapitalized in `js-comint.el'.
|
||||
((string= "*Javascript REPL*" session)
|
||||
(org-require-package 'js-comint)
|
||||
(let ((session-buffer "*Javascript REPL*"))
|
||||
|
|
|
|||
|
|
@ -43,8 +43,15 @@
|
|||
(declare-function inferior-ess-send-input "ext:ess-inf" ())
|
||||
(declare-function ess-make-buffer-current "ext:ess-inf" ())
|
||||
(declare-function ess-eval-buffer "ext:ess-inf" (vis))
|
||||
(declare-function ess-wait-for-process "ext:ess-inf"
|
||||
(&optional proc sec-prompt wait force-redisplay))
|
||||
|
||||
(defvar ess-current-process-name) ; ess-custom.el
|
||||
(defvar ess-local-process-name) ; ess-custom.el
|
||||
(defvar ess-eval-visibly) ; ess-custom.el
|
||||
(defvar ess-local-customize-alist); ess-custom.el
|
||||
(defvar ess-gen-proc-buffer-name-function) ; ess-custom.el
|
||||
(defvar ess-ask-for-ess-directory) ; ess-custom.el
|
||||
(defvar ess-directory-function) ; ess-custom.el
|
||||
(defvar ess-directory) ; ess-custom.el
|
||||
|
||||
(defvar org-babel-header-args:julia
|
||||
'((width . :any)
|
||||
|
|
@ -66,11 +73,6 @@
|
|||
:group 'org-babel
|
||||
:type 'string)
|
||||
|
||||
(defvar ess-current-process-name) ; dynamically scoped
|
||||
(defvar ess-local-process-name) ; dynamically scoped
|
||||
(defvar ess-eval-visibly-p) ; dynamically scoped
|
||||
(defvar ess-local-customize-alist); dynamically scoped
|
||||
(defvar ess-gen-proc-buffer-name-function) ; defined in ess-inf.el
|
||||
(defun org-babel-julia-associate-session (session)
|
||||
"Associate R code buffer with an R session.
|
||||
Make SESSION be the inferior ESS process associated with the
|
||||
|
|
@ -167,7 +169,10 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(min (if lengths (apply #'min lengths) 0)))
|
||||
;; Ensure VALUE has an orgtbl structure (depth of at least 2).
|
||||
(unless (listp (car value)) (setq value (list value)))
|
||||
(let ((file (orgtbl-to-csv value '(:fmt org-babel-julia-quote-csv-field))))
|
||||
(let ((file (orgtbl-to-csv
|
||||
value
|
||||
'( :fmt org-babel-julia-quote-csv-field
|
||||
:with-special-rows nil))))
|
||||
(if (= max min)
|
||||
(format "%s = begin
|
||||
using CSV
|
||||
|
|
@ -181,13 +186,17 @@ end"
|
|||
(format "%s = %s" name (org-babel-julia-quote-csv-field value))))
|
||||
|
||||
(defvar ess-ask-for-ess-directory) ; dynamically scoped
|
||||
(defun org-babel-julia-initiate-session (session params)
|
||||
(defun org-babel-julia-initiate-session (session _params)
|
||||
"If there is not a current julia process then create one."
|
||||
(unless (string= session "none")
|
||||
(let* ((session (or session "*Julia*"))
|
||||
(ess-ask-for-ess-directory
|
||||
(and (bound-and-true-p ess-ask-for-ess-directory)
|
||||
(not (cdr (assq :dir params)))))
|
||||
;; Force using `default-directory', as we promise in the
|
||||
;; manual. The caller should have taken care about setting
|
||||
;; it according to :dir if necessary.
|
||||
;; https://ess.r-project.org/Manual/ess.html#Changing-the-startup-actions
|
||||
(ess-ask-for-ess-directory nil)
|
||||
(ess-directory-function nil)
|
||||
(ess-directory nil)
|
||||
;; Make ESS name the process buffer as SESSION.
|
||||
(ess-gen-proc-buffer-name-function
|
||||
(lambda (_) session)))
|
||||
|
|
@ -293,7 +302,7 @@ last statement in BODY, as elisp."
|
|||
(let ((ess-local-customize-alist t)
|
||||
(ess-local-process-name
|
||||
(process-name (get-buffer-process session)))
|
||||
(ess-eval-visibly-p nil))
|
||||
(ess-eval-visibly nil))
|
||||
(ess-eval-buffer nil)))
|
||||
(let ((tmp-file (org-babel-temp-file "julia-")))
|
||||
(org-babel-comint-eval-invisibly-and-wait-for-file
|
||||
|
|
|
|||
|
|
@ -41,9 +41,6 @@
|
|||
(declare-function org-latex-compile "ox-latex" (texfile &optional snippet))
|
||||
(declare-function org-latex-guess-inputenc "ox-latex" (header))
|
||||
(declare-function org-splice-latex-header "org" (tpl def-pkg pkg snippets-p &optional extra))
|
||||
(declare-function org-at-heading-p "org" (&optional _))
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-next-visible-heading "org" (arg))
|
||||
|
||||
(defvar org-babel-tangle-lang-exts)
|
||||
(add-to-list 'org-babel-tangle-lang-exts '("latex" . "tex"))
|
||||
|
|
@ -80,13 +77,14 @@
|
|||
(defcustom org-babel-latex-preamble
|
||||
(lambda (_)
|
||||
"\\documentclass[preview]{standalone}
|
||||
\\def\\pgfsysdriver{pgfsys-tex4ht.def}
|
||||
")
|
||||
"Closure which evaluates at runtime to the LaTeX preamble.
|
||||
|
||||
It takes 1 argument which is the parameters of the source block."
|
||||
:group 'org-babel
|
||||
:type 'function)
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'function
|
||||
:risky t)
|
||||
|
||||
(defcustom org-babel-latex-begin-env
|
||||
(lambda (_)
|
||||
|
|
@ -130,16 +128,29 @@ exporting the literal LaTeX source."
|
|||
:type '(repeat (string)))
|
||||
|
||||
(defcustom org-babel-latex-process-alist
|
||||
`(,(cons 'png (alist-get 'dvipng org-preview-latex-process-alist)))
|
||||
`((png :programs ("latex" "dvipng") :description "dvi > png"
|
||||
:message
|
||||
"you need to install the programs: latex and dvipng."
|
||||
:image-input-type "dvi" :image-output-type "png"
|
||||
:image-size-adjust (1.0 . 1.0) :latex-compiler
|
||||
,(if (and (executable-find "latexmk") (executable-find "perl"))
|
||||
'("latexmk -f -pdf -latex -interaction=nonstopmode -output-directory=%o %f")
|
||||
'("latex -interaction nonstopmode -output-directory %o %f"
|
||||
"latex -interaction nonstopmode -output-directory %o %f"
|
||||
"latex -interaction nonstopmode -output-directory %o %f"))
|
||||
:image-converter ("dvipng -D %D -T tight -o %O %f")
|
||||
:transparent-image-converter
|
||||
("dvipng -D %D -T tight -bg Transparent -o %O %f")))
|
||||
"Definitions of external processes for LaTeX result generation.
|
||||
See `org-preview-latex-process-alist' for more details.
|
||||
|
||||
The following process symbols are recognized:
|
||||
- `png' :: Process used to produce .png output."
|
||||
:group 'org-babel
|
||||
:package-version '(Org . "9.7")
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(alist :tag "LaTeX to image backends"
|
||||
:value-type (plist)))
|
||||
:value-type (plist))
|
||||
:risky t)
|
||||
|
||||
(defun org-babel-expand-body:latex (body params)
|
||||
"Expand BODY according to PARAMS, return the expanded body."
|
||||
|
|
@ -249,6 +260,8 @@ This function is called by `org-babel-execute-src-block'."
|
|||
((or (string= "pdf" extension) imagemagick)
|
||||
(with-temp-file tex-file
|
||||
(require 'ox-latex)
|
||||
(defvar org-latex-compiler)
|
||||
(declare-function org-latex--remove-packages "ox-latex" (pkg-alist info))
|
||||
(insert
|
||||
(org-latex-guess-inputenc
|
||||
(org-splice-latex-header
|
||||
|
|
@ -259,8 +272,12 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(lambda (el)
|
||||
(unless (and (listp el) (string= "hyperref" (cadr el)))
|
||||
el))
|
||||
org-latex-default-packages-alist))
|
||||
(org-latex--remove-packages
|
||||
org-latex-default-packages-alist
|
||||
(list :latex-compiler org-latex-compiler))))
|
||||
(org-latex--remove-packages
|
||||
org-latex-packages-alist
|
||||
(list :latex-compiler org-latex-compiler))
|
||||
nil))
|
||||
(if fit "\n\\usepackage[active, tightpage]{preview}\n" "")
|
||||
(if border (format "\\setlength{\\PreviewBorder}{%s}" border) "")
|
||||
|
|
|
|||
|
|
@ -61,13 +61,14 @@ Valid values include `slime-eval' and `sly-eval'."
|
|||
:type 'symbol)
|
||||
|
||||
(defcustom org-babel-lisp-dir-fmt
|
||||
"(let ((*default-pathname-defaults* #P%S\n)) %%s\n)"
|
||||
"(cl:let ((cl:*default-pathname-defaults* #P%S\n)) %%s\n)"
|
||||
"Format string used to wrap code bodies to set the current directory.
|
||||
For example a value of \"(progn ;; %s\\n %%s)\" would ignore the
|
||||
current directory string."
|
||||
:group 'org-babel
|
||||
:version "24.1"
|
||||
:type 'string)
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'string
|
||||
:risky t)
|
||||
|
||||
(defun org-babel-expand-body:lisp (body params)
|
||||
"Expand BODY according to PARAMS, return the expanded body."
|
||||
|
|
@ -77,10 +78,10 @@ current directory string."
|
|||
(prologue (cdr (assq :prologue params)))
|
||||
(epilogue (cdr (assq :epilogue params)))
|
||||
(body (if (null vars) (org-trim body)
|
||||
(concat "(let ("
|
||||
(concat "(cl:let ("
|
||||
(mapconcat
|
||||
(lambda (var)
|
||||
(format "(%S (quote %S))" (car var) (cdr var)))
|
||||
(format "(%S (cl:quote %S))" (car var) (cdr var)))
|
||||
vars "\n ")
|
||||
")\n"
|
||||
(and prologue (concat prologue "\n"))
|
||||
|
|
@ -89,7 +90,7 @@ current directory string."
|
|||
")"))))
|
||||
(if (or (member "code" result-params)
|
||||
(member "pp" result-params))
|
||||
(format "(pprint %s)" body)
|
||||
(format "(cl:pprint %s)" body)
|
||||
body)))
|
||||
|
||||
(defun org-babel-execute:lisp (body params)
|
||||
|
|
@ -115,7 +116,7 @@ a property list containing the parameters of the block."
|
|||
default-directory)))
|
||||
(format
|
||||
(if dir (format org-babel-lisp-dir-fmt dir)
|
||||
"(progn %s\n)")
|
||||
"(cl:progn %s\n)")
|
||||
(buffer-substring-no-properties
|
||||
(point-min) (point-max)))))
|
||||
(cdr (assq :package params)))))))
|
||||
|
|
|
|||
|
|
@ -59,10 +59,6 @@ should not be inherited from a source block.")
|
|||
(let* ((info (org-babel-get-src-block-info 'no-eval))
|
||||
(source-name (nth 4 info)))
|
||||
(when source-name
|
||||
(setf (nth 1 info)
|
||||
(if (org-babel-noweb-p (nth 2 info) :eval)
|
||||
(org-babel-expand-noweb-references info)
|
||||
(nth 1 info)))
|
||||
(let ((source (intern source-name)))
|
||||
(setq org-babel-library-of-babel
|
||||
(cons (cons source info)
|
||||
|
|
@ -86,11 +82,13 @@ if so then run the appropriate source block from the Library."
|
|||
(org-babel-execute-src-block nil info nil (org-element-type datum))
|
||||
t)))
|
||||
|
||||
(defun org-babel-lob--src-info (ref)
|
||||
(defun org-babel-lob--src-info (ref &optional eval)
|
||||
"Return internal representation for Babel data referenced as REF.
|
||||
REF is a string. This function looks into the current document
|
||||
for a Babel call or source block. If none is found, it looks
|
||||
after REF in the Library of Babel."
|
||||
after REF in the Library of Babel.
|
||||
When EVAL is non-nil, evaluate src block parameters.
|
||||
"
|
||||
(let ((name ref)
|
||||
(file nil))
|
||||
;; Extract the remote file, if specified in the reference.
|
||||
|
|
@ -112,7 +110,7 @@ after REF in the Library of Babel."
|
|||
(when (equal name (org-element-property :name element))
|
||||
(throw :found
|
||||
(pcase (org-element-type element)
|
||||
(`src-block (org-babel-get-src-block-info t element))
|
||||
(`src-block (org-babel-get-src-block-info (not eval) element))
|
||||
(`babel-call (org-babel-lob-get-info element))
|
||||
;; Non-executable data found. Since names
|
||||
;; are supposed to be unique throughout
|
||||
|
|
@ -131,6 +129,12 @@ remote variable references; a process which could likely result
|
|||
in the execution of other code blocks, and do not evaluate Lisp
|
||||
values in parameters.
|
||||
|
||||
The evaluation happens in the context of DATUM (babel call or inline
|
||||
babel call) for its local arguments, while evaluation of the references
|
||||
code block happens in the context (with point at) of that block.
|
||||
`org-babel-current-src-block-location' is bound to DATUM position
|
||||
during evaluation.
|
||||
|
||||
Return nil when not on an appropriate location. Otherwise return
|
||||
a list compatible with `org-babel-get-src-block-info', which
|
||||
see."
|
||||
|
|
@ -138,12 +142,14 @@ see."
|
|||
(type (org-element-type context))
|
||||
(reference (org-element-property :call context)))
|
||||
(when (memq type '(babel-call inline-babel-call))
|
||||
(pcase (org-babel-lob--src-info reference)
|
||||
(`(,language ,body ,header ,_ ,_ ,_ ,coderef)
|
||||
(let ((begin (org-element-property (if (eq type 'inline-babel-call)
|
||||
(let* ((begin (org-element-property (if (eq type 'inline-babel-call)
|
||||
:begin
|
||||
:post-affiliated)
|
||||
context)))
|
||||
context))
|
||||
;; Signal downstream to lisp parameter values about current location.
|
||||
(org-babel-current-src-block-location begin))
|
||||
(pcase (org-babel-lob--src-info reference (if no-eval nil 'eval))
|
||||
(`(,language ,body ,header ,_ ,_ ,_ ,coderef)
|
||||
(list language
|
||||
body
|
||||
(apply #'org-babel-merge-params
|
||||
|
|
@ -164,8 +170,8 @@ see."
|
|||
nil
|
||||
(org-element-property :name context)
|
||||
begin
|
||||
coderef)))
|
||||
(_ nil)))))
|
||||
coderef))
|
||||
(_ nil))))))
|
||||
|
||||
(provide 'ob-lob)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,18 +23,7 @@
|
|||
|
||||
;;; Commentary:
|
||||
|
||||
;; Org-Babel support for evaluating Lua source code.
|
||||
|
||||
;; Requirements:
|
||||
;; for session support, lua-mode is needed.
|
||||
;;
|
||||
;; lua-mode is not part of GNU Emacs/orgmode, but can be obtained
|
||||
;; from NonGNU ELPA (see `M-x list-packages').
|
||||
;;
|
||||
;; The source repository is here:
|
||||
;; https://github.com/immerrr/lua-mode
|
||||
|
||||
;; However, sessions are not yet working.
|
||||
;; Org Babel support for evaluating Lua source code.
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
|
@ -45,10 +34,6 @@
|
|||
(require 'org-macs)
|
||||
(require 'cl-lib)
|
||||
|
||||
(declare-function lua-shell "ext:lua-mode" (&optional argprompt))
|
||||
(declare-function lua-toggle-shells "ext:lua-mode" (arg))
|
||||
(declare-function run-lua "ext:lua" (cmd &optional dedicated show))
|
||||
|
||||
(defvar org-babel-tangle-lang-exts)
|
||||
(add-to-list 'org-babel-tangle-lang-exts '("lua" . "lua"))
|
||||
|
||||
|
|
@ -62,7 +47,7 @@
|
|||
:type 'string)
|
||||
|
||||
(defcustom org-babel-lua-mode 'lua-mode
|
||||
"Preferred lua mode for use in running lua interactively.
|
||||
"Preferred Lua mode for use in running Lua interactively.
|
||||
This will typically be `lua-mode'."
|
||||
:group 'org-babel
|
||||
:version "26.1"
|
||||
|
|
@ -70,7 +55,7 @@ This will typically be `lua-mode'."
|
|||
:type 'symbol)
|
||||
|
||||
(defcustom org-babel-lua-hline-to "None"
|
||||
"Replace hlines in incoming tables with this when translating to Lua."
|
||||
"Replace `hlines' in incoming tables with this when translating to Lua."
|
||||
:group 'org-babel
|
||||
:version "26.1"
|
||||
:package-version '(Org . "8.3")
|
||||
|
|
@ -92,11 +77,10 @@ This will typically be `lua-mode'."
|
|||
(defun org-babel-execute:lua (body params)
|
||||
"Execute Lua BODY according to PARAMS.
|
||||
This function is called by `org-babel-execute-src-block'."
|
||||
(let* ((session (org-babel-lua-initiate-session
|
||||
(cdr (assq :session params))))
|
||||
(let* ((session (cdr (assq :session params)))
|
||||
(result-params (cdr (assq :result-params params)))
|
||||
(result-type (cdr (assq :result-type params)))
|
||||
(return-val (when (and (eq result-type 'value) (not session))
|
||||
(return-val (when (eq result-type 'value)
|
||||
(cdr (assq :return params))))
|
||||
(preamble (cdr (assq :preamble params)))
|
||||
(full-body
|
||||
|
|
@ -104,7 +88,9 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(concat body (if return-val (format "\nreturn %s" return-val) ""))
|
||||
params (org-babel-variable-assignments:lua params)))
|
||||
(result (org-babel-lua-evaluate
|
||||
session full-body result-type result-params preamble)))
|
||||
full-body result-type result-params preamble)))
|
||||
(when (and session (not (equal session "none")))
|
||||
(user-error "Sessions not supported for Lua"))
|
||||
(org-babel-reassemble-table
|
||||
result
|
||||
(org-babel-pick-name (cdr (assq :colname-names params))
|
||||
|
|
@ -112,28 +98,6 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(org-babel-pick-name (cdr (assq :rowname-names params))
|
||||
(cdr (assq :rownames params))))))
|
||||
|
||||
(defun org-babel-prep-session:lua (session params)
|
||||
"Prepare SESSION according to the header arguments in PARAMS.
|
||||
VARS contains resolved variable references."
|
||||
(let* ((session (org-babel-lua-initiate-session session))
|
||||
(var-lines
|
||||
(org-babel-variable-assignments:lua params)))
|
||||
(org-babel-comint-in-buffer session
|
||||
(mapc (lambda (var)
|
||||
(end-of-line 1) (insert var) (comint-send-input)
|
||||
(org-babel-comint-wait-for-output session))
|
||||
var-lines))
|
||||
session))
|
||||
|
||||
(defun org-babel-load-session:lua (session body params)
|
||||
"Load BODY into SESSION."
|
||||
(save-window-excursion
|
||||
(let ((buffer (org-babel-prep-session:lua session params)))
|
||||
(with-current-buffer buffer
|
||||
(goto-char (process-mark (get-buffer-process (current-buffer))))
|
||||
(insert (org-babel-chomp body)))
|
||||
buffer)))
|
||||
|
||||
;; helper functions
|
||||
|
||||
(defun org-babel-variable-assignments:lua (params)
|
||||
|
|
@ -168,9 +132,9 @@ specifying a variable of the same value."
|
|||
(if (stringp var) (substring-no-properties var) var)))))
|
||||
|
||||
(defun org-babel-lua-table-or-string (results)
|
||||
"Convert RESULTS into an appropriate elisp value.
|
||||
"Convert RESULTS into an appropriate Emacs Lisp value.
|
||||
If the results look like a list or tuple, then convert them into an
|
||||
Emacs-lisp table, otherwise return the results as a string."
|
||||
Emacs Lisp table, otherwise return the results as a string."
|
||||
(let ((res (org-babel-script-escape results)))
|
||||
(if (listp res)
|
||||
(mapcar (lambda (el) (if (eq el 'None)
|
||||
|
|
@ -180,76 +144,6 @@ Emacs-lisp table, otherwise return the results as a string."
|
|||
|
||||
(defvar org-babel-lua-buffers '((:default . "*Lua*")))
|
||||
|
||||
(defun org-babel-lua-session-buffer (session)
|
||||
"Return the buffer associated with SESSION."
|
||||
(cdr (assoc session org-babel-lua-buffers)))
|
||||
|
||||
(defun org-babel-lua-with-earmuffs (session)
|
||||
"Return buffer name for SESSION, as *SESSION*."
|
||||
(let ((name (if (stringp session) session (format "%s" session))))
|
||||
(if (and (string= "*" (substring name 0 1))
|
||||
(string= "*" (substring name (- (length name) 1))))
|
||||
name
|
||||
(format "*%s*" name))))
|
||||
|
||||
(defun org-babel-session-buffer:lua (session &optional _)
|
||||
"Return session buffer name for SESSION."
|
||||
(or (org-babel-lua-session-buffer session)
|
||||
(org-babel-lua-with-earmuffs session)))
|
||||
|
||||
(defun org-babel-lua-without-earmuffs (session)
|
||||
"Remove stars around *SESSION*, leaving SESSION."
|
||||
(let ((name (if (stringp session) session (format "%s" session))))
|
||||
(if (and (string= "*" (substring name 0 1))
|
||||
(string= "*" (substring name (- (length name) 1))))
|
||||
(substring name 1 (- (length name) 1))
|
||||
name)))
|
||||
|
||||
(defvar lua-default-interpreter)
|
||||
(defvar lua-which-bufname)
|
||||
(defvar lua-shell-buffer-name)
|
||||
(defun org-babel-lua-initiate-session-by-key (&optional session)
|
||||
"Initiate a Lua session.
|
||||
If there is not a current inferior-process-buffer in SESSION
|
||||
then create. Return the initialized session."
|
||||
;; (require org-babel-lua-mode)
|
||||
(save-window-excursion
|
||||
(let* ((session (if session (intern session) :default))
|
||||
(lua-buffer (org-babel-lua-session-buffer session))
|
||||
;; (cmd (if (member system-type '(cygwin windows-nt ms-dos))
|
||||
;; (concat org-babel-lua-command " -i")
|
||||
;; org-babel-lua-command))
|
||||
)
|
||||
(cond
|
||||
((and (eq 'lua-mode org-babel-lua-mode)
|
||||
(fboundp 'lua-start-process)) ; lua-mode.el
|
||||
;; Make sure that lua-which-bufname is initialized, as otherwise
|
||||
;; it will be overwritten the first time a Lua buffer is
|
||||
;; created.
|
||||
;;(lua-toggle-shells lua-default-interpreter)
|
||||
;; `lua-shell' creates a buffer whose name is the value of
|
||||
;; `lua-which-bufname' with '*'s at the beginning and end
|
||||
(let* ((bufname (if (and lua-buffer (buffer-live-p lua-buffer))
|
||||
(replace-regexp-in-string ;; zap surrounding *
|
||||
"^\\*\\([^*]+\\)\\*$" "\\1" (buffer-name lua-buffer))
|
||||
(concat "Lua-" (symbol-name session))))
|
||||
(lua-which-bufname bufname))
|
||||
(lua-start-process)
|
||||
(setq lua-buffer (org-babel-lua-with-earmuffs bufname))))
|
||||
(t
|
||||
(error "No function available for running an inferior Lua")))
|
||||
(setq org-babel-lua-buffers
|
||||
(cons (cons session lua-buffer)
|
||||
(assq-delete-all session org-babel-lua-buffers)))
|
||||
session)))
|
||||
|
||||
(defun org-babel-lua-initiate-session (&optional session _params)
|
||||
"Create a session named SESSION according to PARAMS."
|
||||
(unless (string= session "none")
|
||||
(error "Sessions currently not supported, work in progress")
|
||||
(org-babel-lua-session-buffer
|
||||
(org-babel-lua-initiate-session-by-key session))))
|
||||
|
||||
(defvar org-babel-lua-eoe-indicator "--eoe"
|
||||
"A string to indicate that evaluation has completed.")
|
||||
|
||||
|
|
@ -263,38 +157,56 @@ function dump(it, indent)
|
|||
if indent == nil then
|
||||
indent = ''
|
||||
end
|
||||
|
||||
if type(it) == 'table' and %s then
|
||||
local count = 0
|
||||
for _ in pairs(it) do
|
||||
count = count + 1
|
||||
end
|
||||
local result = ''
|
||||
|
||||
if #indent ~= 0 then
|
||||
result = result .. '\\n'
|
||||
end
|
||||
for key, value in pairs(it) do
|
||||
|
||||
local keys = {}
|
||||
for key in pairs(it) do
|
||||
table.insert(keys, key)
|
||||
end
|
||||
|
||||
table.sort(keys)
|
||||
|
||||
for index, key in pairs(keys) do
|
||||
local value = it[key]
|
||||
result = result
|
||||
.. indent
|
||||
.. dump(key)
|
||||
.. ' = '
|
||||
.. dump(value, indent .. ' ')
|
||||
count = count - 1
|
||||
if count ~= 0 then
|
||||
if index ~= #keys then
|
||||
result = result .. '\\n'
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
else
|
||||
return tostring(it)
|
||||
return string.gsub(tostring(it), '\"', '\\\"')
|
||||
end
|
||||
end
|
||||
|
||||
function combine(...)
|
||||
local result = {}
|
||||
|
||||
for index = 1, select('#', ...) do
|
||||
result[index] = dump(select(index, ...))
|
||||
end
|
||||
return table.concat(result, '%s')
|
||||
|
||||
if #result == 1 then
|
||||
local value = result[1]
|
||||
if string.find(value, '[%%(%%[{]') == 1 then
|
||||
return '\"' .. value .. '\"'
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
return '\"' .. table.concat(result, '%s') .. '\"'
|
||||
end
|
||||
|
||||
output = io.open('%s', 'w')
|
||||
|
|
@ -302,19 +214,6 @@ output:write(combine(main()))
|
|||
output:close()")
|
||||
|
||||
(defun org-babel-lua-evaluate
|
||||
(session body &optional result-type result-params preamble)
|
||||
"Evaluate BODY in SESSION as Lua code.
|
||||
RESULT-TYPE and RESULT-PARAMS are passed to
|
||||
`org-babel-lua-evaluate-session' or
|
||||
`org-babel-lua-evaluate-external-process'.
|
||||
PREAMBLE is passed to `org-babel-lua-evaluate-external-process'."
|
||||
(if session
|
||||
(org-babel-lua-evaluate-session
|
||||
session body result-type result-params)
|
||||
(org-babel-lua-evaluate-external-process
|
||||
body result-type result-params preamble)))
|
||||
|
||||
(defun org-babel-lua-evaluate-external-process
|
||||
(body &optional result-type result-params preamble)
|
||||
"Evaluate BODY in external Lua process.
|
||||
If RESULT-TYPE equals `output' then return standard output as a
|
||||
|
|
@ -350,88 +249,6 @@ PREAMBLE string is appended to BODY."
|
|||
raw
|
||||
(org-babel-lua-table-or-string (org-trim raw)))))
|
||||
|
||||
(defun org-babel-lua-evaluate-session
|
||||
(session body &optional result-type result-params)
|
||||
"Pass BODY to the Lua process in SESSION.
|
||||
If RESULT-TYPE equals `output' then return standard output as a
|
||||
string. If RESULT-TYPE equals `value' then return the value of the
|
||||
last statement in BODY, as Emacs Lisp."
|
||||
(let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0.005)))
|
||||
(dump-last-value
|
||||
(lambda
|
||||
(tmp-file pp)
|
||||
(mapc
|
||||
(lambda (statement) (insert statement) (funcall send-wait))
|
||||
(if pp
|
||||
(list
|
||||
"-- table to string
|
||||
function t2s(t, indent)
|
||||
if indent == nil then
|
||||
indent = \"\"
|
||||
end
|
||||
if type(t) == \"table\" then
|
||||
ts = \"\"
|
||||
for k,v in pairs(t) do
|
||||
if type(v) == \"table\" then
|
||||
ts = ts .. indent .. t2s(k,indent .. \" \") .. \" = \\n\" ..
|
||||
t2s(v, indent .. \" \")
|
||||
else
|
||||
ts = ts .. indent .. t2s(k,indent .. \" \") .. \" = \" ..
|
||||
t2s(v, indent .. \" \") .. \"\\n\"
|
||||
end
|
||||
end
|
||||
return ts
|
||||
else
|
||||
return tostring(t)
|
||||
end
|
||||
end
|
||||
"
|
||||
(concat "fd:write(_))
|
||||
fd:close()"
|
||||
(org-babel-process-file-name tmp-file 'noquote)))
|
||||
(list (format "fd=io.open(\"%s\", \"w\")
|
||||
fd:write( _ )
|
||||
fd:close()"
|
||||
(org-babel-process-file-name tmp-file
|
||||
'noquote)))))))
|
||||
(input-body (lambda (body)
|
||||
(mapc (lambda (line) (insert line) (funcall send-wait))
|
||||
(split-string body "[\r\n]"))
|
||||
(funcall send-wait)))
|
||||
(results
|
||||
(pcase result-type
|
||||
(`output
|
||||
(mapconcat
|
||||
#'org-trim
|
||||
(butlast
|
||||
(org-babel-comint-with-output
|
||||
(session org-babel-lua-eoe-indicator t body)
|
||||
(funcall input-body body)
|
||||
(funcall send-wait) (funcall send-wait)
|
||||
(insert org-babel-lua-eoe-indicator)
|
||||
(funcall send-wait))
|
||||
2) "\n"))
|
||||
(`value
|
||||
(let ((tmp-file (org-babel-temp-file "lua-")))
|
||||
(org-babel-comint-with-output
|
||||
(session org-babel-lua-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-lua-eoe-indicator)
|
||||
(funcall send-wait)))
|
||||
(org-babel-eval-read-file tmp-file))))))
|
||||
(unless (string= (substring org-babel-lua-eoe-indicator 1 -1) results)
|
||||
(org-babel-result-cond result-params
|
||||
results
|
||||
(org-babel-lua-table-or-string results)))))
|
||||
|
||||
(defun org-babel-lua-read-string (string)
|
||||
"Strip single quotes from around Lua STRING."
|
||||
(org-unbracket-string "'" "'" string))
|
||||
|
||||
(provide 'ob-lua)
|
||||
|
||||
;;; ob-lua.el ends here
|
||||
|
|
|
|||
|
|
@ -110,11 +110,13 @@ output. See `org-babel-maxima-expand'.")
|
|||
"\n")))
|
||||
|
||||
(defvar org-babel-maxima--output-filter-regexps
|
||||
'("batch" ;; remove the `batch' or `batchload' line
|
||||
'("(linenum:0,$" ;; remove fragment from command-line (see `org-babel-execute:maxima')
|
||||
"batch" ;; remove the `batch' or `batchload' line
|
||||
"^rat: replaced .*$" ;; remove notices from `rat'
|
||||
"^;;; Loading #P" ;; remove notices from the lisp implementation
|
||||
"^read and interpret" ;; remove notice from `batch'
|
||||
"^(%\\([i]-?[0-9]+\\))[ ]$" ;; remove empty input lines from `batch'-ing
|
||||
"^Loading .+maxima-init\\.mac" ;; remove message about loading init file
|
||||
)
|
||||
"Regexps to remove extraneous lines from Maxima's output.
|
||||
See `org-babel-maxima--output-filter'.")
|
||||
|
|
@ -131,7 +133,6 @@ Return nil if LINE is zero-length or it matches a regexp in
|
|||
(defun org-babel-execute:maxima (body params)
|
||||
"Execute Maxima BODY according to PARAMS.
|
||||
This function is called by `org-babel-execute-src-block'."
|
||||
(unless noninteractive (message "Executing Maxima source code block"))
|
||||
(let ((result-params (split-string (or (cdr (assq :results params)) "")))
|
||||
(result
|
||||
(let* ((cmdline (or (cdr (assq :cmdline params)) ""))
|
||||
|
|
@ -151,7 +152,6 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(format "(linenum:0, %s(%S))$" batch/load in-file))
|
||||
cmdline)))
|
||||
(with-temp-file in-file (insert (org-babel-maxima-expand body params)))
|
||||
(unless noninteractive (message cmd))
|
||||
;; " | grep -v batch | grep -v 'replaced' | sed '/^$/d' "
|
||||
(let ((raw (org-babel-eval cmd "")))
|
||||
(mapconcat
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
(require 'org-macs)
|
||||
|
||||
(declare-function tuareg-run-caml "ext:tuareg" ())
|
||||
(declare-function tuareg-run-ocaml "ext:tuareg" ())
|
||||
(declare-function tuareg-interactive-send-input "ext:tuareg" ())
|
||||
|
||||
(defvar org-babel-tangle-lang-exts)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
(require 'org-macs)
|
||||
(require 'python)
|
||||
|
||||
(require 'subr-x) ; For `string-trim-right', Emacs < 28
|
||||
|
||||
(defvar org-babel-tangle-lang-exts)
|
||||
(add-to-list 'org-babel-tangle-lang-exts '("python" . "py"))
|
||||
|
||||
|
|
@ -158,14 +160,14 @@ file to save the graphics to.")
|
|||
|
||||
(defconst org-babel-python--def-format-value "\
|
||||
def __org_babel_python_format_value(result, result_file, result_params):
|
||||
with open(result_file, 'w') as f:
|
||||
with open(result_file, 'w') as __org_babel_python_tmpfile:
|
||||
if 'graphics' in result_params:
|
||||
result.savefig(result_file)
|
||||
elif 'pp' in result_params:
|
||||
import pprint
|
||||
f.write(pprint.pformat(result))
|
||||
__org_babel_python_tmpfile.write(pprint.pformat(result))
|
||||
elif 'list' in result_params and isinstance(result, dict):
|
||||
f.write(str(['{} :: {}'.format(k, v) for k, v in result.items()]))
|
||||
__org_babel_python_tmpfile.write(str(['{} :: {}'.format(k, v) for k, v in result.items()]))
|
||||
else:
|
||||
if not set(result_params).intersection(\
|
||||
['scalar', 'verbatim', 'raw']):
|
||||
|
|
@ -198,7 +200,7 @@ def __org_babel_python_format_value(result, result_file, result_params):
|
|||
result = result.tolist()
|
||||
else:
|
||||
result = repr(result)
|
||||
f.write(str(result))"
|
||||
__org_babel_python_tmpfile.write(str(result))"
|
||||
"Python function to format value result and save it to file.")
|
||||
|
||||
(defun org-babel-variable-assignments:python (params)
|
||||
|
|
@ -451,13 +453,13 @@ __org_babel_python_format_value(main(), '%s', %s)")
|
|||
(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 "\
|
||||
(org-babel-chomp
|
||||
(string-trim-right
|
||||
(org-babel-comint-with-output
|
||||
((org-babel-session-buffer:python session)
|
||||
org-babel-python-eoe-indicator
|
||||
nil nil 'disable-prompt-filtering)
|
||||
(python-shell-send-string (format "\
|
||||
try:
|
||||
%s
|
||||
except:
|
||||
|
|
@ -466,16 +468,7 @@ finally:
|
|||
print('%s')"
|
||||
(org-babel-python--shift-right body 4)
|
||||
org-babel-python-eoe-indicator)))
|
||||
(let ((python-shell-buffer-name
|
||||
(org-babel-python-without-earmuffs session)))
|
||||
(python-shell-send-string body))
|
||||
;; same as `python-shell-comint-end-of-output-p' in emacs-25.1+
|
||||
(while (not (and (python-shell-comint-end-of-output-p string-buffer)
|
||||
(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))))))
|
||||
(rx (literal org-babel-python-eoe-indicator) (zero-or-more anychar)))))
|
||||
|
||||
(defun org-babel-python-evaluate-session
|
||||
(session body &optional result-type result-params graphics-file)
|
||||
|
|
@ -495,8 +488,8 @@ non-nil, then save graphical results to that file instead."
|
|||
(pcase result-type
|
||||
(`output
|
||||
(let ((body (format "\
|
||||
with open('%s') as f:
|
||||
exec(compile(f.read(), f.name, 'exec'))"
|
||||
with open('%s') as __org_babel_python_tmpfile:
|
||||
exec(compile(__org_babel_python_tmpfile.read(), __org_babel_python_tmpfile.name, 'exec'))"
|
||||
(org-babel-process-file-name
|
||||
tmp-src-file 'noquote))))
|
||||
(org-babel-python-send-string session body)))
|
||||
|
|
@ -538,7 +531,8 @@ by `org-babel-comint-async-filter'."
|
|||
(org-babel-comint-async-register
|
||||
session (current-buffer)
|
||||
"ob_comint_async_python_\\(start\\|end\\|file\\)_\\(.+\\)"
|
||||
'org-babel-chomp 'org-babel-python-async-value-callback)
|
||||
'org-babel-chomp 'org-babel-python-async-value-callback
|
||||
'disable-prompt-filtering)
|
||||
(pcase result-type
|
||||
(`output
|
||||
(let ((uuid (org-id-uuid)))
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@
|
|||
(declare-function org-find-property "org" (property &optional value))
|
||||
(declare-function org-id-find-id-file "org-id" (id))
|
||||
(declare-function org-id-find-id-in-file "org-id" (id file &optional markerp))
|
||||
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
|
||||
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance element))
|
||||
(declare-function org-narrow-to-subtree "org" (&optional element))
|
||||
(declare-function org-fold-show-context "org-fold" (&optional key))
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ to \"0:-1\"."
|
|||
(if (or (= 0 (length portion)) (string-match ind-re portion))
|
||||
(mapcar
|
||||
(lambda (n) (nth n lis))
|
||||
(apply 'org-number-sequence
|
||||
(apply #'number-sequence
|
||||
(if (and (> (length portion) 0) (match-string 2 portion))
|
||||
(list
|
||||
(funcall wrap (string-to-number (match-string 2 portion)))
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ Session settings (`:ruby' header arg value) are taken from PARAMS."
|
|||
(when new-session?
|
||||
(with-current-buffer session-buffer
|
||||
(setq-local
|
||||
org-babel-comint-prompt-regexp-old comint-prompt-regexp
|
||||
org-babel-comint-prompt-regexp-fallback comint-prompt-regexp
|
||||
comint-prompt-regexp (concat "^" org-babel-ruby-prompt))
|
||||
(insert org-babel-ruby-define-prompt ";")
|
||||
(insert "_org_prompt_mode=conf.prompt_mode;conf.prompt_mode=:CUSTOM;")
|
||||
|
|
@ -213,20 +213,18 @@ Session settings (`:ruby' header arg value) are taken from PARAMS."
|
|||
|
||||
(defvar org-babel-ruby-wrapper-method
|
||||
"
|
||||
def main()
|
||||
results = (lambda do
|
||||
%s
|
||||
end
|
||||
results = main()
|
||||
end).call
|
||||
File.open('%s', 'w'){ |f| f.write((results.class == String) ? results : results.inspect) }
|
||||
")
|
||||
|
||||
(defvar org-babel-ruby-pp-wrapper-method
|
||||
"
|
||||
require 'pp'
|
||||
def main()
|
||||
results = (lambda do
|
||||
%s
|
||||
end
|
||||
results = main()
|
||||
end).call
|
||||
File.open('%s', 'w') do |f|
|
||||
$stdout = f
|
||||
pp results
|
||||
|
|
|
|||
|
|
@ -66,11 +66,10 @@
|
|||
(declare-function geiser-eval--retort-output "ext:geiser-eval" (ret))
|
||||
(declare-function geiser-eval--retort-result-str "ext:geiser-eval" (ret prefix))
|
||||
(declare-function geiser-eval--retort-error "ext:geiser-eval" (ret))
|
||||
(declare-function geiser-eval--retort-error-msg "ext:geiser-eval" (err))
|
||||
(declare-function geiser-eval--error-msg "ext:geiser-eval" (err))
|
||||
|
||||
(defcustom org-babel-scheme-null-to 'hline
|
||||
"Replace `null' and empty lists in scheme tables with this before returning."
|
||||
"Replacement for `()' and `null' in tabulated Scheme results."
|
||||
:group 'org-babel
|
||||
:version "26.1"
|
||||
:package-version '(Org . "9.1")
|
||||
|
|
@ -86,7 +85,7 @@
|
|||
"Expand :var header arguments given as VARS."
|
||||
(mapconcat
|
||||
(lambda (var)
|
||||
(format "(define %S %S)" (car var) (cdr var)))
|
||||
(format "(define %S '%S)" (car var) (cdr var)))
|
||||
vars
|
||||
"\n"))
|
||||
|
||||
|
|
@ -131,12 +130,17 @@ If the variables HOST and PORT are set, connect to the running Scheme REPL."
|
|||
(let ((buffer (org-babel-scheme-get-session-buffer name)))
|
||||
(or buffer
|
||||
(progn
|
||||
(let ((geiser-repl-window-allow-split nil)
|
||||
(geiser-repl-use-other-window nil)
|
||||
(switch-to-buffer-obey-display-actions t)
|
||||
(display-buffer-overriding-action '(display-buffer-no-window
|
||||
(allow-no-window t))))
|
||||
(if (fboundp 'geiser)
|
||||
(if (and host port)
|
||||
(geiser-connect impl host port)
|
||||
(geiser impl))
|
||||
;; Obsolete since Geiser 0.26.
|
||||
(run-geiser impl))
|
||||
(run-geiser impl)))
|
||||
(when name
|
||||
(rename-buffer name t)
|
||||
(org-babel-scheme-set-session-buffer name (current-buffer)))
|
||||
|
|
@ -185,8 +189,6 @@ is true; otherwise returns the last value."
|
|||
(let ((beg (point)))
|
||||
(insert code)
|
||||
(geiser-mode)
|
||||
(let ((geiser-repl-window-allow-split nil)
|
||||
(geiser-repl-use-other-window nil))
|
||||
(let ((repl-buffer (save-current-buffer
|
||||
(org-babel-scheme-get-repl impl repl host port))))
|
||||
(when (not (eq impl (org-babel-scheme-get-buffer-impl
|
||||
|
|
@ -226,15 +228,15 @@ is true; otherwise returns the last value."
|
|||
(let ((msg (geiser-eval--error-msg err)))
|
||||
(org-babel-eval-error-notify
|
||||
nil
|
||||
(concat (if (listp msg) (car msg) msg) "\n")))))))))))
|
||||
(concat (if (listp msg) (car msg) msg) "\n"))))))))))
|
||||
result))
|
||||
|
||||
(defun org-babel-scheme--table-or-string (results)
|
||||
"Convert RESULTS into an appropriate elisp value.
|
||||
If the results look like a list or tuple, then convert them into an
|
||||
Emacs-lisp table, otherwise return the results as a string."
|
||||
"Convert RESULTS into an appropriate Elisp value.
|
||||
If the results are in the form of a proper list, then convert them into
|
||||
an Emacs Lisp table, otherwise return the results as a string."
|
||||
(let ((res (and results (org-babel-script-escape results))))
|
||||
(cond ((listp res)
|
||||
(cond ((proper-list-p res)
|
||||
(mapcar (lambda (el)
|
||||
(if (or (null el) (eq el 'null))
|
||||
org-babel-scheme-null-to
|
||||
|
|
@ -242,6 +244,14 @@ Emacs-lisp table, otherwise return the results as a string."
|
|||
res))
|
||||
(t res))))
|
||||
|
||||
(defun org-babel-scheme--get-impl (&optional params)
|
||||
"Return Scheme implementation to be used according to PARAMS."
|
||||
(or (when (cdr (assq :scheme params))
|
||||
(intern (cdr (assq :scheme params))))
|
||||
geiser-scheme-implementation
|
||||
geiser-default-implementation
|
||||
(car geiser-active-implementations)))
|
||||
|
||||
(defun org-babel-execute:scheme (body params)
|
||||
"Execute a block of Scheme code with org-babel.
|
||||
This function is called by `org-babel-execute-src-block'."
|
||||
|
|
@ -251,11 +261,7 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(buffer-name source-buffer))))
|
||||
(save-excursion
|
||||
(let* ((result-type (cdr (assq :result-type params)))
|
||||
(impl (or (when (cdr (assq :scheme params))
|
||||
(intern (cdr (assq :scheme params))))
|
||||
geiser-scheme-implementation
|
||||
geiser-default-implementation
|
||||
(car geiser-active-implementations)))
|
||||
(impl (org-babel-scheme--get-impl params))
|
||||
(host (cdr (assq :host params)))
|
||||
(port (cdr (assq :port params)))
|
||||
(session (org-babel-scheme-make-session-name
|
||||
|
|
@ -281,6 +287,38 @@ This function is called by `org-babel-execute-src-block'."
|
|||
result
|
||||
(org-babel-scheme--table-or-string table)))))))
|
||||
|
||||
(defun org-babel-scheme-initiate-session (session params)
|
||||
"Return scheme buffer for SESSION according to PARAMS.
|
||||
|
||||
Creates new session buffer if necessary."
|
||||
(let ((impl (org-babel-scheme--get-impl params))
|
||||
(host (cdr (assq :host params)))
|
||||
(port (cdr (assq :port params))))
|
||||
(save-current-buffer
|
||||
(org-babel-scheme-get-repl impl
|
||||
session
|
||||
host
|
||||
port))))
|
||||
|
||||
(defun org-babel-prep-session:scheme (session params)
|
||||
"Prepare SESSION according to header arguments in PARAMS."
|
||||
(let ((repl (org-babel-scheme-initiate-session session params)))
|
||||
(org-babel-scheme-execute-with-geiser
|
||||
(org-babel-scheme-expand-header-arg-vars (org-babel--get-vars params))
|
||||
nil
|
||||
(org-babel-scheme--get-impl params)
|
||||
session)
|
||||
repl))
|
||||
|
||||
(defun org-babel-load-session:scheme (session body params)
|
||||
"Load BODY into SESSION.
|
||||
|
||||
Also evaluates any variable assignments in PARAMS before loading BODY."
|
||||
(with-current-buffer (org-babel-prep-session:scheme session params)
|
||||
(goto-char (process-mark (get-buffer-process (current-buffer))))
|
||||
(insert (org-babel-chomp body))
|
||||
(current-buffer)))
|
||||
|
||||
(provide 'ob-scheme)
|
||||
|
||||
;;; ob-scheme.el ends here
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ In case you want to use a different screen than one selected by your $PATH")
|
|||
(defun org-babel-execute:screen (body params)
|
||||
"Send BODY via screen to a terminal using Babel, according to PARAMS.
|
||||
\"default\" session is used when none is specified in the PARAMS."
|
||||
(unless noninteractive (message "Sending source code block to interactive terminal session..."))
|
||||
(save-window-excursion
|
||||
(let* ((session (cdr (assq :session params)))
|
||||
(socket (org-babel-screen-session-socketname session)))
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@
|
|||
BODY is the source inside a sed source block and PARAMS is an
|
||||
association list over the source block configurations. This
|
||||
function is called by `org-babel-execute-src-block'."
|
||||
(unless noninteractive (message "Executing sed source code block"))
|
||||
(let* ((result-params (cdr (assq :result-params params)))
|
||||
(cmd-line (cdr (assq :cmd-line params)))
|
||||
(in-file (cdr (assq :in-file params)))
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@
|
|||
("fish" . "function fish_prompt\n\techo \"%s\"\nend")
|
||||
;; prompt2 is like PS2 in POSIX shells.
|
||||
("csh" . "set prompt=\"%s\"\nset prompt2=\"\"")
|
||||
;; Disable bracketed paste - it messes up out processing and,
|
||||
;; apparently, comint.el. Also, unset "% \r" prompts.
|
||||
("zsh" . "setopt nopromptcr;unset zle_bracketed_paste;PROMPT_COMMAND=;PS1=\"%s\";PS2=")
|
||||
;; PROMPT_COMMAND can override PS1 settings. Disable it.
|
||||
;; Disable PS2 to avoid garbage in multi-line inputs.
|
||||
(t . "PROMPT_COMMAND=;PS1=\"%s\";PS2="))
|
||||
|
|
@ -85,6 +88,24 @@ is modified outside the Customize interface."
|
|||
(shell-file-name name))
|
||||
(org-babel-execute:shell body params))))
|
||||
(put fname 'definition-name 'org-babel-shell-initialize))
|
||||
(let ((fname (intern (concat "org-babel-prep-session:" name))))
|
||||
(defalias fname
|
||||
(lambda (session params)
|
||||
(:documentation
|
||||
(format "Prepare %s SESSION according to the header arguments specified in PARAMS." name))
|
||||
(let ((explicit-shell-file-name name)
|
||||
(shell-file-name name))
|
||||
(org-babel-prep-session:shell session params))))
|
||||
(put fname 'definition-name 'org-babel-shell-initialize))
|
||||
(let ((fname (intern (format "org-babel-%s-initiate-session" name))))
|
||||
(defalias fname
|
||||
(lambda (session _params)
|
||||
(:documentation
|
||||
(format "Initiate %s session named SESSION." name))
|
||||
(let ((explicit-shell-file-name name)
|
||||
(shell-file-name name))
|
||||
(org-babel-sh-initiate-session session))))
|
||||
(put fname 'definition-name 'org-babel-shell-initialize))
|
||||
(defalias (intern (concat "org-babel-variable-assignments:" name))
|
||||
#'org-babel-variable-assignments:shell
|
||||
(format "Return list of %s statements assigning to the block's \
|
||||
|
|
@ -245,8 +266,11 @@ var of the same value."
|
|||
(let ((echo-var (lambda (v) (if (stringp v) v (format "%S" v)))))
|
||||
(cond
|
||||
((and (listp var) (or (listp (car var)) (eq (car var) 'hline)))
|
||||
(orgtbl-to-generic var (list :sep (or sep "\t") :fmt echo-var
|
||||
:hline hline)))
|
||||
(orgtbl-to-generic
|
||||
var
|
||||
(list :sep (or sep "\t") :fmt echo-var
|
||||
:hline hline
|
||||
:with-special-rows nil)))
|
||||
((listp var)
|
||||
(mapconcat echo-var var "\n"))
|
||||
(t (funcall echo-var var)))))
|
||||
|
|
@ -255,18 +279,36 @@ var of the same value."
|
|||
"String to indicate that evaluation has completed.")
|
||||
(defvar org-babel-sh-eoe-output "org_babel_sh_eoe"
|
||||
"String to indicate that evaluation has completed.")
|
||||
(defvar org-babel-sh-prompt "org_babel_sh_prompt> "
|
||||
(defvar org-babel-sh-prompt
|
||||
;; FIXME: Emacs 27 CI fails non-interactively. Play it safe and
|
||||
;; keep the old prompt until we drop Emacs 27 support.
|
||||
(if (version< emacs-version "28") "org_babel_sh_prompt> " "𒆸 ")
|
||||
"String to set prompt in session shell.")
|
||||
|
||||
(defvar-local org-babel-sh--prompt-initialized nil
|
||||
"When non-nil, ob-shell already initialized the prompt in current buffer.")
|
||||
|
||||
(defalias 'org-babel-shell-initiate-session #'org-babel-sh-initiate-session)
|
||||
(defun org-babel-sh-initiate-session (&optional session _params)
|
||||
"Initiate a session named SESSION according to PARAMS."
|
||||
(when (and session (not (string= session "none")))
|
||||
(save-window-excursion
|
||||
(or (org-babel-comint-buffer-livep session)
|
||||
(or (and (org-babel-comint-buffer-livep session)
|
||||
(buffer-local-value
|
||||
'org-babel-sh--prompt-initialized
|
||||
(get-buffer session))
|
||||
session)
|
||||
(progn
|
||||
(if (org-babel-comint-buffer-livep session)
|
||||
(set-buffer session)
|
||||
(shell session)
|
||||
;; Set unique prompt for easier analysis of the output.
|
||||
(org-babel-comint-wait-for-output (current-buffer))
|
||||
(org-babel-comint-wait-for-output (current-buffer)))
|
||||
(setq-local
|
||||
org-babel-comint-prompt-regexp-fallback comint-prompt-regexp
|
||||
comint-prompt-regexp
|
||||
(concat "^" (regexp-quote org-babel-sh-prompt)
|
||||
" *"))
|
||||
(org-babel-comint-input-command
|
||||
(current-buffer)
|
||||
(format
|
||||
|
|
@ -274,11 +316,7 @@ var of the same value."
|
|||
org-babel-shell-set-prompt-commands))
|
||||
(alist-get t org-babel-shell-set-prompt-commands))
|
||||
org-babel-sh-prompt))
|
||||
(setq-local
|
||||
org-babel-comint-prompt-regexp-old comint-prompt-regexp
|
||||
comint-prompt-regexp
|
||||
(concat "^" (regexp-quote org-babel-sh-prompt)
|
||||
" *"))
|
||||
(setq org-babel-sh--prompt-initialized t)
|
||||
;; Needed for Emacs 23 since the marker is initially
|
||||
;; undefined and the filter functions try to use it without
|
||||
;; checking.
|
||||
|
|
@ -314,22 +352,28 @@ return the value of the last statement in BODY."
|
|||
(stdin-file (org-babel-temp-file "sh-stdin-"))
|
||||
(padline (not (string= "no" (cdr (assq :padline params))))))
|
||||
(with-temp-file script-file
|
||||
(when shebang (insert shebang "\n"))
|
||||
(if shebang
|
||||
(insert shebang "\n")
|
||||
;; Provide shell name explicitly.
|
||||
;; This is necessary because running, for example,
|
||||
;; dash script-for-dash.sh will use /bin/sh.
|
||||
(insert (format "#!/usr/bin/env %s" shell-file-name) "\n"))
|
||||
(when padline (insert "\n"))
|
||||
(insert body))
|
||||
(set-file-modes script-file #o755)
|
||||
(with-temp-file stdin-file (insert (or stdin "")))
|
||||
(with-temp-buffer
|
||||
(with-connection-local-variables
|
||||
;; `with-connection-local-variables' will override
|
||||
;; `shell-file-name' and `shell-command-swtich' as
|
||||
;; needed for the remote connection.
|
||||
(apply #'process-file
|
||||
(if shebang (file-local-name script-file)
|
||||
shell-file-name)
|
||||
shell-file-name
|
||||
stdin-file
|
||||
(current-buffer)
|
||||
nil
|
||||
(if shebang (when cmdline (list cmdline))
|
||||
(list shell-command-switch
|
||||
(concat (file-local-name script-file) " " cmdline)))))
|
||||
(concat (file-local-name script-file) " " (format "%s" cmdline)))))
|
||||
(buffer-string))))
|
||||
(session ; session evaluation
|
||||
(if async
|
||||
|
|
|
|||
|
|
@ -117,23 +117,27 @@ corresponding :engine source block header argument."
|
|||
|
||||
(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."
|
||||
(combine-and-quote-strings
|
||||
(mapconcat
|
||||
#'identity
|
||||
(delq nil
|
||||
(list (when host (concat "-h" host))
|
||||
(list (when host (concat "-h" (shell-quote-argument host)))
|
||||
(when port (format "-P%d" port))
|
||||
(when user (concat "-u" user))
|
||||
(when password (concat "-p" password))
|
||||
(when database (concat "-D" database))))))
|
||||
(when user (concat "-u" (shell-quote-argument user)))
|
||||
(when password (concat "-p" (shell-quote-argument password)))
|
||||
(when database (concat "-D" (shell-quote-argument database)))))
|
||||
" "))
|
||||
|
||||
(defun org-babel-sql-dbstring-postgresql (host port user database)
|
||||
"Make PostgreSQL command line args for database connection.
|
||||
Pass nil to omit that arg."
|
||||
(combine-and-quote-strings
|
||||
(mapconcat
|
||||
#'identity
|
||||
(delq nil
|
||||
(list (when host (concat "-h" host))
|
||||
(list (when host (concat "-h" (shell-quote-argument host)))
|
||||
(when port (format "-p%d" port))
|
||||
(when user (concat "-U" user))
|
||||
(when database (concat "-d" database))))))
|
||||
(when user (concat "-U" (shell-quote-argument user)))
|
||||
(when database (concat "-d" (shell-quote-argument database)))))
|
||||
" "))
|
||||
|
||||
(defun org-babel-sql-dbstring-oracle (host port user password database)
|
||||
"Make Oracle command line arguments for database connection.
|
||||
|
|
@ -149,8 +153,12 @@ or
|
|||
<user>/<password>@<database>
|
||||
|
||||
using its alias."
|
||||
(when user (setq user (shell-quote-argument user)))
|
||||
(when password (setq password (shell-quote-argument password)))
|
||||
(when database (setq database (shell-quote-argument database)))
|
||||
(when host (setq host (shell-quote-argument host)))
|
||||
(cond ((and user password database host port)
|
||||
(format "%s/%s@%s:%s/%s" user password host port database))
|
||||
(format "%s/%s@%s:%d/%s" user password host port database))
|
||||
((and user password database)
|
||||
(format "%s/%s@%s" user password database))
|
||||
(t (user-error "Missing information to connect to database"))))
|
||||
|
|
@ -161,10 +169,10 @@ using its alias."
|
|||
SQL Server on Windows and Linux platform."
|
||||
(mapconcat #'identity
|
||||
(delq nil
|
||||
(list (when host (format "-S \"%s\"" host))
|
||||
(when user (format "-U \"%s\"" user))
|
||||
(when password (format "-P \"%s\"" password))
|
||||
(when database (format "-d \"%s\"" database))))
|
||||
(list (when host (format "-S \"%s\"" (shell-quote-argument host)))
|
||||
(when user (format "-U \"%s\"" (shell-quote-argument user)))
|
||||
(when password (format "-P \"%s\"" (shell-quote-argument password)))
|
||||
(when database (format "-d \"%s\"" (shell-quote-argument database)))))
|
||||
" "))
|
||||
|
||||
(defun org-babel-sql-dbstring-sqsh (host user password database)
|
||||
|
|
@ -172,10 +180,10 @@ SQL Server on Windows and Linux platform."
|
|||
\"sqsh\" is one method to access Sybase or MS SQL via Linux platform"
|
||||
(mapconcat #'identity
|
||||
(delq nil
|
||||
(list (when host (format "-S \"%s\"" host))
|
||||
(when user (format "-U \"%s\"" user))
|
||||
(when password (format "-P \"%s\"" password))
|
||||
(when database (format "-D \"%s\"" database))))
|
||||
(list (when host (format "-S \"%s\"" (shell-quote-argument host)))
|
||||
(when user (format "-U \"%s\"" (shell-quote-argument user)))
|
||||
(when password (format "-P \"%s\"" (shell-quote-argument password)))
|
||||
(when database (format "-D \"%s\"" (shell-quote-argument database)))))
|
||||
" "))
|
||||
|
||||
(defun org-babel-sql-dbstring-vertica (host port user password database)
|
||||
|
|
@ -183,11 +191,11 @@ SQL Server on Windows and Linux platform."
|
|||
Pass nil to omit that arg."
|
||||
(mapconcat #'identity
|
||||
(delq nil
|
||||
(list (when host (format "-h %s" host))
|
||||
(list (when host (format "-h %s" (shell-quote-argument host)))
|
||||
(when port (format "-p %d" port))
|
||||
(when user (format "-U %s" user))
|
||||
(when user (format "-U %s" (shell-quote-argument user)))
|
||||
(when password (format "-w %s" (shell-quote-argument password) ))
|
||||
(when database (format "-d %s" database))))
|
||||
(when database (format "-d %s" (shell-quote-argument database)))))
|
||||
" "))
|
||||
|
||||
(defun org-babel-sql-dbstring-saphana (host port instance user password database)
|
||||
|
|
@ -195,13 +203,15 @@ Pass nil to omit that arg."
|
|||
Pass nil to omit that arg."
|
||||
(mapconcat #'identity
|
||||
(delq nil
|
||||
(list (and host port (format "-n %s:%s" host port))
|
||||
(and host (not port) (format "-n %s" host))
|
||||
(list (and host port (format "-n %s:%s"
|
||||
(shell-quote-argument host)
|
||||
port))
|
||||
(and host (not port) (format "-n %s" (shell-quote-argument host)))
|
||||
(and instance (format "-i %d" instance))
|
||||
(and user (format "-u %s" user))
|
||||
(and user (format "-u %s" (shell-quote-argument user)))
|
||||
(and password (format "-p %s"
|
||||
(shell-quote-argument password)))
|
||||
(and database (format "-d %s" database))))
|
||||
(and database (format "-d %s" (shell-quote-argument database)))))
|
||||
" "))
|
||||
|
||||
(defun org-babel-sql-convert-standard-filename (file)
|
||||
|
|
@ -276,11 +286,13 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(or cmdline "")
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)))
|
||||
((postgresql postgres) (format
|
||||
((postgresql postgres)
|
||||
(format
|
||||
"%s%s --set=\"ON_ERROR_STOP=1\" %s -A -P \
|
||||
footer=off -F \"\t\" %s -f %s -o %s %s"
|
||||
(if dbpassword
|
||||
(format "PGPASSWORD=%s " dbpassword)
|
||||
(format "PGPASSWORD=%s "
|
||||
(shell-quote-argument dbpassword))
|
||||
"")
|
||||
(or (bound-and-true-p
|
||||
sql-postgres-program)
|
||||
|
|
@ -375,7 +387,7 @@ SET COLSEP '|'
|
|||
(goto-char (point-max))
|
||||
(forward-char -1))
|
||||
(write-file out-file))))
|
||||
(org-table-import out-file (if (string= engine "sqsh") '(4) '(16)))
|
||||
(org-table-import out-file (if (memq (intern engine) '(saphana sqsh)) '(4) '(16)))
|
||||
(org-babel-reassemble-table
|
||||
(mapcar (lambda (x)
|
||||
(if (string= (car x) header-delim)
|
||||
|
|
@ -406,9 +418,11 @@ argument mechanism."
|
|||
(insert (orgtbl-to-csv
|
||||
val (if sqlite
|
||||
nil
|
||||
'(:fmt (lambda (el) (if (stringp el)
|
||||
'( :fmt (lambda (el)
|
||||
(if (stringp el)
|
||||
el
|
||||
(format "%S" el))))))))
|
||||
(format "%S" el)))
|
||||
:with-special-rows nil)))))
|
||||
data-file)
|
||||
(if (stringp val) val (format "%S" val))))
|
||||
body t t)))
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
(declare-function org-table-convert-region "org-table"
|
||||
(beg0 end0 &optional separator))
|
||||
(declare-function orgtbl-to-csv "org-table" (table params))
|
||||
(declare-function org-table-to-lisp "org-table" (&optional txt))
|
||||
|
||||
(defvar org-babel-default-header-args:sqlite '())
|
||||
|
|
@ -52,7 +51,8 @@
|
|||
(line . :any)
|
||||
(list . :any)
|
||||
(separator . :any)
|
||||
(nullvalue . :any))
|
||||
(nullvalue . :any)
|
||||
(readonly-p . ((yes no))))
|
||||
"Sqlite specific header args.")
|
||||
|
||||
(defun org-babel-expand-body:sqlite (body params)
|
||||
|
|
@ -77,6 +77,7 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(separator (cdr (assq :separator params)))
|
||||
(nullvalue (cdr (assq :nullvalue params)))
|
||||
(headers-p (equal "yes" (cdr (assq :colnames params))))
|
||||
(readonly-p (equal "yes" (cdr (assq :readonly params))))
|
||||
(others (delq nil (mapcar
|
||||
(lambda (arg) (car (assq arg params)))
|
||||
(list :header :echo :bail :column
|
||||
|
|
@ -85,7 +86,7 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(insert
|
||||
(org-babel-eval
|
||||
(org-fill-template
|
||||
"%cmd %header %separator %nullvalue %others %csv %db "
|
||||
"%cmd %header %separator %nullvalue %others %csv %readonly %db "
|
||||
(list
|
||||
(cons "cmd" org-babel-sqlite3-command)
|
||||
(cons "header" (if headers-p "-header" "-noheader"))
|
||||
|
|
@ -103,6 +104,8 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(member :html others) separator)
|
||||
""
|
||||
"-csv"))
|
||||
(cons "readonly"
|
||||
(if readonly-p "-readonly" ""))
|
||||
(cons "db" (or db ""))))
|
||||
;; body of the code block
|
||||
(org-babel-expand-body:sqlite body params)))
|
||||
|
|
|
|||
|
|
@ -41,14 +41,12 @@
|
|||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-before-first-heading-p "org" ())
|
||||
(declare-function org-element-lineage "org-element-ast" (datum &optional types with-self))
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
(declare-function org-element-begin "org-element" (node))
|
||||
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
|
||||
(declare-function org-element-type-p "org-element-ast" (node types))
|
||||
(declare-function org-heading-components "org" ())
|
||||
(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 org-in-commented-heading-p "org" (&optional no-inheritance element))
|
||||
(declare-function org-in-archived-heading-p "org" (&optional no-inheritance element))
|
||||
(defvar org-id-link-to-org-use-id) ; Dynamically scoped
|
||||
|
||||
(defgroup org-babel-tangle nil
|
||||
|
|
@ -58,18 +56,20 @@
|
|||
|
||||
(defcustom org-babel-tangle-lang-exts
|
||||
'(("emacs-lisp" . "el")
|
||||
("elisp" . "el"))
|
||||
("elisp" . "el")
|
||||
("bibtex" . "bib"))
|
||||
"Alist mapping languages to their file extensions.
|
||||
The key is the language name, the value is the string that should
|
||||
be inserted as the extension commonly used to identify files
|
||||
written in this language. If no entry is found in this list,
|
||||
then the name of the language is used."
|
||||
:group 'org-babel-tangle
|
||||
:version "24.1"
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(repeat
|
||||
(cons
|
||||
(string "Language name")
|
||||
(string "File Extension"))))
|
||||
(string "File Extension")))
|
||||
:safe #'listp)
|
||||
|
||||
(defcustom org-babel-tangle-use-relative-file-links t
|
||||
"Use relative path names in links from tangled source back the Org file."
|
||||
|
|
@ -159,9 +159,10 @@ result. The default value is `org-remove-indentation'."
|
|||
:type 'function)
|
||||
|
||||
(defcustom org-babel-tangle-default-file-mode #o644
|
||||
"The default mode used for tangled files, as an integer.
|
||||
The default value 420 correspands to the octal #o644, which is
|
||||
read-write permissions for the user, read-only for everyone else."
|
||||
"The default mode, an integer value, only used when the :tangle-mode
|
||||
header argument specifies chmod-style symbolic notation. The default
|
||||
value 420 corresponds to the octal #o644, which is read-write
|
||||
permissions for the user, read-only for everyone else."
|
||||
:group 'org-babel-tangle
|
||||
:package-version '(Org . "9.6")
|
||||
:type 'integer)
|
||||
|
|
@ -181,7 +182,7 @@ replace contents otherwise."
|
|||
(const :tag "Replace contents, but keep the same file" nil)
|
||||
(const :tag "Re-create file" t)
|
||||
(const :tag "Re-create when read-only" auto))
|
||||
:safe t)
|
||||
:safe #'symbolp)
|
||||
|
||||
(defun org-babel-find-file-noselect-refresh (file)
|
||||
"Find file ensuring that the latest changes on disk are represented in the file."
|
||||
|
|
@ -227,13 +228,11 @@ Return list of the tangled file names."
|
|||
(org-babel-tangle nil target-file lang-re)))))
|
||||
|
||||
(defun org-babel-tangle-publish (_ filename pub-dir)
|
||||
"Tangle FILENAME and place the results in PUB-DIR."
|
||||
(unless (file-exists-p pub-dir)
|
||||
(make-directory pub-dir t))
|
||||
(setq pub-dir (file-name-as-directory pub-dir))
|
||||
;; Rename files to avoid copying to same file when publishing to ./
|
||||
;; `copy-file' would throw an error when copying file to self.
|
||||
(mapc (lambda (el) (rename-file el pub-dir t))
|
||||
"Tangle FILENAME and copy the tangled file to PUB-DIR."
|
||||
(require 'ox-publish)
|
||||
(declare-function org-publish-attachment "ox-publish"
|
||||
(plist filename pub-dir))
|
||||
(mapc (lambda (el) (org-publish-attachment nil el pub-dir))
|
||||
(org-babel-tangle-file filename)))
|
||||
|
||||
;;;###autoload
|
||||
|
|
@ -269,7 +268,7 @@ matching a regular expression."
|
|||
(or (cdr (assq :tangle (nth 2 (org-babel-get-src-block-info 'no-eval))))
|
||||
(user-error "Point is not in a source code block"))))
|
||||
path-collector
|
||||
(source-file buffer-file-name))
|
||||
(source-file (org-base-buffer-file-name)))
|
||||
(mapc ;; map over file-names
|
||||
(lambda (by-fn)
|
||||
(let ((file-name (car by-fn)))
|
||||
|
|
@ -290,8 +289,8 @@ matching a regular expression."
|
|||
(tangle-mode (funcall get-spec :tangle-mode)))
|
||||
(unless (string-equal block-lang lang)
|
||||
(setq lang block-lang)
|
||||
(let ((lang-f (org-src-get-lang-mode lang)))
|
||||
(when (fboundp lang-f) (ignore-errors (funcall lang-f)))))
|
||||
(when-let* ((lang-f (org-src-get-lang-mode-if-bound lang)))
|
||||
(ignore-errors (funcall lang-f))))
|
||||
;; if file contains she-bangs, then make it executable
|
||||
(when she-bang
|
||||
(unless tangle-mode (setq tangle-mode #o755)))
|
||||
|
|
@ -509,9 +508,13 @@ code blocks by target file."
|
|||
(src-lang (nth 0 info))
|
||||
(src-tfile (cdr (assq :tangle (nth 2 info)))))
|
||||
(unless (or (string= src-tfile "no")
|
||||
(not src-lang) ;; src block without lang
|
||||
;; src block without lang
|
||||
(and (not src-lang) (string= src-tfile "yes"))
|
||||
(and tangle-file (not (equal tangle-file src-tfile)))
|
||||
(and lang-re (not (string-match-p lang-re src-lang))))
|
||||
;; lang-re but either no lang or lang doesn't match
|
||||
(and lang-re
|
||||
(or (not src-lang)
|
||||
(not (string-match-p lang-re src-lang)))))
|
||||
;; Add the spec for this block to blocks under its tangled
|
||||
;; file name.
|
||||
(let* ((block (org-babel-tangle-single-block counter))
|
||||
|
|
@ -531,10 +534,7 @@ code blocks by target file."
|
|||
The PARAMS are the 3rd element of the info for the same src block."
|
||||
(unless (string= "no" (cdr (assq :comments params)))
|
||||
(save-match-data
|
||||
(let* ((l (org-no-properties
|
||||
(cl-letf (((symbol-function 'org-store-link-functions)
|
||||
(lambda () nil)))
|
||||
(org-store-link nil))))
|
||||
(let* ((l (org-no-properties (org-store-link nil)))
|
||||
(bare (and l
|
||||
(string-match org-link-bracket-re l)
|
||||
(match-string 1 l))))
|
||||
|
|
@ -580,7 +580,8 @@ non-nil, return the full association list to be used by
|
|||
(let ((body (if (org-babel-noweb-p params :tangle)
|
||||
(if (string= "strip-tangle" (cdr (assq :noweb (nth 2 info))))
|
||||
(replace-regexp-in-string (org-babel-noweb-wrap) "" (nth 1 info))
|
||||
(org-babel-expand-noweb-references info))
|
||||
(org-babel-expand-noweb-references
|
||||
info nil :tangle))
|
||||
(nth 1 info))))
|
||||
(with-temp-buffer
|
||||
(insert
|
||||
|
|
|
|||
|
|
@ -92,9 +92,9 @@
|
|||
(declare-function org-element-type-p "org-element-ast" (node types))
|
||||
(declare-function org-element-contents "org-element-ast" (node))
|
||||
|
||||
(declare-function org-export-data "org-export" (data info))
|
||||
(declare-function org-export-derived-backend-p "org-export" (backend &rest backends))
|
||||
(declare-function org-export-raw-string "org-export" (contents))
|
||||
(declare-function org-export-data "ox" (data info))
|
||||
(declare-function org-export-derived-backend-p "ox" (backend &rest backends))
|
||||
(declare-function org-export-raw-string "ox" (contents))
|
||||
|
||||
|
||||
;;; Customization
|
||||
|
|
@ -140,6 +140,31 @@
|
|||
:type 'face
|
||||
:safe #'facep)
|
||||
|
||||
(defcustom org-cite-basic-complete-key-crm-separator nil
|
||||
"When non-nil, use `completing-read-multiple' with this as the separator.
|
||||
When nil, use multiple `completing-read' prompts. When set to a string,
|
||||
it should be a regexp to be used as `crm-separator' (which see). The
|
||||
regexp string can carry the text properties `separator', which if
|
||||
present `completing-read-multiple' will show as part of the prompt.
|
||||
When set to symbol `dynamic', use \";;...\" as a separator with the
|
||||
number of \";\" sufficient so that none of the completion candidates
|
||||
contain the separator."
|
||||
:group 'org-cite
|
||||
:package-version '(Org . "9.8")
|
||||
:type
|
||||
'(choice
|
||||
(const
|
||||
:tag
|
||||
"Use \";;\" as the separator."
|
||||
(propertize "[ \t]*;;[ \t]*" 'separator ";;"))
|
||||
(const
|
||||
:tag
|
||||
"Dynamically compute \";\"+ with the needed length."
|
||||
dynamic)
|
||||
(string :tag "Custom regexp for the separator.")
|
||||
(const :tag "Prompt multiple times." nil))
|
||||
:safe (lambda (obj) (or (string-or-null-p obj) (member obj '(dynamic)))))
|
||||
|
||||
|
||||
;;; Internal variables
|
||||
(defvar org-cite-basic--bibliography-cache nil
|
||||
|
|
@ -884,6 +909,39 @@ Return nil if there are no bibliography files or no entries."
|
|||
(puthash entries t org-cite-basic--completion-cache)
|
||||
org-cite-basic--completion-cache)))))
|
||||
|
||||
(defun org-cite-basic--complete-key-dynamic-crm-separator
|
||||
(completion-candidates separator)
|
||||
"Return a repeated version of SEPARATOR as needed.
|
||||
The number of appeared SEPARATORs in the returned string is sufficient
|
||||
so that none of COMPLETION-CANDIDATES contains it. SEPARATOR should be
|
||||
a literal string."
|
||||
(let* ((dyn-sep separator)
|
||||
(consecutive-sep-regexp
|
||||
(format "%s+" (regexp-opt (list separator)))))
|
||||
(with-temp-buffer
|
||||
(dolist (cand completion-candidates)
|
||||
(when (stringp cand)
|
||||
(insert cand "\n")))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward consecutive-sep-regexp nil t)
|
||||
(while (<= (length dyn-sep) (length (match-string 0)))
|
||||
(setq dyn-sep (concat dyn-sep separator)))))
|
||||
dyn-sep))
|
||||
|
||||
(defvar crm-separator) ; defined in crm.el
|
||||
|
||||
(defun org-cite-basic--crm-indicate-prompt (orig-prompt)
|
||||
"Return annotated ORIG-PROMPT with `crm-separator'.
|
||||
For Emacs version 31 and above, just return ORIG-PROMPT."
|
||||
(cond
|
||||
((boundp 'crm-prompt)
|
||||
orig-prompt)
|
||||
(t
|
||||
(let ((sep
|
||||
(or (get-text-property 0 'separator crm-separator)
|
||||
(string-replace "[ \t]*" "" crm-separator))))
|
||||
(format "[list separated by %s] %s" sep orig-prompt)))))
|
||||
|
||||
(defun org-cite-basic--complete-key (&optional multiple)
|
||||
"Prompt for a reference key and return a citation reference string.
|
||||
|
||||
|
|
@ -895,12 +953,39 @@ Raise an error when no bibliography is set in the buffer."
|
|||
(let* ((table
|
||||
(or (org-cite-basic--key-completion-table)
|
||||
(user-error "No bibliography set")))
|
||||
(prompt
|
||||
(lambda (text)
|
||||
(completing-read text table nil t))))
|
||||
(if (null multiple)
|
||||
(let ((key (gethash (funcall prompt "Key: ") table)))
|
||||
(org-string-nw-p key))
|
||||
(prompt-single
|
||||
(lambda (text) (completing-read text table nil t)))
|
||||
(choice-to-citation
|
||||
(lambda (choice)
|
||||
(let ((key (gethash choice table)))
|
||||
(org-string-nw-p key)))))
|
||||
(cond
|
||||
((null multiple)
|
||||
(funcall choice-to-citation
|
||||
(completing-read "Key: " table nil t)))
|
||||
(org-cite-basic-complete-key-crm-separator
|
||||
(let*
|
||||
((crm-separator
|
||||
(pcase org-cite-basic-complete-key-crm-separator
|
||||
((pred stringp)
|
||||
org-cite-basic-complete-key-crm-separator)
|
||||
(`dynamic
|
||||
(let
|
||||
((repeated-sep
|
||||
(regexp-quote
|
||||
(org-cite-basic--complete-key-dynamic-crm-separator
|
||||
(hash-table-keys table) ";"))))
|
||||
(propertize (format "[ \t]*%s[ \t]*" repeated-sep)
|
||||
'separator
|
||||
repeated-sep)))))
|
||||
(prompt (org-cite-basic--crm-indicate-prompt "Keys: ")))
|
||||
;; FIXME: Use `seq-keep' after we drop Emacs 28 support.
|
||||
(delq
|
||||
nil
|
||||
(seq-map
|
||||
choice-to-citation
|
||||
(completing-read-multiple prompt table nil t)))))
|
||||
(t
|
||||
(let* ((keys nil)
|
||||
(build-prompt
|
||||
(lambda ()
|
||||
|
|
@ -908,11 +993,12 @@ Raise an error when no bibliography is set in the buffer."
|
|||
(format "Key (empty input exits) %s: "
|
||||
(mapconcat #'identity (reverse keys) ";"))
|
||||
"Key (empty input exits): "))))
|
||||
(let ((key (funcall prompt (funcall build-prompt))))
|
||||
(let ((key (funcall prompt-single (funcall build-prompt))))
|
||||
(while (org-string-nw-p key)
|
||||
(push (gethash key table) keys)
|
||||
(setq key (funcall prompt (funcall build-prompt)))))
|
||||
keys))))
|
||||
(setq key
|
||||
(funcall prompt-single (funcall build-prompt)))))
|
||||
keys)))))
|
||||
|
||||
|
||||
;;; Register processor
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
(declare-function org-element-parent "org-element-ast" (node))
|
||||
(declare-function org-export-data "org-export" (data info))
|
||||
(declare-function org-export-data "ox" (data info))
|
||||
|
||||
|
||||
;;; Customization
|
||||
|
|
@ -179,7 +179,7 @@ a style in `org-cite-biblatex-styles'."
|
|||
(cons :tag "Shortcut"
|
||||
(string :tag "Name")
|
||||
(string :tag "Full name")))
|
||||
:safe t)
|
||||
:safe #'listp)
|
||||
|
||||
|
||||
;;; Internal functions
|
||||
|
|
|
|||
|
|
@ -43,7 +43,35 @@
|
|||
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
|
||||
(declare-function org-export-data "org-export" (data info))
|
||||
(declare-function org-export-data "ox" (data info))
|
||||
|
||||
(defcustom org-cite-bibtex-bibliography-style "plain"
|
||||
"Default BibTeX bibliography style.
|
||||
|
||||
BibTeX provides the following default styles:
|
||||
|
||||
\"plain\" Sorted numbered entries
|
||||
\"abbrv\" Sorted numbered entries with abbreviated author name
|
||||
\"unsrt\" Unsorted numbered entries
|
||||
\"alpha\" Alphabetized entries with unique short id
|
||||
\"acm\" ACM Transactions
|
||||
\"apalike\" APA-like
|
||||
\"ieeetr\" IEEE Transactions
|
||||
\"siam\" SIAM"
|
||||
:group 'org-cite
|
||||
:package-version '(Org . "9.8")
|
||||
:type
|
||||
'(choice
|
||||
(const :tag "Plain" "plain")
|
||||
(const :tag "Abbreviated" "abbrv")
|
||||
(const :tag "Unsorted" "unsrt")
|
||||
(const :tag "Alphabetic" "alpha")
|
||||
(const :tag "ACM" "acm")
|
||||
(const :tag "APA-like" "apalike")
|
||||
(const :tag "IEEE" "ieeetr")
|
||||
(const :tag "SIAM" "siam")
|
||||
(string :tag "Other"))
|
||||
:safe #'stringp)
|
||||
|
||||
|
||||
;;; Export capability
|
||||
|
|
@ -51,7 +79,8 @@
|
|||
"Print references from bibliography FILES.
|
||||
FILES is a list of absolute file names. STYLE is the bibliography style, as
|
||||
a string or nil."
|
||||
(concat (and style (format "\\bibliographystyle{%s}\n" style))
|
||||
(concat (format "\\bibliographystyle{%s}\n"
|
||||
(or style org-cite-bibtex-bibliography-style))
|
||||
(format "\\bibliography{%s}"
|
||||
(mapconcat #'file-name-sans-extension
|
||||
files
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@
|
|||
(require 'citeproc nil t)
|
||||
(declare-function citeproc-style-cite-note "ext:citeproc")
|
||||
(declare-function citeproc-proc-style "ext:citeproc")
|
||||
(declare-function citeproc-bt-entry-to-csl "ext:citeproc")
|
||||
(declare-function citeproc-locale-getter-from-dir "ext:citeproc")
|
||||
(declare-function citeproc-create "ext:citeproc")
|
||||
(declare-function citeproc-citation-create "ext:citeproc")
|
||||
|
|
@ -137,13 +136,12 @@
|
|||
(declare-function citeproc-style-cite-superscript-p "ext:citeproc")
|
||||
|
||||
(declare-function org-element-interpret-data "org-element" (data))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated no-undefer))
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
(declare-function org-element-put-property "org-element-ast" (node property value))
|
||||
|
||||
(declare-function org-export-data "org-export" (data info))
|
||||
(declare-function org-export-derived-backend-p "org-export" (backend &rest backends))
|
||||
(declare-function org-export-get-footnote-number "org-export" (footnote info &optional data body-first))
|
||||
(declare-function org-export-data "ox" (data info))
|
||||
(declare-function org-export-derived-backend-p "ox" (backend &rest backends))
|
||||
(declare-function org-export-get-footnote-number "ox" (footnote info &optional data body-first))
|
||||
|
||||
|
||||
;;; Customization
|
||||
|
|
@ -321,6 +319,24 @@ in the bibliography measured in characters."
|
|||
:type 'string
|
||||
:package-version '(Org . "9.7"))
|
||||
|
||||
(defcustom org-cite-csl-bibtex-titles-to-sentence-case t
|
||||
"Convert bibtex title fields to sentence-case by default.
|
||||
|
||||
When non-nil, title fields in bibtex bibliography entries are
|
||||
converted to sentence-case before being formatted according to a
|
||||
CSL style, except for entries with a `langid' field specifying a
|
||||
non-English language. When nil, title conversion is limited to
|
||||
entries having a `langid' field specifying a variant of English.
|
||||
|
||||
Conversion of titles to sentence-case by default is in most cases
|
||||
useful because the CSL standard assumes that English titles are
|
||||
specified in sentence-case but the bibtex bibliography format
|
||||
requires them to be written in title-case."
|
||||
:group 'org-cite
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'boolean
|
||||
:safe #'booleanp)
|
||||
|
||||
|
||||
;;; Internal variables
|
||||
(defconst org-cite-csl--etc-dir
|
||||
|
|
@ -579,7 +595,8 @@ property in INFO."
|
|||
(processor
|
||||
(citeproc-create
|
||||
(org-cite-csl--style-file info)
|
||||
(citeproc-hash-itemgetter-from-any bibliography)
|
||||
(citeproc-hash-itemgetter-from-any
|
||||
bibliography (not org-cite-csl-bibtex-titles-to-sentence-case))
|
||||
(org-cite-csl--locale-getter)
|
||||
locale)))
|
||||
(plist-put info :cite-citeproc-processor processor)
|
||||
|
|
@ -803,28 +820,12 @@ INFO is the export state, as a property list."
|
|||
"\\[CSL-MAXLABEL-CHARS\\]" ,(number-to-string max-offset)))
|
||||
result))
|
||||
|
||||
|
||||
;;; Export capability
|
||||
(defun org-cite-csl-render-citation (citation _style _backend info)
|
||||
"Export CITATION object.
|
||||
INFO is the export state, as a property list."
|
||||
(org-require-package 'citeproc)
|
||||
(let ((output (cdr (assq citation (org-cite-csl--rendered-citations info)))))
|
||||
(if (not (eq 'org (org-cite-csl--output-format info)))
|
||||
output
|
||||
;; Parse Org output to re-export it during the regular export
|
||||
;; process.
|
||||
(org-cite-parse-objects output))))
|
||||
|
||||
(defun org-cite-csl-render-bibliography (_keys _files _style props _backend info)
|
||||
"Export bibliography.
|
||||
INFO is the export state, as a property list."
|
||||
(org-require-package 'citeproc)
|
||||
(pcase-let* ((format (org-cite-csl--output-format info))
|
||||
(`(,outputs ,parameters) (org-cite-csl--rendered-bibliographies info))
|
||||
(output (cdr (assoc props outputs))))
|
||||
(pcase format
|
||||
('html
|
||||
(defun org-cite-csl--generate-html-head (info)
|
||||
"Generate the CSL-related part of the HTML head.
|
||||
INFO is the export state, as a property list. Return the generated head
|
||||
fragment or nil if no fragment should be inserted."
|
||||
(let* ((parameters (cadr (org-cite-csl--rendered-bibliographies info)))
|
||||
(head-part
|
||||
(concat
|
||||
(and (cdr (assq 'second-field-align parameters))
|
||||
(let* ((max-offset (cdr (assq 'max-offset parameters)))
|
||||
|
|
@ -845,12 +846,40 @@ INFO is the export state, as a property list."
|
|||
(format
|
||||
"<style>.csl-entry{text-indent: -%s; margin-left: %s;}</style>"
|
||||
org-cite-csl-html-hanging-indent
|
||||
org-cite-csl-html-hanging-indent))
|
||||
output))
|
||||
('org-latex output)
|
||||
(_
|
||||
org-cite-csl-html-hanging-indent)))))
|
||||
(and (not (string= "" head-part)) head-part)))
|
||||
|
||||
|
||||
;;; Export capability
|
||||
(defun org-cite-csl-render-citation (citation _style _backend info)
|
||||
"Export CITATION object.
|
||||
INFO is the export state, as a property list."
|
||||
(org-require-package 'citeproc)
|
||||
(let ((output (cdr (assq citation (org-cite-csl--rendered-citations info)))))
|
||||
(if (not (eq 'org (org-cite-csl--output-format info)))
|
||||
output
|
||||
;; Parse Org output to re-export it during the regular export
|
||||
;; process.
|
||||
(org-cite-parse-objects output))))
|
||||
|
||||
(defun org-cite-csl-render-bibliography (_keys _files _style props _backend info)
|
||||
"Export bibliography.
|
||||
INFO is the export state, as a property list."
|
||||
(org-require-package 'citeproc)
|
||||
(let* ((format (org-cite-csl--output-format info))
|
||||
(outputs (car (org-cite-csl--rendered-bibliographies info)))
|
||||
(output (cdr (assoc props outputs))))
|
||||
(pcase format
|
||||
('html
|
||||
(unless (plist-get info :html-head-csl-styles-added)
|
||||
(if-let* ((head-part (org-cite-csl--generate-html-head info)))
|
||||
(plist-put info :html-head
|
||||
(concat (plist-get info :html-head) head-part)))
|
||||
(plist-put info :html-head-csl-styles-added t))
|
||||
output)
|
||||
('org-latex output)
|
||||
(_
|
||||
;; Parse Org output to re-export it during the regular export process.
|
||||
(org-cite-parse-elements output)))))
|
||||
|
||||
(defun org-cite-csl-finalizer (output _keys _files _style _backend info)
|
||||
|
|
|
|||
|
|
@ -48,9 +48,7 @@
|
|||
|
||||
(require 'oc)
|
||||
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
|
||||
(declare-function org-export-data "org-export" (data info))
|
||||
(declare-function org-export-data "ox" (data info))
|
||||
|
||||
|
||||
;;; Customization
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@
|
|||
(declare-function org-element-extract "org-element-ast" (node))
|
||||
(declare-function org-element-insert-before "org-element-ast" (node location))
|
||||
(declare-function org-element-lineage "org-element-ast" (datum &optional types with-self))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated))
|
||||
(declare-function org-element-normalize-string "org-element" (s))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated no-undefer))
|
||||
(declare-function org-element-normalize-string "org-element" (s &optional keep-newlines))
|
||||
(declare-function org-element-parse-buffer "org-element" (&optional granularity visible-only keep-deferred))
|
||||
(declare-function org-element-parse-secondary-string "org-element" (string restriction &optional parent))
|
||||
(declare-function org-element-context "org-element" (&optional element))
|
||||
|
|
@ -95,14 +95,14 @@
|
|||
(declare-function org-element-parent "org-element-ast" (node))
|
||||
(declare-function org-element-put-property "org-element-ast" (node property value))
|
||||
(declare-function org-element-restriction "org-element" (element))
|
||||
(declare-function org-element-set "org-element-ast" (old new))
|
||||
(declare-function org-element-set "org-element-ast" (old new &optional keep-props))
|
||||
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
|
||||
(declare-function org-element-type-p "org-element-ast" (node types))
|
||||
|
||||
(declare-function org-export-derived-backend-p "org-export" (backend &rest backends))
|
||||
(declare-function org-export-get-next-element "org-export" (blob info &optional n))
|
||||
(declare-function org-export-get-previous-element "org-export" (blob info &optional n))
|
||||
(declare-function org-export-raw-string "org-export" (s))
|
||||
(declare-function org-export-derived-backend-p "ox" (backend &rest backends))
|
||||
(declare-function org-export-get-next-element "ox" (blob info &optional n))
|
||||
(declare-function org-export-get-previous-element "ox" (blob info &optional n))
|
||||
(declare-function org-export-raw-string "ox" (s))
|
||||
|
||||
(defvar org-complex-heading-regexp)
|
||||
(defvar org-element-all-objects)
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@
|
|||
(declare-function bbdb-records "ext:bbdb" (&optional dont-check-disk already-in-db-buffer))
|
||||
(declare-function bbdb-split "ext:bbdb" (string separators))
|
||||
(declare-function bbdb-string-trim "ext:bbdb" (string))
|
||||
(declare-function bbdb-record-get-field "ext:bbdb" (record field))
|
||||
(declare-function bbdb-search-name "ext:bbdb-com" (regexp &optional layout))
|
||||
(declare-function bbdb-search-organization "ext:bbdb-com" (regexp &optional layout))
|
||||
|
||||
|
|
@ -222,6 +221,7 @@ date year)."
|
|||
:follow #'org-bbdb-open
|
||||
:export #'org-bbdb-export
|
||||
:complete #'org-bbdb-complete-link
|
||||
:insert-description #'org-bbdb-describe-link
|
||||
:store #'org-bbdb-store-link)
|
||||
|
||||
;;; Implementation
|
||||
|
|
@ -499,7 +499,7 @@ must be positive"))
|
|||
dates)))))
|
||||
|
||||
(defun org-bbdb-complete-link ()
|
||||
"Read a bbdb link with name completion."
|
||||
"Read a BBDB link with name completion."
|
||||
(org-require-package 'bbdb-com "bbdb")
|
||||
(let ((rec (bbdb-completing-read-record "Name: ")))
|
||||
(concat "bbdb:"
|
||||
|
|
@ -507,6 +507,12 @@ must be positive"))
|
|||
(car rec)
|
||||
rec)))))
|
||||
|
||||
(defun org-bbdb-describe-link (link desc)
|
||||
"Return a description for a BBDB link."
|
||||
(or (org-string-nw-p desc)
|
||||
(if (string-prefix-p "bbdb:" link)
|
||||
(string-remove-prefix "bbdb:" link))))
|
||||
|
||||
(defun org-bbdb-anniv-export-ical ()
|
||||
"Extract anniversaries from BBDB and convert them to icalendar format."
|
||||
(org-require-package 'bbdb)
|
||||
|
|
|
|||
|
|
@ -123,11 +123,7 @@
|
|||
(defvar org-property-end-re)
|
||||
(defvar org-special-properties)
|
||||
(defvar org-window-config-before-follow-link)
|
||||
|
||||
(declare-function bibtex-beginning-of-entry "bibtex" ())
|
||||
(declare-function bibtex-generate-autokey "bibtex" ())
|
||||
(declare-function bibtex-parse-entry "bibtex" (&optional content))
|
||||
(declare-function bibtex-url "bibtex" (&optional pos no-browse))
|
||||
(defvar org-tag--invalid-char-re)
|
||||
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
|
||||
|
|
@ -754,7 +750,7 @@ entry at point."
|
|||
(funcall
|
||||
togtag
|
||||
(replace-regexp-in-string
|
||||
"[^[:alnum:]_@#%]" ""
|
||||
org-tag--invalid-char-re ""
|
||||
(replace-regexp-in-string "[ \t]+" "_" kw))))
|
||||
(org-bibtex-put (car pair) (cdr pair) insert-raw)))
|
||||
(_ (org-bibtex-put (car pair) (cdr pair) insert-raw))))
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
(require 'doc-view)
|
||||
(require 'ol)
|
||||
|
||||
(declare-function doc-view-goto-page "doc-view" (page))
|
||||
(declare-function image-mode-window-get "image-mode" (prop &optional winprops))
|
||||
(declare-function org-open-file "org" (path &optional in-emacs line search))
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
(require 'esh-mode)
|
||||
(require 'ol)
|
||||
|
||||
(declare-function eshell/pwd "em-dirs.el" (&rest args))
|
||||
(declare-function eshell/pwd "em-dirs" ())
|
||||
|
||||
(org-link-set-parameters "eshell"
|
||||
:follow #'org-eshell-open
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@
|
|||
|
||||
(declare-function gnus-activate-group "gnus-start" (group &optional scan dont-check method dont-sub-check))
|
||||
(declare-function gnus-find-method-for-group "gnus" (group &optional info))
|
||||
(declare-function gnus-article-show-summary "gnus-art" ())
|
||||
(declare-function gnus-group-group-name "gnus-group")
|
||||
(declare-function gnus-group-jump-to-group "gnus-group" (group &optional prompt))
|
||||
(declare-function gnus-group-read-group "gnus-group" (&optional all no-article group select-articles))
|
||||
|
|
@ -227,8 +226,13 @@ If `org-store-link' was called with a prefix arg the meaning of
|
|||
(defun org-gnus-follow-link (&optional group article)
|
||||
"Follow a Gnus link to GROUP and ARTICLE."
|
||||
(require 'gnus)
|
||||
(funcall (cdr (assq 'gnus org-link-frame-setup)))
|
||||
(when gnus-other-frame-object (select-frame gnus-other-frame-object))
|
||||
(funcall (org-link-frame-setup-function 'gnus))
|
||||
(when gnus-other-frame-object
|
||||
(if (not (frame-live-p gnus-other-frame-object))
|
||||
;; Error out in case org-link-frame-setup did not take care of setting up
|
||||
;; the gnus frame if was activate previously.
|
||||
(error "Couldn't select \'gnus-other-frame-object\', make sure it is active"))
|
||||
(select-frame gnus-other-frame-object))
|
||||
(let ((group (org-no-properties group))
|
||||
(article (org-no-properties article)))
|
||||
(cond
|
||||
|
|
@ -260,11 +264,24 @@ If `org-store-link' was called with a prefix arg the meaning of
|
|||
(message "Couldn't follow Gnus link. The linked group is empty."))))
|
||||
(group (gnus-group-jump-to-group group)))))
|
||||
|
||||
(defun org-gnus-no-new-news ()
|
||||
"Like `\\[gnus]' but doesn't check for new news."
|
||||
(cond ((gnus-alive-p) nil)
|
||||
(org-gnus-no-server (gnus-no-server))
|
||||
(t (gnus))))
|
||||
(defun org-gnus-no-new-news (&optional other-frame)
|
||||
"Like `\\[gnus]' but doesn't check for new news.
|
||||
In case of OTHER-FRAME or `gnus-other-frame-object' call `gnus-other-frame'.
|
||||
|
||||
Ensures that `gnus-other-frame' is activated correctly if dead."
|
||||
(let ((action (cond (org-gnus-no-server #'gnus-no-server)
|
||||
(t #'gnus))))
|
||||
(cond ((or other-frame gnus-other-frame-object)
|
||||
(let ((gnus-other-frame-function action)
|
||||
(gnus-other-frame-resume-function action))
|
||||
(gnus-other-frame)))
|
||||
(t (if (not (gnus-alive-p))
|
||||
(funcall action))))))
|
||||
|
||||
(defun org-gnus-no-new-news-other-frame ()
|
||||
"Like `org-gnus-no-new-news' but always in another frame."
|
||||
(org-gnus-no-new-news t))
|
||||
|
||||
|
||||
(provide 'ol-gnus)
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
;; Declare external functions and variables
|
||||
|
||||
(declare-function Info-find-node "info"
|
||||
(filename nodename &optional no-going-back strict-case))
|
||||
(filename nodename &optional no-going-back strict-case noerror))
|
||||
(defvar Info-current-file)
|
||||
(defvar Info-current-node)
|
||||
|
||||
|
|
@ -68,11 +68,12 @@
|
|||
(org-info-follow-link path))
|
||||
|
||||
(defun org-info--link-file-node (path)
|
||||
"Extract file name and node from info link PATH.
|
||||
"Extract the file name and Info node from the Info link PATH.
|
||||
|
||||
Return cons consisting of file name and node name or \"Top\" if node
|
||||
part is not specified. Components may be separated by \":\" or by \"#\".
|
||||
File may be a virtual one, see `Info-virtual-files'."
|
||||
Return a cons consisting of the file name and node name or \"Top\" if
|
||||
the node part is not specified. Components may be separated by \":\"
|
||||
or by \"#\". The file name may be a virtual one, see
|
||||
`Info-virtual-files'."
|
||||
(if (not path)
|
||||
'("dir" . "Top")
|
||||
(string-match "\\`\\([^#:]*\\)\\(?:[#:]:?\\(.*\\)\\)?\\'" path)
|
||||
|
|
@ -84,7 +85,7 @@ File may be a virtual one, see `Info-virtual-files'."
|
|||
(if (org-string-nw-p node) (org-trim node) "Top")))))
|
||||
|
||||
(defun org-info-description-as-command (link desc)
|
||||
"Info link description that can be pasted as command.
|
||||
"Return an Info link description that can be evaluated as a command.
|
||||
|
||||
For the following LINK
|
||||
|
||||
|
|
@ -99,8 +100,8 @@ that may be executed as shell command or evaluated by
|
|||
in Emacs.
|
||||
|
||||
Calling convention is similar to `org-link-make-description-function'.
|
||||
DESC has higher priority and returned when it is not nil or empty string.
|
||||
If LINK is not an info link then DESC is returned."
|
||||
DESC has higher priority and returned when it is both non-nil and
|
||||
non-empty. If LINK is not an Info link, DESC is returned."
|
||||
(let* ((prefix "info:")
|
||||
(need-file-node (and (not (org-string-nw-p desc))
|
||||
(string-prefix-p prefix link))))
|
||||
|
|
@ -144,19 +145,20 @@ Taken from <https://www.gnu.org/software/emacs/manual/html_mono/.>")
|
|||
("libc" . "https://www.gnu.org/software/libc/manual/html_mono/libc.html")
|
||||
("make" . "https://www.gnu.org/software/make/manual/make.html"))
|
||||
"Alist of documents generated from Texinfo source.
|
||||
When converting info links to HTML, links to any one of these manuals are
|
||||
When converting Info links to HTML, links to any one of these manuals are
|
||||
converted to use these URL."
|
||||
:group 'org-link
|
||||
:type '(alist :key-type string :value-type string)
|
||||
:package-version '(Org . "9.7")
|
||||
:safe t)
|
||||
:safe #'listp)
|
||||
|
||||
(defun org-info-map-html-url (filename)
|
||||
"Return URL or HTML file associated to Info FILENAME.
|
||||
If FILENAME refers to an official GNU document, return a URL pointing to
|
||||
the official page for that document, e.g., use \"gnu.org\" for all Emacs
|
||||
related documents. Otherwise, append \".html\" extension to FILENAME.
|
||||
See `org-info-emacs-documents' and `org-info-other-documents' for details."
|
||||
"Return the URL or HTML file associated with the Info FILENAME.
|
||||
If FILENAME refers to an official GNU document, return the URL of the
|
||||
official page for that document, e.g., use \"gnu.org\" for all Emacs
|
||||
related documents. Otherwise, append \".html\" to the FILENAME. See
|
||||
`org-info-emacs-documents' and `org-info-other-documents' for
|
||||
details."
|
||||
(cond ((cdr (assoc filename org-info-other-documents)))
|
||||
((member filename org-info-emacs-documents)
|
||||
(format "https://www.gnu.org/software/emacs/manual/html_mono/%s.html"
|
||||
|
|
@ -164,7 +166,7 @@ See `org-info-emacs-documents' and `org-info-other-documents' for details."
|
|||
(t (concat filename ".html"))))
|
||||
|
||||
(defun org-info--expand-node-name (node)
|
||||
"Expand Info NODE to HTML cross reference."
|
||||
"Expand the Info NODE to an HTML cross reference."
|
||||
;; See (info "(texinfo) HTML Xref Node Name Expansion") for the
|
||||
;; expansion rule.
|
||||
(let ((node (replace-regexp-in-string
|
||||
|
|
@ -177,7 +179,7 @@ See `org-info-emacs-documents' and `org-info-other-documents' for details."
|
|||
(t node))))
|
||||
|
||||
(defun org-info-export (path desc format)
|
||||
"Export an info link.
|
||||
"Export an Info link.
|
||||
See `org-link-parameters' for details about PATH, DESC and FORMAT."
|
||||
(pcase-let ((`(,manual . ,node) (org-info--link-file-node path)))
|
||||
(pcase format
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
;;
|
||||
;; Copyright (C) 2020-2026 Free Software Foundation, Inc.
|
||||
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
|
||||
;; Maintainer: Bastien Guerry <bzg@gnu.org>
|
||||
;; Keywords: outlines, hypermedia, calendar, text
|
||||
;; URL: https://orgmode.org
|
||||
;;
|
||||
|
|
@ -52,7 +51,8 @@ If PATH contains extra ::STRING which will use `occur' to search
|
|||
matched strings in man buffer."
|
||||
(require 'man) ; For `Man-translate-references'
|
||||
(string-match "\\(.*?\\)\\(?:::\\(.*\\)\\)?$" path)
|
||||
(let* ((command (match-string 1 path))
|
||||
(let* ((search (match-string 2 path))
|
||||
(command (match-string 1 path))
|
||||
;; FIXME: Remove after we drop Emacs 29 support.
|
||||
;; Working around security bug #66390.
|
||||
(command (if (not (equal (Man-translate-references ";id") ";id"))
|
||||
|
|
@ -65,7 +65,6 @@ matched strings in man buffer."
|
|||
(mapcar #'shell-quote-argument
|
||||
(split-string command "\\s-+"))
|
||||
" ")))
|
||||
(search (match-string 2 path))
|
||||
(buffer (funcall org-man-command command)))
|
||||
(when search
|
||||
(with-current-buffer buffer
|
||||
|
|
|
|||
991
lisp/org/ol.el
991
lisp/org/ol.el
File diff suppressed because it is too large
Load diff
|
|
@ -75,11 +75,9 @@
|
|||
(declare-function calendar-persian-date-string "cal-persia" (&optional date))
|
||||
(declare-function calendar-check-holidays "holidays" (date))
|
||||
|
||||
(declare-function org-columns-remove-overlays "org-colview" ())
|
||||
(declare-function org-datetree-find-date-create "org-datetree"
|
||||
(date &optional keep-restriction))
|
||||
(declare-function org-columns-quit "org-colview" ())
|
||||
(declare-function diary-date-display-form "diary-lib" (&optional type))
|
||||
(declare-function org-mobile-write-agenda-for-mobile "org-mobile" (file))
|
||||
(declare-function org-habit-insert-consistency-graphs
|
||||
"org-habit" (&optional line))
|
||||
|
|
@ -1346,7 +1344,7 @@ When set to the symbol `next' only the first future repeat is shown."
|
|||
:group 'org-agenda-daily/weekly
|
||||
:type 'boolean
|
||||
:package-version '(Org . "9.7")
|
||||
:safe t)
|
||||
:safe #'booleanp)
|
||||
|
||||
(defcustom org-agenda-prefer-last-repeat nil
|
||||
"Non-nil sets date for repeated entries to their last repeat.
|
||||
|
|
@ -1637,16 +1635,16 @@ symbols are recognized:
|
|||
|
||||
time-up Put entries with time-of-day indications first, early first.
|
||||
time-down Put entries with time-of-day indications first, late first.
|
||||
timestamp-up Sort by any timestamp, early first.
|
||||
timestamp-down Sort by any timestamp, late first.
|
||||
scheduled-up Sort by scheduled timestamp, early first.
|
||||
scheduled-down Sort by scheduled timestamp, late first.
|
||||
deadline-up Sort by deadline timestamp, early first.
|
||||
deadline-down Sort by deadline timestamp, late first.
|
||||
ts-up Sort by active timestamp, early first.
|
||||
ts-down Sort by active timestamp, late first.
|
||||
tsia-up Sort by inactive timestamp, early first.
|
||||
tsia-down Sort by inactive timestamp, late first.
|
||||
timestamp-up Sort by any timestamp date, early first.
|
||||
timestamp-down Sort by any timestamp date, late first.
|
||||
scheduled-up Sort by scheduled timestamp date, early first.
|
||||
scheduled-down Sort by scheduled timestamp date, late first.
|
||||
deadline-up Sort by deadline timestamp date, early first.
|
||||
deadline-down Sort by deadline timestamp date, late first.
|
||||
ts-up Sort by active timestamp date, early first.
|
||||
ts-down Sort by active timestamp date, late first.
|
||||
tsia-up Sort by inactive timestamp date, early first.
|
||||
tsia-down Sort by inactive timestamp date, late first.
|
||||
category-keep Keep the default order of categories, corresponding to the
|
||||
sequence in `org-agenda-files'.
|
||||
category-up Sort alphabetically by category, A-Z.
|
||||
|
|
@ -1750,7 +1748,8 @@ An alist with one entry per agenda type. The keys of the
|
|||
sublists are `agenda', `todo', `search' and `tags'. The values
|
||||
are format strings.
|
||||
|
||||
This format works similar to a printf format, with the following meaning:
|
||||
This format works similar to a `format' string, with the following
|
||||
meaning:
|
||||
|
||||
%c the category of the item, \"Diary\" for entries from the diary,
|
||||
or as given by the CATEGORY keyword or derived from the file name
|
||||
|
|
@ -1761,12 +1760,20 @@ This format works similar to a printf format, with the following meaning:
|
|||
%t the HH:MM time-of-day specification if one applies to the entry
|
||||
%s Scheduling/Deadline information, a short string
|
||||
%b show breadcrumbs, i.e., the names of the higher levels
|
||||
%(expression) Eval EXPRESSION and replace the control string
|
||||
by the result
|
||||
%(expression) Eval `(EXPRESSION)' and replace the control string by
|
||||
the result.
|
||||
|
||||
All specifiers work basically like the standard `%s' of printf, but may
|
||||
contain two additional characters: a question mark just after the `%'
|
||||
and a whitespace/punctuation character just before the final letter.
|
||||
|
||||
`(EXPRESSION)' is evaluated with point and buffer associated with
|
||||
agenda entry/line being rendered. For example, heading lines will be
|
||||
evaluated with point in the Org buffer at that corresponding heading.
|
||||
However, diary records will not be evaluated in an Org buffer, but
|
||||
inside diary buffer. Auxiliary agenda lines like time grids will be
|
||||
evaluated with the point inside agenda buffer itself.
|
||||
|
||||
All specifiers work basically like the standard `%s' of `format', but
|
||||
may contain two additional characters: a question mark just after the
|
||||
`%' and a whitespace/punctuation character just before the final letter.
|
||||
|
||||
If the first character after `%' is a question mark, the entire field
|
||||
will only be included if the corresponding value applies to the current
|
||||
|
|
@ -2018,23 +2025,24 @@ When t, the highest priority entries are bold, lowest priority italic.
|
|||
However, settings in `org-priority-faces' will overrule these faces.
|
||||
When this variable is the symbol `cookies', only fontify the
|
||||
cookies, not the entire task.
|
||||
This may also be an association list of priority faces, whose
|
||||
keys are the character values of `org-priority-highest',
|
||||
`org-priority-default', and `org-priority-lowest' (the default values
|
||||
are ?A, ?B, and ?C, respectively). The face may be a named face, a
|
||||
color as a string, or a list like `(:background \"Red\")'.
|
||||
If it is a color, the variable `org-faces-easy-properties'
|
||||
determines if it is a foreground or a background color."
|
||||
|
||||
This may also be an association list of priority faces, whose keys are
|
||||
priorities and values are faces. The face may be a named face, a color
|
||||
as a string, or a list like `(:background \"Red\")'. If it is a color,
|
||||
the variable `org-faces-easy-properties' determines if it is a
|
||||
foreground or a background color."
|
||||
:group 'org-agenda-line-format
|
||||
:type '(choice
|
||||
(const :tag "Never" nil)
|
||||
(const :tag "Defaults" t)
|
||||
(const :tag "Cookies only" cookies)
|
||||
(repeat :tag "Specify"
|
||||
(list (character :tag "Priority" :value ?A)
|
||||
(choice :tag "Face "
|
||||
(alist :tag "Association list"
|
||||
:key-type (choice :tag "Priority"
|
||||
(character :tag "Character" :value ?A)
|
||||
(natnum :tag "Number" :value 1))
|
||||
:value-type (choice :tag "Face "
|
||||
(string :tag "Color")
|
||||
(sexp :tag "Face"))))))
|
||||
(sexp :tag "Face")))))
|
||||
|
||||
(defcustom org-agenda-day-face-function nil
|
||||
"Function called to determine what face should be used to display a day.
|
||||
|
|
@ -2391,7 +2399,7 @@ The following commands are available:
|
|||
(list
|
||||
(vector
|
||||
(if (get 'org-agenda-files 'org-restrict)
|
||||
"Restricted to single file"
|
||||
"Restricted to Single File"
|
||||
"Edit File List")
|
||||
'(org-edit-agenda-file-list)
|
||||
(not (get 'org-agenda-files 'org-restrict)))
|
||||
|
|
@ -2829,7 +2837,7 @@ type."
|
|||
:version "24.4"
|
||||
:package-version '(Org . "8.0")
|
||||
:group 'org-agenda-custom-commands
|
||||
:type '(choice (symbol :tag "No limit" nil)
|
||||
:type '(choice (const :tag "No limit" nil)
|
||||
(integer :tag "Max number of entries")
|
||||
(repeat
|
||||
(cons (choice :tag "Agenda type"
|
||||
|
|
@ -2847,7 +2855,7 @@ type."
|
|||
:version "24.4"
|
||||
:package-version '(Org . "8.0")
|
||||
:group 'org-agenda-custom-commands
|
||||
:type '(choice (symbol :tag "No limit" nil)
|
||||
:type '(choice (const :tag "No limit" nil)
|
||||
(integer :tag "Max number of TODOs")
|
||||
(repeat
|
||||
(cons (choice :tag "Agenda type"
|
||||
|
|
@ -2865,7 +2873,7 @@ type."
|
|||
:version "24.4"
|
||||
:package-version '(Org . "8.0")
|
||||
:group 'org-agenda-custom-commands
|
||||
:type '(choice (symbol :tag "No limit" nil)
|
||||
:type '(choice (const :tag "No limit" nil)
|
||||
(integer :tag "Max number of tagged entries")
|
||||
(repeat
|
||||
(cons (choice :tag "Agenda type"
|
||||
|
|
@ -2883,7 +2891,7 @@ to limit entries to in this type."
|
|||
:version "24.4"
|
||||
:package-version '(Org . "8.0")
|
||||
:group 'org-agenda-custom-commands
|
||||
:type '(choice (symbol :tag "No limit" nil)
|
||||
:type '(choice (const :tag "No limit" nil)
|
||||
(integer :tag "Max number of minutes")
|
||||
(repeat
|
||||
(cons (choice :tag "Agenda type"
|
||||
|
|
@ -3571,8 +3579,7 @@ This ensures the export commands can easily use it."
|
|||
(set-buffer bufname)
|
||||
(while files
|
||||
(cl-progv vars vals
|
||||
(org-agenda-write (expand-file-name (pop files) dir)
|
||||
nil t bufname))))
|
||||
(org-agenda-write (expand-file-name (pop files) dir) nil t))))
|
||||
(and (get-buffer bufname)
|
||||
(kill-buffer bufname)))))))
|
||||
|
||||
|
|
@ -3590,7 +3597,7 @@ This ensures the export commands can easily use it."
|
|||
|
||||
(defvar org-mobile-creating-agendas) ; defined in org-mobile.el
|
||||
(defvar org-agenda-write-buffer-name "Agenda View")
|
||||
(defun org-agenda-write (file &optional open nosettings agenda-bufname)
|
||||
(defun org-agenda-write (file &optional open nosettings _)
|
||||
"Write the current buffer (an agenda view) as a file.
|
||||
|
||||
Depending on the extension of the file name, plain text (.txt),
|
||||
|
|
@ -3603,9 +3610,7 @@ With prefix argument OPEN, open the new file immediately. If
|
|||
NOSETTINGS is given, do not scope the settings of
|
||||
`org-agenda-exporter-settings' into the export commands. This is
|
||||
used when the settings have already been scoped and we do not
|
||||
wish to overrule other, higher priority settings. If
|
||||
AGENDA-BUFFER-NAME is provided, use this as the buffer name for
|
||||
the agenda to write."
|
||||
wish to overrule other, higher priority settings."
|
||||
(interactive "FWrite agenda to file: \nP")
|
||||
(if (or (not (file-writable-p file))
|
||||
(and (file-exists-p file)
|
||||
|
|
@ -3652,7 +3657,7 @@ the agenda to write."
|
|||
(message "Org file written to %s" file)))
|
||||
((member extension '("html" "htm"))
|
||||
(org-require-package 'htmlize)
|
||||
(declare-function htmlize-buffer "htmlize" (&optional buffer))
|
||||
(declare-function htmlize-buffer "ext:htmlize" (&optional buffer))
|
||||
(set-buffer (htmlize-buffer (current-buffer)))
|
||||
(when org-agenda-export-html-style
|
||||
;; replace <style> section with org-agenda-export-html-style
|
||||
|
|
@ -3684,12 +3689,7 @@ the agenda to write."
|
|||
(org-icalendar-export-current-agenda (expand-file-name file)))
|
||||
(t
|
||||
(write-region nil nil file)
|
||||
(message "Plain text written to %s" file)))))))
|
||||
(set-buffer (or agenda-bufname
|
||||
;; FIXME: I'm pretty sure called-interactively-p
|
||||
;; doesn't do what we want here!
|
||||
(and (called-interactively-p 'any) (buffer-name))
|
||||
org-agenda-buffer-name)))
|
||||
(message "Plain text written to %s" file))))))))
|
||||
(when open (org-open-file file)))
|
||||
|
||||
(defun org-agenda-remove-marked-text (property &optional value)
|
||||
|
|
@ -4130,7 +4130,7 @@ agenda display, configure `org-agenda-finalize-hook'."
|
|||
org-priority-highest)
|
||||
l (or (get-char-property (point) 'org-priority-lowest)
|
||||
org-priority-lowest)
|
||||
p (string-to-char (match-string 2))
|
||||
p (org-priority-to-value (match-string 2))
|
||||
b (match-beginning 1)
|
||||
e (if (eq org-agenda-fontify-priorities 'cookies)
|
||||
(1+ (match-end 2))
|
||||
|
|
@ -4819,7 +4819,7 @@ is active."
|
|||
(setq rtn (list (format "ORG-AGENDA-ERROR: No such org-file %s"
|
||||
file))))
|
||||
(with-current-buffer buffer
|
||||
(with-syntax-table (org-search-syntax-table)
|
||||
(org-with-syntax-table (org-search-syntax-table)
|
||||
(unless (derived-mode-p 'org-mode)
|
||||
(error "Agenda file %s is not in Org mode" file))
|
||||
(let ((case-fold-search t))
|
||||
|
|
@ -6779,10 +6779,13 @@ scheduled items with an hour specification like [h]h:mm."
|
|||
'help-echo
|
||||
(format "mouse-2 or RET jump to org file %s"
|
||||
(abbreviate-file-name buffer-file-name))))
|
||||
;; Group 1: starting date timestamp without braces
|
||||
;; Group 2: ending date timestamp without braces
|
||||
(regexp (if org-agenda-include-inactive-timestamps
|
||||
org-tr-regexp-both org-tr-regexp))
|
||||
(d0 (calendar-absolute-from-gregorian date))
|
||||
face marker hdmarker ee txt d1 d2 s1 s2 category level
|
||||
(agenda-today (calendar-absolute-from-gregorian date))
|
||||
face marker hdmarker block-list txt start-day end-day
|
||||
category level
|
||||
todo-state tags pos head donep inherited-tags effort
|
||||
effort-minutes inactive?)
|
||||
(goto-char (point-min))
|
||||
|
|
@ -6793,29 +6796,28 @@ scheduled items with an hour specification like [h]h:mm."
|
|||
(setq inactive? (eq ?\[ (char-after (match-beginning 0))))
|
||||
(let ((start-time (match-string 1))
|
||||
(end-time (match-string 2)))
|
||||
(setq s1 (match-string 1)
|
||||
s2 (match-string 2)
|
||||
d1 (time-to-days
|
||||
(setq start-day (time-to-days
|
||||
(condition-case err
|
||||
(org-time-string-to-time s1)
|
||||
(org-time-string-to-time start-time)
|
||||
(error
|
||||
(error
|
||||
"Bad timestamp %S at %d in buffer %S\nError was: %s"
|
||||
s1
|
||||
start-time
|
||||
pos
|
||||
(current-buffer)
|
||||
(error-message-string err)))))
|
||||
d2 (time-to-days
|
||||
end-day (time-to-days
|
||||
(condition-case err
|
||||
(org-time-string-to-time s2)
|
||||
(org-time-string-to-time end-time)
|
||||
(error
|
||||
(error
|
||||
"Bad timestamp %S at %d in buffer %S\nError was: %s"
|
||||
s2
|
||||
end-time
|
||||
pos
|
||||
(current-buffer)
|
||||
(error-message-string err))))))
|
||||
(when (and (> (- d0 d1) -1) (> (- d2 d0) -1))
|
||||
(when (and (> (- agenda-today start-day) -1)
|
||||
(> (- end-day agenda-today) -1))
|
||||
;; Only allow days between the limits, because the normal
|
||||
;; date stamps will catch the limits.
|
||||
(save-excursion
|
||||
|
|
@ -6823,7 +6825,7 @@ scheduled items with an hour specification like [h]h:mm."
|
|||
(setq donep (member todo-state org-done-keywords))
|
||||
(when (and donep org-agenda-skip-timestamp-if-done)
|
||||
(throw :skip t))
|
||||
(setq face (if (= d1 d2)
|
||||
(setq face (if (= start-day end-day)
|
||||
'org-agenda-calendar-event
|
||||
'org-agenda-calendar-daterange))
|
||||
(setq marker (org-agenda-new-marker (point))
|
||||
|
|
@ -6849,29 +6851,36 @@ scheduled items with an hour specification like [h]h:mm."
|
|||
(let ((remove-re
|
||||
(if org-agenda-remove-timeranges-from-blocks
|
||||
(concat
|
||||
"<" (regexp-quote s1) ".*?>"
|
||||
"<" (regexp-quote start-time) ".*?>"
|
||||
"--"
|
||||
"<" (regexp-quote s2) ".*?>")
|
||||
"<" (regexp-quote end-time) ".*?>")
|
||||
nil)))
|
||||
;; `org-agenda-format-item' automatically creates a
|
||||
;; time range when
|
||||
;; `org-agenda-default-appointment-duration' is
|
||||
;; non-nil and only start/end time is given.
|
||||
;; We do not want it here, when the range spans
|
||||
;; multiple days.
|
||||
(let ((org-agenda-default-appointment-duration nil))
|
||||
(setq txt (org-agenda-format-item
|
||||
(concat
|
||||
(when inactive? org-agenda-inactive-leader)
|
||||
(format
|
||||
(nth (if (= d1 d2) 0 1)
|
||||
(nth (if (= start-day end-day) 0 1)
|
||||
org-agenda-timerange-leaders)
|
||||
(1+ (- d0 d1)) (1+ (- d2 d1))))
|
||||
(1+ (- agenda-today start-day)) (1+ (- end-day start-day))))
|
||||
(org-add-props head nil
|
||||
'effort effort
|
||||
'effort-minutes effort-minutes)
|
||||
level category tags
|
||||
(cond
|
||||
((and (= d1 d0) (= d2 d0))
|
||||
((and (= start-day agenda-today) (= end-day agenda-today))
|
||||
(concat "<" start-time ">--<" end-time ">"))
|
||||
((= d1 d0)
|
||||
((= start-day agenda-today)
|
||||
(concat "<" start-time ">"))
|
||||
((= d2 d0)
|
||||
((= end-day agenda-today)
|
||||
(concat "<" end-time ">")))
|
||||
remove-re))))
|
||||
remove-re)))))
|
||||
(org-add-props txt props
|
||||
'face face
|
||||
'org-marker marker 'org-hd-marker hdmarker
|
||||
|
|
@ -6881,10 +6890,10 @@ scheduled items with an hour specification like [h]h:mm."
|
|||
'todo-state todo-state
|
||||
'urgency (org-get-priority txt)
|
||||
'priority (org-get-priority txt))
|
||||
(push txt ee))))
|
||||
(push txt block-list))))
|
||||
(goto-char pos)))
|
||||
;; Sort the entries by expiration date.
|
||||
(nreverse ee)))
|
||||
(nreverse block-list)))
|
||||
|
||||
;;; Agenda presentation and sorting
|
||||
|
||||
|
|
@ -6973,7 +6982,8 @@ Any match of REMOVE-RE will be removed from TXT."
|
|||
(time-grid-trailing-characters (nth 2 org-agenda-time-grid))
|
||||
(extra (or (and (not habitp) extra) ""))
|
||||
time
|
||||
(ts (when dotime (concat
|
||||
(string-containing-time
|
||||
(when dotime (concat
|
||||
(if (stringp dotime) dotime "")
|
||||
(and org-agenda-search-headline-for-time
|
||||
;; Do not search inside
|
||||
|
|
@ -6982,49 +6992,61 @@ Any match of REMOVE-RE will be removed from TXT."
|
|||
(replace-regexp-in-string
|
||||
org-ts-regexp-both ""
|
||||
txt)))))
|
||||
(time-of-day (and dotime (org-get-time-of-day ts)))
|
||||
stamp plain s0 s1 s2 rtn srp l
|
||||
(time-of-day (and dotime (org-get-time-of-day string-containing-time)))
|
||||
timestamp-range? plain-time? date-range-same-day?
|
||||
time-string start-time end-time rtn
|
||||
duration breadcrumbs)
|
||||
(and (derived-mode-p 'org-mode) buffer-file-name
|
||||
(add-to-list 'org-agenda-contributing-files buffer-file-name))
|
||||
(when (and dotime time-of-day)
|
||||
;; Extract starting and ending time and move them to prefix
|
||||
(when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts))
|
||||
(setq plain (string-match org-plain-time-of-day-regexp ts)))
|
||||
(setq s0 (match-string 0 ts)
|
||||
srp (and stamp (match-end 3))
|
||||
s1 (match-string (if plain 1 2) ts)
|
||||
s2 (match-string (if plain 8 (if srp 4 6)) ts))
|
||||
(when (or (setq timestamp-range?
|
||||
(string-match org-stamp-time-of-day-regexp
|
||||
string-containing-time))
|
||||
(setq plain-time?
|
||||
(string-match org-plain-time-of-day-regexp
|
||||
string-containing-time)))
|
||||
(setq time-string (match-string 0 string-containing-time)
|
||||
date-range-same-day? (and timestamp-range? (match-end 3))
|
||||
start-time (match-string (if plain-time? 1 2)
|
||||
string-containing-time)
|
||||
end-time (match-string (if plain-time? 8
|
||||
(if date-range-same-day? 4 6))
|
||||
string-containing-time))
|
||||
|
||||
;; If the times are in TXT (not in DOTIMES), and the prefix will list
|
||||
;; them, we might want to remove them there to avoid duplication.
|
||||
;; The user can turn this off with a variable.
|
||||
(when (and org-prefix-has-time
|
||||
org-agenda-remove-times-when-in-prefix (or stamp plain)
|
||||
(string-match (concat (regexp-quote s0) " *") txt)
|
||||
org-agenda-remove-times-when-in-prefix
|
||||
(or timestamp-range? plain-time?)
|
||||
(string-match (concat (regexp-quote time-string) " *") txt)
|
||||
(not (equal ?\] (string-to-char (substring txt (match-end 0)))))
|
||||
(if (eq org-agenda-remove-times-when-in-prefix 'beg)
|
||||
(= (match-beginning 0) 0)
|
||||
t))
|
||||
(setq txt (replace-match "" nil nil txt))))
|
||||
;; Normalize the time(s) to 24 hour.
|
||||
(when s1 (setq s1 (org-get-time-of-day s1 t)))
|
||||
(when s2 (setq s2 (org-get-time-of-day s2 t)))
|
||||
(when start-time (setq start-time (org-get-time-of-day start-time t)))
|
||||
(when end-time (setq end-time (org-get-time-of-day end-time t)))
|
||||
;; Try to set s2 if s1 and
|
||||
;; `org-agenda-default-appointment-duration' are set
|
||||
(when (and s1 (not s2) org-agenda-default-appointment-duration)
|
||||
(setq s2
|
||||
(when (and start-time (not end-time)
|
||||
org-agenda-default-appointment-duration)
|
||||
(setq end-time
|
||||
(org-duration-from-minutes
|
||||
(+ (org-duration-to-minutes s1 t)
|
||||
(+ (org-duration-to-minutes start-time t)
|
||||
org-agenda-default-appointment-duration)
|
||||
nil t)))
|
||||
;; Compute the duration
|
||||
(when s2
|
||||
(setq duration (- (org-duration-to-minutes s2)
|
||||
(org-duration-to-minutes s1))))
|
||||
(when end-time
|
||||
(setq duration (- (org-duration-to-minutes end-time)
|
||||
(org-duration-to-minutes start-time))))
|
||||
;; Format S1 and S2 for display.
|
||||
(when s1 (setq s1 (format "%5s" (org-get-time-of-day s1 'overtime))))
|
||||
(when s2 (setq s2 (org-get-time-of-day s2 'overtime))))
|
||||
(when start-time
|
||||
(setq start-time (format "%5s" (org-get-time-of-day start-time 'overtime))))
|
||||
(when end-time
|
||||
(setq end-time (org-get-time-of-day end-time 'overtime))))
|
||||
(when (string-match org-tag-group-re txt)
|
||||
;; Tags are in the string
|
||||
(if (or (eq org-agenda-remove-tags t)
|
||||
|
|
@ -7061,12 +7083,14 @@ Any match of REMOVE-RE will be removed from TXT."
|
|||
;; particular heading.
|
||||
"")))
|
||||
(if (equal "" s) "" (concat s org-agenda-breadcrumbs-separator))))))
|
||||
(setq time (cond (s2 (concat
|
||||
(org-agenda-time-of-day-to-ampm-maybe s1)
|
||||
"-" (org-agenda-time-of-day-to-ampm-maybe s2)
|
||||
(setq time (cond (end-time
|
||||
(concat
|
||||
(org-agenda-time-of-day-to-ampm-maybe start-time)
|
||||
"-" (org-agenda-time-of-day-to-ampm-maybe end-time)
|
||||
(when org-agenda-timegrid-use-ampm " ")))
|
||||
(s1 (concat
|
||||
(org-agenda-time-of-day-to-ampm-maybe s1)
|
||||
(start-time
|
||||
(concat
|
||||
(org-agenda-time-of-day-to-ampm-maybe start-time)
|
||||
(if org-agenda-timegrid-use-ampm
|
||||
(concat time-grid-trailing-characters " ")
|
||||
time-grid-trailing-characters)))
|
||||
|
|
@ -7074,13 +7098,12 @@ Any match of REMOVE-RE will be removed from TXT."
|
|||
category (if (symbolp category) (symbol-name category) category)
|
||||
level (or with-level ""))
|
||||
(if (string-match org-link-bracket-re category)
|
||||
(progn
|
||||
(setq l (string-width (or (match-string 2) (match-string 1))))
|
||||
(when (< l (or org-prefix-category-length 0))
|
||||
(let ((link-width (string-width (or (match-string 2) (match-string 1)))))
|
||||
(when (< link-width (or org-prefix-category-length 0))
|
||||
(setq category (copy-sequence category))
|
||||
(org-add-props category nil
|
||||
'extra-space (make-string
|
||||
(- org-prefix-category-length l 1) ?\ ))))
|
||||
(- org-prefix-category-length link-width 1) ?\ ))))
|
||||
(when (and org-prefix-category-max-length
|
||||
(>= (length category) org-prefix-category-max-length))
|
||||
(setq category (substring category 0 (1- org-prefix-category-max-length)))))
|
||||
|
|
@ -7345,6 +7368,15 @@ The optional argument TYPE tells the agenda type."
|
|||
(max-entries (cond ((listp org-agenda-max-entries)
|
||||
(cdr (assoc type org-agenda-max-entries)))
|
||||
(t org-agenda-max-entries))))
|
||||
;; Make sure that read-only is not set on entries. Agenda expects
|
||||
;; all the inserted text to be editable, while e.g. column view
|
||||
;; may apply read-only text properties in org buffers.
|
||||
(mapc (lambda (entry)
|
||||
(remove-text-properties
|
||||
0 (length entry)
|
||||
'(read-only nil)
|
||||
entry))
|
||||
list)
|
||||
(when org-agenda-before-sorting-filter-function
|
||||
(setq list
|
||||
(delq nil
|
||||
|
|
@ -7356,7 +7388,7 @@ The optional argument TYPE tells the agenda type."
|
|||
(setq list (org-agenda-limit-entries
|
||||
list 'effort-minutes max-effort
|
||||
(lambda (e) (or e (if org-agenda-sort-noeffort-is-high
|
||||
32767 -1))))))
|
||||
most-positive-fixnum -1))))))
|
||||
(when max-todo
|
||||
(setq list (org-agenda-limit-entries list 'todo-state max-todo)))
|
||||
(when max-tags
|
||||
|
|
@ -7473,7 +7505,7 @@ The optional argument TYPE tells the agenda type."
|
|||
|
||||
(defsubst org-cmp-effort (a b)
|
||||
"Compare the effort values of string A and B."
|
||||
(let* ((def (if org-agenda-sort-noeffort-is-high 32767 -1))
|
||||
(let* ((def (if org-agenda-sort-noeffort-is-high most-positive-fixnum -1))
|
||||
;; `effort-minutes' property is not directly accessible from
|
||||
;; the strings, but is stored as a property in `txt'.
|
||||
(ea (or (get-text-property
|
||||
|
|
@ -7546,8 +7578,8 @@ The optional argument TYPE tells the agenda type."
|
|||
(cond ((not (or ta tb)) nil)
|
||||
((not ta) +1)
|
||||
((not tb) -1)
|
||||
((funcall (or org-tags-sort-function #'org-string<) ta tb) -1)
|
||||
((funcall (or org-tags-sort-function #'org-string<) tb ta) +1))))
|
||||
((org-tags-sort ta tb) -1)
|
||||
((org-tags-sort tb ta) +1))))
|
||||
|
||||
(defsubst org-cmp-time (a b)
|
||||
"Compare the time-of-day values of strings A and B."
|
||||
|
|
@ -7563,15 +7595,14 @@ When TYPE is \"scheduled\", \"deadline\", \"timestamp\" or
|
|||
\"timestamp_ia\", compare within each of these type. When TYPE
|
||||
is the empty string, compare all timestamps without respect of
|
||||
their type."
|
||||
(let* ((def (if org-agenda-sort-notime-is-late 99999999 -1))
|
||||
(ta (or (and (string-match type (or (get-text-property 1 'type a) ""))
|
||||
(get-text-property 1 'ts-date a))
|
||||
def))
|
||||
(tb (or (and (string-match type (or (get-text-property 1 'type b) ""))
|
||||
(get-text-property 1 'ts-date b))
|
||||
def)))
|
||||
(cond ((if ta (and tb (< ta tb)) tb) -1)
|
||||
((if tb (and ta (< tb ta)) ta) +1))))
|
||||
(cl-flet ((get-timestamp (entry)
|
||||
(or (and (string-match type (or (get-text-property 1 'type entry) ""))
|
||||
(get-text-property 1 'ts-date entry))
|
||||
(if org-agenda-sort-notime-is-late most-positive-fixnum -1))))
|
||||
(let ((ta (get-timestamp a))
|
||||
(tb (get-timestamp b)))
|
||||
(cond ((< ta tb) -1)
|
||||
((< tb ta) +1)))))
|
||||
|
||||
(defsubst org-cmp-habit-p (a b)
|
||||
"Compare the todo states of strings A and B."
|
||||
|
|
@ -7581,68 +7612,54 @@ their type."
|
|||
((and (not ha) hb) +1))))
|
||||
|
||||
(defun org-entries-lessp (a b)
|
||||
"Predicate for sorting agenda entries."
|
||||
;; The following variables will be used when the form is evaluated.
|
||||
;; So even though the compiler complains, keep them.
|
||||
(let ((ss org-agenda-sorting-strategy-selected))
|
||||
(org-dlet
|
||||
((timestamp-up (and (org-em 'timestamp-up 'timestamp-down ss)
|
||||
(org-cmp-ts a b "")))
|
||||
(timestamp-down (if timestamp-up (- timestamp-up) nil))
|
||||
(scheduled-up (and (org-em 'scheduled-up 'scheduled-down ss)
|
||||
(org-cmp-ts a b "scheduled")))
|
||||
(scheduled-down (if scheduled-up (- scheduled-up) nil))
|
||||
(deadline-up (and (org-em 'deadline-up 'deadline-down ss)
|
||||
(org-cmp-ts a b "deadline")))
|
||||
(deadline-down (if deadline-up (- deadline-up) nil))
|
||||
(tsia-up (and (org-em 'tsia-up 'tsia-down ss)
|
||||
(org-cmp-ts a b "timestamp_ia")))
|
||||
(tsia-down (if tsia-up (- tsia-up) nil))
|
||||
(ts-up (and (org-em 'ts-up 'ts-down ss)
|
||||
(org-cmp-ts a b "timestamp")))
|
||||
(ts-down (if ts-up (- ts-up) nil))
|
||||
(time-up (and (org-em 'time-up 'time-down ss)
|
||||
(org-cmp-time a b)))
|
||||
(time-down (if time-up (- time-up) nil))
|
||||
(stats-up (and (org-em 'stats-up 'stats-down ss)
|
||||
(org-cmp-values a b 'org-stats)))
|
||||
(stats-down (if stats-up (- stats-up) nil))
|
||||
(priority-up (and (org-em 'priority-up 'priority-down ss)
|
||||
(org-cmp-values a b 'priority)))
|
||||
(priority-down (if priority-up (- priority-up) nil))
|
||||
(urgency-up (and (org-em 'urgency-up 'urgency-down ss)
|
||||
(org-cmp-values a b 'urgency)))
|
||||
(urgency-down (if urgency-up (- urgency-up) nil))
|
||||
(effort-up (and (org-em 'effort-up 'effort-down ss)
|
||||
(org-cmp-effort a b)))
|
||||
(effort-down (if effort-up (- effort-up) nil))
|
||||
(category-up (and (or (org-em 'category-up 'category-down ss)
|
||||
(memq 'category-keep ss))
|
||||
(org-cmp-category a b)))
|
||||
(category-down (if category-up (- category-up) nil))
|
||||
(category-keep (if category-up +1 nil))
|
||||
(tag-up (and (org-em 'tag-up 'tag-down ss)
|
||||
(org-cmp-tag a b)))
|
||||
(tag-down (if tag-up (- tag-up) nil))
|
||||
(todo-state-up (and (org-em 'todo-state-up 'todo-state-down ss)
|
||||
(org-cmp-todo-state a b)))
|
||||
(todo-state-down (if todo-state-up (- todo-state-up) nil))
|
||||
(habit-up (and (org-em 'habit-up 'habit-down ss)
|
||||
(org-cmp-habit-p a b)))
|
||||
(habit-down (if habit-up (- habit-up) nil))
|
||||
(alpha-up (and (org-em 'alpha-up 'alpha-down ss)
|
||||
(org-cmp-alpha a b)))
|
||||
(alpha-down (if alpha-up (- alpha-up) nil))
|
||||
(need-user-cmp (org-em 'user-defined-up 'user-defined-down ss))
|
||||
user-defined-up user-defined-down)
|
||||
(when (and need-user-cmp org-agenda-cmp-user-defined
|
||||
(functionp org-agenda-cmp-user-defined))
|
||||
(setq user-defined-up
|
||||
(funcall org-agenda-cmp-user-defined a b)
|
||||
user-defined-down (if user-defined-up (- user-defined-up) nil)))
|
||||
(cdr (assoc
|
||||
(eval (cons 'or org-agenda-sorting-strategy-selected) t)
|
||||
'((-1 . t) (1 . nil) (nil . nil)))))))
|
||||
"Predicate for sorting agenda entries A and B."
|
||||
(catch :org-entries-lessp-return
|
||||
(dolist (strategy org-agenda-sorting-strategy-selected)
|
||||
(when-let*
|
||||
((result
|
||||
(cl-case strategy
|
||||
(timestamp-up (org-cmp-ts a b ""))
|
||||
(timestamp-down (org-cmp-ts b a ""))
|
||||
(scheduled-up (org-cmp-ts a b "scheduled"))
|
||||
(scheduled-down (org-cmp-ts b a "scheduled"))
|
||||
(deadline-up (org-cmp-ts a b "deadline"))
|
||||
(deadline-down (org-cmp-ts b a "deadline"))
|
||||
(tsia-up (org-cmp-ts a b "timestamp_ia"))
|
||||
(tsia-down (org-cmp-ts b a "timestamp_ia"))
|
||||
(ts-up (org-cmp-ts a b "timestamp"))
|
||||
(ts-down (org-cmp-ts b a "timestamp"))
|
||||
(time-up (org-cmp-time a b))
|
||||
(time-down (org-cmp-time b a))
|
||||
(stats-up (org-cmp-values a b 'org-stats))
|
||||
(stats-down (org-cmp-values b a 'org-stats))
|
||||
(priority-up (org-cmp-values a b 'priority))
|
||||
(priority-down (org-cmp-values b a 'priority))
|
||||
(urgency-up (org-cmp-values a b 'urgency))
|
||||
(urgency-down (org-cmp-values b a 'urgency))
|
||||
(effort-up (org-cmp-effort a b))
|
||||
(effort-down (org-cmp-effort b a))
|
||||
(category-up (org-cmp-category a b))
|
||||
(category-down (org-cmp-category b a))
|
||||
(category-keep (and (org-cmp-category a b) +1))
|
||||
(tag-up (org-cmp-tag a b))
|
||||
(tag-down (org-cmp-tag b a))
|
||||
(todo-state-up (org-cmp-todo-state a b))
|
||||
(todo-state-down (org-cmp-todo-state b a))
|
||||
(habit-up (org-cmp-habit-p a b))
|
||||
(habit-down (org-cmp-habit-p b a))
|
||||
(alpha-up (org-cmp-alpha a b))
|
||||
(alpha-down (org-cmp-alpha b a))
|
||||
(user-defined-up (unless (functionp org-agenda-cmp-user-defined)
|
||||
(error "Please set `org-agenda-cmp-user-defined' to a function or remove `user-defined-up' from `org-agenda-sorting-strategy'"))
|
||||
(funcall org-agenda-cmp-user-defined a b))
|
||||
(user-defined-down (unless (functionp org-agenda-cmp-user-defined)
|
||||
(error "Please set `org-agenda-cmp-user-defined' to a function or remove `user-defined-down' from `org-agenda-sorting-strategy'"))
|
||||
(funcall org-agenda-cmp-user-defined b a))
|
||||
(t (error "Invalid value %S in `org-agenda-sorting-strategy'" strategy)))))
|
||||
(cond
|
||||
((eq -1 result) (throw :org-entries-lessp-return t))
|
||||
((eq 1 result) (throw :org-entries-lessp-return nil)))))
|
||||
nil))
|
||||
|
||||
;;; Agenda restriction lock
|
||||
|
||||
|
|
@ -8182,6 +8199,9 @@ the variable `org-agenda-auto-exclude-function'."
|
|||
|
||||
(defun org-agenda-filter-completion-function (string _predicate &optional flag)
|
||||
"Complete a complex filter string.
|
||||
|
||||
See the Info Node `(org) Filtering/limiting agenda items'.
|
||||
|
||||
FLAG specifies the type of completion operation to perform. This
|
||||
function is passed as a collection function to `completing-read',
|
||||
which see."
|
||||
|
|
@ -8213,7 +8233,7 @@ which see."
|
|||
(`lambda (assoc string table)) ;exact match?
|
||||
(`(boundaries . ,suffix)
|
||||
(let ((end (if (string-match "[-+<>=]" suffix)
|
||||
(match-string 0 suffix)
|
||||
(match-beginning 0)
|
||||
(length suffix))))
|
||||
`(boundaries ,(or begin 0) . ,end)))
|
||||
(`nil
|
||||
|
|
@ -8460,7 +8480,7 @@ If the line does not have an effort defined, return nil."
|
|||
;; current line but is stored as a property in `txt'.
|
||||
(let ((effort (get-text-property 0 'effort-minutes (org-get-at-bol 'txt))))
|
||||
(funcall op
|
||||
(or effort (if org-agenda-sort-noeffort-is-high 32767 -1))
|
||||
(or effort (if org-agenda-sort-noeffort-is-high most-positive-fixnum -1))
|
||||
value)))
|
||||
|
||||
(defun org-agenda-filter-expand-tags (filter &optional no-operator)
|
||||
|
|
@ -8774,7 +8794,7 @@ See also:
|
|||
(list (car args) sd span)))
|
||||
(org-agenda-redo)
|
||||
(org-agenda-find-same-or-today-or-agenda cnt))
|
||||
(set-window-start nil wstart)))
|
||||
(set-window-start nil wstart 'noforce)))
|
||||
|
||||
(defun org-agenda-earlier (arg)
|
||||
"Go backward in time by the current span in the agenda buffer.
|
||||
|
|
@ -9243,8 +9263,12 @@ When called with a prefix argument, include all archive files as well."
|
|||
(org-agenda-error)))
|
||||
(buffer (marker-buffer marker))
|
||||
(pos (marker-position marker)))
|
||||
(switch-to-buffer-other-window buffer)
|
||||
(widen)
|
||||
(pop-to-buffer
|
||||
buffer
|
||||
`((display-buffer-reuse-window display-buffer-pop-up-window)
|
||||
(reuse-indirect . buffer)))
|
||||
(unless (<= (point-min) pos (point-max))
|
||||
(widen))
|
||||
(push-mark)
|
||||
(goto-char pos)
|
||||
(when (derived-mode-p 'org-mode)
|
||||
|
|
@ -9637,7 +9661,7 @@ if it was hidden in the outline."
|
|||
(defun org-agenda-cycle-show (&optional n)
|
||||
"Show the current entry in another window, with default settings.
|
||||
|
||||
Default settings are taken from `org-show-context-detail'. When
|
||||
Default settings are taken from `org-fold-show-context-detail'. When
|
||||
use repeatedly in immediate succession, the remote entry will
|
||||
cycle through visibility
|
||||
|
||||
|
|
@ -10106,15 +10130,15 @@ When called programmatically, FORCE-DIRECTION can be `set', `up',
|
|||
(org-agenda-date-later (- arg) what))
|
||||
|
||||
(defun org-agenda-date-later-minutes (arg)
|
||||
"Change the time of this item, in units of `org-timestamp-rounding-minutes'."
|
||||
"Change the time of this item, in units of `org-time-stamp-rounding-minutes'."
|
||||
(interactive "p")
|
||||
(setq arg (* arg (cadr org-timestamp-rounding-minutes)))
|
||||
(setq arg (* arg (cadr org-time-stamp-rounding-minutes)))
|
||||
(org-agenda-date-later arg 'minute))
|
||||
|
||||
(defun org-agenda-date-earlier-minutes (arg)
|
||||
"Change the time of this item, in units of `org-timestamp-rounding-minutes'."
|
||||
"Change the time of this item, in units of `org-time-stamp-rounding-minutes'."
|
||||
(interactive "p")
|
||||
(setq arg (* arg (cadr org-timestamp-rounding-minutes)))
|
||||
(setq arg (* arg (cadr org-time-stamp-rounding-minutes)))
|
||||
(org-agenda-date-earlier arg 'minute))
|
||||
|
||||
(defun org-agenda-date-later-hours (arg)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
(declare-function org-datetree-find-date-create "org-datetree" (date &optional keep-restriction))
|
||||
(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
|
||||
(declare-function org-timestamp-to-now "org" (timestamp-string &optional seconds))
|
||||
|
||||
;; From org-element.el
|
||||
(defvar org-element--cache-avoid-synchronous-headline-re-parsing)
|
||||
|
|
@ -136,6 +135,7 @@ For each symbol present in the list, a property will be created in
|
|||
the archived entry, with a prefix \"ARCHIVE_\", to remember this
|
||||
information."
|
||||
:group 'org-archive
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(set :greedy t
|
||||
(const :tag "Time" time)
|
||||
(const :tag "File" file)
|
||||
|
|
@ -144,13 +144,30 @@ information."
|
|||
(const :tag "Priority" priority)
|
||||
(const :tag "Inherited tags" itags)
|
||||
(const :tag "Outline path" olpath)
|
||||
(const :tag "Local tags" ltags)))
|
||||
(const :tag "Outline parent id" olid)
|
||||
(const :tag "Local tags" ltags))
|
||||
:safe #'listp)
|
||||
|
||||
(defvar org-archive-hook nil
|
||||
(defcustom org-archive-hook nil
|
||||
"Hook run after successfully archiving a subtree.
|
||||
Hook functions are called with point on the subtree in the
|
||||
original file. At this stage, the subtree has been added to the
|
||||
archive location, but not yet deleted from the original file.")
|
||||
archive location, but not yet deleted from the original file."
|
||||
:group 'org-archive
|
||||
:type 'hook
|
||||
:risky t)
|
||||
|
||||
(defcustom org-archive-finalize-hook nil
|
||||
"Hook run after successfully archiving a subtree in final location.
|
||||
Hook functions are called with point on the subtree in the
|
||||
destination file. Compare this with `org-archive-hook', which
|
||||
runs in the original file. At this stage, the subtree has been
|
||||
added to the archive location, but not yet deleted from the
|
||||
original file."
|
||||
:group 'org-archive
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'hook
|
||||
:risky t)
|
||||
|
||||
;;;###autoload
|
||||
(defun org-add-archive-files (files)
|
||||
|
|
@ -207,8 +224,9 @@ an error if LOCATION is not a valid archive location."
|
|||
"Move the current subtree to the archive.
|
||||
The archive can be a certain top-level heading in the current
|
||||
file, or in a different file. The tree will be moved to that
|
||||
location, the subtree heading be marked DONE, and the current
|
||||
time will be added.
|
||||
location. If `org-archive-mark-done' is non-nil and the subtree
|
||||
has a TODO keyword, the subtree heading will be marked DONE.
|
||||
And the current time will be added.
|
||||
|
||||
When called with a single prefix argument FIND-DONE, find whole
|
||||
trees without any open TODO items and archive them (after getting
|
||||
|
|
@ -299,6 +317,9 @@ direct children of this heading."
|
|||
(olpath . ,(mapconcat #'identity
|
||||
(org-get-outline-path)
|
||||
"/"))
|
||||
(olid . ,(org-with-wide-buffer
|
||||
(and (org-up-heading-safe)
|
||||
(org-entry-get (point) "ID"))))
|
||||
(time . ,time)
|
||||
(todo . ,(org-entry-get (point) "TODO")))))
|
||||
;; We first only copy, in case something goes wrong
|
||||
|
|
@ -306,6 +327,7 @@ direct children of this heading."
|
|||
;; which would lead to duplication of subtrees
|
||||
(let (this-command) (org-copy-subtree 1 nil t))
|
||||
(set-buffer buffer)
|
||||
(org-with-wide-buffer
|
||||
;; Enforce Org mode for the archive buffer
|
||||
(if (not (derived-mode-p 'org-mode))
|
||||
;; Force the mode for future visits.
|
||||
|
|
@ -328,7 +350,6 @@ direct children of this heading."
|
|||
(org-todo-regexp tr-org-todo-regexp)
|
||||
(org-todo-line-regexp tr-org-todo-line-regexp))
|
||||
(goto-char (point-min))
|
||||
(org-fold-show-all '(headings blocks))
|
||||
(if (and heading (not (and datetree-date (not datetree-subheading-p))))
|
||||
(progn
|
||||
(if (re-search-forward
|
||||
|
|
@ -393,6 +414,7 @@ direct children of this heading."
|
|||
(point)
|
||||
(concat "ARCHIVE_" (upcase (symbol-name item)))
|
||||
value))))
|
||||
(run-hooks 'org-archive-finalize-hook)
|
||||
;; Save the buffer, if it is not the same buffer and
|
||||
;; depending on `org-archive-subtree-save-file-p'.
|
||||
(unless (eq this-buffer buffer)
|
||||
|
|
@ -401,8 +423,7 @@ direct children of this heading."
|
|||
(if (boundp 'org-archive-from-agenda)
|
||||
'from-agenda
|
||||
'from-org)))
|
||||
(save-buffer)))
|
||||
(widen))))
|
||||
(save-buffer)))))))
|
||||
;; Here we are back in the original buffer. Everything seems
|
||||
;; to have worked. So now run hooks, cut the tree and finish
|
||||
;; up.
|
||||
|
|
|
|||
|
|
@ -437,18 +437,38 @@ adjust `org-attach-id-to-path-function-list'"
|
|||
"Return a folder path based on `org-attach-id-dir' and ID.
|
||||
Try id-to-path functions in `org-attach-id-to-path-function-list'
|
||||
ignoring nils. If EXISTING is non-nil, then return the first path
|
||||
found in the filesystem. Otherwise return the first non-nil value."
|
||||
found in the filesystem. Otherwise return the first non-nil value.
|
||||
|
||||
The existing paths are searched in
|
||||
1. `org-attach-id-dir';
|
||||
2. in \"data/\" dir - the default value of `org-attach-id-dir';
|
||||
3. if current buffer is a symlink, (1) and (2) searches are repeated
|
||||
in the `default-directory' of symlink target."
|
||||
(let ((fun-list org-attach-id-to-path-function-list)
|
||||
(base-dir (expand-file-name org-attach-id-dir))
|
||||
(default-base-dir (expand-file-name "data/"))
|
||||
(fallback-dirs (list (expand-file-name "data/")))
|
||||
preferred first)
|
||||
(when (and (buffer-file-name)
|
||||
(file-symlink-p (buffer-file-name)))
|
||||
(let ((default-directory
|
||||
(file-name-directory
|
||||
(file-truename (buffer-file-name)))))
|
||||
(cl-pushnew (expand-file-name org-attach-id-dir) fallback-dirs)
|
||||
(cl-pushnew (expand-file-name "data/") fallback-dirs)))
|
||||
(setq fallback-dirs (delete base-dir fallback-dirs))
|
||||
(setq fallback-dirs (seq-filter #'file-directory-p fallback-dirs))
|
||||
(while (and fun-list
|
||||
(not preferred))
|
||||
(let* ((name (funcall (car fun-list) id))
|
||||
(candidate (and name (expand-file-name name base-dir)))
|
||||
;; Try the default value `org-attach-id-dir' as a fallback.
|
||||
(candidate2 (and name (not (equal base-dir default-base-dir))
|
||||
(expand-file-name name default-base-dir))))
|
||||
;; Try the default value `org-attach-id-dir', and linked
|
||||
;; dirs if buffer is a symlink as a fallback.
|
||||
(fallback-candidates
|
||||
(and name (mapcar
|
||||
(lambda (dir) (expand-file-name name dir))
|
||||
fallback-dirs)))
|
||||
(fallback-candidates
|
||||
(seq-filter #'file-directory-p fallback-candidates)))
|
||||
(setq fun-list (cdr fun-list))
|
||||
(when candidate
|
||||
(if (or (not existing) (file-directory-p candidate))
|
||||
|
|
@ -456,10 +476,9 @@ found in the filesystem. Otherwise return the first non-nil value."
|
|||
(unless first
|
||||
(setq first candidate)))
|
||||
(when (and existing
|
||||
candidate2
|
||||
(not (file-directory-p candidate))
|
||||
(file-directory-p candidate2))
|
||||
(setq preferred candidate2)))))
|
||||
fallback-candidates
|
||||
(not (file-directory-p candidate)))
|
||||
(setq preferred (car fallback-candidates))))))
|
||||
(or preferred first)))
|
||||
|
||||
(defun org-attach-check-absolute-path (dir)
|
||||
|
|
@ -567,7 +586,13 @@ if it would overwrite an existing filename."
|
|||
"Move/copy/link FILE into the attachment directory of the current outline node.
|
||||
If VISIT-DIR is non-nil, visit the directory with `dired'.
|
||||
METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
|
||||
`org-attach-method'."
|
||||
`org-attach-method'.
|
||||
|
||||
Return a list (LINK DESCRIPTION), representing the file stored.
|
||||
When `org-attach-store-link-p' is non-nil, LINK and DESCRIPTION will
|
||||
be the same as in the link stored.
|
||||
When `org-attach-store-link-p' is nil, LINK will be an attachment: link
|
||||
and DESCRIPTION be the file name."
|
||||
(interactive
|
||||
(list
|
||||
(read-file-name "File to keep as an attachment: "
|
||||
|
|
@ -580,7 +605,8 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
|
|||
(setq method (or method org-attach-method))
|
||||
(when (file-directory-p file)
|
||||
(setq file (directory-file-name file)))
|
||||
(let ((basename (file-name-nondirectory file)))
|
||||
(let ((basename (file-name-nondirectory file))
|
||||
link description)
|
||||
(let* ((attach-dir (org-attach-dir 'get-create))
|
||||
(attach-file (expand-file-name basename attach-dir)))
|
||||
(cond
|
||||
|
|
@ -599,20 +625,25 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
|
|||
(run-hook-with-args 'org-attach-after-change-hook attach-dir)
|
||||
(org-attach-tag)
|
||||
(cond ((eq org-attach-store-link-p 'attached)
|
||||
(push (list (concat "attachment:" (file-name-nondirectory attach-file))
|
||||
(file-name-nondirectory attach-file))
|
||||
org-stored-links))
|
||||
(setq link (concat "attachment:" (file-name-nondirectory attach-file))
|
||||
description (file-name-nondirectory attach-file))
|
||||
(push (list link description) org-stored-links))
|
||||
((eq org-attach-store-link-p t)
|
||||
(push (list (concat "file:" file)
|
||||
(file-name-nondirectory file))
|
||||
org-stored-links))
|
||||
(setq link (concat "file:" file)
|
||||
description (file-name-nondirectory file))
|
||||
(push (list link description) org-stored-links))
|
||||
((eq org-attach-store-link-p 'file)
|
||||
(push (list (concat "file:" attach-file)
|
||||
(file-name-nondirectory attach-file))
|
||||
org-stored-links)))
|
||||
(setq link (concat "file:" attach-file)
|
||||
description (file-name-nondirectory attach-file))
|
||||
(push (list link description) org-stored-links))
|
||||
(t
|
||||
;; Do not save link, just return.
|
||||
(setq link (concat "attachment:" (file-name-nondirectory attach-file))
|
||||
description (file-name-nondirectory attach-file))))
|
||||
(if visit-dir
|
||||
(dired attach-dir)
|
||||
(message "File %S is now an attachment" basename)))))
|
||||
(message "File %S is now an attachment" basename))
|
||||
(list link description))))
|
||||
|
||||
(defun org-attach-attach-cp ()
|
||||
"Attach a file by copying it."
|
||||
|
|
@ -753,7 +784,7 @@ Basically, this adds the path to the attachment directory."
|
|||
|
||||
(defun org-attach-expand-links (_)
|
||||
"Expand links in current buffer.
|
||||
It is meant to be added to `org-export-before-parsing-hook'."
|
||||
It is meant to be added to `org-export-before-parsing-functions'."
|
||||
(save-excursion
|
||||
(while (re-search-forward "attachment:" nil t)
|
||||
(let ((link (org-element-context)))
|
||||
|
|
@ -778,9 +809,18 @@ It is meant to be added to `org-export-before-parsing-hook'."
|
|||
See `org-open-file' for details about ARG."
|
||||
(org-link-open-as-file (org-attach-expand file) arg))
|
||||
|
||||
(defun org-attach-preview-file (ov path link)
|
||||
"Preview attachment with PATH in overlay OV.
|
||||
|
||||
LINK is the Org link element being previewed."
|
||||
(org-with-point-at (org-element-begin link)
|
||||
(org-link-preview-file
|
||||
ov (org-attach-expand path) link)))
|
||||
|
||||
(org-link-set-parameters "attachment"
|
||||
:follow #'org-attach-follow
|
||||
:complete #'org-attach-complete-link)
|
||||
:complete #'org-attach-complete-link
|
||||
:preview #'org-attach-preview-file)
|
||||
|
||||
(defun org-attach-complete-link ()
|
||||
"Advise the user with the available files in the attachment directory."
|
||||
|
|
@ -833,7 +873,7 @@ Idea taken from `gnus-dired-attach'."
|
|||
(get-window-with-predicate
|
||||
(lambda (window)
|
||||
(with-current-buffer (window-buffer window)
|
||||
(eq major-mode 'org-mode))))))
|
||||
(derived-mode-p 'org-mode))))))
|
||||
(unless other-win
|
||||
(user-error
|
||||
"Can't attach to subtree. No window displaying an Org buffer"))
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
(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-month-create "org-datetree" (d &optional keep-restriction))
|
||||
(declare-function org-datetree-find-create-hierarchy "org-datetree" (hier-pairs &optional keep-restriction legacy-prop))
|
||||
(declare-function org-decrypt-entry "org-crypt" ())
|
||||
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
|
||||
(declare-function org-element-lineage "org-element-ast" (datum &optional types with-self))
|
||||
|
|
@ -67,7 +68,6 @@
|
|||
(declare-function org-element-post-affiliated "org-element" (node))
|
||||
(declare-function org-encrypt-entry "org-crypt" ())
|
||||
(declare-function org-insert-link "ol" (&optional complete-file link-location default-description))
|
||||
(declare-function org-link-make-string "ol" (link &optional description))
|
||||
(declare-function org-table-analyze "org-table" ())
|
||||
(declare-function org-table-current-dline "org-table" ())
|
||||
(declare-function org-table-fix-formulas "org-table" (key replace &optional limit delta remove))
|
||||
|
|
@ -182,10 +182,12 @@ type The type of entry. Valid types are:
|
|||
plain text to be inserted as it is.
|
||||
|
||||
target Specification of where the captured item should be placed.
|
||||
In Org files, targets usually define a node. Entries will
|
||||
become children of this node, other types will be added to the
|
||||
table or list in the body of this node.
|
||||
In Org files, targets usually define a node. Entries
|
||||
(type `entry') will become children of this node, other
|
||||
types will be added to the table or list in the body of
|
||||
this node.
|
||||
|
||||
<file-spec>
|
||||
Most target specifications contain a file name. If that file
|
||||
name is the empty string, it defaults to `org-default-notes-file'.
|
||||
A file can also be given as a variable or as a function called
|
||||
|
|
@ -194,41 +196,73 @@ target Specification of where the captured item should be placed.
|
|||
|
||||
Valid values are:
|
||||
|
||||
(file \"path/to/file\")
|
||||
(file <file-spec>)
|
||||
Text will be placed at the beginning or end of that file
|
||||
|
||||
(id \"id of existing Org entry\")
|
||||
File as child of this entry, or in the body of the entry
|
||||
|
||||
(file+headline \"path/to/file\" \"node headline\")
|
||||
(file+headline <file-spec> \"node headline\")
|
||||
(file+headline <file-spec> function-returning-string)
|
||||
(file+headline <file-spec> symbol-containing-string)
|
||||
Fast configuration if the target heading is unique in the file
|
||||
|
||||
(file+olp \"path/to/file\" \"Level 1 heading\" \"Level 2\" ...)
|
||||
(file+olp <file-spec> \"Level 1 heading\" \"Level 2\" ...)
|
||||
(file+olp <file-spec> function-returning-list-of-strings)
|
||||
(file+olp <file-spec> symbol-containing-list-of-strings)
|
||||
For non-unique headings, the full outline path is safer
|
||||
|
||||
(file+regexp \"path/to/file\" \"regexp to find location\")
|
||||
File to the entry matching regexp
|
||||
(file+regexp <file-spec> \"regexp to find location\")
|
||||
File to the entry containing matching regexp
|
||||
|
||||
(file+olp+datetree \"path/to/file\" \"Level 1 heading\" ...)
|
||||
(file+olp+datetree <file-spec> \"Level 1 heading\" ...)
|
||||
(file+olp+datetree <file-spec> function-returning-list-of-strings)
|
||||
(file+olp+datetree <file-spec> symbol-containing-list-of-strings)
|
||||
Will create a heading in a date tree for today's date.
|
||||
If no heading is given, the tree will be on top level.
|
||||
To prompt for date instead of using TODAY, use the
|
||||
:time-prompt property. To create a week-tree, use the
|
||||
:tree-type property.
|
||||
|
||||
(file+function \"path/to/file\" function-finding-location)
|
||||
(file+function <file-spec> function-finding-location)
|
||||
A function to find the right location in the file
|
||||
|
||||
(clock)
|
||||
File to the entry that is currently being clocked
|
||||
|
||||
(here)
|
||||
The position of point
|
||||
The exact position to insert the template
|
||||
|
||||
(function function-finding-location)
|
||||
Most general way: write your own function which both visits
|
||||
the file and moves point to the right location
|
||||
|
||||
|
||||
For (here) target, the template will be always inserted
|
||||
in place.
|
||||
|
||||
When the target points to headline, the template will
|
||||
be inserted into the headline body (for non-`entry' types)
|
||||
or as an immediate child.
|
||||
|
||||
When the target points to text inside heading body, the
|
||||
exact place where the template will be inserted depends
|
||||
on its type:
|
||||
|
||||
entry will be inserted as a child of the Org
|
||||
heading the point is in.
|
||||
|
||||
item, will be inserted in the nearest existing Org
|
||||
checkitem list, if there is one. The list will be
|
||||
searched from the point to the end of current
|
||||
heading body.
|
||||
|
||||
table-line will be inserted into the nearest table, if any
|
||||
searching from point to the end of current
|
||||
heading body.
|
||||
|
||||
plain plain text will be inserted in place.
|
||||
|
||||
template The template for creating the capture item.
|
||||
If it is an empty string or nil, a default template based on
|
||||
the entry type will be used (see the \"type\" section above).
|
||||
|
|
@ -285,7 +319,13 @@ properties are:
|
|||
|
||||
: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.
|
||||
month-day tree. When any subset of
|
||||
`(year quarter month week day)', create a
|
||||
datetree hierarchy with the specified
|
||||
levels. Can also be a function, in which
|
||||
case it should take the date as an argument
|
||||
and generate a list of pairs to pass to
|
||||
`org-datetree-find-create-hierarchy'.
|
||||
|
||||
:unnarrowed Do not narrow the target buffer, simply show the
|
||||
full buffer. Default is to narrow it so that you
|
||||
|
|
@ -334,6 +374,7 @@ be replaced with content and expanded:
|
|||
%-escapes, those can be used to fill the expression.
|
||||
The evaluation happens with Org mode set as major mode
|
||||
in a temporary buffer.
|
||||
Examples: %(org-id-new), %(eval default-directory)
|
||||
%<...> The result of `format-time-string' on the ... format
|
||||
specification.
|
||||
%t Time stamp, date only. The time stamp is the current
|
||||
|
|
@ -376,8 +417,10 @@ be replaced with content and expanded:
|
|||
prompt/completions. Default value and completions as in
|
||||
%^{prompt|default|...}X are allowed.
|
||||
%? After completing the template, position cursor here.
|
||||
%\\1 ... %\\N Insert the text entered at the nth %^{prompt}, where N
|
||||
is a number, starting from 1.
|
||||
%\\1 ... %\\N Insert the text entered at the nth %^{prompt} (but not
|
||||
%^{prompt}X), where N is a number, starting from 1.
|
||||
%\\*1...%\\*N Same as \\N, but for all the prompts, including
|
||||
%^{prompt} and %^{prompt}X.
|
||||
|
||||
Apart from these general escapes, you can access information specific to
|
||||
the link type that is created. For example, calling `org-capture' in emails
|
||||
|
|
@ -402,12 +445,17 @@ calendar | %:type %:date
|
|||
When you need to insert a literal percent sign in the template,
|
||||
you can escape ambiguous cases with a backward slash, e.g., \\%i."
|
||||
:group 'org-capture
|
||||
:package-version '(Org . "9.7")
|
||||
:package-version '(Org . "9.8")
|
||||
:set (lambda (s v) (set-default-toplevel-value s (org-capture-upgrade-templates v)))
|
||||
:type
|
||||
(let ((file-variants '(choice :tag "Filename "
|
||||
(file :tag "Literal")
|
||||
(function :tag "Function")
|
||||
(variable :tag "Variable")))
|
||||
(olp-variants '(choice :tag "Outline path"
|
||||
(repeat :tag "Outline path" :inline t
|
||||
(string :tag "Headline"))
|
||||
(function :tag "Function")
|
||||
(variable :tag "Variable"))))
|
||||
`(repeat
|
||||
(choice :value ("" "" entry (file "~/org/notes.org") "")
|
||||
|
|
@ -433,12 +481,14 @@ you can escape ambiguous cases with a backward slash, e.g., \\%i."
|
|||
(list :tag "File & Headline"
|
||||
(const :format "" file+headline)
|
||||
,file-variants
|
||||
(string :tag " Headline"))
|
||||
(choice :tag "Headline"
|
||||
(string :tag "Headline")
|
||||
(function :tag "Function")
|
||||
(variable :tag "Variable")))
|
||||
(list :tag "File & Outline path"
|
||||
(const :format "" file+olp)
|
||||
,file-variants
|
||||
(repeat :tag "Outline path" :inline t
|
||||
(string :tag "Headline")))
|
||||
,olp-variants)
|
||||
(list :tag "File & Regexp"
|
||||
(const :format "" file+regexp)
|
||||
,file-variants
|
||||
|
|
@ -446,19 +496,23 @@ you can escape ambiguous cases with a backward slash, e.g., \\%i."
|
|||
(list :tag "File [ & Outline path ] & Date tree"
|
||||
(const :format "" file+olp+datetree)
|
||||
,file-variants
|
||||
(option (repeat :tag "Outline path" :inline t
|
||||
(string :tag "Headline"))))
|
||||
,(append
|
||||
olp-variants
|
||||
'((const :tag "Date tree at top level" nil))))
|
||||
(list :tag "File & function"
|
||||
(const :format "" file+function)
|
||||
,file-variants
|
||||
(function :tag " Function"))
|
||||
(list :tag "Current clocking task"
|
||||
(const :format "" clock))
|
||||
(list :tag "The position at point"
|
||||
(const :format "" here))
|
||||
(list :tag "Function"
|
||||
(const :format "" function)
|
||||
(function :tag " Function")))
|
||||
(choice :tag "Template "
|
||||
(string)
|
||||
(const :tag "Empty" nil)
|
||||
(list :tag "File"
|
||||
(const :format "" file)
|
||||
(file :tag "Template file"))
|
||||
|
|
@ -480,7 +534,8 @@ you can escape ambiguous cases with a backward slash, e.g., \\%i."
|
|||
((const :format "%v " :tree-type) (const week))
|
||||
((const :format "%v " :unnarrowed) (const t))
|
||||
((const :format "%v " :table-line-pos) (string))
|
||||
((const :format "%v " :kill-buffer) (const t)))))))))
|
||||
((const :format "%v " :kill-buffer) (const t))))))))
|
||||
:risky t)
|
||||
|
||||
(defcustom org-capture-before-finalize-hook nil
|
||||
"Hook that is run right before a capture process is finalized.
|
||||
|
|
@ -610,10 +665,9 @@ key for the capture template otherwise associated with \"d\".
|
|||
to avoid duplicates.)"
|
||||
:version "24.3"
|
||||
:group 'org-capture
|
||||
:type '(repeat (list :tag "Rule"
|
||||
(string :tag " Capture key")
|
||||
(string :tag "Replace by template")
|
||||
(repeat :tag "Available when"
|
||||
:type
|
||||
(let ((available-when
|
||||
'(repeat :tag "Available when"
|
||||
(choice
|
||||
(cons :tag "Condition"
|
||||
(choice
|
||||
|
|
@ -624,7 +678,16 @@ to avoid duplicates.)"
|
|||
(const :tag "In mode" in-mode)
|
||||
(const :tag "Not in mode" not-in-mode))
|
||||
(regexp))
|
||||
(function :tag "Custom function"))))))
|
||||
(function :tag "Custom function")))))
|
||||
`(repeat
|
||||
(choice
|
||||
(list :tag "Short rule"
|
||||
(string :tag " Capture key")
|
||||
,available-when)
|
||||
(list :tag "Full rule"
|
||||
(string :tag " Capture key")
|
||||
(string :tag "Replace by template")
|
||||
,available-when)))))
|
||||
|
||||
(defcustom org-capture-use-agenda-date nil
|
||||
"Non-nil means use the date at point when capturing from agendas.
|
||||
|
|
@ -716,7 +779,6 @@ of the day at point (if any) or the current HH:MM time."
|
|||
(condition-case error
|
||||
(org-capture-put :template (org-capture-fill-template))
|
||||
((error quit)
|
||||
(if (get-buffer "*Capture*") (kill-buffer "*Capture*"))
|
||||
(error "Capture abort: %s" (error-message-string error))))
|
||||
|
||||
(setq org-capture-clock-keep (org-capture-get :clock-keep))
|
||||
|
|
@ -794,7 +856,7 @@ captured item after finalizing."
|
|||
(when (and org-capture-clock-was-started
|
||||
(equal org-clock-marker org-capture-clock-was-started))
|
||||
;; Looks like the clock we started is still running.
|
||||
(if org-capture-clock-keep
|
||||
(if (and org-capture-clock-keep (not org-note-abort))
|
||||
;; User may have completed clocked heading from the template.
|
||||
;; Refresh clock mode line.
|
||||
(org-clock-update-mode-line t)
|
||||
|
|
@ -983,7 +1045,7 @@ for `entry'-type templates"))
|
|||
(org-capture-put
|
||||
:initial-target-region
|
||||
;; Check if the buffer is currently narrowed
|
||||
(when (org-buffer-narrowed-p)
|
||||
(when (buffer-narrowed-p)
|
||||
(cons (point-min) (point-max))))
|
||||
;; store the current point
|
||||
(org-capture-put :initial-target-position (point)))
|
||||
|
|
@ -1011,7 +1073,7 @@ Store them in the capture property list."
|
|||
(org-capture-put-target-region-and-position)
|
||||
(goto-char position))
|
||||
(_ (error "Cannot find target ID \"%s\"" id))))
|
||||
(`(file+headline ,path ,(and headline (pred stringp)))
|
||||
(`(file+headline ,path ,headline)
|
||||
(set-buffer (org-capture-target-buffer path))
|
||||
;; Org expects the target file to be in Org mode, otherwise
|
||||
;; it throws an error. However, the default notes files
|
||||
|
|
@ -1025,6 +1087,7 @@ Store them in the capture property list."
|
|||
(org-capture-put-target-region-and-position)
|
||||
(widen)
|
||||
(goto-char (point-min))
|
||||
(setq headline (org-capture-expand-headline headline))
|
||||
(if (re-search-forward (format org-complex-heading-regexp-format
|
||||
(regexp-quote headline))
|
||||
nil t)
|
||||
|
|
@ -1034,8 +1097,9 @@ Store them in the capture property list."
|
|||
(insert "* " headline "\n")
|
||||
(forward-line -1)))
|
||||
(`(file+olp ,path . ,(and outline-path (guard outline-path)))
|
||||
(let ((m (org-find-olp (cons (org-capture-expand-file path)
|
||||
outline-path))))
|
||||
(let* ((expanded-file-path (org-capture-expand-file path))
|
||||
(m (org-find-olp (cons expanded-file-path
|
||||
(apply #'org-capture-expand-olp expanded-file-path outline-path)))))
|
||||
(set-buffer (marker-buffer m))
|
||||
(org-capture-put-target-region-and-position)
|
||||
(widen)
|
||||
|
|
@ -1056,8 +1120,9 @@ Store them in the capture property list."
|
|||
(and (derived-mode-p 'org-mode) (org-at-heading-p)))))
|
||||
(`(file+olp+datetree ,path . ,outline-path)
|
||||
(let ((m (if outline-path
|
||||
(org-find-olp (cons (org-capture-expand-file path)
|
||||
outline-path))
|
||||
(let ((expanded-file-path (org-capture-expand-file path)))
|
||||
(org-find-olp (cons expanded-file-path
|
||||
(apply #'org-capture-expand-olp expanded-file-path outline-path))))
|
||||
(set-buffer (org-capture-target-buffer path))
|
||||
(point-marker))))
|
||||
(set-buffer (marker-buffer m))
|
||||
|
|
@ -1075,7 +1140,19 @@ Store them in the capture property list."
|
|||
(pcase (org-capture-get :tree-type)
|
||||
(`week #'org-datetree-find-iso-week-create)
|
||||
(`month #'org-datetree-find-month-create)
|
||||
(_ #'org-datetree-find-date-create))
|
||||
(`day #'org-datetree-find-date-create)
|
||||
((pred not) #'org-datetree-find-date-create)
|
||||
;; NOTE function case needs to be before list case to
|
||||
;; handle lambda forms correctly
|
||||
((and (pred functionp) fun)
|
||||
(lambda (d keep-restriction)
|
||||
(org-datetree-find-create-hierarchy
|
||||
(funcall fun d) keep-restriction)))
|
||||
((and (pred listp) grouping)
|
||||
(lambda (d keep-restriction)
|
||||
(funcall #'org-datetree-find-create-entry grouping
|
||||
d keep-restriction)))
|
||||
(_ (error "Unrecognized :tree-type")))
|
||||
(calendar-gregorian-from-absolute
|
||||
(cond
|
||||
(org-overriding-default-time
|
||||
|
|
@ -1142,6 +1219,36 @@ Store them in the capture property list."
|
|||
(org-decrypt-entry)
|
||||
(and (org-back-to-heading t) (point))))))))
|
||||
|
||||
(defun org-capture-expand-headline (headline)
|
||||
"Expand functions, symbols and headline names for HEADLINE.
|
||||
When HEADLINE is a function, call it. When it is a variable, return
|
||||
its value. When it is a string, return it. In any other case, signal
|
||||
an error."
|
||||
(let* ((final-headline (cond ((stringp headline) headline)
|
||||
((functionp headline) (funcall headline))
|
||||
((and (symbolp headline) (boundp headline))
|
||||
(symbol-value headline))
|
||||
(t nil))))
|
||||
(or final-headline
|
||||
(error "org-capture: Invalid headline target: %S" headline))))
|
||||
|
||||
(defun org-capture-expand-olp (file &rest olp)
|
||||
"Expand functions, symbols and outline paths in FILE for OLP.
|
||||
When OLP is a function, call it with no arguments while the current
|
||||
buffer is the FILE-visiting buffer. When it is a variable, return its
|
||||
value. When it is a list of string, return it. In any other case,
|
||||
signal an error."
|
||||
(let* ((first (car olp))
|
||||
(final-olp (cond ((not (memq nil (mapcar #'stringp olp))) olp)
|
||||
((and (not (cdr olp)) (functionp first))
|
||||
(with-current-buffer (find-file-noselect file)
|
||||
(funcall first)))
|
||||
((and (not (cdr olp)) (symbolp first) (boundp first))
|
||||
(symbol-value first))
|
||||
(t nil))))
|
||||
(or final-olp
|
||||
(error "org-capture: Invalid outline path target: %S" olp))))
|
||||
|
||||
(defun org-capture-expand-file (file)
|
||||
"Expand functions, symbols and file names for FILE.
|
||||
When FILE is a function, call it. When it is a form, evaluate
|
||||
|
|
@ -1197,6 +1304,8 @@ may have been stored before."
|
|||
(exact-position (org-capture-get :exact-position))
|
||||
(insert-here? (org-capture-get :insert-here))
|
||||
(level 1))
|
||||
(unless (string-match org-outline-regexp-bol template)
|
||||
(setq template (concat "* " template)))
|
||||
(org-capture-verify-tree template)
|
||||
(when exact-position (goto-char exact-position))
|
||||
(cond
|
||||
|
|
@ -1226,7 +1335,12 @@ may have been stored before."
|
|||
(org-fold-region (max 1 (1- (point-max))) (point-max) nil))))
|
||||
(let ((origin (point-marker)))
|
||||
(unless (bolp) (insert "\n"))
|
||||
(org-capture-empty-lines-before)
|
||||
(org-capture-empty-lines-before
|
||||
(or (org-capture-get :empty-lines-before)
|
||||
(org-capture-get :empty-lines)
|
||||
(when (and (org--blank-before-heading-p)
|
||||
(not (org-previous-line-empty-p)))
|
||||
1)))
|
||||
(let ((beg (point)))
|
||||
(save-restriction
|
||||
(when insert-here? (narrow-to-region beg beg))
|
||||
|
|
@ -1305,6 +1419,8 @@ may have been stored before."
|
|||
(org-capture-empty-lines-before
|
||||
(and item
|
||||
(not prepend?)
|
||||
;; FIXME: We should obey `org-blank-before-new-entry'
|
||||
;; when :empty-lines* is not given.
|
||||
(min 1 (or (org-capture-get :empty-lines-before)
|
||||
(org-capture-get :empty-lines)
|
||||
0)))))
|
||||
|
|
@ -1353,10 +1469,11 @@ may have been stored before."
|
|||
(defun org-capture-place-table-line ()
|
||||
"Place the template as a table line."
|
||||
(require 'org-table)
|
||||
(let ((text
|
||||
(pcase (org-trim (org-capture-get :template))
|
||||
(let* ((template (org-trim (org-capture-get :template)))
|
||||
(text
|
||||
(pcase template
|
||||
((pred (string-match-p org-table-border-regexp))
|
||||
"| %?Bad template |")
|
||||
(concat "| " template))
|
||||
(text (concat text "\n"))))
|
||||
(table-line-pos (org-capture-get :table-line-pos))
|
||||
beg end)
|
||||
|
|
@ -1439,7 +1556,7 @@ the text of the entry, before the first child. If not, place the
|
|||
template at the beginning or end of the file.
|
||||
Of course, if exact position has been required, just put it there."
|
||||
(cond
|
||||
((org-capture-get :exact-position)
|
||||
((org-capture-get :insert-here)
|
||||
(goto-char (org-capture-get :exact-position)))
|
||||
((org-capture-get :target-entry-p)
|
||||
;; Place the text into this entry.
|
||||
|
|
@ -1448,6 +1565,8 @@ Of course, if exact position has been required, just put it there."
|
|||
(org-end-of-meta-data t)
|
||||
;; Go to end of the entry text, before the next headline.
|
||||
(outline-next-heading)))
|
||||
((org-capture-get :exact-position)
|
||||
(goto-char (org-capture-get :exact-position)))
|
||||
(t
|
||||
;; Beginning or end of file.
|
||||
(goto-char (if (org-capture-get :prepend) (point-min) (point-max)))))
|
||||
|
|
@ -1628,7 +1747,10 @@ The template may still contain \"%?\" for cursor positioning.
|
|||
INITIAL content and/or ANNOTATION may be specified, but will be overridden
|
||||
by their respective `org-store-link-plist' properties if present.
|
||||
|
||||
Expansion occurs in a temporary Org mode buffer."
|
||||
Expansion occurs in a temporary Org mode buffer that will be displayed
|
||||
if the template expansion triggers user prompt. Beware that displaying
|
||||
the temporary buffer may alter point position in the already displayed
|
||||
buffers."
|
||||
(let* ((template (or template (org-capture-get :template)))
|
||||
(buffer (org-capture-get :buffer))
|
||||
(file (buffer-file-name (or (buffer-base-buffer buffer) buffer)))
|
||||
|
|
@ -1695,8 +1817,10 @@ Expansion occurs in a temporary Org mode buffer."
|
|||
(setq template "")
|
||||
(message "no template") (ding)
|
||||
(sit-for 1))
|
||||
(let ((capture-tmp-buffer (generate-new-buffer "*Capture*")))
|
||||
(unwind-protect
|
||||
(save-window-excursion
|
||||
(switch-to-buffer-other-window (get-buffer-create "*Capture*"))
|
||||
(switch-to-buffer-other-window capture-tmp-buffer)
|
||||
(erase-buffer)
|
||||
(setq buffer-file-name nil)
|
||||
(setq mark-active nil)
|
||||
|
|
@ -1779,7 +1903,9 @@ Expansion occurs in a temporary Org mode buffer."
|
|||
;; completion in interactive prompts.
|
||||
(let ((org-inhibit-startup t)) (org-mode))
|
||||
(org-clone-local-variables buffer "\\`org-")
|
||||
(let (strings) ; Stores interactive answers.
|
||||
(let (strings ; Stores interactive answers.
|
||||
strings-all ; ... include %^{prompt}X answers
|
||||
)
|
||||
(save-excursion
|
||||
(let ((regexp "%\\^\\(?:{\\([^}]*\\)}\\)?\\([CgGLptTuU]\\)?"))
|
||||
(while (re-search-forward regexp nil t)
|
||||
|
|
@ -1814,6 +1940,7 @@ Expansion occurs in a temporary Org mode buffer."
|
|||
'org-tags-history))
|
||||
":")))
|
||||
(when (org-string-nw-p ins)
|
||||
(push (concat ":" ins ":") strings-all)
|
||||
(unless (eq (char-before) ?:) (insert ":"))
|
||||
(insert ins)
|
||||
(unless (eq (char-after) ?:) (insert ":"))
|
||||
|
|
@ -1823,13 +1950,18 @@ Expansion occurs in a temporary Org mode buffer."
|
|||
(lambda (s) (org-insert-link 0 s)))))
|
||||
(pcase org-capture--clipboards
|
||||
(`nil nil)
|
||||
(`(,value) (funcall insert-fun value))
|
||||
(`(,value)
|
||||
(funcall insert-fun value)
|
||||
(push value strings-all))
|
||||
(`(,first-value . ,_)
|
||||
(funcall insert-fun
|
||||
(let ((val
|
||||
(read-string "Clipboard/kill value: "
|
||||
first-value
|
||||
'org-capture--clipboards
|
||||
first-value)))
|
||||
(push val strings-all)
|
||||
val)))
|
||||
(_ (error "Invalid `org-capture--clipboards' value: %S"
|
||||
org-capture--clipboards)))))
|
||||
("p"
|
||||
|
|
@ -1862,16 +1994,19 @@ Expansion occurs in a temporary Org mode buffer."
|
|||
(point-min-marker)))))))
|
||||
(value
|
||||
(org-read-property-value prompt pom default)))
|
||||
(org-set-property prompt value)))
|
||||
(org-set-property prompt value)
|
||||
(push value strings-all)))
|
||||
((or "t" "T" "u" "U")
|
||||
;; These are the date/time related ones.
|
||||
(let* ((upcase? (equal (upcase key) key))
|
||||
(org-end-time-was-given nil)
|
||||
(time (org-read-date upcase? t nil prompt)))
|
||||
(push
|
||||
(org-insert-timestamp
|
||||
time (or org-time-was-given upcase?)
|
||||
(member key '("u" "U"))
|
||||
nil nil (list org-end-time-was-given))))
|
||||
nil nil (list org-end-time-was-given))
|
||||
strings-all)))
|
||||
(`nil
|
||||
;; Load history list for current prompt.
|
||||
(setq org-capture--prompt-history
|
||||
|
|
@ -1881,6 +2016,7 @@ Expansion occurs in a temporary Org mode buffer."
|
|||
completions
|
||||
nil nil nil 'org-capture--prompt-history default)
|
||||
strings)
|
||||
(push (car strings) strings-all)
|
||||
(insert (car strings))
|
||||
;; Save updated history list for current prompt.
|
||||
(puthash prompt org-capture--prompt-history
|
||||
|
|
@ -1895,6 +2031,14 @@ Expansion occurs in a temporary Org mode buffer."
|
|||
(unless (org-capture-escaped-%)
|
||||
(replace-match
|
||||
(nth (1- (string-to-number (match-string 1))) strings)
|
||||
nil t))))
|
||||
;; Replace %*n escapes with nth %^{...} string.
|
||||
(setq strings-all (nreverse strings-all))
|
||||
(save-excursion
|
||||
(while (re-search-forward "%\\\\\\(\\*\\([1-9][0-9]*\\)\\)" nil t)
|
||||
(unless (org-capture-escaped-%)
|
||||
(replace-match
|
||||
(nth (1- (string-to-number (match-string 2))) strings-all)
|
||||
nil t)))))
|
||||
;; Make sure there are no empty lines before the text, and that
|
||||
;; it ends with a newline character or it is empty.
|
||||
|
|
@ -1908,9 +2052,11 @@ Expansion occurs in a temporary Org mode buffer."
|
|||
(insert "\n"))
|
||||
;; Return the expanded template and kill the capture buffer.
|
||||
(untabify (point-min) (point-max))
|
||||
(buffer-substring-no-properties (point-min) (point-max)))
|
||||
(when (buffer-live-p capture-tmp-buffer)
|
||||
(with-current-buffer capture-tmp-buffer
|
||||
(set-buffer-modified-p nil)
|
||||
(prog1 (buffer-substring-no-properties (point-min) (point-max))
|
||||
(kill-buffer (current-buffer))))))
|
||||
(kill-buffer)))))))
|
||||
|
||||
(defun org-capture-escaped-% ()
|
||||
"Non-nil if % was escaped.
|
||||
|
|
@ -1950,7 +2096,7 @@ marked Sexp are evaluated when this argument is nil."
|
|||
;; Only mark valid and non-escaped sexp.
|
||||
((org-capture-escaped-%) nil)
|
||||
(t
|
||||
(let ((end (with-syntax-table emacs-lisp-mode-syntax-table
|
||||
(let ((end (org-with-syntax-table emacs-lisp-mode-syntax-table
|
||||
(ignore-errors (scan-sexps (1- (point)) 1)))))
|
||||
(when end
|
||||
(put-text-property (- (point) 2) end 'org-embedded-elisp t))))))))
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@
|
|||
(declare-function org-link-heading-search-string "ol" (&optional string))
|
||||
(declare-function org-link-make-string "ol" (link &optional description))
|
||||
(declare-function org-table-goto-line "org-table" (n))
|
||||
(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))
|
||||
(declare-function dbus-list-activatable-names "dbus" (&optional bus))
|
||||
|
|
@ -132,7 +131,7 @@ clocking out."
|
|||
"Rounding minutes when clocking in or out.
|
||||
The default value is 0 so that no rounding is done.
|
||||
When set to a non-integer value, use the car of
|
||||
`org-timestamp-rounding-minutes', like for setting a timestamp.
|
||||
`org-time-stamp-rounding-minutes', like for setting a timestamp.
|
||||
|
||||
E.g. if `org-clock-rounding-minutes' is set to 5, time is 14:47
|
||||
and you clock in: then the clock starts at 14:45. If you clock
|
||||
|
|
@ -144,7 +143,7 @@ out time will be 14:50."
|
|||
:package-version '(Org . "8.0")
|
||||
:type '(choice
|
||||
(integer :tag "Minutes (0 for no rounding)")
|
||||
(symbol :tag "Use `org-time-stamp-rounding-minutes'" 'same-as-time-stamp)))
|
||||
(const :tag "Use `org-time-stamp-rounding-minutes'" same-as-time-stamp)))
|
||||
|
||||
(defcustom org-clock-out-remove-zero-time-clocks nil
|
||||
"Non-nil means remove the clock line when the resulting time is zero."
|
||||
|
|
@ -741,27 +740,80 @@ pointing to it."
|
|||
(defvar org-clock-update-period 60
|
||||
"Number of seconds between mode line clock string updates.")
|
||||
|
||||
(defun org-clock-get-clock-string ()
|
||||
(defun org-clock-get-clock-string (&optional max-length)
|
||||
"Form a clock-string, that will be shown in the mode line.
|
||||
If an effort estimate was defined for the current item, use
|
||||
01:30/01:50 format (clocked/estimated).
|
||||
If not, show simply the clocked time like 01:50."
|
||||
(let ((clocked-time (org-clock-get-clocked-time)))
|
||||
(if org-clock-effort
|
||||
(let* ((effort-in-minutes (org-duration-to-minutes org-clock-effort))
|
||||
(work-done-str
|
||||
(propertize (org-duration-from-minutes clocked-time)
|
||||
01:30/01:50 format (clocked/estimated). If not, show simply
|
||||
the clocked time like 01:50.
|
||||
|
||||
When the optional MAX-LENGTH argument is given, this function
|
||||
will preferentially truncate the headline in order to ensure
|
||||
that the entire clock string's length remains under the
|
||||
limit."
|
||||
(let* ((max-string-length (or max-length 0))
|
||||
(clocked-time (org-clock-get-clocked-time))
|
||||
(clock-str (org-duration-from-minutes clocked-time))
|
||||
(clock-format-str (propertize "[%s]" 'face 'org-mode-line-clock))
|
||||
(clock-format-effort-str (propertize "[%s/%s]"
|
||||
'face
|
||||
'org-mode-line-clock))
|
||||
(mode-line-str-with-headline (propertize "%s (%s) "
|
||||
'face
|
||||
'org-mode-line-clock))
|
||||
(mode-line-str-without-headline (propertize "%s "
|
||||
'face
|
||||
'org-mode-line-clock))
|
||||
(effort-estimate-str (if org-clock-effort
|
||||
(org-duration-from-minutes
|
||||
(org-duration-to-minutes
|
||||
org-clock-effort))
|
||||
nil))
|
||||
(time-str (if (not org-clock-effort)
|
||||
(format clock-format-str clock-str)
|
||||
(format clock-format-effort-str
|
||||
(propertize clock-str
|
||||
'face
|
||||
(if (and org-clock-task-overrun
|
||||
(not org-clock-task-overrun-text))
|
||||
(not
|
||||
org-clock-task-overrun-text))
|
||||
'org-mode-line-clock-overrun
|
||||
'org-mode-line-clock)))
|
||||
(effort-str (org-duration-from-minutes effort-in-minutes)))
|
||||
(format (propertize "[%s/%s] (%s) " 'face 'org-mode-line-clock)
|
||||
work-done-str effort-str org-clock-heading))
|
||||
(format (propertize "[%s] (%s) " 'face 'org-mode-line-clock)
|
||||
(org-duration-from-minutes clocked-time)
|
||||
org-clock-heading))))
|
||||
'org-mode-line-clock))
|
||||
effort-estimate-str)))
|
||||
(spaces-and-parens-length (1+ (length
|
||||
(format
|
||||
mode-line-str-with-headline "" ""))))
|
||||
(untruncated-length (+ spaces-and-parens-length (length time-str)
|
||||
(length org-clock-heading))))
|
||||
;; There are three cases for displaying the mode-line clock string.
|
||||
;; 1. MAX-STRING-LENGTH is zero or greater than UNTRUNCATED-LENGTH
|
||||
;; - We can display the clock and the headline without truncation
|
||||
;; 2. MAX-STRING-LENGTH is above zero and less than or equal to
|
||||
;; (+ SPACES-AND-PARENS-LENGTH (LENGTH TIME-STR))
|
||||
;; - There isn't enough room to display any of the headline so just
|
||||
;; display a (truncated) time string
|
||||
;; 3. ORG-CLOCK-STRING-LIMIT is greater than
|
||||
;; (+ SPACES-AND-PARENS-LENGTH (LENGTH TIME-STR)) but less than
|
||||
;; UNTRUNCATED-LENGTH
|
||||
;; - Intelligently truncate the headline such that the total length of
|
||||
;; the mode line string is less than ORG-CLOCK-STRING-LIMIT
|
||||
(cond ((or (<= max-string-length 0)
|
||||
(>= max-string-length untruncated-length))
|
||||
(format mode-line-str-with-headline time-str org-clock-heading))
|
||||
((or (<= max-string-length 0)
|
||||
(<= max-string-length (+ spaces-and-parens-length
|
||||
(length time-str))))
|
||||
(format mode-line-str-without-headline
|
||||
(substring time-str 0 (min (length time-str)
|
||||
max-string-length))))
|
||||
(t
|
||||
(let ((heading-length (- max-string-length
|
||||
(+ spaces-and-parens-length
|
||||
(length time-str)))))
|
||||
(format mode-line-str-with-headline
|
||||
time-str
|
||||
(string-join `(,(substring org-clock-heading
|
||||
0 heading-length)
|
||||
"…"))))))))
|
||||
|
||||
(defun org-clock-get-last-clock-out-time ()
|
||||
"Get the last clock-out time for the current subtree."
|
||||
|
|
@ -781,15 +833,10 @@ When optional argument is non-nil, refresh cached heading."
|
|||
(when refresh (setq org-clock-heading (org-clock--mode-line-heading)))
|
||||
(setq org-mode-line-string
|
||||
(propertize
|
||||
(let ((clock-string (org-clock-get-clock-string))
|
||||
(let ((clock-string (org-clock-get-clock-string org-clock-string-limit))
|
||||
(help-text "Org mode clock is running.\nmouse-1 shows a \
|
||||
menu\nmouse-2 will jump to task"))
|
||||
(if (and (> org-clock-string-limit 0)
|
||||
(> (length clock-string) org-clock-string-limit))
|
||||
(propertize
|
||||
(substring clock-string 0 org-clock-string-limit)
|
||||
'help-echo (concat help-text ": " org-clock-heading))
|
||||
(propertize clock-string 'help-echo help-text)))
|
||||
(propertize clock-string 'help-echo help-text))
|
||||
'local-map org-clock-mode-line-map
|
||||
'mouse-face 'mode-line-highlight))
|
||||
(if (and org-clock-task-overrun org-clock-task-overrun-text)
|
||||
|
|
@ -1245,14 +1292,11 @@ If `only-dangling-p' is non-nil, only ask to resolve dangling
|
|||
|
||||
(defvar org-x11idle-exists-p
|
||||
;; Check that x11idle exists. But don't do that on DOS/Windows,
|
||||
;; since the command definitely does NOT exist there, and invoking
|
||||
;; COMMAND.COM on MS-Windows is a bad idea -- it hangs.
|
||||
;; since the command definitely does NOT exist there.
|
||||
(and (null (memq system-type '(windows-nt ms-dos)))
|
||||
(eq 0 (call-process-shell-command
|
||||
(format "command -v %s" org-clock-x11idle-program-name)))
|
||||
(executable-find org-clock-x11idle-program-name)
|
||||
;; Check that x11idle can retrieve the idle time
|
||||
;; FIXME: Why "..-shell-command" rather than just `call-process'?
|
||||
(eq 0 (call-process-shell-command org-clock-x11idle-program-name))))
|
||||
(eq 0 (call-process org-clock-x11idle-program-name))))
|
||||
|
||||
(defun org-x11-idle-seconds ()
|
||||
"Return the current X11 idle time in seconds."
|
||||
|
|
@ -1287,6 +1331,8 @@ This routine returns a floating point number."
|
|||
(org-mac-idle-seconds))
|
||||
((and (eq window-system 'x) org-x11idle-exists-p)
|
||||
(org-x11-idle-seconds))
|
||||
((fboundp 'w32-system-idle-time)
|
||||
(/ (w32-system-idle-time) 1000.0))
|
||||
((and
|
||||
org-logind-dbus-session-path
|
||||
(dbus-get-property
|
||||
|
|
@ -3251,7 +3297,7 @@ The details of what will be saved are regulated by the variable
|
|||
org-clock-has-been-used
|
||||
(not (file-exists-p org-clock-persist-file))))
|
||||
(with-temp-file org-clock-persist-file
|
||||
(insert (format ";; %s - %s at %s\n"
|
||||
(insert (format ";; %s - %s at %s -*- lexical-binding: t; -*-\n"
|
||||
(file-name-nondirectory org-clock-persist-file)
|
||||
(system-name)
|
||||
(format-time-string (org-time-stamp-format t))))
|
||||
|
|
@ -3316,7 +3362,7 @@ The details of what will be saved are regulated by the variable
|
|||
"Query user when killing Emacs.
|
||||
This function is added to `kill-emacs-query-functions'."
|
||||
(let ((buf (org-clocking-buffer)))
|
||||
(when (and buf (yes-or-no-p "Clock out and save? "))
|
||||
(when (and buf (yes-or-no-p "Clock out before exiting? "))
|
||||
(with-current-buffer buf
|
||||
(org-clock-out)
|
||||
(save-buffer))))
|
||||
|
|
|
|||
|
|
@ -39,12 +39,11 @@
|
|||
(declare-function org-clock-sum-today "org-clock" (&optional headline-filter))
|
||||
(declare-function org-element-extract "org-element-ast" (node))
|
||||
(declare-function org-element-interpret-data "org-element" (data))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated no-undefer))
|
||||
(declare-function org-element-parse-secondary-string "org-element" (string restriction &optional parent))
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
(declare-function org-element-restriction "org-element" (element))
|
||||
(declare-function org-element-type-p "org-element-ast" (node types))
|
||||
(declare-function org-dynamic-block-define "org" (type func))
|
||||
(declare-function org-link-display-format "ol" (s))
|
||||
(declare-function org-link-open-from-string "ol" (s &optional arg))
|
||||
(declare-function face-remap-remove-relative "face-remap" (cookie))
|
||||
|
|
@ -74,7 +73,7 @@ node `(org)Column attributes')."
|
|||
|
||||
(defcustom org-columns-modify-value-for-display-function nil
|
||||
"Function that modifies values for display in column view.
|
||||
For example, it can be used to cut out a certain part from a time stamp.
|
||||
For example, it can be used to cut out a certain part from a timestamp.
|
||||
The function must take 2 arguments:
|
||||
|
||||
column-title The title of the column (*not* the property name)
|
||||
|
|
@ -107,9 +106,8 @@ or (LABEL SUMMARIZE COLLECT) where
|
|||
properties is set, e.g., to return VACATION_DAYS only if
|
||||
CONFIRMED is true.
|
||||
|
||||
Note that the return value can become one value for an higher
|
||||
order summary, so the function is expected to handle its own
|
||||
output.
|
||||
Note that the return value can become one value for a higher-order
|
||||
summary, so the function is expected to handle its own output.
|
||||
|
||||
Types defined in this variable take precedence over those defined
|
||||
in `org-columns-summary-types-default', which see."
|
||||
|
|
@ -151,10 +149,10 @@ This is the compiled version of the format.")
|
|||
"Currently active maximum column widths, as a vector.")
|
||||
|
||||
(defvar-local org-columns-begin-marker nil
|
||||
"Points to the position where last a column creation command was called.")
|
||||
"Points to the position where a column creation command was last called.")
|
||||
|
||||
(defvar-local org-columns-top-level-marker nil
|
||||
"Points to the position where current columns region starts.")
|
||||
"Points to the position where the current columns region starts.")
|
||||
|
||||
(defvar org-columns--time 0.0
|
||||
"Number of seconds since the epoch, as a floating point number.")
|
||||
|
|
@ -179,7 +177,7 @@ This is the compiled version of the format.")
|
|||
("@mean" . org-columns--summary-mean-age)
|
||||
("@min" . org-columns--summary-min-age)
|
||||
("est+" . org-columns--summary-estimate))
|
||||
"Map operators to summarize functions.
|
||||
"Map operators to summary functions.
|
||||
See `org-columns-summary-types' for details.")
|
||||
|
||||
(defun org-columns-content ()
|
||||
|
|
@ -274,12 +272,12 @@ value for ITEM property."
|
|||
(`(,(or "DEADLINE" "SCHEDULED" "TIMESTAMP") . ,_)
|
||||
(replace-regexp-in-string org-ts-regexp "[\\1]" value))
|
||||
(`(,_ ,_ ,_ ,_ nil) value)
|
||||
;; If PRINTF is set, assume we are displaying a number and
|
||||
;; If FMT is set, assume we are displaying a number and
|
||||
;; obey to the format string.
|
||||
(`(,_ ,_ ,_ ,_ ,printf) (format printf (string-to-number value)))
|
||||
(`(,_ ,_ ,_ ,_ ,fmt) (format fmt (string-to-number value)))
|
||||
(_ (error "Invalid column specification format: %S" spec)))))
|
||||
|
||||
(defun org-columns--collect-values (&optional compiled-fmt)
|
||||
(defun org-columns--collect-values (&optional compiled-fmt agenda-marker)
|
||||
"Collect values for columns on the current line.
|
||||
|
||||
Return a list of triplets (SPEC VALUE DISPLAYED) suitable for
|
||||
|
|
@ -287,7 +285,11 @@ Return a list of triplets (SPEC VALUE DISPLAYED) suitable for
|
|||
|
||||
This function assumes `org-columns-current-fmt-compiled' is
|
||||
initialized is set in the current buffer. However, it is
|
||||
possible to override it with optional argument COMPILED-FMT."
|
||||
possible to override it with optional argument COMPILED-FMT.
|
||||
|
||||
The optional argument AGENDA-MARKER is used when called from the
|
||||
agenda to pass a marker to the agenda line.
|
||||
"
|
||||
(let ((summaries (get-text-property (point) 'org-summaries)))
|
||||
(mapcar
|
||||
(lambda (spec)
|
||||
|
|
@ -299,10 +301,18 @@ possible to override it with optional argument COMPILED-FMT."
|
|||
;; Effort property is not defined. Try
|
||||
;; to use appointment duration.
|
||||
org-agenda-columns-add-appointments-to-effort-sum
|
||||
agenda-marker
|
||||
(string= p (upcase org-effort-property))
|
||||
(get-text-property (point) 'duration)
|
||||
(propertize (org-duration-from-minutes
|
||||
(get-text-property (point) 'duration))
|
||||
(get-text-property
|
||||
(marker-position agenda-marker)
|
||||
'duration
|
||||
(marker-buffer agenda-marker))
|
||||
(propertize
|
||||
(org-duration-from-minutes
|
||||
(get-text-property
|
||||
(marker-position agenda-marker)
|
||||
'duration
|
||||
(marker-buffer agenda-marker)))
|
||||
'face 'org-warning))
|
||||
"")))
|
||||
;; A non-nil COMPILED-FMT means we're calling from Org
|
||||
|
|
@ -498,7 +508,11 @@ substring whose `string-width' does not exceed WIDTH."
|
|||
"Inhibit recomputing of columns on column view startup.")
|
||||
(defvar org-columns-flyspell-was-active nil
|
||||
"Remember the state of `flyspell-mode' before column view.
|
||||
Flyspell-mode can cause problems in columns view, so it is turned off
|
||||
Flyspell mode can cause problems in columns view, so it is turned off
|
||||
for the duration of the command.")
|
||||
(defvar org-columns-org-num-was-active nil
|
||||
"Remember the state of `org-num-mode' before column view.
|
||||
Org-num mode can cause problems in columns view, so it is turned off
|
||||
for the duration of the command.")
|
||||
|
||||
(defvar header-line-format)
|
||||
|
|
@ -564,6 +578,8 @@ for the duration of the command.")
|
|||
(remove-text-properties (point-min) (point-max) '(read-only t))))
|
||||
(when org-columns-flyspell-was-active
|
||||
(flyspell-mode 1))
|
||||
(when org-columns-org-num-was-active
|
||||
(org-num-mode 1))
|
||||
(when (local-variable-p 'org-colview-initial-truncate-line-value)
|
||||
(setq truncate-lines org-colview-initial-truncate-line-value))))
|
||||
|
||||
|
|
@ -685,7 +701,7 @@ Where possible, use the standard interface for changing this line."
|
|||
((eq major-mode 'org-agenda-mode)
|
||||
(org-columns--call action)
|
||||
;; The following let preserves the current format, and makes
|
||||
;; sure that in only a single file things need to be updated.
|
||||
;; sure that only a single file needs to be updated.
|
||||
(let* ((org-overriding-columns-format org-columns-current-fmt)
|
||||
(buffer (marker-buffer pom))
|
||||
(org-agenda-contributing-files
|
||||
|
|
@ -801,8 +817,8 @@ an integer, select that value."
|
|||
|
||||
(defun org-colview-construct-allowed-dates (s)
|
||||
"Construct a list of three dates around the date in S.
|
||||
This respects the format of the time stamp in S, active or non-active,
|
||||
and also including time or not. S must be just a time stamp, no text
|
||||
This respects the format of the timestamp in S, active or non-active,
|
||||
and also including time or not. S must be just a timestamp, no text
|
||||
around it."
|
||||
(when (and s (string-match (concat "^" org-ts-regexp3 "$") s))
|
||||
(let* ((time (org-parse-time-string s 'nodefaults))
|
||||
|
|
@ -873,7 +889,7 @@ Also sets `org-columns-top-level-marker' to the new position."
|
|||
Column view applies to the whole buffer if point is before the first
|
||||
headline. Otherwise, it applies to the first ancestor setting
|
||||
\"COLUMNS\" property. If there is none, it defaults to the current
|
||||
headline. With a `\\[universal-argument]' prefix \ argument, GLOBAL,
|
||||
headline. With a `\\[universal-argument]' prefix argument, GLOBAL,
|
||||
turn on column view for the whole buffer unconditionally.
|
||||
|
||||
When COLUMNS-FMT-STRING is non-nil, use it as the column format."
|
||||
|
|
@ -909,6 +925,9 @@ When COLUMNS-FMT-STRING is non-nil, use it as the column format."
|
|||
(when (setq-local org-columns-flyspell-was-active
|
||||
(bound-and-true-p flyspell-mode))
|
||||
(flyspell-mode 0))
|
||||
(when (setq-local org-columns-org-num-was-active
|
||||
(bound-and-true-p org-num-mode))
|
||||
(org-num-mode 0))
|
||||
(unless (local-variable-p 'org-colview-initial-truncate-line-value)
|
||||
(setq-local org-colview-initial-truncate-line-value
|
||||
truncate-lines))
|
||||
|
|
@ -918,15 +937,37 @@ When COLUMNS-FMT-STRING is non-nil, use it as the column format."
|
|||
(goto-char (car entry))
|
||||
(org-columns--display-here (cdr entry)))))))))
|
||||
|
||||
(defun org-columns--summary-types-completion-function (string pred flag)
|
||||
(let ((completion-table
|
||||
(org-completion-table-with-metadata
|
||||
(lambda (str pred comp)
|
||||
(complete-with-action comp
|
||||
(delete-dups
|
||||
(cons '("" "")
|
||||
(mapcar #'car
|
||||
(append org-columns-summary-types
|
||||
org-columns-summary-types-default))))
|
||||
str pred))
|
||||
`(metadata
|
||||
. ((annotation-function
|
||||
. ,(lambda (string)
|
||||
(let* ((doc (ignore-errors
|
||||
(documentation
|
||||
(cdr (assoc string
|
||||
(append org-columns-summary-types
|
||||
org-columns-summary-types-default))))))
|
||||
(doc (and doc (substring doc 0 (string-search "\n" doc)))))
|
||||
(if doc (format " -- %s" doc) "")))))))))
|
||||
(complete-with-action flag completion-table string pred)))
|
||||
|
||||
(defun org-columns-new (&optional spec &rest attributes)
|
||||
"Insert a new column, to the left of the current column.
|
||||
Interactively fill attributes for new column. When column format
|
||||
specification SPEC is provided, edit it instead.
|
||||
|
||||
When optional argument attributes can be a list of columns
|
||||
specifications attributes to create the new column
|
||||
non-interactively. See `org-columns-compile-format' for
|
||||
details."
|
||||
When optional argument ATTRIBUTES is provided, it should be a list of
|
||||
column specification attributes to create the new column
|
||||
non-interactively. See `org-columns-compile-format' for details."
|
||||
(interactive)
|
||||
(let ((new (or attributes
|
||||
(let ((prop
|
||||
|
|
@ -935,8 +976,10 @@ details."
|
|||
(mapcar #'list (org-buffer-property-keys t nil t))
|
||||
nil nil (nth 0 spec))))
|
||||
(list prop
|
||||
;; Discard useless whitespace-only titles.
|
||||
(org-string-nw-p
|
||||
(read-string (format "Column title [%s]: " prop)
|
||||
(nth 1 spec))
|
||||
(nth 1 spec)))
|
||||
;; Use `read-string' instead of `read-number'
|
||||
;; to allow empty width.
|
||||
(let ((w (read-string
|
||||
|
|
@ -947,12 +990,7 @@ details."
|
|||
(org-string-nw-p
|
||||
(completing-read
|
||||
"Summary: "
|
||||
(delete-dups
|
||||
(cons '("") ;Allow empty operator.
|
||||
(mapcar (lambda (x) (list (car x)))
|
||||
(append
|
||||
org-columns-summary-types
|
||||
org-columns-summary-types-default))))
|
||||
'org-columns--summary-types-completion-function
|
||||
nil t (nth 3 spec)))
|
||||
(org-string-nw-p
|
||||
(read-string "Format: " (nth 4 spec))))))))
|
||||
|
|
@ -964,7 +1002,7 @@ details."
|
|||
(org-columns-redo)))
|
||||
|
||||
(defun org-columns-delete ()
|
||||
"Delete the column at point from columns view."
|
||||
"Delete the column at point from column view."
|
||||
(interactive)
|
||||
(let ((spec (nth (org-current-text-column) org-columns-current-fmt-compiled)))
|
||||
(when (y-or-n-p (format "Are you sure you want to remove column %S? "
|
||||
|
|
@ -1158,13 +1196,13 @@ COMPILED is an alist, as returned by `org-columns-compile-format'."
|
|||
(mapconcat
|
||||
(lambda (spec)
|
||||
(pcase spec
|
||||
(`(,prop ,title ,width ,op ,printf)
|
||||
(`(,prop ,title ,width ,op ,fmt)
|
||||
(concat "%"
|
||||
(and width (number-to-string width))
|
||||
prop
|
||||
(and title (not (equal prop title)) (format "(%s)" title))
|
||||
(cond ((not op) nil)
|
||||
(printf (format "{%s;%s}" op printf))
|
||||
(fmt (format "{%s;%s}" op fmt))
|
||||
(t (format "{%s}" op)))))))
|
||||
compiled " "))
|
||||
|
||||
|
|
@ -1177,26 +1215,30 @@ property the property name, as an upper-case string
|
|||
title the title field for the columns, as a string
|
||||
width the column width in characters, can be nil for automatic width
|
||||
operator the summary operator, as a string, or nil
|
||||
printf a printf format for computed values, as a string, or nil
|
||||
format a `format' string for computed values, or nil
|
||||
|
||||
This function updates `org-columns-current-fmt-compiled'."
|
||||
(setq org-columns-current-fmt-compiled nil)
|
||||
(let ((start 0))
|
||||
(while (string-match
|
||||
"%\\([0-9]+\\)?\\([[:alnum:]_-]+\\)\\(?:(\\([^)]+\\))\\)?\
|
||||
\\(?:{\\([^}]+\\)}\\)?\\s-*"
|
||||
(rx "%"
|
||||
(optional (group (+ digit)))
|
||||
(group (one-or-more (in alnum "_-")))
|
||||
(optional "(" (group (zero-or-more (not (any ")")))) ")")
|
||||
(optional "{" (group (zero-or-more (not (any "}")))) "}")
|
||||
(zero-or-more space))
|
||||
fmt start)
|
||||
(setq start (match-end 0))
|
||||
(let* ((width (and (match-end 1) (string-to-number (match-string 1 fmt))))
|
||||
(prop (match-string-no-properties 2 fmt))
|
||||
(title (or (match-string-no-properties 3 fmt) prop))
|
||||
(operator (match-string-no-properties 4 fmt)))
|
||||
(title (or (org-string-nw-p (match-string-no-properties 3 fmt)) prop))
|
||||
(operator (org-string-nw-p (match-string-no-properties 4 fmt))))
|
||||
(push (if (not operator) (list (upcase prop) title width nil nil)
|
||||
(let (printf)
|
||||
(let (fmt)
|
||||
(when (string-match ";" operator)
|
||||
(setq printf (substring operator (match-end 0)))
|
||||
(setq fmt (substring operator (match-end 0)))
|
||||
(setq operator (substring operator 0 (match-beginning 0))))
|
||||
(list (upcase prop) title width operator printf)))
|
||||
(list (upcase prop) title width operator fmt)))
|
||||
org-columns-current-fmt-compiled)))
|
||||
(setq org-columns-current-fmt-compiled
|
||||
(nreverse org-columns-current-fmt-compiled))))
|
||||
|
|
@ -1243,7 +1285,7 @@ properties drawers."
|
|||
(inminlevel lmax)
|
||||
(last-level lmax)
|
||||
(property (car spec))
|
||||
(printf (nth 4 spec))
|
||||
(fmt (nth 4 spec))
|
||||
;; Special properties cannot be collected nor summarized, as
|
||||
;; they have their own way to be computed. Therefore, ignore
|
||||
;; any operator attached to them.
|
||||
|
|
@ -1275,7 +1317,7 @@ properties drawers."
|
|||
(let ((values
|
||||
(cl-loop for l from (1+ level) to lmax
|
||||
append (aref lvals l))))
|
||||
(and values (funcall summarize values printf))))))
|
||||
(and values (funcall summarize values fmt))))))
|
||||
;; Leaf values are not summaries: do not mark them.
|
||||
(when summary
|
||||
(let* ((summaries-alist (get-text-property pos 'org-summaries))
|
||||
|
|
@ -1331,10 +1373,10 @@ column specification."
|
|||
(org-columns--compute-spec spec (not (member property seen)))
|
||||
(push property seen)))))
|
||||
|
||||
(defun org-columns--summary-sum (values printf)
|
||||
(defun org-columns--summary-sum (values fmt)
|
||||
"Compute the sum of VALUES.
|
||||
When PRINTF is non-nil, use it to format the result."
|
||||
(format (or printf "%s") (apply #'+ (mapcar #'string-to-number values))))
|
||||
When FMT is non-nil, use it to format the result."
|
||||
(format (or fmt "%s") (apply #'+ (mapcar #'string-to-number values))))
|
||||
|
||||
(defun org-columns--summary-currencies (values _)
|
||||
"Compute the sum of VALUES, with two decimals."
|
||||
|
|
@ -1363,22 +1405,22 @@ When PRINTF is non-nil, use it to format the result."
|
|||
check-boxes))
|
||||
(length check-boxes))))
|
||||
|
||||
(defun org-columns--summary-min (values printf)
|
||||
(defun org-columns--summary-min (values fmt)
|
||||
"Compute the minimum of VALUES.
|
||||
When PRINTF is non-nil, use it to format the result."
|
||||
(format (or printf "%s")
|
||||
When FMT is non-nil, use it to format the result."
|
||||
(format (or fmt "%s")
|
||||
(apply #'min (mapcar #'string-to-number values))))
|
||||
|
||||
(defun org-columns--summary-max (values printf)
|
||||
(defun org-columns--summary-max (values fmt)
|
||||
"Compute the maximum of VALUES.
|
||||
When PRINTF is non-nil, use it to format the result."
|
||||
(format (or printf "%s")
|
||||
When FMT is non-nil, use it to format the result."
|
||||
(format (or fmt "%s")
|
||||
(apply #'max (mapcar #'string-to-number values))))
|
||||
|
||||
(defun org-columns--summary-mean (values printf)
|
||||
(defun org-columns--summary-mean (values fmt)
|
||||
"Compute the mean of VALUES.
|
||||
When PRINTF is non-nil, use it to format the result."
|
||||
(format (or printf "%s")
|
||||
When FMT is non-nil, use it to format the result."
|
||||
(format (or fmt "%s")
|
||||
(/ (apply #'+ (mapcar #'string-to-number values))
|
||||
(float (length values)))))
|
||||
|
||||
|
|
@ -1600,7 +1642,7 @@ PARAMS is a property list of parameters:
|
|||
(funcall formatter (point) table params)))
|
||||
|
||||
(defun org-columns-dblock-write-default (ipos table params)
|
||||
"Write out a columnview table at position IPOS in the current buffer.
|
||||
"Write out a column view table at position IPOS in the current buffer.
|
||||
TABLE is a table with data as produced by `org-columns--capture-view'.
|
||||
PARAMS is the parameter property list obtained from the dynamic block
|
||||
definition."
|
||||
|
|
@ -1752,8 +1794,9 @@ definition."
|
|||
;; agenda buffer. Since current buffer is
|
||||
;; changing, we need to force the original
|
||||
;; compiled-fmt there.
|
||||
(let ((agenda-marker (point-marker)))
|
||||
(org-with-point-at m
|
||||
(org-columns--collect-values compiled-fmt)))
|
||||
(org-columns--collect-values compiled-fmt agenda-marker))))
|
||||
cache)))
|
||||
(forward-line))
|
||||
(when cache
|
||||
|
|
@ -1762,6 +1805,9 @@ definition."
|
|||
(when (setq-local org-columns-flyspell-was-active
|
||||
(bound-and-true-p flyspell-mode))
|
||||
(flyspell-mode 0))
|
||||
(when (setq-local org-columns-org-num-was-active
|
||||
(bound-and-true-p org-num-mode))
|
||||
(org-num-mode 0))
|
||||
(dolist (entry cache)
|
||||
(goto-char (car entry))
|
||||
(org-columns--display-here (cdr entry)))
|
||||
|
|
@ -1812,7 +1858,7 @@ This will add overlays to the date lines, to show the summary for each day."
|
|||
(line-end-position))))
|
||||
(list spec date date)))
|
||||
(`(,_ ,_ ,_ nil ,_) (list spec "" ""))
|
||||
(`(,_ ,_ ,_ ,operator ,printf)
|
||||
(`(,_ ,_ ,_ ,operator ,fmt)
|
||||
(let* ((summarize (org-columns--summarize operator))
|
||||
(values
|
||||
;; Use real values for summary, not
|
||||
|
|
@ -1823,7 +1869,7 @@ This will add overlays to the date lines, to show the summary for each day."
|
|||
(nth 1 (assoc spec e))))
|
||||
entries)))
|
||||
(final (if values
|
||||
(funcall summarize values printf)
|
||||
(funcall summarize values fmt)
|
||||
"")))
|
||||
(unless (equal final "")
|
||||
(put-text-property 0 (length final)
|
||||
|
|
|
|||
|
|
@ -61,13 +61,12 @@
|
|||
(declare-function org-element-contents-begin "org-element" (node))
|
||||
(declare-function org-element-contents-end "org-element" (node))
|
||||
(declare-function org-element-post-affiliated "org-element" (node))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading element))
|
||||
(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-fold-hide-block-toggle "org-fold" (&optional force no-error element))
|
||||
(declare-function org-link-display-format "ol" (s))
|
||||
(declare-function org-link-set-parameters "ol" (type &rest rest))
|
||||
(declare-function org-log-into-drawer "org" ())
|
||||
(declare-function org-make-tag-string "org" (tags))
|
||||
(declare-function org-next-visible-heading "org" (arg))
|
||||
(declare-function org-reduced-level "org" (l))
|
||||
|
|
@ -78,7 +77,6 @@
|
|||
(declare-function speedbar-line-directory "speedbar" (&optional depth))
|
||||
(declare-function table--at-cell-p "table" (position &optional object at-column))
|
||||
(declare-function ob-clojure-eval-with-cmd "ob-clojure" (cmd expanded))
|
||||
(declare-function org-fold-folded-p "org-fold" (&optional pos spec-or-alias))
|
||||
(declare-function org-fold-hide-sublevels "org-fold" (levels))
|
||||
(declare-function org-fold-hide-subtree "org-fold" ())
|
||||
(declare-function org-fold-region "org-fold" (from to flag &optional spec))
|
||||
|
|
@ -100,6 +98,19 @@
|
|||
(defvar org-table1-hline-regexp)
|
||||
(defvar org-fold-core-style)
|
||||
|
||||
|
||||
;;; Emacs < 31 compatibility
|
||||
(if (fboundp 'completion-table-with-metadata)
|
||||
(defalias 'org-completion-table-with-metadata #'completion-table-with-metadata)
|
||||
(defun org-completion-table-with-metadata (table metadata)
|
||||
"Return new completion TABLE with METADATA.
|
||||
METADATA should be an alist of completion metadata. See
|
||||
`completion-metadata' for a list of supported metadata."
|
||||
(lambda (string pred action)
|
||||
(if (eq action 'metadata)
|
||||
`(metadata . ,metadata)
|
||||
(complete-with-action action table string pred)))))
|
||||
|
||||
|
||||
;;; Emacs < 29 compatibility
|
||||
|
||||
|
|
@ -180,6 +191,33 @@ back to `window-text-pixel-size' otherwise."
|
|||
(set-window-buffer nil oldbuffer)
|
||||
(set-window-dedicated-p nil dedicatedp))))))
|
||||
|
||||
|
||||
(if (fboundp 'with-undo-amalgamate)
|
||||
(defalias 'org-with-undo-amalgamate 'with-undo-amalgamate)
|
||||
;; Copied from Emacs source.
|
||||
(defmacro org-with-undo-amalgamate (&rest body)
|
||||
"Like `progn' but perform BODY with amalgamated undo barriers.
|
||||
|
||||
This allows multiple operations to be undone in a single step.
|
||||
When undo is disabled this behaves like `progn'."
|
||||
(declare (indent 0) (debug t))
|
||||
(let ((handle (make-symbol "--change-group-handle--")))
|
||||
`(let ((,handle (prepare-change-group))
|
||||
;; Don't truncate any undo data in the middle of this,
|
||||
;; otherwise Emacs might truncate part of the resulting
|
||||
;; undo step: we want to mimic the behavior we'd get if the
|
||||
;; undo-boundaries were never added in the first place.
|
||||
(undo-outer-limit nil)
|
||||
(undo-limit most-positive-fixnum)
|
||||
(undo-strong-limit most-positive-fixnum))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(activate-change-group ,handle)
|
||||
,@body)
|
||||
(progn
|
||||
(accept-change-group ,handle)
|
||||
(undo-amalgamate-change-group ,handle)))))))
|
||||
|
||||
|
||||
;;; Emacs < 28.1 compatibility
|
||||
|
||||
|
|
@ -207,7 +245,7 @@ inserted before concatenating."
|
|||
(mapcar
|
||||
(lambda (str)
|
||||
(when (and str (not (seq-empty-p str))
|
||||
(string-match "\\(.+\\)/?" str))
|
||||
(string-match "\\(.+?\\)/?$" str))
|
||||
(match-string 1 str)))
|
||||
(cons directory components)))
|
||||
"/"))))
|
||||
|
|
@ -292,20 +330,16 @@ older than 27.1"
|
|||
(if tree (push tree elems))
|
||||
(nreverse elems))))
|
||||
|
||||
(defalias 'org-replace-region-contents
|
||||
(if (> emacs-major-version 30)
|
||||
#'replace-region-contents
|
||||
;; The `replace-region-contents' in Emacs<31 does not accept a buffer
|
||||
;; as SOURCE argument and does not preserve the position well enough.
|
||||
(lambda (beg end source &optional max-secs max-costs)
|
||||
(save-restriction
|
||||
(narrow-to-region beg end)
|
||||
(let ((eobp (eobp)))
|
||||
(with-no-warnings
|
||||
(if (< emacs-major-version 27)
|
||||
(replace-buffer-contents source)
|
||||
(replace-buffer-contents source max-secs max-costs)))
|
||||
(if eobp (goto-char (point-max))))))))
|
||||
(with-no-warnings ; `replace-buffer-contents' is obsolete in Emacs 31
|
||||
(cond
|
||||
((version< emacs-version "27.1")
|
||||
(defsubst org-replace-buffer-contents (source &optional _max-secs _max-costs)
|
||||
(replace-buffer-contents source)))
|
||||
((version< emacs-version "31")
|
||||
(defalias 'org-replace-buffer-contents #'replace-buffer-contents))
|
||||
(t
|
||||
(defsubst org-replace-buffer-contents (source &optional max-secs max-costs)
|
||||
(replace-region-contents (point-min) (point-max) source max-secs max-costs)))))
|
||||
|
||||
(unless (fboundp 'proper-list-p)
|
||||
;; `proper-list-p' was added in Emacs 27.1. The function below is
|
||||
|
|
@ -502,6 +536,8 @@ Counting starts at 1."
|
|||
(define-obsolete-function-alias 'org-string-match-p 'string-match-p "9.0")
|
||||
|
||||
;;;; Functions and variables from previous releases now obsolete.
|
||||
(define-obsolete-variable-alias 'org-edit-src-content-indentation
|
||||
'org-src-content-indentation "Org 9.8")
|
||||
(define-obsolete-variable-alias 'org-export-ignored-local-variables
|
||||
'org-element-ignored-local-variables "Org 9.7")
|
||||
(define-obsolete-function-alias 'org-habit-get-priority
|
||||
|
|
@ -718,19 +754,6 @@ This constant, for example, makes the below code not err:
|
|||
"use `org-element' library"
|
||||
"9.0")
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-let (list &rest body) ;FIXME: So many kittens are suffering here.
|
||||
(declare (indent 1) (obsolete cl-progv "2021"))
|
||||
(eval (cons 'let (cons list body))))
|
||||
|
||||
;; FIXME: Unused; obsoleted; to be removed.
|
||||
(defun org-let2 (list1 list2 &rest body) ;FIXME: Where did our karma go?
|
||||
(declare (indent 2) (obsolete cl-progv "2021"))
|
||||
(eval (cons 'let (cons list1 (list (cons 'let (cons list2 body)))))))
|
||||
|
||||
(make-obsolete 'org-let "to be removed" "9.6")
|
||||
(make-obsolete 'org-let2 "to be removed" "9.6")
|
||||
|
||||
(define-obsolete-function-alias 'org--math-always-on
|
||||
'org--math-p "9.7")
|
||||
|
||||
|
|
@ -1020,6 +1043,191 @@ use of this function is for the stuck project list."
|
|||
(define-obsolete-function-alias 'org-add-angle-brackets
|
||||
'org-link-add-angle-brackets "9.3")
|
||||
|
||||
(declare-function org-link-preview--remove-overlay "ol"
|
||||
(ov after beg end &optional len))
|
||||
(declare-function org-link-preview--get-overlays "ol" (&optional beg end))
|
||||
(declare-function org-link-preview-clear "ol" (&optional beg end))
|
||||
(declare-function org-link-preview--remove-overlay "ol"
|
||||
(ov after beg end &optional len))
|
||||
(declare-function org-attach-expand "org-attach" (file))
|
||||
(declare-function org-display-inline-image--width "ol" (link))
|
||||
(declare-function org-image--align "ol" (link))
|
||||
(declare-function org--create-inline-image "ol" (file width))
|
||||
|
||||
(define-obsolete-function-alias 'org-display-inline-remove-overlay
|
||||
'org-link-preview--remove-overlay "9.8")
|
||||
(define-obsolete-function-alias 'org--inline-image-overlays
|
||||
'org-link-preview--get-overlays "9.8")
|
||||
(define-obsolete-function-alias 'org-remove-inline-images
|
||||
'org-link-preview-clear "9.8")
|
||||
(define-obsolete-function-alias 'org-redisplay-inline-images
|
||||
'org-link-preview-refresh "9.8")
|
||||
(define-obsolete-variable-alias 'org-inline-image-overlays
|
||||
'org-link-preview-overlays "9.8")
|
||||
(defvar org-link-preview-overlays)
|
||||
(defvar org-link-abbrev-alist-local)
|
||||
(defvar org-link-abbrev-alist)
|
||||
(defvar org-link-angle-re)
|
||||
(defvar org-link-plain-re)
|
||||
|
||||
(make-obsolete 'org-display-inline-images
|
||||
'org-link-preview-region "9.8")
|
||||
;; FIXME: Unused; obsoleted; to be removed
|
||||
(defun org-display-inline-images (&optional include-linked refresh beg end)
|
||||
"Display inline images.
|
||||
|
||||
An inline image is a link which follows either of these
|
||||
conventions:
|
||||
|
||||
1. Its path is a file with an extension matching return value
|
||||
from `image-file-name-regexp' and it has no contents.
|
||||
|
||||
2. Its description consists in a single link of the previous
|
||||
type. In this case, that link must be a well-formed plain
|
||||
or angle link, i.e., it must have an explicit \"file\" or
|
||||
\"attachment\" type.
|
||||
|
||||
Equip each image with the key-map `image-map'.
|
||||
|
||||
When optional argument INCLUDE-LINKED is non-nil, also links with
|
||||
a text description part will be inlined. This can be nice for
|
||||
a quick look at those images, but it does not reflect what
|
||||
exported files will look like.
|
||||
|
||||
When optional argument REFRESH is non-nil, refresh existing
|
||||
images between BEG and END. This will create new image displays
|
||||
only if necessary.
|
||||
|
||||
BEG and END define the considered part. They default to the
|
||||
buffer boundaries with possible narrowing."
|
||||
(interactive "P")
|
||||
(when (display-graphic-p)
|
||||
(when refresh
|
||||
(org-link-preview-clear beg end)
|
||||
(when (fboundp 'clear-image-cache) (clear-image-cache)))
|
||||
(let ((end (or end (point-max))))
|
||||
(org-with-point-at (or beg (point-min))
|
||||
(let* ((case-fold-search t)
|
||||
(file-extension-re (image-file-name-regexp))
|
||||
(link-abbrevs (mapcar #'car
|
||||
(append org-link-abbrev-alist-local
|
||||
org-link-abbrev-alist)))
|
||||
;; Check absolute, relative file names and explicit
|
||||
;; "file:" links. Also check link abbreviations since
|
||||
;; some might expand to "file" links.
|
||||
(file-types-re
|
||||
(format "\\[\\[\\(?:file%s:\\|attachment:\\|[./~]\\)\\|\\]\\[\\(<?\\(?:file\\|attachment\\):\\)"
|
||||
(if (not link-abbrevs) ""
|
||||
(concat "\\|" (regexp-opt link-abbrevs))))))
|
||||
(while (re-search-forward file-types-re end t)
|
||||
(let* ((link (org-element-lineage
|
||||
(save-match-data (org-element-context))
|
||||
'link t))
|
||||
(linktype (org-element-property :type link))
|
||||
(inner-start (match-beginning 1))
|
||||
(path
|
||||
(cond
|
||||
;; No link at point; no inline image.
|
||||
((not link) nil)
|
||||
;; File link without a description. Also handle
|
||||
;; INCLUDE-LINKED here since it should have
|
||||
;; precedence over the next case. I.e., if link
|
||||
;; contains filenames in both the path and the
|
||||
;; description, prioritize the path only when
|
||||
;; INCLUDE-LINKED is non-nil.
|
||||
((or (not (org-element-contents-begin link))
|
||||
include-linked)
|
||||
(and (or (equal "file" linktype)
|
||||
(equal "attachment" linktype))
|
||||
(org-element-property :path link)))
|
||||
;; Link with a description. Check if description
|
||||
;; is a filename. Even if Org doesn't have syntax
|
||||
;; for those -- clickable image -- constructs, fake
|
||||
;; them, as in `org-export-insert-image-links'.
|
||||
((not inner-start) nil)
|
||||
(t
|
||||
(org-with-point-at inner-start
|
||||
(and (looking-at
|
||||
(if (char-equal ?< (char-after inner-start))
|
||||
org-link-angle-re
|
||||
org-link-plain-re))
|
||||
;; File name must fill the whole
|
||||
;; description.
|
||||
(= (org-element-contents-end link)
|
||||
(match-end 0))
|
||||
(progn
|
||||
(setq linktype (match-string 1))
|
||||
(match-string 2))))))))
|
||||
(when (and path (string-match-p file-extension-re path))
|
||||
(let ((file (if (equal "attachment" linktype)
|
||||
(progn
|
||||
(require 'org-attach)
|
||||
(ignore-errors (org-attach-expand path)))
|
||||
(expand-file-name path))))
|
||||
;; Expand environment variables.
|
||||
(when file (setq file (substitute-in-file-name file)))
|
||||
(when (and file (file-exists-p file))
|
||||
(let ((width (org-display-inline-image--width link))
|
||||
(align (org-image--align link))
|
||||
(old (get-char-property-and-overlay
|
||||
(org-element-begin link)
|
||||
'org-image-overlay)))
|
||||
(if (and (car-safe old) refresh)
|
||||
(image-flush (overlay-get (cdr old) 'display))
|
||||
(let ((image (org--create-inline-image file width)))
|
||||
(when image
|
||||
(let ((ov (make-overlay
|
||||
(org-element-begin link)
|
||||
(progn
|
||||
(goto-char
|
||||
(org-element-end link))
|
||||
(unless (eolp) (skip-chars-backward " \t"))
|
||||
(point)))))
|
||||
;; See bug#59902. We cannot rely
|
||||
;; on Emacs to update image if the file
|
||||
;; has changed.
|
||||
(image-flush image)
|
||||
(overlay-put ov 'display image)
|
||||
(overlay-put ov 'face 'default)
|
||||
(overlay-put ov 'org-image-overlay t)
|
||||
(overlay-put
|
||||
ov 'modification-hooks
|
||||
(list 'org-link-preview--remove-overlay))
|
||||
(when (boundp 'image-map)
|
||||
(overlay-put ov 'keymap image-map))
|
||||
(when align
|
||||
(overlay-put
|
||||
ov 'before-string
|
||||
(propertize
|
||||
" " 'face 'default
|
||||
'display
|
||||
(pcase align
|
||||
("center" `(space :align-to (- center (0.5 . ,image))))
|
||||
("right" `(space :align-to (- right ,image)))))))
|
||||
(push ov org-inline-image-overlays))))))))))))))))
|
||||
|
||||
(make-obsolete 'org-toggle-inline-images
|
||||
'org-link-preview "9.8")
|
||||
(declare-function org-link-preview-region "ol")
|
||||
;; FIXME: Unused; obsoleted; to be removed
|
||||
(defun org-toggle-inline-images (&optional include-linked beg end)
|
||||
"Toggle the display of inline images.
|
||||
INCLUDE-LINKED is passed to `org-display-inline-images'."
|
||||
(interactive "P")
|
||||
(if (org-link-preview--get-overlays beg end)
|
||||
(progn
|
||||
(org-link-preview-clear beg end)
|
||||
(when (called-interactively-p 'interactive)
|
||||
(message "Inline image display turned off")))
|
||||
(org-link-preview-region include-linked nil beg end)
|
||||
(when (called-interactively-p 'interactive)
|
||||
(let ((new (org-link-preview--get-overlays beg end)))
|
||||
(message (if new
|
||||
(format "%d images displayed inline"
|
||||
(length new))
|
||||
"No images to display inline"))))))
|
||||
|
||||
|
||||
;; The function was made obsolete by commit 65399674d5 of 2013-02-22.
|
||||
;; This make-obsolete call was added 2016-09-01.
|
||||
(make-obsolete 'org-capture-import-remember-templates
|
||||
|
|
@ -1032,7 +1240,7 @@ use of this function is for the stuck project list."
|
|||
(org-fold-show-all '(blocks)))
|
||||
|
||||
(make-obsolete 'org-show-block-all
|
||||
"use `org-show-all' instead."
|
||||
"use `org-fold-show-all' instead."
|
||||
"9.2")
|
||||
|
||||
(define-obsolete-function-alias 'org-get-tags-at 'org-get-tags "9.2")
|
||||
|
|
@ -1071,7 +1279,7 @@ When optional argument ELEMENT is a parsed drawer, as returned by
|
|||
|
||||
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." "9.4"))
|
||||
(declare (obsolete "use `org-fold-hide-drawer-toggle' instead." "9.4"))
|
||||
(if (and beg end) (org-fold-region beg end flag 'drawer)
|
||||
(let ((drawer
|
||||
(or element
|
||||
|
|
@ -1094,9 +1302,9 @@ region as a drawer without further ado."
|
|||
|
||||
(defun org-hide-block-toggle-maybe ()
|
||||
"Toggle visibility of block at point.
|
||||
Unlike to `org-hide-block-toggle', this function does not throw
|
||||
Unlike to `org-fold-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." "9.4"))
|
||||
(declare (obsolete "use `org-fold-hide-block-toggle' instead." "9.4"))
|
||||
(interactive)
|
||||
(org-fold-hide-block-toggle nil t))
|
||||
|
||||
|
|
@ -1468,8 +1676,8 @@ This also applied for speedbar access."
|
|||
(let* ((m (point-marker))
|
||||
(item (propertize headline 'org-imenu-marker m 'org-imenu t)))
|
||||
(push m org-imenu-markers)
|
||||
(if (>= level last-level)
|
||||
(push (cons item m) (aref subs level))
|
||||
(unless (>= level last-level)
|
||||
(push (cons item
|
||||
(cl-mapcan #'identity (cl-subseq subs (1+ level))))
|
||||
(aref subs level))
|
||||
|
|
@ -1567,19 +1775,21 @@ ELEMENT is the element at point."
|
|||
(when (looking-at-p "\\>") (backward-char))
|
||||
(org-element-context element))))
|
||||
(cl-case (org-element-type object)
|
||||
;; Prevent checks in links due to keybinding conflict with
|
||||
;; Flyspell.
|
||||
((citation citation-reference code entity export-snippet inline-babel-call
|
||||
inline-src-block line-break latex-fragment link macro
|
||||
inline-src-block line-break latex-fragment macro
|
||||
statistics-cookie target timestamp verbatim)
|
||||
nil)
|
||||
(link
|
||||
;; Only check link description
|
||||
(when-let* ((cbeg (org-element-contents-begin object))
|
||||
(cend (org-element-contents-end object)))
|
||||
(<= cbeg (point) cend)))
|
||||
(footnote-reference
|
||||
;; Only in inline footnotes, within the definition.
|
||||
(and (eq (org-element-property :type object) 'inline)
|
||||
(< (save-excursion
|
||||
(goto-char (org-element-begin object))
|
||||
(search-forward ":" nil t 2))
|
||||
(point))))
|
||||
(<= (org-element-contents-begin object)
|
||||
(point)
|
||||
(org-element-contents-end object))))
|
||||
(otherwise t))))
|
||||
|
||||
(defun org-mode-flyspell-verify ()
|
||||
|
|
@ -1607,14 +1817,6 @@ ELEMENT is the element at point."
|
|||
(let ((case-fold-search t)) (looking-at "[ \t]*#\\+CAPTION:")))
|
||||
(> (point) (match-end 0))
|
||||
(org--flyspell-object-check-p element)))
|
||||
;; Ignore checks in LOGBOOK (or equivalent) drawer.
|
||||
((let ((log (org-log-into-drawer)))
|
||||
(and log
|
||||
(let ((drawer (org-element-lineage element 'drawer)))
|
||||
(and drawer
|
||||
(org-string-equal-ignore-case
|
||||
log (org-element-property :drawer-name drawer))))))
|
||||
nil)
|
||||
(t
|
||||
(cl-case (org-element-type element)
|
||||
((comment quote-section) t)
|
||||
|
|
@ -1730,7 +1932,7 @@ key."
|
|||
;;;; Simple
|
||||
|
||||
(defun org-mark-jump-unhide (&rest _)
|
||||
"Make the point visible with `org-show-context' after jumping to the mark."
|
||||
"Make the point visible with `org-fold-show-context' after jumping to the mark."
|
||||
(when (and (derived-mode-p 'org-mode)
|
||||
(org-invisible-p))
|
||||
(org-fold-show-context 'mark-goto)))
|
||||
|
|
@ -1780,7 +1982,7 @@ key."
|
|||
(or (re-search-backward (concat "^\\(?:" outline-regexp "\\)")
|
||||
nil t)
|
||||
(signal 'outline-before-first-heading nil))
|
||||
(setq found (and (or invisible-ok (not (org-fold-folded-p)))
|
||||
(setq found (and (or invisible-ok (not (org-invisible-p)))
|
||||
(point)))))
|
||||
(goto-char found)
|
||||
found)))
|
||||
|
|
@ -1809,7 +2011,7 @@ key."
|
|||
(if (derived-mode-p 'org-mode)
|
||||
(save-excursion
|
||||
(org-back-to-heading)
|
||||
(if (not (org-fold-folded-p (line-end-position)))
|
||||
(if (not (org-invisible-p (line-end-position)))
|
||||
(org-fold-hide-subtree)
|
||||
(org-fold-show-children)
|
||||
(org-fold-show-entry 'hide-drawers)))
|
||||
|
|
@ -1825,6 +2027,26 @@ key."
|
|||
"configure `org-speed-commands' instead." "9.5")
|
||||
(provide 'org-compat)
|
||||
|
||||
;;;; yank-media
|
||||
;; Emacs 29's pgtk port has a bug where it might fail to return the
|
||||
;; right TARGET. Install a workaround for Emacs <=29 since the fix
|
||||
;; went to Emacs 30. See bug#72254.
|
||||
;; Org bug report link: https://list.orgmode.org/orgmode/87ed7kttoa.fsf@k-7.ch
|
||||
;; This should be removed once we drop Emacs 29 support.
|
||||
(when (and (fboundp 'pgtk-get-selection-internal)
|
||||
(<= emacs-major-version 29))
|
||||
;; Only define the method if it hasn't been previously defined.
|
||||
(unless (cl-find-method 'gui-backend-get-selection nil
|
||||
'((eql 'CLIPBOARD) (eql 'TARGETS)
|
||||
((&context . window-system) eql 'pgtk)))
|
||||
(cl-defmethod gui-backend-get-selection ((selection-symbol (eql 'CLIPBOARD))
|
||||
(target-type (eql 'TARGETS))
|
||||
&context (window-system pgtk))
|
||||
(let ((sel (pgtk-get-selection-internal selection-symbol target-type)))
|
||||
(if (vectorp sel)
|
||||
sel
|
||||
(vector sel))))))
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@
|
|||
(declare-function org-make-tags-matcher "org" (match &optional only-local-tags))
|
||||
(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))
|
||||
(declare-function org-cycle-set-startup-visibility "org-cycle" ())
|
||||
|
||||
(defgroup org-crypt nil
|
||||
|
|
|
|||
|
|
@ -40,27 +40,27 @@
|
|||
(declare-function org-element-post-affiliated "org-element" (node))
|
||||
(declare-function org-element-lineage "org-element-ast" (datum &optional types with-self))
|
||||
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
|
||||
(declare-function org-display-inline-images "org" (&optional include-linked refresh beg end))
|
||||
(declare-function org-get-tags "org" (&optional pos local fontify))
|
||||
(declare-function org-link-preview-region "ol" (&optional include-linked refresh beg end))
|
||||
(declare-function org-get-tags "org" (&optional epom local))
|
||||
(declare-function org-subtree-end-visible-p "org" ())
|
||||
(declare-function org-narrow-to-subtree "org" (&optional element))
|
||||
(declare-function org-next-visible-heading "org" (arg))
|
||||
(declare-function org-at-property-p "org" ())
|
||||
(declare-function org-re-property "org" (property &optional literal allow-null value))
|
||||
(declare-function org-remove-inline-images "org" (&optional beg end))
|
||||
(declare-function org-item-beginning-re "org" ())
|
||||
(declare-function org-link-preview-clear "ol" (&optional beg end))
|
||||
(declare-function org-item-beginning-re "org-list" ())
|
||||
(declare-function org-at-heading-p "org" (&optional invisible-not-ok))
|
||||
(declare-function org-at-item-p "org" ())
|
||||
(declare-function org-at-item-p "org-list" ())
|
||||
(declare-function org-before-first-heading-p "org" ())
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading element))
|
||||
(declare-function org-entry-end-position "org" ())
|
||||
(declare-function org-try-cdlatex-tab "org" ())
|
||||
(declare-function org-cycle-level "org" ())
|
||||
(declare-function org-table-next-field "org-table" ())
|
||||
(declare-function org-table-justify-field-maybe "org-table" (&optional new))
|
||||
(declare-function org-inlinetask-at-task-p "org-inlinetask" ())
|
||||
(declare-function org-inlinetask-toggle-visibility "org-inlinetask" ())
|
||||
(declare-function org-inlinetask-toggle-visibility "org-inlinetask" (&optional state))
|
||||
(declare-function org-list-get-all-items "org-list" (item struct prevs))
|
||||
(declare-function org-list-get-bottom-point "org-list" (struct))
|
||||
(declare-function org-list-prevs-alist "org-list" (struct))
|
||||
|
|
@ -71,7 +71,6 @@
|
|||
(declare-function org-list-struct "org-list" ())
|
||||
(declare-function org-cycle-item-indentation "org-list" ())
|
||||
|
||||
(declare-function outline-previous-heading "outline" ())
|
||||
(declare-function outline-next-heading "outline" ())
|
||||
(declare-function outline-end-of-heading "outline" ())
|
||||
(declare-function outline-up-heading "outline" (arg &optional invisible-ok))
|
||||
|
|
@ -217,7 +216,7 @@ the values `folded', `children', or `subtree'."
|
|||
(defcustom org-cycle-hook '(org-cycle-hide-archived-subtrees
|
||||
org-cycle-show-empty-lines
|
||||
org-cycle-optimize-window-after-visibility-change
|
||||
org-cycle-display-inline-images)
|
||||
org-cycle-display-link-previews)
|
||||
"Hook that is run after `org-cycle' has changed the buffer visibility.
|
||||
The function(s) in this hook must accept a single argument which indicates
|
||||
the new state that was set by the most recent `org-cycle' command. The
|
||||
|
|
@ -237,12 +236,17 @@ normal outline commands like `show-all', but not with the cycling commands."
|
|||
:group 'org-cycle
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom org-cycle-inline-images-display nil
|
||||
"Non-nil means auto display inline images under subtree when cycling."
|
||||
(defvaralias 'org-cycle-inline-images-display
|
||||
'org-cycle-link-previews-display
|
||||
"Non-nil means auto display inline images under subtree when cycling.")
|
||||
|
||||
(defcustom org-cycle-link-previews-display nil
|
||||
"Non-nil means auto display link previews under subtree when cycling."
|
||||
:group 'org-startup
|
||||
:group 'org-cycle
|
||||
:package-version '(Org . "9.6")
|
||||
:type 'boolean)
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'boolean
|
||||
:safe #'booleanp)
|
||||
|
||||
(defvaralias 'org-tab-first-hook 'org-cycle-tab-first-hook)
|
||||
(defvar org-cycle-tab-first-hook nil
|
||||
|
|
@ -514,7 +518,7 @@ Use `\\[org-edit-special]' to edit table.el tables"))
|
|||
(forward-line 1)
|
||||
(if (eq org-fold-core-style 'text-properties)
|
||||
(while (and (not (eobp)) ;this is like `next-line'
|
||||
(org-fold-folded-p (1- (point))))
|
||||
(org-invisible-p (1- (point))))
|
||||
(goto-char (org-fold-next-visibility-change nil nil t))
|
||||
(and (eolp) (forward-line 1)))
|
||||
(while (and (not (eobp)) ;this is like `next-line'
|
||||
|
|
@ -745,7 +749,9 @@ symbols `content', `all', `folded', `children', or `subtree'."
|
|||
The region to be covered depends on STATE when called through
|
||||
`org-cycle-hook'. Lisp program can use t for STATE to get the
|
||||
entire buffer covered. Note that an empty line is only shown if there
|
||||
are at least `org-cycle-separator-lines' empty lines before the headline."
|
||||
are at least `org-cycle-separator-lines' empty lines before the headline.
|
||||
|
||||
Always show empty lines at the end of file."
|
||||
(when (/= org-cycle-separator-lines 0)
|
||||
(save-excursion
|
||||
(let* ((n (abs org-cycle-separator-lines))
|
||||
|
|
@ -778,11 +784,8 @@ are at least `org-cycle-separator-lines' empty lines before the headline."
|
|||
;; Never hide empty lines at the end of the file.
|
||||
(save-excursion
|
||||
(goto-char (point-max))
|
||||
(outline-previous-heading)
|
||||
(outline-end-of-heading)
|
||||
(when (and (looking-at "[ \t\n]+")
|
||||
(= (match-end 0) (point-max)))
|
||||
(org-fold-region (point) (match-end 0) nil 'outline))))
|
||||
(skip-chars-backward " \t\n")
|
||||
(org-fold-region (point) (point-max) nil 'outline)))
|
||||
|
||||
(defun org-cycle-hide-archived-subtrees (state)
|
||||
"Re-hide all archived subtrees after a visibility state change.
|
||||
|
|
@ -804,12 +807,15 @@ STATE should be one of the symbols listed in the docstring of
|
|||
"Subtree is archived and stays closed. Use \
|
||||
`\\[org-cycle-force-archived]' to cycle it anyway."))))))
|
||||
|
||||
(defun org-cycle-display-inline-images (state)
|
||||
(defalias 'org-cycle-inline-images-display
|
||||
'org-cycle-display-link-previews)
|
||||
|
||||
(defun org-cycle-display-link-previews (state)
|
||||
"Auto display inline images under subtree when cycling.
|
||||
It works when `org-cycle-inline-images-display' is non-nil.
|
||||
It works when `org-cycle-link-previews-display' is non-nil.
|
||||
STATE is the current outline visibility state. It should be one of
|
||||
symbols `content', `all', `folded', `children', or `subtree'."
|
||||
(when org-cycle-inline-images-display
|
||||
(when org-cycle-link-previews-display
|
||||
(pcase state
|
||||
('children
|
||||
(org-with-wide-buffer
|
||||
|
|
@ -817,19 +823,19 @@ symbols `content', `all', `folded', `children', or `subtree'."
|
|||
;; If has nested headlines, beg,end only from parent headline
|
||||
;; to first child headline which reference to upper
|
||||
;; let-binding `org-next-visible-heading'.
|
||||
(org-display-inline-images
|
||||
(org-link-preview-region
|
||||
nil nil
|
||||
(point-min) (progn (org-next-visible-heading 1) (point)))))
|
||||
('subtree
|
||||
(org-with-wide-buffer
|
||||
(org-narrow-to-subtree)
|
||||
;; If has nested headlines, also inline display images under all sub-headlines.
|
||||
(org-display-inline-images nil nil (point-min) (point-max))))
|
||||
(org-link-preview-region nil nil (point-min) (point-max))))
|
||||
('folded
|
||||
(org-with-wide-buffer
|
||||
(org-narrow-to-subtree)
|
||||
(if (numberp (point-max))
|
||||
(org-remove-inline-images (point-min) (point-max))
|
||||
(org-link-preview-clear (point-min) (point-max))
|
||||
(ignore)))))))
|
||||
|
||||
(provide 'org-cycle)
|
||||
|
|
|
|||
|
|
@ -24,23 +24,20 @@
|
|||
;;
|
||||
;;; Commentary:
|
||||
|
||||
;; This file contains code to create entries in a tree where the top-level
|
||||
;; nodes represent years, the level 2 nodes represent the months, and the
|
||||
;; level 1 entries days.
|
||||
;; This file contains code to create entries in a tree where the
|
||||
;; top-level nodes represent years, the level 2 nodes represent the
|
||||
;; months, and the level 1 entries days. It also implements
|
||||
;; extensions to the datetree that allow for other levels such as
|
||||
;; quarters and weeks.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'org-macs)
|
||||
(org-assert-version)
|
||||
|
||||
(require 'cal-iso)
|
||||
(require 'org)
|
||||
|
||||
(defvar org-datetree-base-level 1
|
||||
"The level at which years should be placed in the date tree.
|
||||
This is normally one, but if the buffer has an entry with a
|
||||
DATE_TREE (or WEEK_TREE for ISO week entries) property (any
|
||||
value), the date tree will become a subtree under that entry, so
|
||||
the base level will be properly adjusted.")
|
||||
(require 'org-element)
|
||||
|
||||
(defcustom org-datetree-add-timestamp nil
|
||||
"When non-nil, add a time stamp matching date of entry.
|
||||
|
|
@ -59,174 +56,264 @@ 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 'day keep-restriction))
|
||||
(org-datetree-find-create-entry '(year month day) d 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.
|
||||
entries grouped by year-month instead of year-month-day.
|
||||
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)
|
||||
(save-restriction
|
||||
(if (eq keep-restriction 'subtree-at-point)
|
||||
(progn
|
||||
(unless (org-at-heading-p) (error "Not at heading"))
|
||||
(widen)
|
||||
(org-narrow-to-subtree)
|
||||
(setq-local org-datetree-base-level
|
||||
(org-get-valid-level (org-current-level) 1)))
|
||||
(unless keep-restriction (widen))
|
||||
;; Support the old way of tree placement, using a property
|
||||
(let ((prop (org-find-property "DATE_TREE")))
|
||||
(when prop
|
||||
(goto-char prop)
|
||||
(setq-local org-datetree-base-level
|
||||
(org-get-valid-level (org-current-level) 1))
|
||||
(org-narrow-to-subtree))))
|
||||
(goto-char (point-min))
|
||||
(let ((year (calendar-extract-year d))
|
||||
(month (calendar-extract-month d))
|
||||
(day (calendar-extract-day d)))
|
||||
(org-datetree--find-create
|
||||
"\\([12][0-9]\\{3\\}\\)"
|
||||
year nil nil nil t)
|
||||
(org-datetree--find-create
|
||||
"%d-\\([01][0-9]\\) \\w+"
|
||||
year month nil nil t)
|
||||
(when (eq time-grouping 'day)
|
||||
(org-datetree--find-create
|
||||
"%d-%02d-\\([0123][0-9]\\) \\w+"
|
||||
year month day nil t)))))
|
||||
(org-datetree-find-create-entry '(year month) d keep-restriction))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-datetree-find-iso-week-create (d &optional keep-restriction)
|
||||
"Find or create an ISO week entry for date D.
|
||||
Compared to `org-datetree-find-date-create' this function creates
|
||||
entries ordered by week instead of months.
|
||||
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."
|
||||
(setq-local org-datetree-base-level 1)
|
||||
(save-restriction
|
||||
(if (eq keep-restriction 'subtree-at-point)
|
||||
(progn
|
||||
(unless (org-at-heading-p) (error "Not at heading"))
|
||||
(widen)
|
||||
(org-narrow-to-subtree)
|
||||
(setq-local org-datetree-base-level
|
||||
(org-get-valid-level (org-current-level) 1)))
|
||||
(unless keep-restriction (widen))
|
||||
;; Support the old way of tree placement, using a property
|
||||
(let ((prop (org-find-property "WEEK_TREE")))
|
||||
(when prop
|
||||
(goto-char prop)
|
||||
(setq-local org-datetree-base-level
|
||||
(org-get-valid-level (org-current-level) 1))
|
||||
(org-narrow-to-subtree))))
|
||||
(goto-char (point-min))
|
||||
(require 'cal-iso)
|
||||
entries grouped by year-week-day instead of year-month-day. 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-entry '(year week day) d keep-restriction))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-datetree-find-create-entry
|
||||
(time-grouping d &optional keep-restriction)
|
||||
"Find or create an entry for date D.
|
||||
Moves point to the beginning of the entry.
|
||||
|
||||
TIME-GROUPING specifies the grouping levels of the datetree, and
|
||||
should be a subset of `(year quarter month week day)'. Weeks are
|
||||
assigned to years according to ISO-8601. If TIME-GROUPING
|
||||
contains both `month' and `week', then weeks are assigned to the
|
||||
month containing Thursday, for consistency with the ISO-8601
|
||||
year-week rule. If TIME-GROUPING contains `quarter' and `week'
|
||||
but not `month', quarters are defined as 13-week periods;
|
||||
otherwise they are defined as 3-month periods.
|
||||
|
||||
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.
|
||||
|
||||
If `org-datetree-add-timestamp' is non-nil and TIME-GROUPING
|
||||
includes `day' and a new entry is created, adds a time stamp
|
||||
after the new headline."
|
||||
(when-let* ((setdiff (seq-difference time-grouping
|
||||
'(year quarter month week day))))
|
||||
(error (format "Unrecognized datetree grouping elements %s" setdiff)))
|
||||
(let* ((year (calendar-extract-year d))
|
||||
(month (calendar-extract-month d))
|
||||
(day (calendar-extract-day d))
|
||||
(time (org-encode-time 0 0 0 day month year))
|
||||
(iso-date (calendar-iso-from-absolute
|
||||
(calendar-absolute-from-gregorian d)))
|
||||
(weekyear (nth 2 iso-date))
|
||||
(week (nth 0 iso-date)))
|
||||
;; ISO 8601 week format is %G-W%V(-%u)
|
||||
(org-datetree--find-create
|
||||
"\\([12][0-9]\\{3\\}\\)"
|
||||
weekyear nil nil (format-time-string "%G" time) t)
|
||||
(org-datetree--find-create
|
||||
"%d-W\\([0-5][0-9]\\)"
|
||||
weekyear week nil (format-time-string "%G-W%V" time) t)
|
||||
;; For the actual day we use the regular date instead of ISO week.
|
||||
(org-datetree--find-create
|
||||
"%d-%02d-\\([0123][0-9]\\) \\w+" year month day nil t))))
|
||||
|
||||
(defun org-datetree--find-create
|
||||
(regex-template year &optional month day insert match-title)
|
||||
"Find the datetree matched by REGEX-TEMPLATE for YEAR, MONTH, or DAY.
|
||||
REGEX-TEMPLATE is passed to `format' with YEAR, MONTH, and DAY as
|
||||
arguments.
|
||||
|
||||
If MATCH-TITLE is non-nil, REGEX-TEMPLATE is matched against
|
||||
heading title and the exact regexp matched against heading line is:
|
||||
|
||||
(format org-complex-heading-regexp-format
|
||||
(format regex-template year month day))
|
||||
|
||||
If MATCH-TITLE is nil, the regexp matched against heading line is
|
||||
REGEX-TEMPLATE:
|
||||
|
||||
(format regex-template year month day)
|
||||
|
||||
Match group 1 in REGEX-TEMPLATE is compared against the specified date
|
||||
component. If INSERT is non-nil and there is no match then it is
|
||||
inserted into the buffer."
|
||||
(when (or month day)
|
||||
(org-narrow-to-subtree))
|
||||
;; ensure that the first match group in REGEX-TEMPLATE
|
||||
;; is the first inside `org-complex-heading-regexp-format'
|
||||
(when (and match-title
|
||||
(not (string-match-p "\\\\(\\?1:" regex-template))
|
||||
(string-match "\\\\(" regex-template))
|
||||
(setq regex-template (replace-match "\\(?1:" nil t regex-template)))
|
||||
(let ((re (if match-title
|
||||
(format org-complex-heading-regexp-format
|
||||
(format regex-template year month day))
|
||||
(format regex-template year month day)))
|
||||
match)
|
||||
(goto-char (point-min))
|
||||
(while (and (setq match (re-search-forward re nil t))
|
||||
(goto-char (match-beginning 1))
|
||||
(< (string-to-number (match-string 1)) (or day month year))))
|
||||
(week (nth 0 iso-date))
|
||||
(nominal-year
|
||||
(if (memq 'week time-grouping)
|
||||
(nth 2 iso-date)
|
||||
year))
|
||||
(nominal-month
|
||||
(if (memq 'week time-grouping)
|
||||
(calendar-extract-month
|
||||
;; anchor on Thurs, to be consistent with weekyear
|
||||
(calendar-gregorian-from-absolute
|
||||
(calendar-iso-to-absolute
|
||||
`(,week 4 ,nominal-year))))
|
||||
month))
|
||||
(quarter (if (and (memq 'week time-grouping)
|
||||
(not (memq 'month time-grouping)))
|
||||
(min 4 (1+ (/ (1- week) 13)))
|
||||
(1+ (/ (1- nominal-month) 3))))
|
||||
(found-p
|
||||
(org-datetree-find-create-hierarchy
|
||||
(append
|
||||
(when (memq 'year time-grouping)
|
||||
(list (list (number-to-string nominal-year)
|
||||
(org-datetree-comparefun-from-regex
|
||||
"\\([12][0-9]\\{3\\}\\)"))))
|
||||
(when (memq 'quarter time-grouping)
|
||||
(list (list (format "%d-Q%d" nominal-year quarter)
|
||||
(org-datetree-comparefun-from-regex
|
||||
"\\([12][0-9]\\{3\\}-Q[1-4]\\)"))))
|
||||
(when (memq 'month time-grouping)
|
||||
(list (list (format-time-string
|
||||
"%Y-%m %B" (org-encode-time 0 0 0 1 nominal-month
|
||||
nominal-year))
|
||||
(org-datetree-comparefun-from-regex
|
||||
"\\([12][0-9]\\{3\\}-[01][0-9]\\) \\w+"))))
|
||||
(when (memq 'week time-grouping)
|
||||
(list (list (format-time-string "%G-W%V" time)
|
||||
(org-datetree-comparefun-from-regex
|
||||
"\\([12][0-9]\\{3\\}-W[0-5][0-9]\\)"))))
|
||||
(when (memq 'day time-grouping)
|
||||
;; Use regular date instead of ISO-week year/month
|
||||
(list (list (format-time-string
|
||||
"%Y-%m-%d %A" (org-encode-time 0 0 0 day month year))
|
||||
(org-datetree-comparefun-from-regex
|
||||
"\\([12][0-9]\\{3\\}-[01][0-9]-[0123][0-9]\\) \\w+")))))
|
||||
keep-restriction
|
||||
;; Support the old way of tree placement, using a property
|
||||
(cond
|
||||
((not match)
|
||||
(goto-char (point-max))
|
||||
(unless (bolp) (insert "\n"))
|
||||
(org-datetree-insert-line year month day insert))
|
||||
((= (string-to-number (match-string 1)) (or day month year))
|
||||
(forward-line 0))
|
||||
(t
|
||||
(forward-line 0)
|
||||
(org-datetree-insert-line year month day insert)))))
|
||||
|
||||
(defun org-datetree-insert-line (year &optional month day text)
|
||||
(delete-region (save-excursion (skip-chars-backward " \t\n") (point)) (point))
|
||||
(when (org--blank-before-heading-p) (insert "\n"))
|
||||
(insert "\n" (make-string org-datetree-base-level ?*) " \n")
|
||||
(backward-char)
|
||||
(when month (org-do-demote))
|
||||
(when day (org-do-demote))
|
||||
(if text
|
||||
(insert text)
|
||||
(insert (format "%d" year))
|
||||
(when month
|
||||
(insert
|
||||
(if day
|
||||
(format-time-string "-%m-%d %A" (org-encode-time 0 0 0 day month year))
|
||||
(format-time-string "-%m %B" (org-encode-time 0 0 0 1 month year))))))
|
||||
(when (and day org-datetree-add-timestamp)
|
||||
((seq-set-equal-p time-grouping '(year month day))
|
||||
"DATE_TREE")
|
||||
((seq-set-equal-p time-grouping '(year month))
|
||||
"DATE_TREE")
|
||||
((seq-set-equal-p time-grouping '(year week day))
|
||||
"WEEK_TREE")))))
|
||||
(when (memq 'day time-grouping)
|
||||
(when (and (not found-p) org-datetree-add-timestamp)
|
||||
(save-excursion
|
||||
(end-of-line)
|
||||
(insert "\n")
|
||||
(org-indent-line)
|
||||
(org-insert-timestamp
|
||||
(org-encode-time 0 0 0 day month year)
|
||||
nil
|
||||
(eq org-datetree-add-timestamp 'inactive))))
|
||||
(forward-line 0))
|
||||
(eq org-datetree-add-timestamp 'inactive)))))))
|
||||
|
||||
(defun org-datetree-comparefun-from-regex (sibling-regex)
|
||||
"Construct comparison function based on regular expression.
|
||||
The generated comparison function can be used with
|
||||
`org-datetree-find-create-hierarchy'. SIBLING-REGEX should be a
|
||||
regex that matches the headline and its siblings, with 1 match
|
||||
group. Headlines are compared by the lexicographic ordering of
|
||||
match group 1. The generated function returns -1 if the first
|
||||
argument is earlier, 1 if later, 0 if equal, or nil if either
|
||||
argument doesn't match."
|
||||
(lambda (sibling-title new-title)
|
||||
(let ((target-match (and (string-match sibling-regex new-title)
|
||||
(match-string 1 new-title)))
|
||||
(sibling-match (and (string-match sibling-regex sibling-title)
|
||||
(match-string 1 sibling-title))))
|
||||
(cond
|
||||
((not (and target-match sibling-match)) nil)
|
||||
((string< sibling-match target-match) -1)
|
||||
((string> sibling-match target-match) 1)
|
||||
(t 0)))))
|
||||
|
||||
(defun org-datetree-find-create-hierarchy
|
||||
(hier-pairs &optional keep-restriction legacy-prop)
|
||||
"Find or create entry in datetree using the full date hierarchy.
|
||||
Moves point to the beginning of the entry. Returns non-nil if an
|
||||
existing entry was found, or nil if a new entry was created.
|
||||
|
||||
HIER-PAIRS is a list whose first entry corresponds to the outermost element
|
||||
(e.g. year) and last entry corresponds to the innermost (e.g. day).
|
||||
Each entry of the list is a pair, the car is the headline for that level
|
||||
(e.g. \"2024\" or \"2024-12-28 Saturday\"), and the cadr is a
|
||||
string comparison function for sorting each headline among its
|
||||
siblings. The comparison function should take 2 arguments,
|
||||
corresponding to the titles of 2 headlines, and return a negative
|
||||
number if the first headline is earlier, a positive number if the
|
||||
second headline is earlier, 0 or t if the headlines are at the
|
||||
same time, or `nil' if a headline isn't a valid datetree
|
||||
subheading. For example, HIER-PAIRS could look like
|
||||
|
||||
((\"2024\" compare-year-fun)
|
||||
(\"2024-12 December\" compare-month-fun)
|
||||
(\"2024-12-28 Saturday\" compare-day-fun))
|
||||
|
||||
where compare-month-fun would be some function where
|
||||
(compare-month-fun \"2024-11 November\" \"2024-12 December\") is
|
||||
negative, and (compare-month-fun \"2024-12-December\" \"Potato\")
|
||||
is nil. One way to construct such a comparison function is with
|
||||
`org-datetree-comparefun-from-regex'.
|
||||
|
||||
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.
|
||||
|
||||
If LEGACY-PROP is non-nil, the tree is located by searching for a
|
||||
headline with property LEGACY-PROP, supporting the old way of
|
||||
tree placement via a property."
|
||||
(let ((level 1)
|
||||
found-p)
|
||||
(save-restriction
|
||||
;; get the datetree base and narrow to it
|
||||
(if (eq keep-restriction 'subtree-at-point)
|
||||
(progn
|
||||
(unless (org-at-heading-p) (error "Not at heading"))
|
||||
(widen)
|
||||
(org-narrow-to-subtree)
|
||||
(setq level (org-get-valid-level (org-current-level) 1)))
|
||||
(unless keep-restriction (widen))
|
||||
;; Support the old way of tree placement, using a property
|
||||
(let ((prop (and legacy-prop (org-find-property legacy-prop))))
|
||||
(when prop
|
||||
(progn
|
||||
(goto-char prop)
|
||||
(org-narrow-to-subtree)
|
||||
(setq level (org-get-valid-level (org-current-level) 1))))))
|
||||
(cl-loop
|
||||
for pair in hier-pairs
|
||||
do
|
||||
(setq found-p (org-datetree--find-create-subheading
|
||||
(cadr pair) (car pair) level))
|
||||
(setq level (1+ level))))
|
||||
found-p))
|
||||
|
||||
(defun org-datetree--find-create-subheading
|
||||
(compare-fun new-title level)
|
||||
"Find datetree subheading, or create it if it doesn't exist.
|
||||
After insertion, move point to beginning of the subheading, and
|
||||
narrow to its subtree. Returns non-nil if the heading was found,
|
||||
or nil if a new heading was created.
|
||||
|
||||
NEW-TITLE is the title of the subheading to be found or created.
|
||||
LEVEL is the level of the headline to be found or created.
|
||||
COMPARE-FUN is a function of 2 arguments for comparing headline
|
||||
titles; it should return a negative number if the first headline
|
||||
precedes the second, a positive number if the second number has
|
||||
precedence, 0 or t if the headlines are at the same time, and nil
|
||||
if a headline isn't a valid datetree subheading at this level."
|
||||
(let* ((nstars (if org-odd-levels-only (1- (* 2 level)) level))
|
||||
(heading-re (format "^\\*\\{%d\\}" nstars))
|
||||
(sibling (car (org-element-cache-map
|
||||
(lambda (d)
|
||||
(when (= (org-element-property :level d) level)
|
||||
(let ((compare-result
|
||||
(funcall compare-fun
|
||||
(org-element-property :raw-value d)
|
||||
new-title)))
|
||||
(and compare-result
|
||||
(or (eq compare-result t) (>= compare-result 0))
|
||||
d))))
|
||||
:granularity 'headline
|
||||
:restrict-elements '(headline)
|
||||
:next-re heading-re
|
||||
:fail-re heading-re
|
||||
:narrow t
|
||||
:limit-count 1))))
|
||||
;; go to headline, or first successor sibling, or end of buffer
|
||||
(if sibling
|
||||
(goto-char (org-element-property :begin sibling))
|
||||
(goto-char (point-max))
|
||||
(unless (bolp) (insert "\n")))
|
||||
(if (and sibling
|
||||
(memq (funcall compare-fun
|
||||
(org-element-property :raw-value sibling)
|
||||
new-title)
|
||||
'(0 t)))
|
||||
;; narrow and return the matched headline
|
||||
(progn
|
||||
(org-narrow-to-subtree)
|
||||
t)
|
||||
;; insert new headline, narrow, and return it
|
||||
(delete-region (save-excursion (skip-chars-backward " \t\n") (point)) (point))
|
||||
(when (org--blank-before-heading-p) (insert "\n"))
|
||||
(insert
|
||||
(format "\n%s %s\n"
|
||||
(make-string nstars ?*)
|
||||
new-title))
|
||||
(forward-line -1)
|
||||
(org-narrow-to-subtree)
|
||||
nil)))
|
||||
|
||||
(defun org-datetree-file-entry-under (txt d)
|
||||
"Insert a node TXT into the date tree under date D."
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2023-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Keywords: data, lisp
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
|
@ -136,6 +137,9 @@
|
|||
;; properties. This is useful to generate pure (in functional sense)
|
||||
;; AST.
|
||||
;;
|
||||
;; To force resolving deferred properties, you can use
|
||||
;; `org-element-properties-resolve'.
|
||||
;;
|
||||
;; The properties listed in `org-element--standard-properties', except
|
||||
;; `:deferred' and `:parent' are never considered to have deferred value.
|
||||
;; This constraint makes org-element API significantly faster.
|
||||
|
|
@ -645,7 +649,7 @@ Return the modified NODE."
|
|||
(if force-undefer
|
||||
#'org-element--deferred-resolve-force-rec
|
||||
#'org-element--deferred-resolve-rec)
|
||||
node 'set 'no-standard)
|
||||
node 'set)
|
||||
node)
|
||||
|
||||
(defsubst org-element-properties-mapc (fun node &optional undefer)
|
||||
|
|
@ -728,6 +732,11 @@ nodes. This way,
|
|||
will yield expected results with contents of another node adopted into
|
||||
a newly created one.
|
||||
|
||||
nil elements in CHILDREN are ignored. This way,
|
||||
(let ((children nil))
|
||||
(org-element-create \\='section nil children))
|
||||
will yield expected results.
|
||||
|
||||
When TYPE is `plain-text', CHILDREN must contain a single node -
|
||||
string. Alternatively, TYPE can be a string. When TYPE is nil or
|
||||
`anonymous', PROPS must be nil."
|
||||
|
|
@ -735,6 +744,12 @@ string. Alternatively, TYPE can be a string. When TYPE is nil or
|
|||
(plistp props)
|
||||
(let ((len (proper-list-p props)))
|
||||
(and len (cl-evenp len)))))
|
||||
;; Special case: CHILDREN is a single anonymous node
|
||||
(when (and (= 1 (length children))
|
||||
(org-element-type-p (car children) 'anonymous))
|
||||
(setq children (car children)))
|
||||
;; Filter out nil values from CHILDREN
|
||||
(setq children (delq nil children))
|
||||
;; Assign parray.
|
||||
(when (and props (not (stringp type)) (not (eq type 'plain-text)))
|
||||
(let ((node (list 'dummy props)))
|
||||
|
|
@ -750,7 +765,7 @@ string. Alternatively, TYPE can be a string. When TYPE is nil or
|
|||
(setq props (nbutlast props 2)
|
||||
ptail nil)
|
||||
(setcar ptail (nth 2 ptail))
|
||||
(setcdr ptail (seq-drop ptail 3))))))))
|
||||
(setcdr ptail (cdddr ptail))))))))
|
||||
(pcase type
|
||||
((or `nil `anonymous)
|
||||
(cl-assert (null props))
|
||||
|
|
@ -761,10 +776,7 @@ string. Alternatively, TYPE can be a string. When TYPE is nil or
|
|||
((pred stringp)
|
||||
(if props (org-add-props type props) type))
|
||||
(_
|
||||
(if (and (= 1 (length children))
|
||||
(org-element-type-p (car children) 'anonymous))
|
||||
(apply #'org-element-adopt (list type props) (car children))
|
||||
(apply #'org-element-adopt (list type props) children)))))
|
||||
(apply #'org-element-adopt (list type props) children))))
|
||||
|
||||
(defun org-element-copy (datum &optional keep-contents)
|
||||
"Return a copy of DATUM.
|
||||
|
|
@ -822,6 +834,7 @@ When DATUM is `plain-text', all the properties are removed."
|
|||
(while contents
|
||||
(setcar contents (org-element-copy (car contents) t))
|
||||
(setq contents (cdr contents)))))
|
||||
(org-element-resolve-deferred node-copy 'force)
|
||||
node-copy))))
|
||||
|
||||
;;;; AST queries
|
||||
|
|
|
|||
|
|
@ -76,20 +76,17 @@
|
|||
(require 'org-table)
|
||||
(require 'org-fold-core)
|
||||
|
||||
(declare-function org-at-heading-p "org" (&optional _))
|
||||
(declare-function org-escape-code-in-string "org-src" (s))
|
||||
(declare-function org-src-preserve-indentation-p "org-src" (&optional node))
|
||||
(declare-function org-macro-escape-arguments "org-macro" (&rest args))
|
||||
(declare-function org-macro-extract-arguments "org-macro" (s))
|
||||
(declare-function org-reduced-level "org" (l))
|
||||
(declare-function org-unescape-code-in-string "org-src" (s))
|
||||
(declare-function org-inlinetask-outline-regexp "org-inlinetask" ())
|
||||
(declare-function outline-next-heading "outline" ())
|
||||
(declare-function outline-previous-heading "outline" ())
|
||||
|
||||
(defvar org-complex-heading-regexp)
|
||||
(defvar org-done-keywords)
|
||||
(defvar org-edit-src-content-indentation)
|
||||
(defvar org-src-content-indentation)
|
||||
(defvar org-match-substring-regexp)
|
||||
(defvar org-odd-levels-only)
|
||||
(defvar org-property-drawer-re)
|
||||
|
|
@ -335,6 +332,12 @@ specially in `org-element--object-lex'.")
|
|||
(append org-element-recursive-objects '(paragraph table-row verse-block))
|
||||
"List of object or element types that can directly contain objects.")
|
||||
|
||||
(defconst org-element-elements-no-affiliated
|
||||
'(org-data comment clock headline inlinetask item
|
||||
node-property planning property-drawer
|
||||
section table-row)
|
||||
"List of paragraph-level node types that cannot have affiliated keywords.")
|
||||
|
||||
(defconst org-element-affiliated-keywords
|
||||
'("CAPTION" "DATA" "HEADER" "HEADERS" "LABEL" "NAME" "PLOT" "RESNAME" "RESULT"
|
||||
"RESULTS" "SOURCE" "SRCNAME" "TBLNAME")
|
||||
|
|
@ -504,7 +507,7 @@ past the brackets."
|
|||
(_ nil)))
|
||||
(pos (point)))
|
||||
(when syntax-table
|
||||
(with-syntax-table syntax-table
|
||||
(org-with-syntax-table syntax-table
|
||||
(let ((end (ignore-errors (scan-lists pos 1 0))))
|
||||
(when end
|
||||
(goto-char end)
|
||||
|
|
@ -533,13 +536,11 @@ created, all Org related local variables not in this list are copied
|
|||
to the new buffer. Variables with an unreadable value are also
|
||||
ignored.")
|
||||
|
||||
(cl-defun org-element--generate-copy-script (buffer
|
||||
(cl-defun org-element--generate-copy-script
|
||||
(buffer
|
||||
&key
|
||||
copy-unreadable
|
||||
drop-visibility
|
||||
drop-narrowing
|
||||
drop-contents
|
||||
drop-locals)
|
||||
copy-unreadable drop-visibility drop-narrowing
|
||||
drop-contents drop-text-properties drop-locals)
|
||||
"Generate a function duplicating BUFFER.
|
||||
|
||||
The copy will preserve local variables, visibility, contents and
|
||||
|
|
@ -549,18 +550,21 @@ BUFFER, contents will be narrowed to that region instead.
|
|||
When optional key COPY-UNREADABLE is non-nil, do not ensure that all
|
||||
the copied local variables will be readable in another Emacs session.
|
||||
|
||||
When optional keys DROP-VISIBILITY, DROP-NARROWING, DROP-CONTENTS, or
|
||||
DROP-LOCALS are non-nil, do not preserve visibility, narrowing,
|
||||
contents, or local variables correspondingly.
|
||||
When optional keys DROP-VISIBILITY, DROP-NARROWING, DROP-CONTENTS,
|
||||
DROP-TEXT-PROPERTIES, or DROP-LOCALS are non-nil, do not preserve
|
||||
visibility, narrowing, contents, text properties of contents, or local
|
||||
variables correspondingly.
|
||||
|
||||
The resulting function can be evaluated at a later time, from
|
||||
another buffer, effectively cloning the original buffer there.
|
||||
|
||||
The function assumes BUFFER's major mode is `org-mode'."
|
||||
(declare-function org-fold-core--update-buffer-folds "org-fold-core" ())
|
||||
(require 'org-fold-core)
|
||||
(with-current-buffer buffer
|
||||
(let ((str (unless drop-contents (org-with-wide-buffer (buffer-string))))
|
||||
(let ((str (unless drop-contents
|
||||
(org-with-wide-buffer
|
||||
(if drop-text-properties
|
||||
(substring-no-properties (buffer-string))
|
||||
(buffer-string)))))
|
||||
(narrowing
|
||||
(unless drop-narrowing
|
||||
(if (org-region-active-p)
|
||||
|
|
@ -849,6 +853,48 @@ and END-OFFSET."
|
|||
(org-unescape-code-in-string
|
||||
(org-element--substring element beg-offset end-offset)))
|
||||
|
||||
(defvar org-element--cache-diagnostics-level 2
|
||||
"Detail level of the diagnostics.")
|
||||
|
||||
(defvar-local org-element--cache-diagnostics-ring nil
|
||||
"Ring containing cache process log entries.
|
||||
The ring size is `org-element--cache-diagnostics-ring-size'.")
|
||||
|
||||
(defvar org-element--cache-diagnostics-ring-size 5000
|
||||
"Size of `org-element--cache-diagnostics-ring'.")
|
||||
|
||||
(defvar org-element--cache-self-verify nil
|
||||
"Activate extra consistency checks for the cache.
|
||||
|
||||
This may cause serious performance degradation depending on the value
|
||||
of `org-element--cache-self-verify-frequency'.
|
||||
|
||||
When set to symbol `backtrace', record and display backtrace log if
|
||||
any inconsistency is detected.")
|
||||
|
||||
(defmacro org-element--cache-warn (format-string &rest args)
|
||||
"Raise warning for org-element-cache.
|
||||
FORMAT-STRING and ARGS are the same arguments as in `format'."
|
||||
`(let* ((format-string (funcall #'format ,format-string ,@args))
|
||||
(format-string
|
||||
(if (or (not org-element--cache-diagnostics-ring)
|
||||
(not (eq 'backtrace org-element--cache-self-verify)))
|
||||
format-string
|
||||
(prog1
|
||||
(concat (format "Warning(%s): "
|
||||
(buffer-name (current-buffer)))
|
||||
format-string
|
||||
"\nBacktrace:\n "
|
||||
(mapconcat #'identity
|
||||
(ring-elements org-element--cache-diagnostics-ring)
|
||||
"\n "))
|
||||
(setq org-element--cache-diagnostics-ring nil)))))
|
||||
(if (and (boundp 'org-batch-test) org-batch-test)
|
||||
(error "%s" (concat "org-element--cache: " format-string))
|
||||
(push (concat "org-element--cache: " format-string) org--warnings)
|
||||
(display-warning '(org-element org-element-cache)
|
||||
(concat "org-element--cache: " format-string)))))
|
||||
|
||||
|
||||
;;; Greater elements
|
||||
;;
|
||||
|
|
@ -944,6 +990,8 @@ Assume point is at the beginning of the block."
|
|||
:end end
|
||||
:contents-begin contents-begin
|
||||
:contents-end contents-end
|
||||
:robust-begin contents-begin
|
||||
:robust-end contents-end
|
||||
:post-blank (count-lines pos-before-blank end)
|
||||
:post-affiliated post-affiliated)
|
||||
(cdr affiliated))))))))
|
||||
|
|
@ -985,8 +1033,13 @@ Assume point is at beginning of drawer."
|
|||
(post-affiliated (point))
|
||||
;; Empty drawers have no contents.
|
||||
(contents-begin (progn (forward-line)
|
||||
(org-skip-whitespace)
|
||||
(forward-line 0)
|
||||
(and (< (point) drawer-end-line)
|
||||
(point))))
|
||||
(pre-blank (1- (count-lines
|
||||
post-affiliated
|
||||
(or contents-begin drawer-end-line))))
|
||||
(contents-end (and contents-begin drawer-end-line))
|
||||
(pos-before-blank (progn (goto-char drawer-end-line)
|
||||
(forward-line)
|
||||
|
|
@ -998,9 +1051,20 @@ Assume point is at beginning of drawer."
|
|||
(nconc
|
||||
(list :begin begin
|
||||
:end end
|
||||
:pre-blank pre-blank
|
||||
:drawer-name name
|
||||
:contents-begin contents-begin
|
||||
:contents-end contents-end
|
||||
:robust-begin
|
||||
(and contents-begin
|
||||
;; We might be dealing with broken properties
|
||||
;; drawer. Every change inside is sensitive.
|
||||
(not (org-string-equal-ignore-case name "PROPERTIES"))
|
||||
;; Inserting blank line at contents-begin
|
||||
;; will trigger :pre-blank change and may not
|
||||
;; be robust.
|
||||
(min (1+ contents-begin) contents-end))
|
||||
:robust-end contents-end
|
||||
:post-blank (count-lines pos-before-blank end)
|
||||
:post-affiliated post-affiliated)
|
||||
(cdr affiliated))))))))
|
||||
|
|
@ -1008,9 +1072,10 @@ Assume point is at beginning of drawer."
|
|||
(defun org-element-drawer-interpreter (drawer contents)
|
||||
"Interpret DRAWER element as Org syntax.
|
||||
CONTENTS is the contents of the element."
|
||||
(format ":%s:\n%s:END:"
|
||||
(format ":%s:\n%s%s:END:"
|
||||
(org-element-property :drawer-name drawer)
|
||||
contents))
|
||||
(make-string (org-element-property :pre-blank drawer) ?\n)
|
||||
(or contents "")))
|
||||
|
||||
|
||||
;;;; Dynamic Block
|
||||
|
|
@ -1060,6 +1125,8 @@ Assume point is at beginning of dynamic block."
|
|||
:arguments arguments
|
||||
:contents-begin contents-begin
|
||||
:contents-end contents-end
|
||||
:robust-begin contents-begin
|
||||
:robust-end contents-end
|
||||
:post-blank (count-lines pos-before-blank end)
|
||||
:post-affiliated post-affiliated)
|
||||
(cdr affiliated)))))))))
|
||||
|
|
@ -1334,9 +1401,9 @@ Throw `:org-element-deferred-retry' signal at the end."
|
|||
(org-element--get-cached-string (match-string-no-properties 1)))))
|
||||
(todo-type
|
||||
(and todo (if (member todo org-done-keywords) 'done 'todo)))
|
||||
(priority (and (looking-at "\\[#.\\][ \t]*")
|
||||
(priority (and (looking-at org-priority-regexp)
|
||||
(progn (goto-char (match-end 0))
|
||||
(aref (match-string 0) 2))))
|
||||
(org-priority-to-value (match-string 2)))))
|
||||
(commentedp
|
||||
(and (let ((case-fold-search nil))
|
||||
(looking-at org-element--headline-comment-re))
|
||||
|
|
@ -1344,10 +1411,13 @@ Throw `:org-element-deferred-retry' signal at the end."
|
|||
(goto-char (match-end 0))
|
||||
(skip-chars-forward " \t"))))
|
||||
(title-start (point))
|
||||
(tags (when (re-search-forward
|
||||
"\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"
|
||||
(line-end-position)
|
||||
'move)
|
||||
(tags (when (progn
|
||||
;; `org-tag-group-re' includes spaces before tags.
|
||||
;; Start search before preceding spaces, if any.
|
||||
;; If there are no spaces before point here,
|
||||
;; We are not looking at the tags.
|
||||
(skip-chars-backward " \t")
|
||||
(re-search-forward org-tag-group-re (line-end-position) 'move))
|
||||
(goto-char (match-beginning 0))
|
||||
(mapcar #'org-element--get-cached-string
|
||||
(org-split-string (match-string-no-properties 1) ":"))))
|
||||
|
|
@ -1494,8 +1564,8 @@ CONTENTS is the contents of the element."
|
|||
(concat (make-string (if org-odd-levels-only (1- (* level 2)) level)
|
||||
?*)
|
||||
(and todo (concat " " todo))
|
||||
(and priority (format " [#%s]" (org-priority-to-string priority)))
|
||||
(and commentedp (concat " " org-element-comment-string))
|
||||
(and priority (format " [#%c]" priority))
|
||||
" "
|
||||
(if (and org-footnote-section
|
||||
(org-element-property :footnote-section-p headline))
|
||||
|
|
@ -1580,8 +1650,8 @@ Alter DATA by side effect."
|
|||
"Parse org-data.
|
||||
|
||||
Return a new syntax node of `org-data' type containing `:begin',
|
||||
`:contents-begin', `:contents-end', `:end', `:post-blank',
|
||||
`:post-affiliated', and `:path' properties."
|
||||
`:pre-blank', `:contents-begin', `:contents-end', `:end',
|
||||
`:post-blank', `:post-affiliated', and `:path' properties."
|
||||
(org-with-wide-buffer
|
||||
(let* ((begin 1)
|
||||
(contents-begin (progn
|
||||
|
|
@ -1612,6 +1682,7 @@ Return a new syntax node of `org-data' type containing `:begin',
|
|||
:end end
|
||||
:robust-begin robust-begin
|
||||
:robust-end robust-end
|
||||
:pre-blank (count-lines begin contents-begin)
|
||||
;; Trailing blank lines in org-data, headlines, and
|
||||
;; sections belong to the containing elements.
|
||||
:post-blank 0
|
||||
|
|
@ -1621,10 +1692,12 @@ Return a new syntax node of `org-data' type containing `:begin',
|
|||
:buffer (current-buffer)
|
||||
:deferred org-element--get-global-node-properties)))))
|
||||
|
||||
(defun org-element-org-data-interpreter (_ contents)
|
||||
(defun org-element-org-data-interpreter (org-data contents)
|
||||
"Interpret ORG-DATA element as Org syntax.
|
||||
CONTENTS is the contents of the element."
|
||||
contents)
|
||||
(concat
|
||||
(make-string (or (org-element-property :pre-blank org-data) 0) ?\n)
|
||||
contents))
|
||||
|
||||
;;;; Inlinetask
|
||||
|
||||
|
|
@ -1711,7 +1784,7 @@ CONTENTS is the contents of inlinetask."
|
|||
(format ":%s:" (mapconcat 'identity tag-list ":")))))
|
||||
(task (concat (make-string level ?*)
|
||||
(and todo (concat " " todo))
|
||||
(and priority (format " [#%c]" priority))
|
||||
(and priority (format " [#%s]" (org-priority-to-string priority)))
|
||||
(and title (concat " " title)))))
|
||||
(concat task
|
||||
;; Align tags.
|
||||
|
|
@ -1969,6 +2042,14 @@ Return a new syntax node of `plain-list' type containing `:type',
|
|||
`:post-blank' and `:post-affiliated' properties.
|
||||
|
||||
Assume point is at the beginning of the list."
|
||||
(when (and structure (not (assq (point) structure)))
|
||||
;; STRUCT is corrupted - cannot find list inside.
|
||||
(org-element--cache-warn
|
||||
"Invalid :struct passed to plain-list parser at %S: %S
|
||||
If this warning appears regularly, please report the warning text to Org mode mailing list (M-x org-submit-bug-report)."
|
||||
(point) structure)
|
||||
;; Try to recover
|
||||
(setq structure nil))
|
||||
(save-excursion
|
||||
(let* ((struct (or structure (org-element--list-struct limit)))
|
||||
(type (cond ((looking-at-p "[ \t]*[A-Za-z0-9]") 'ordered)
|
||||
|
|
@ -2050,6 +2131,10 @@ Assume point is at the beginning of the property drawer."
|
|||
:end end
|
||||
:contents-begin (and contents-end contents-begin)
|
||||
:contents-end contents-end
|
||||
;; Changing anything inside property drawer may
|
||||
;; change property drawer to ordinary drawer.
|
||||
:robust-begin nil
|
||||
:robust-end nil
|
||||
:post-blank (count-lines before-blank end)
|
||||
:post-affiliated begin))))))
|
||||
|
||||
|
|
@ -2100,6 +2185,8 @@ Assume point is at the beginning of the block."
|
|||
:end end
|
||||
:contents-begin contents-begin
|
||||
:contents-end contents-end
|
||||
:robust-begin contents-begin
|
||||
:robust-end contents-end
|
||||
:post-blank (count-lines pos-before-blank end)
|
||||
:post-affiliated post-affiliated)
|
||||
(cdr affiliated)))))))))
|
||||
|
|
@ -2198,6 +2285,8 @@ Assume point is at the beginning of the block."
|
|||
:end end
|
||||
:contents-begin contents-begin
|
||||
:contents-end contents-end
|
||||
:robust-begin contents-begin
|
||||
:robust-end contents-end
|
||||
:post-blank (count-lines pos-before-blank end)
|
||||
:post-affiliated post-affiliated)
|
||||
(cdr affiliated)))))))))
|
||||
|
|
@ -2562,10 +2651,10 @@ Return a new syntax node of `example-block' type containing `:begin',
|
|||
(let ((val (org-element-property :value example-block)))
|
||||
(cond
|
||||
((org-src-preserve-indentation-p example-block) val)
|
||||
((= 0 org-edit-src-content-indentation)
|
||||
((= 0 org-src-content-indentation)
|
||||
(org-remove-indentation val))
|
||||
(t
|
||||
(let ((ind (make-string org-edit-src-content-indentation ?\s)))
|
||||
(let ((ind (make-string org-src-content-indentation ?\s)))
|
||||
(replace-regexp-in-string "^[ \t]*\\S-"
|
||||
(concat ind "\\&")
|
||||
(org-remove-indentation val))))))))
|
||||
|
|
@ -2649,11 +2738,13 @@ Assume point is at the beginning of the fixed-width area."
|
|||
(save-excursion
|
||||
(let* ((begin (car affiliated))
|
||||
(post-affiliated (point))
|
||||
pos-before-blank
|
||||
(end-area
|
||||
(progn
|
||||
(while (and (< (point) limit)
|
||||
(looking-at-p "[ \t]*:\\( \\|$\\)"))
|
||||
(forward-line))
|
||||
(setq pos-before-blank (point))
|
||||
(if (bolp) (line-end-position 0) (point))))
|
||||
(end (progn (skip-chars-forward " \r\t\n" limit)
|
||||
(if (eobp) (point) (line-beginning-position)))))
|
||||
|
|
@ -2666,7 +2757,7 @@ Assume point is at the beginning of the fixed-width area."
|
|||
"^[ \t]*: ?" ""
|
||||
(buffer-substring-no-properties post-affiliated
|
||||
end-area))
|
||||
:post-blank (count-lines end-area end)
|
||||
:post-blank (count-lines pos-before-blank end)
|
||||
:post-affiliated post-affiliated)
|
||||
(cdr affiliated))))))
|
||||
|
||||
|
|
@ -3096,10 +3187,10 @@ Assume point is at the beginning of the block."
|
|||
(let ((val (org-element-property :value src-block)))
|
||||
(cond
|
||||
((org-src-preserve-indentation-p src-block) val)
|
||||
((zerop org-edit-src-content-indentation)
|
||||
((zerop org-src-content-indentation)
|
||||
(org-remove-indentation val))
|
||||
(t
|
||||
(let ((ind (make-string org-edit-src-content-indentation ?\s)))
|
||||
(let ((ind (make-string org-src-content-indentation ?\s)))
|
||||
(replace-regexp-in-string "^[ \t]*\\S-"
|
||||
(concat ind "\\&")
|
||||
(org-remove-indentation val))))))))
|
||||
|
|
@ -3361,7 +3452,7 @@ Assume point is at the beginning of the citation."
|
|||
(match-string-no-properties 1))))
|
||||
;; Ignore blanks between cite type and prefix or key.
|
||||
(start (match-end 0))
|
||||
(closing (with-syntax-table org-element--pair-square-table
|
||||
(closing (org-with-syntax-table org-element--pair-square-table
|
||||
(ignore-errors (scan-lists begin 1 0)))))
|
||||
(save-excursion
|
||||
(when (and closing
|
||||
|
|
@ -3602,7 +3693,7 @@ When at a footnote reference, return a new syntax node of
|
|||
`:end', `:contents-begin', `:contents-end' and `:post-blank' as
|
||||
properties. Otherwise, return nil."
|
||||
(when (looking-at org-footnote-re)
|
||||
(let ((closing (with-syntax-table org-element--pair-square-table
|
||||
(let ((closing (org-with-syntax-table org-element--pair-square-table
|
||||
(ignore-errors (scan-lists (point) 1 0)))))
|
||||
(when closing
|
||||
(save-excursion
|
||||
|
|
@ -3694,6 +3785,9 @@ Assume point is at the beginning of the babel call."
|
|||
|
||||
;;;; Inline Src Block
|
||||
|
||||
(defconst org-element-inline-src-block-regexp "\\<src_\\([^ \t\n[{]+\\)[{[]"
|
||||
"Regexp matching inline source blocks.")
|
||||
|
||||
(defun org-element-inline-src-block-parser ()
|
||||
"Parse inline source block at point, if any.
|
||||
|
||||
|
|
@ -3706,7 +3800,7 @@ Assume point is at the beginning of the inline source block."
|
|||
(save-excursion
|
||||
(catch :no-object
|
||||
(when (let ((case-fold-search nil))
|
||||
(looking-at "\\<src_\\([^ \t\n[{]+\\)[{[]"))
|
||||
(looking-at org-element-inline-src-block-regexp))
|
||||
(goto-char (match-end 1))
|
||||
(let ((begin (match-beginning 0))
|
||||
(language (org-element--get-cached-string
|
||||
|
|
@ -4278,8 +4372,6 @@ Assume point is at the target."
|
|||
|
||||
(defconst org-element--timestamp-regexp
|
||||
(concat org-ts-regexp-both
|
||||
"\\|"
|
||||
"\\(?:<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[dwmy]>\\)"
|
||||
"\\|"
|
||||
"\\(?:<%%\\(?:([^>\n]+)\\)\\([^\n>]*\\)>\\)")
|
||||
"Regexp matching any timestamp type object.")
|
||||
|
|
@ -4709,14 +4801,7 @@ element it has to parse."
|
|||
;; Property drawer.
|
||||
((and (pcase mode
|
||||
(`planning (eq ?* (char-after (line-beginning-position 0))))
|
||||
((or `property-drawer `top-comment)
|
||||
;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=63225#80
|
||||
(save-excursion
|
||||
(forward-line -1) ; faster than beginning-of-line
|
||||
(skip-chars-forward "[:blank:]") ; faster than looking-at-p
|
||||
(or (not (eolp)) ; very cheap
|
||||
;; Document-wide property drawer may be preceded by blank lines.
|
||||
(progn (skip-chars-backward " \t\n\r") (bobp)))))
|
||||
((or `property-drawer `top-comment) t)
|
||||
(_ nil))
|
||||
(looking-at-p org-property-drawer-re))
|
||||
(org-element-property-drawer-parser limit))
|
||||
|
|
@ -4937,10 +5022,13 @@ When PARSE is non-nil, values from keywords belonging to
|
|||
;; parts of the parse tree.
|
||||
|
||||
(defun org-element-parse-buffer (&optional granularity visible-only keep-deferred)
|
||||
"Recursively parse the buffer and return structure.
|
||||
"Recursively parse the current Org mode buffer and return structure.
|
||||
If narrowing is in effect, only parse the visible part of the
|
||||
buffer.
|
||||
|
||||
This function assumes that current major mode is `org-mode'. When the
|
||||
major mode is different, the behaviour is undefined.
|
||||
|
||||
Optional argument GRANULARITY determines the depth of the
|
||||
recursion. It can be set to the following symbols:
|
||||
|
||||
|
|
@ -4979,9 +5067,7 @@ pattern (TYPE PROPERTIES CONTENTS), where :
|
|||
|
||||
The Org buffer has `org-data' as type and nil as properties.
|
||||
`org-element-map' function can be used to find specific elements
|
||||
or objects within the parse tree.
|
||||
|
||||
This function assumes that current major mode is `org-mode'."
|
||||
or objects within the parse tree."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let ((org-data (org-element-org-data-parser))
|
||||
|
|
@ -5470,11 +5556,6 @@ to interpret. Return Org syntax as a string."
|
|||
(mapconcat (lambda (obj) (funcall fun obj parent))
|
||||
data
|
||||
""))
|
||||
;; Full Org document.
|
||||
((eq type 'org-data)
|
||||
(mapconcat (lambda (obj) (funcall fun obj parent))
|
||||
(org-element-contents data)
|
||||
""))
|
||||
;; Plain text: return it.
|
||||
((stringp data) data)
|
||||
;; Element or object without contents.
|
||||
|
|
@ -5514,15 +5595,17 @@ to interpret. Return Org syntax as a string."
|
|||
(if (eq (org-element-class data parent) 'object)
|
||||
(concat results (make-string blank ?\s))
|
||||
(concat (org-element--interpret-affiliated-keywords data)
|
||||
(org-element-normalize-string results)
|
||||
;; Make sure that we have at least a
|
||||
;; single newline after (if non-empty),
|
||||
;; but keep any existing newlines (they
|
||||
;; come from :post-blank inside
|
||||
;; contents)
|
||||
(org-element-normalize-string results 'keep-newlines)
|
||||
(make-string blank ?\n)))))))))
|
||||
(funcall fun data nil)))
|
||||
|
||||
(defun org-element--interpret-affiliated-keywords (element)
|
||||
"Return ELEMENT's affiliated keywords as Org syntax.
|
||||
If there is no affiliated keyword, return the empty string."
|
||||
(let ((keyword-to-org
|
||||
(lambda (key value)
|
||||
(defun org-element--interpret-affiliated-keyword (key value)
|
||||
"Interpret affiliated keyword with KEY and VALUE."
|
||||
(let (dual)
|
||||
(when (member key org-element-dual-keywords)
|
||||
(setq dual (cdr value) value (car value)))
|
||||
|
|
@ -5533,34 +5616,38 @@ If there is no affiliated keyword, return the empty string."
|
|||
(if (member key org-element-parsed-keywords)
|
||||
(org-element-interpret-data value)
|
||||
value)
|
||||
"\n")))))
|
||||
(mapconcat
|
||||
(lambda (prop)
|
||||
(let ((value (org-element-property prop element))
|
||||
(keyword (upcase (substring (symbol-name prop) 1))))
|
||||
(when value
|
||||
(if (or (member keyword org-element-multiple-keywords)
|
||||
;; All attribute keywords can have multiple lines.
|
||||
(string-match-p "^ATTR_" keyword))
|
||||
(mapconcat (lambda (line) (funcall keyword-to-org keyword line))
|
||||
value "")
|
||||
(funcall keyword-to-org keyword value)))))
|
||||
"\n")))
|
||||
|
||||
(defun org-element--interpret-affiliated-keywords (element)
|
||||
"Return ELEMENT's affiliated keywords as Org syntax.
|
||||
If there is no affiliated keyword, return the empty string."
|
||||
;; there are some elements that will never have affiliated keywords,
|
||||
;; so do nothing for these
|
||||
(if (member (org-element-type element)
|
||||
org-element-elements-no-affiliated)
|
||||
""
|
||||
(let (acc)
|
||||
;; List all ELEMENT's properties matching an attribute line or an
|
||||
;; affiliated keyword, but ignore translated keywords since they
|
||||
;; cannot belong to the property list.
|
||||
(let (acc)
|
||||
(org-element-properties-mapc
|
||||
(lambda (prop _ __)
|
||||
(let ((keyword (upcase (substring (symbol-name prop) 1))))
|
||||
(when (or (string-match-p "^ATTR_" keyword)
|
||||
(lambda (prop value)
|
||||
(when value
|
||||
(let* ((keyword (upcase (substring (symbol-name prop) 1)))
|
||||
(attrp (string-prefix-p "ATTR_" keyword)))
|
||||
(when (or attrp
|
||||
(and
|
||||
(member keyword org-element-affiliated-keywords)
|
||||
(not (assoc keyword
|
||||
org-element-keyword-translation-alist))))
|
||||
(push prop acc))))
|
||||
(push (if (or attrp ; All attribute keywords can have multiple lines.
|
||||
(member keyword org-element-multiple-keywords))
|
||||
(mapconcat (lambda (line) (org-element--interpret-affiliated-keyword keyword line))
|
||||
value "")
|
||||
(org-element--interpret-affiliated-keyword keyword value))
|
||||
acc)))))
|
||||
element t)
|
||||
(nreverse acc))
|
||||
"")))
|
||||
(apply #'concat (nreverse acc)))))
|
||||
|
||||
;; Because interpretation of the parse tree must return the same
|
||||
;; number of blank lines between elements and the same number of white
|
||||
|
|
@ -5574,15 +5661,20 @@ If there is no affiliated keyword, return the empty string."
|
|||
;; The second function, `org-element-normalize-contents', removes
|
||||
;; global indentation from the contents of the current element.
|
||||
|
||||
(defun org-element-normalize-string (s)
|
||||
(defun org-element-normalize-string (s &optional keep-newlines)
|
||||
"Ensure string S ends with a single newline character.
|
||||
|
||||
If S isn't a string return it unchanged. If S is the empty
|
||||
string, return it. Otherwise, return a new string with a single
|
||||
newline character at its end."
|
||||
newline character at its end.
|
||||
|
||||
When optional argument KEEP-NEWLINES is non-nil, keep any newlines that
|
||||
are present, even when there are more than one."
|
||||
(cond
|
||||
((not (stringp s)) s)
|
||||
((string= "" s) "")
|
||||
(keep-newlines
|
||||
(if (string-suffix-p "\n" s) s (concat s "\n")))
|
||||
(t (and (string-match "\\(\n[ \t]*\\)*\\'" s)
|
||||
(replace-match "\n" nil nil s)))))
|
||||
|
||||
|
|
@ -5766,15 +5858,6 @@ seconds.")
|
|||
"Duration, as a time value, of the pause between synchronizations.
|
||||
See `org-element-cache-sync-duration' for more information.")
|
||||
|
||||
(defvar org-element--cache-self-verify nil
|
||||
"Activate extra consistency checks for the cache.
|
||||
|
||||
This may cause serious performance degradation depending on the value
|
||||
of `org-element--cache-self-verify-frequency'.
|
||||
|
||||
When set to symbol `backtrace', record and display backtrace log if
|
||||
any inconsistency is detected.")
|
||||
|
||||
(defvar org-element--cache-self-verify-before-persisting nil
|
||||
"Perform consistency checks for the cache before writing to disk.
|
||||
|
||||
|
|
@ -5797,16 +5880,6 @@ to be correct. Setting this to a value less than 0.0001 is useless.")
|
|||
(defvar org-element--cache-map-statistics-threshold 0.1
|
||||
"Time threshold in seconds to log statistics for `org-element-cache-map'.")
|
||||
|
||||
(defvar org-element--cache-diagnostics-level 2
|
||||
"Detail level of the diagnostics.")
|
||||
|
||||
(defvar-local org-element--cache-diagnostics-ring nil
|
||||
"Ring containing cache process log entries.
|
||||
The ring size is `org-element--cache-diagnostics-ring-size'.")
|
||||
|
||||
(defvar org-element--cache-diagnostics-ring-size 5000
|
||||
"Size of `org-element--cache-diagnostics-ring'.")
|
||||
|
||||
;;;; Data Structure
|
||||
|
||||
(defvar-local org-element--cache nil
|
||||
|
|
@ -5969,29 +6042,6 @@ FORMAT-STRING and ARGS are the same arguments as in `format'."
|
|||
(make-ring org-element--cache-diagnostics-ring-size)))
|
||||
(ring-insert org-element--cache-diagnostics-ring format-string)))))
|
||||
|
||||
(defmacro org-element--cache-warn (format-string &rest args)
|
||||
"Raise warning for org-element-cache.
|
||||
FORMAT-STRING and ARGS are the same arguments as in `format'."
|
||||
`(let* ((format-string (funcall #'format ,format-string ,@args))
|
||||
(format-string
|
||||
(if (or (not org-element--cache-diagnostics-ring)
|
||||
(not (eq 'backtrace org-element--cache-self-verify)))
|
||||
format-string
|
||||
(prog1
|
||||
(concat (format "Warning(%s): "
|
||||
(buffer-name (current-buffer)))
|
||||
format-string
|
||||
"\nBacktrace:\n "
|
||||
(mapconcat #'identity
|
||||
(ring-elements org-element--cache-diagnostics-ring)
|
||||
"\n "))
|
||||
(setq org-element--cache-diagnostics-ring nil)))))
|
||||
(if (and (boundp 'org-batch-test) org-batch-test)
|
||||
(error "%s" (concat "org-element--cache: " format-string))
|
||||
(push (concat "org-element--cache: " format-string) org--warnings)
|
||||
(display-warning '(org-element org-element-cache)
|
||||
(concat "org-element--cache: " format-string)))))
|
||||
|
||||
(defsubst org-element--cache-key (element)
|
||||
"Return a unique key for ELEMENT in cache tree.
|
||||
|
||||
|
|
@ -7036,6 +7086,14 @@ If you observe Emacs hangs frequently, please report this to Org mode mailing li
|
|||
(unless (save-excursion
|
||||
(org-skip-whitespace)
|
||||
(eobp))
|
||||
(unless (>= end (point))
|
||||
(org-element--cache-warn
|
||||
"Invalid LIMIT boundary during parsing. Please report it to Org mode mailing list (M-x org-submit-bug-report).\n Backtrace:\n%S"
|
||||
(when (and (fboundp 'backtrace-get-frames)
|
||||
(fboundp 'backtrace-to-string))
|
||||
(backtrace-to-string (backtrace-get-frames 'backtrace))
|
||||
(org-element-cache-reset)
|
||||
(error "org-element--cache: Emergency exit"))))
|
||||
(setq element (org-element--current-element
|
||||
end 'element mode
|
||||
(org-element-property :structure parent))))
|
||||
|
|
@ -7307,18 +7365,12 @@ known element in cache (it may start after END)."
|
|||
(or (and (memq type '( center-block dynamic-block
|
||||
quote-block special-block
|
||||
drawer))
|
||||
(or (not (eq type 'drawer))
|
||||
(not (string= "PROPERTIES" (org-element-property :drawer-name up))))
|
||||
;; Sensitive change. This is
|
||||
;; unconditionally non-robust change.
|
||||
(not org-element--cache-change-warning)
|
||||
(let ((cbeg (org-element-contents-begin up))
|
||||
(cend (org-element-contents-end up)))
|
||||
(and cbeg
|
||||
(<= cbeg beg)
|
||||
(or (> cend end)
|
||||
(and (= cend end)
|
||||
(= (+ end offset) (point-max)))))))
|
||||
(let ((rbeg (org-element-property :robust-begin up))
|
||||
(rend (org-element-property :robust-end up)))
|
||||
(and rbeg rend (<= rbeg beg) (>= rend end))))
|
||||
(and (memq type '(headline section org-data))
|
||||
(let ((rbeg (org-element-property :robust-begin up))
|
||||
(rend (org-element-property :robust-end up)))
|
||||
|
|
@ -7991,7 +8043,8 @@ the cache."
|
|||
;; Bind variables used inside loop to avoid memory
|
||||
;; re-allocation on every iteration.
|
||||
;; See https://emacsconf.org/2021/talks/faster/
|
||||
tmpnext-start tmpparent tmpelement)
|
||||
tmpnext-start tmpparent tmpelement
|
||||
func-match-data)
|
||||
(save-excursion
|
||||
(save-restriction
|
||||
(unless narrow (widen))
|
||||
|
|
@ -8062,8 +8115,7 @@ the cache."
|
|||
;; point.
|
||||
(move-start-to-next-match
|
||||
;; Preserve match data that might be set by FUNC.
|
||||
(re) `(save-match-data
|
||||
(if (or (not ,re)
|
||||
(re) `(if (or (not ,re)
|
||||
(if org-element--cache-map-statistics
|
||||
(progn
|
||||
(setq before-time (float-time))
|
||||
|
|
@ -8085,7 +8137,7 @@ the cache."
|
|||
(or (org-element-begin (element-match-at-point)) -1))))
|
||||
(when (>= start to-pos) (cache-walk-abort))
|
||||
(when (eq start -1) (setq start nil)))
|
||||
(cache-walk-abort))))
|
||||
(cache-walk-abort)))
|
||||
;; Find expected begin position of an element after
|
||||
;; DATA.
|
||||
(next-element-start
|
||||
|
|
@ -8277,6 +8329,8 @@ the cache."
|
|||
;;
|
||||
;; Call FUNC. FUNC may move point.
|
||||
(setq org-element-cache-map-continue-from nil)
|
||||
(when func-match-data
|
||||
(set-match-data func-match-data t))
|
||||
(if (org-with-base-buffer nil org-element--cache-map-statistics)
|
||||
(progn
|
||||
(setq before-time (float-time))
|
||||
|
|
@ -8289,6 +8343,7 @@ the cache."
|
|||
(cl-incf count-predicate-calls-fail)))
|
||||
(push (funcall func data) result)
|
||||
(when (car result) (cl-incf count-predicate-calls-match)))
|
||||
(setq func-match-data (match-data))
|
||||
;; Set `last-match'.
|
||||
(setq last-match (car result))
|
||||
;; If FUNC moved point forward, update
|
||||
|
|
@ -8511,7 +8566,7 @@ This function may modify the match data."
|
|||
(org-element-at-point (1+ epom) cached-only))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defsubst org-element-at-point-no-context (&optional pom)
|
||||
(defun org-element-at-point-no-context (&optional pom)
|
||||
"Quickly find element at point or POM.
|
||||
|
||||
It is a faster version of `org-element-at-point' that is not
|
||||
|
|
@ -8586,7 +8641,7 @@ This function may modify match data."
|
|||
(goto-char (org-element-begin element))
|
||||
(looking-at org-complex-heading-regexp)
|
||||
(let ((end (match-end 4)))
|
||||
(if (not end) (throw 'objects-forbidden element)
|
||||
(if (or (not end) (> pos end)) (throw 'objects-forbidden element)
|
||||
(goto-char (match-beginning 4))
|
||||
(when (looking-at org-element-comment-string)
|
||||
(goto-char (match-end 0)))
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
;; Author: Carsten Dominik <carsten.dominik@gmail.com>,
|
||||
;; Ulf Stegemann <ulf at zeitform dot de>
|
||||
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Keywords: outlines, calendar, text
|
||||
;; URL: https://orgmode.org
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2004-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
|
||||
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Keywords: outlines, hypermedia, calendar, text
|
||||
;; URL: https://orgmode.org
|
||||
;;
|
||||
|
|
@ -324,18 +325,21 @@ determines if it is a foreground or a background color."
|
|||
|
||||
(defcustom org-priority-faces nil
|
||||
"Faces for specific Priorities.
|
||||
This is a list of cons cells, with priority character in the car
|
||||
and faces in the cdr. The face can be a symbol, a color
|
||||
as a string, or a property list of attributes, like
|
||||
This is an association list, whose keys are priorities and values are
|
||||
faces. The face can be a symbol, a color as a string, or a property
|
||||
list of attributes, like
|
||||
(:foreground \"blue\" :weight bold :underline t).
|
||||
If it is a color string, the variable `org-faces-easy-properties'
|
||||
determines if it is a foreground or a background color."
|
||||
:group 'org-faces
|
||||
:group 'org-todo
|
||||
:type '(repeat
|
||||
(cons
|
||||
(character :tag "Priority")
|
||||
(choice :tag "Face "
|
||||
:type '(choice (const :tag "Defaults" nil)
|
||||
(alist :tag "Association list"
|
||||
:key-type
|
||||
(choice :tag "Priority"
|
||||
(character :tag "Character" :value ?A)
|
||||
(natnum :tag "Number" :value 1))
|
||||
:value-type (choice :tag "Face "
|
||||
(string :tag "Color")
|
||||
(sexp :tag "Face")))))
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2020-2026 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; Author: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Keywords: folding, invisible text
|
||||
;; URL: https://orgmode.org
|
||||
;;
|
||||
|
|
@ -27,6 +28,11 @@
|
|||
;; This file contains library to control temporary invisibility
|
||||
;; (folding and unfolding) of text in buffers.
|
||||
|
||||
;; Do note that something being folded does not necessarily mean
|
||||
;; that it is invisible. Folded regions might be permanently visible
|
||||
;; by the means of `:visible' folding spec or because isearch
|
||||
;; temporarily revealed the folds.
|
||||
|
||||
;; The file implements the following functionality:
|
||||
;;
|
||||
;; - Folding/unfolding regions of text
|
||||
|
|
@ -245,7 +251,7 @@
|
|||
;; with `grab-invisible' option, folded regions copied to other
|
||||
;; buffers (including buffers that do not use this library) will
|
||||
;; remain invisible. org-fold-core provides functions to work around
|
||||
;; this issue: `org-fold-core-remove-optimisation' and `org-fold-core-update-optimisation', but
|
||||
;; this issue: `org-fold-core-remove-optimization' and `org-fold-core-update-optimization', but
|
||||
;; it is unlikely that a random external package will use them.
|
||||
|
||||
;; Another possible bottleneck is the fragility check after the change
|
||||
|
|
@ -276,8 +282,6 @@
|
|||
(require 'org-macs)
|
||||
(require 'org-compat)
|
||||
|
||||
(declare-function isearch-filter-visible "isearch" (beg end))
|
||||
|
||||
;;; Customization
|
||||
|
||||
(defcustom org-fold-core-style (if (version< emacs-version "29")
|
||||
|
|
@ -1070,8 +1074,9 @@ If SPEC-OR-ALIAS is omitted and FLAG is nil, unfold everything in the region."
|
|||
(overlay-get ov 'invisible)
|
||||
(org-fold-core-get-folding-spec-property
|
||||
(overlay-get ov 'invisible) :isearch-open))
|
||||
(when (overlay-get ov 'invisible)
|
||||
(overlay-put ov 'org-invisible (overlay-get ov 'invisible)))
|
||||
(when-let* ((spec (overlay-get ov 'invisible)))
|
||||
(overlay-put ov 'org-invisible spec)
|
||||
(overlay-put ov (org-fold-core--property-symbol-get-create spec) nil))
|
||||
(overlay-put ov 'invisible nil)
|
||||
(when org-fold-core--isearch-active
|
||||
(cl-pushnew ov org-fold-core--isearch-overlays)))))
|
||||
|
|
@ -1244,11 +1249,11 @@ This function is intended to be used as `isearch-filter-predicate'."
|
|||
(setq beg (car overlay-or-region)
|
||||
end (cdr overlay-or-region)))
|
||||
;; FIXME: Reveal the match (usually point, but may sometimes go beyond the region).
|
||||
(when (< beg (point) end)
|
||||
(funcall org-fold-core-isearch-open-function (point)))
|
||||
(if (<= beg (point) end)
|
||||
(funcall org-fold-core-isearch-open-function (point))
|
||||
(if (overlayp overlay-or-region)
|
||||
(delete-overlay overlay-or-region)
|
||||
(org-fold-core-region beg end nil))))
|
||||
(org-fold-core-region beg end nil)))))
|
||||
|
||||
(defun org-fold-core--isearch-show-temporary (region hide-p)
|
||||
"Temporarily reveal text in REGION.
|
||||
|
|
@ -1259,8 +1264,9 @@ REGION can also be an overlay in current buffer."
|
|||
(if hide-p
|
||||
(if (not (overlayp region))
|
||||
nil ;; FIXME: after isearch supports text properties.
|
||||
(when (overlay-get region 'org-invisible)
|
||||
(overlay-put region 'invisible (overlay-get region 'org-invisible))))
|
||||
(when-let* ((spec (overlay-get region 'org-invisible)))
|
||||
(overlay-put region 'invisible spec)
|
||||
(overlay-put region (org-fold-core--property-symbol-get-create spec) spec)))
|
||||
;; isearch expects all the temporarily opened overlays to exist.
|
||||
;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=60399
|
||||
(org-fold-core--keep-overlays
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2020-2026 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; Author: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Keywords: folding, invisible text
|
||||
;; URL: https://orgmode.org
|
||||
;;
|
||||
|
|
@ -58,29 +59,25 @@
|
|||
(defvar org-custom-properties-overlays)
|
||||
(defvar org-element-headline-re)
|
||||
|
||||
(declare-function isearch-filter-visible "isearch" (beg end))
|
||||
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
|
||||
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
(declare-function org-element-end "org-element" (node))
|
||||
(declare-function org-element-post-affiliated "org-element" (node))
|
||||
(declare-function org-element--current-element "org-element" (limit &optional granularity mode structure))
|
||||
(declare-function org-toggle-custom-properties-visibility "org" ())
|
||||
(declare-function org-item-re "org-list" ())
|
||||
(declare-function org-up-heading-safe "org" ())
|
||||
(declare-function org-get-tags "org" (&optional pos local fontify))
|
||||
(declare-function org-get-tags "org" (&optional epom local))
|
||||
(declare-function org-get-valid-level "org" (level &optional change))
|
||||
(declare-function org-before-first-heading-p "org" ())
|
||||
(declare-function org-goto-sibling "org" (&optional previous))
|
||||
(declare-function org-block-map "org" (function &optional start end))
|
||||
(declare-function org-map-region "org" (fun beg end))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading element))
|
||||
(declare-function org-back-to-heading-or-point-min "org" (&optional invisible-ok))
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-at-heading-p "org" (&optional invisible-not-ok))
|
||||
(declare-function org-cycle-hide-drawers "org-cycle" (state))
|
||||
|
||||
(declare-function outline-show-branches "outline" ())
|
||||
(declare-function outline-hide-sublevels "outline" (levels))
|
||||
(declare-function outline-get-next-sibling "outline" ())
|
||||
(declare-function outline-invisible-p "outline" (&optional pos))
|
||||
|
|
@ -249,7 +246,7 @@ Also, see `org-fold-catch-invisible-edits'."
|
|||
;; overlays for isearch.
|
||||
(setq-local org-fold-core--isearch-special-specs '(org-link))
|
||||
(org-fold-core-initialize
|
||||
`((,(if (eq org-fold-core-style 'text-properties) 'org-fold-outline 'outline)
|
||||
`((org-fold-outline
|
||||
(:ellipsis . ,ellipsis)
|
||||
(:fragile . ,#'org-fold--reveal-outline-maybe)
|
||||
(:isearch-open . t)
|
||||
|
|
@ -650,7 +647,7 @@ be shown."
|
|||
"Set visibility around point according to DETAIL.
|
||||
DETAIL is either nil, `minimal', `local', `ancestors',
|
||||
`ancestors-full', `lineage', `tree', `canonical' or t. See
|
||||
`org-show-context-detail' for more information."
|
||||
`org-fold-show-context-detail' for more information."
|
||||
;; Show current heading and possibly its entry, following headline
|
||||
;; or all children.
|
||||
(if (and (org-at-heading-p) (not (eq detail 'local)))
|
||||
|
|
@ -745,15 +742,18 @@ This function is intended to be used as a member of
|
|||
(setq from (save-excursion (goto-char from) (line-beginning-position 0)))
|
||||
(cons from to))
|
||||
|
||||
(defun org-fold--reveal-headline-at-point ()
|
||||
(defun org-fold--reveal-headline-at-point-delayed ()
|
||||
"Reveal header line and empty contents inside.
|
||||
Reveal the header line and, if present, also reveal its contents, when
|
||||
the contents consists of blank lines.
|
||||
|
||||
Only perform actual unfolding in `post-command-hook' by calling
|
||||
`org-fold-core--region-delayed'.
|
||||
|
||||
Assume that point is located at the header line."
|
||||
(org-with-wide-buffer
|
||||
(forward-line 0)
|
||||
(org-fold-region
|
||||
(org-fold-core--region-delayed
|
||||
(max (point-min) (1- (point)))
|
||||
(let ((endl (line-end-position)))
|
||||
(save-excursion
|
||||
|
|
@ -783,19 +783,19 @@ This function is intended to be used as :fragile property of
|
|||
(forward-line 0)
|
||||
;; Make sure that headline is not partially hidden.
|
||||
(unless (org-fold-folded-p nil 'headline)
|
||||
(org-fold--reveal-headline-at-point))
|
||||
(org-fold--reveal-headline-at-point-delayed))
|
||||
;; Never hide level 1 headlines
|
||||
(save-excursion
|
||||
(goto-char (line-end-position))
|
||||
(unless (>= (point) (cdr region))
|
||||
(when (re-search-forward (rx bol "* ") (cdr region) t)
|
||||
(org-fold--reveal-headline-at-point))))
|
||||
(org-fold--reveal-headline-at-point-delayed))))
|
||||
;; Make sure that headline after is not partially hidden.
|
||||
(goto-char (cdr region))
|
||||
(forward-line 0)
|
||||
(unless (org-fold-folded-p nil 'headline)
|
||||
(when (looking-at-p org-element-headline-re)
|
||||
(org-fold--reveal-headline-at-point)))
|
||||
(org-fold--reveal-headline-at-point-delayed)))
|
||||
;; Check the validity of headline
|
||||
(goto-char (car region))
|
||||
(backward-char)
|
||||
|
|
|
|||
|
|
@ -49,11 +49,11 @@
|
|||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
|
||||
(declare-function org-element-type-p "org-element-ast" (node types))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading element))
|
||||
(declare-function org-fill-paragraph "org" (&optional justify region))
|
||||
(declare-function org-in-block-p "org" (names))
|
||||
(declare-function org-in-verbatim-emphasis "org" ())
|
||||
(declare-function org-inside-LaTeX-fragment-p "org" ())
|
||||
(declare-function org-inside-LaTeX-fragment-p "org" (&optional element))
|
||||
(declare-function org-inside-latex-macro-p "org" ())
|
||||
(declare-function org-mark-ring-push "org" (&optional pos buffer))
|
||||
(declare-function org-fold-show-context "org-fold" (&optional key))
|
||||
|
|
@ -248,13 +248,16 @@ otherwise."
|
|||
|
||||
;;;; Internal functions
|
||||
|
||||
(defun org-footnote--allow-reference-p ()
|
||||
"Non-nil when a footnote reference can be inserted at point."
|
||||
(defun org-footnote--allow-reference-p (&optional inline)
|
||||
"Non-nil when a footnote reference can be inserted at point.
|
||||
When optional argument INLINE is non-nil, assume that the footnote
|
||||
reference is an inline or anonymous footnote (and can be placed at the
|
||||
beginning of the line)."
|
||||
;; XXX: This is similar to `org-footnote-in-valid-context-p' but
|
||||
;; more accurate and usually faster, except in some corner cases.
|
||||
;; It may replace it after doing proper benchmarks as it would be
|
||||
;; used in fontification.
|
||||
(unless (bolp)
|
||||
(unless (and (not inline) (bolp))
|
||||
(let* ((context (org-element-context))
|
||||
(type (org-element-type context)))
|
||||
(cond
|
||||
|
|
@ -401,7 +404,8 @@ References are sorted according to a deep-reading order."
|
|||
(dolist (r (mapcar (lambda (l) (assoc l references))
|
||||
(reverse
|
||||
(cdr (assoc (nth 0 ref) nested)))))
|
||||
(funcall add-reference r t))))))
|
||||
(unless (member r ordered) ; avoid infinite recursion when references link to each other
|
||||
(funcall add-reference r t)))))))
|
||||
(dolist (r (reverse references) (nreverse ordered))
|
||||
(funcall add-reference r nil))))))
|
||||
|
||||
|
|
@ -665,8 +669,6 @@ This command prompts for a label. If this is a label referencing an
|
|||
existing label, only insert the label. If the footnote label is empty
|
||||
or new, let the user edit the definition of the footnote."
|
||||
(interactive)
|
||||
(unless (org-footnote--allow-reference-p)
|
||||
(user-error "Cannot insert a footnote here"))
|
||||
(let* ((all (org-footnote-all-labels))
|
||||
(label
|
||||
(unless (eq org-footnote-auto-label 'anonymous)
|
||||
|
|
@ -680,16 +682,24 @@ or new, let the user edit the definition of the footnote."
|
|||
(mapcar #'list all) nil nil
|
||||
(and (eq org-footnote-auto-label 'confirm) propose)))))))))
|
||||
(cond ((not label)
|
||||
(unless (org-footnote--allow-reference-p 'anonymous)
|
||||
(user-error "Cannot insert a footnote here"))
|
||||
(insert "[fn::]")
|
||||
(backward-char 1))
|
||||
((member label all)
|
||||
(unless (org-footnote--allow-reference-p)
|
||||
(user-error "Cannot insert a footnote here"))
|
||||
(insert "[fn:" label "]")
|
||||
(message "New reference to existing note"))
|
||||
(org-footnote-define-inline
|
||||
(unless (org-footnote--allow-reference-p 'inline)
|
||||
(user-error "Cannot insert a footnote here"))
|
||||
(insert "[fn:" label ":]")
|
||||
(backward-char 1)
|
||||
(org-footnote-auto-adjust-maybe))
|
||||
(t
|
||||
(unless (org-footnote--allow-reference-p)
|
||||
(user-error "Cannot insert a footnote here"))
|
||||
(insert "[fn:" label "]")
|
||||
(let ((p (org-footnote-create-definition label)))
|
||||
;; `org-footnote-goto-definition' needs to be called
|
||||
|
|
|
|||
|
|
@ -134,14 +134,9 @@ When nil, you can use these keybindings to navigate the buffer:
|
|||
(org-defkey map "\C-c\C-u" 'outline-up-heading)
|
||||
map)))
|
||||
|
||||
;; `isearch-other-control-char' was removed in Emacs 24.4.
|
||||
(if (fboundp 'isearch-other-control-char)
|
||||
(progn
|
||||
(define-key org-goto-local-auto-isearch-map "\C-i" 'isearch-other-control-char)
|
||||
(define-key org-goto-local-auto-isearch-map "\C-m" 'isearch-other-control-char))
|
||||
(define-key org-goto-local-auto-isearch-map "\C-i" nil)
|
||||
(define-key org-goto-local-auto-isearch-map "\C-m" nil)
|
||||
(define-key org-goto-local-auto-isearch-map [return] nil))
|
||||
(define-key org-goto-local-auto-isearch-map "\C-i" nil)
|
||||
(define-key org-goto-local-auto-isearch-map "\C-m" nil)
|
||||
(define-key org-goto-local-auto-isearch-map [return] nil)
|
||||
|
||||
(defun org-goto--local-search-headings (string bound noerror)
|
||||
"Search and make sure that any matches are in headlines."
|
||||
|
|
|
|||
|
|
@ -80,8 +80,6 @@
|
|||
|
||||
(declare-function message-make-fqdn "message" ())
|
||||
(declare-function org-goto-location "org-goto" (&optional _buf help))
|
||||
;; Declared inside `org-element-with-disabled-cache' macro.
|
||||
(declare-function org-element--cache-active-p "org-element.el" (&optional called-from-cache-change-func-p))
|
||||
|
||||
;;; Customization
|
||||
|
||||
|
|
@ -295,6 +293,16 @@ This variable is only relevant when `org-id-track-globally' is set."
|
|||
:group 'org-id
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom org-id-completion-targets
|
||||
'((nil . t)
|
||||
(org-id-files . t))
|
||||
"Candidate headings for completing \"id:\" links in `\\[org-insert-link]'.
|
||||
This variable has the same form as `org-refile-targets', which see."
|
||||
:group 'org-id
|
||||
:type (get 'org-refile-targets 'custom-type)
|
||||
:package-version '(Org . "9.8")
|
||||
:risky t)
|
||||
|
||||
;;; The API functions
|
||||
|
||||
;;;###autoload
|
||||
|
|
@ -354,7 +362,7 @@ TARGETS may be a setting for `org-refile-targets' to define
|
|||
eligible headlines. When omitted, all headlines in the current
|
||||
file are eligible. This function returns the ID of the entry.
|
||||
If necessary, the ID is created."
|
||||
(let* ((org-refile-targets (or targets '((nil . (:maxlevel . 10)))))
|
||||
(let* ((org-refile-targets (or targets '((nil . t))))
|
||||
(org-refile-use-outline-path
|
||||
(if (caar org-refile-targets) 'file t))
|
||||
(org-refile-target-verify-function nil)
|
||||
|
|
@ -631,7 +639,10 @@ If SILENT is non-nil, messages are suppressed."
|
|||
(let ((loc (file-name-directory org-id-locations-file)))
|
||||
(mapc (lambda (item)
|
||||
(unless (file-name-absolute-p (car item))
|
||||
(setf (car item) (expand-file-name (car item) loc))))
|
||||
(setf (car item)
|
||||
;; Abbreviate as `org-id-add-location' does.
|
||||
(abbreviate-file-name
|
||||
(expand-file-name (car item) loc)))))
|
||||
org-id-locations)))
|
||||
(error
|
||||
(message "Could not read `org-id-locations' from %s, setting it to nil"
|
||||
|
|
@ -705,8 +716,9 @@ This is to be able to write it to a file."
|
|||
(hash-table-p org-id-locations)
|
||||
(gethash id org-id-locations))
|
||||
;; Fall back on current buffer
|
||||
(when (derived-mode-p 'org-mode)
|
||||
(buffer-file-name (or (buffer-base-buffer (current-buffer))
|
||||
(current-buffer)))))
|
||||
(current-buffer))))))
|
||||
|
||||
(defun org-id-find-id-in-file (id file &optional markerp)
|
||||
"Return the position of the entry ID in FILE.
|
||||
|
|
@ -884,9 +896,47 @@ will be tried as an ID."
|
|||
(org-element-lineage (org-element-at-point) 'headline t))))
|
||||
(org-fold-show-context)))
|
||||
|
||||
(defun org-id-complete (&optional _arg)
|
||||
"Complete IDs for `org-insert-link'.
|
||||
|
||||
If a headline without an ID is selected, one will automatically be
|
||||
created."
|
||||
(unless org-id-locations (org-id-locations-load))
|
||||
(or (ignore-errors ; Catch the error if we have no refile targets.
|
||||
(when-let* ((id (org-id-get-with-outline-path-completion
|
||||
(if (buffer-file-name) org-id-completion-targets
|
||||
;; If the current buffer isn't associated
|
||||
;; with a file, we can't include it so we
|
||||
;; exclude all "targets" where the car is
|
||||
;; nil.
|
||||
(seq-filter #'car org-id-completion-targets)))))
|
||||
(concat "id:" id)))
|
||||
(read-string "Link: " "id:")))
|
||||
|
||||
(defun org-id-description (link desc)
|
||||
"Return a description for an ID link, derived from the linked headline.
|
||||
|
||||
Calling convention is similar to `org-link-make-description-function'.
|
||||
DESC has higher priority and is returned if it is both non-nil and
|
||||
non-empty. Otherwise, if the passed LINK is an ID link and can be
|
||||
resolved to an existing headline, the target headline is returned. If
|
||||
all else fails, DESC is returned as-is.
|
||||
|
||||
TODO keywords, tags, and priorities are stripped from the description."
|
||||
(or (org-string-nw-p desc)
|
||||
(when-let* ((loc (org-id-find (string-remove-prefix "id:" link))))
|
||||
(org-with-file-buffer (car loc)
|
||||
(org-with-wide-buffer
|
||||
(goto-char (cdr loc))
|
||||
(org-link-display-format
|
||||
(org-get-heading t t t t)))))
|
||||
desc))
|
||||
|
||||
(org-link-set-parameters "id"
|
||||
:follow #'org-id-open
|
||||
:store #'org-id-store-link-maybe)
|
||||
:store #'org-id-store-link-maybe
|
||||
:complete #'org-id-complete
|
||||
:insert-description #'org-id-description)
|
||||
|
||||
(provide 'org-id)
|
||||
|
||||
|
|
|
|||
|
|
@ -45,8 +45,6 @@
|
|||
|
||||
(require 'cl-lib)
|
||||
|
||||
(declare-function org-inlinetask-get-task-level "org-inlinetask" ())
|
||||
(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
|
||||
(declare-function org-list-item-body-column "org-list" (item))
|
||||
(defvar org-inlinetask-show-first-star)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2018-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
|
||||
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
|
|
@ -37,29 +38,29 @@
|
|||
(require 'oc)
|
||||
|
||||
(declare-function org-add-note "org" ())
|
||||
(declare-function org-agenda "org" (&optional arg org-keys restriction))
|
||||
(declare-function org-agenda "org-agenda" (&optional arg org-keys restriction))
|
||||
(declare-function org-agenda-file-to-front "org" (&optional to-end))
|
||||
(declare-function org-agenda-remove-restriction-lock "org" (&optional noupdate))
|
||||
(declare-function org-agenda-set-restriction-lock "org" (&optional type))
|
||||
(declare-function org-archive-subtree "org" (&optional find-done))
|
||||
(declare-function org-archive-subtree-default "org" ())
|
||||
(declare-function org-archive-subtree-default-with-confirmation "org" ())
|
||||
(declare-function org-archive-to-archive-sibling "org" ())
|
||||
(declare-function org-agenda-remove-restriction-lock "org-agenda" (&optional noupdate))
|
||||
(declare-function org-agenda-set-restriction-lock "org-agenda" (&optional type))
|
||||
(declare-function org-archive-subtree "org-archive" (&optional find-done))
|
||||
(declare-function org-archive-subtree-default "org-archive" ())
|
||||
(declare-function org-archive-subtree-default-with-confirmation "org-archive" ())
|
||||
(declare-function org-archive-to-archive-sibling "org-archive" ())
|
||||
(declare-function org-at-heading-p "org" (&optional ignored))
|
||||
(declare-function org-attach "org" ())
|
||||
(declare-function org-attach "org-attach" ())
|
||||
(declare-function org-backward-element "org" ())
|
||||
(declare-function org-backward-heading-same-level "org" (arg &optional invisible-ok))
|
||||
(declare-function org-backward-paragraph "org" ())
|
||||
(declare-function org-backward-paragraph "org" (&optional arg))
|
||||
(declare-function org-backward-sentence "org" (&optional arg))
|
||||
(declare-function org-beginning-of-line "org" (&optional n))
|
||||
(declare-function org-clock-cancel "org" ())
|
||||
(declare-function org-clock-display "org" (&optional arg))
|
||||
(declare-function org-clock-goto "org" (&optional select))
|
||||
(declare-function org-clock-in "org" (&optional select start-time))
|
||||
(declare-function org-clock-in-last "org" (&optional arg))
|
||||
(declare-function org-clock-out "org" (&optional switch-to-state fail-quietly at-time))
|
||||
(declare-function org-clock-cancel "org-clock" ())
|
||||
(declare-function org-clock-display "org-clock" (&optional arg))
|
||||
(declare-function org-clock-goto "org-clock" (&optional select))
|
||||
(declare-function org-clock-in "org-clock" (&optional select start-time))
|
||||
(declare-function org-clock-in-last "org-clock" (&optional arg))
|
||||
(declare-function org-clock-out "org-clock" (&optional switch-to-state fail-quietly at-time))
|
||||
(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-colview" (&optional global columns-fmt-string))
|
||||
(declare-function org-comment-dwim "org" (arg))
|
||||
(declare-function org-copy-special "org" ())
|
||||
(declare-function org-copy-visible "org" (beg end))
|
||||
|
|
@ -71,15 +72,15 @@
|
|||
(declare-function org-cut-special "org" ())
|
||||
(declare-function org-cut-subtree "org" (&optional n))
|
||||
(declare-function org-cycle "org-cycle" (&optional arg))
|
||||
(declare-function org-cycle-agenda-files "org-cycle" ())
|
||||
(declare-function org-cycle-agenda-files "org" ())
|
||||
(declare-function org-date-from-calendar "org" ())
|
||||
(declare-function org-dynamic-block-insert-dblock "org" (&optional arg))
|
||||
(declare-function org-dynamic-block-insert-dblock "org" (type &optional interactive-p))
|
||||
(declare-function org-dblock-update "org" (&optional arg))
|
||||
(declare-function org-deadline "org" (arg1 &optional time))
|
||||
(declare-function org-decrease-number-at-point "org" (&optional inc))
|
||||
(declare-function org-delete-backward-char "org" (n))
|
||||
(declare-function org-delete-char "org" (n))
|
||||
(declare-function org-delete-indentation "org" (&optional arg))
|
||||
(declare-function org-delete-indentation "org" (&optional arg beg end))
|
||||
(declare-function org-demote-subtree "org" ())
|
||||
(declare-function org-display-outline-path "org" (&optional file current separator just-return-string))
|
||||
(declare-function org-down-element "org" ())
|
||||
|
|
@ -89,7 +90,6 @@
|
|||
(declare-function org-emphasize "org" (&optional char))
|
||||
(declare-function org-end-of-line "org" (&optional n))
|
||||
(declare-function org-entry-put "org" (pom property value))
|
||||
(declare-function org-eval-in-calendar "org" (form &optional keepdate))
|
||||
(declare-function org-calendar-goto-today-or-insert-dot "org" ())
|
||||
(declare-function org-calendar-goto-today "org" ())
|
||||
(declare-function org-calendar-backward-month "org" ())
|
||||
|
|
@ -106,34 +106,34 @@
|
|||
(declare-function org-calendar-scroll-three-months-left "org" ())
|
||||
(declare-function org-calendar-scroll-three-months-right "org" ())
|
||||
(declare-function org-evaluate-time-range "org" (&optional to-buffer))
|
||||
(declare-function org-export-dispatch "org" (&optional arg))
|
||||
(declare-function org-feed-goto-inbox "org" (feed))
|
||||
(declare-function org-feed-update-all "org" ())
|
||||
(declare-function org-export-dispatch "ox" (&optional arg))
|
||||
(declare-function org-feed-goto-inbox "org-feed" (feed))
|
||||
(declare-function org-feed-update-all "org-feed" ())
|
||||
(declare-function org-fill-paragraph "org" (&optional justify region))
|
||||
(declare-function org-find-file-at-mouse "org" (ev))
|
||||
(declare-function org-footnote-action "org" (&optional special))
|
||||
(declare-function org-footnote-action "org-footnote" (&optional special))
|
||||
(declare-function org-cycle-force-archived "org-cycle" ())
|
||||
(declare-function org-force-self-insert "org" (n))
|
||||
(declare-function org-forward-element "org" ())
|
||||
(declare-function org-forward-heading-same-level "org" (arg &optional invisible-ok))
|
||||
(declare-function org-forward-paragraph "org" ())
|
||||
(declare-function org-forward-paragraph "org" (&optional arg))
|
||||
(declare-function org-forward-sentence "org" (&optional arg))
|
||||
(declare-function org-goto "org" (&optional alternative-interface))
|
||||
(declare-function org-goto "org-goto" (&optional alternative-interface))
|
||||
(declare-function org-goto-calendar "org" (&optional arg))
|
||||
(declare-function org-inc-effort "org" ())
|
||||
(declare-function org-increase-number-at-point "org" (&optional inc))
|
||||
(declare-function org-info-find-node "org" (&optional nodename))
|
||||
(declare-function org-insert-all-links "org" (arg &optional pre post))
|
||||
(declare-function org-insert-all-links "ol" (arg &optional pre post))
|
||||
(declare-function org-insert-drawer "org" (&optional arg drawer))
|
||||
(declare-function org-insert-heading-respect-content "org" (&optional invisible-ok))
|
||||
(declare-function org-insert-last-stored-link "org" (arg))
|
||||
(declare-function org-insert-link "org" (&optional complete-file link-location default-description))
|
||||
(declare-function org-insert-last-stored-link "ol" (arg))
|
||||
(declare-function org-insert-link "ol" (&optional complete-file link-location default-description))
|
||||
(declare-function org-insert-structure-template "org" (type))
|
||||
(declare-function org-insert-todo-heading "org" (arg &optional force-heading))
|
||||
(declare-function org-insert-todo-heading-respect-content "org" (&optional force-state))
|
||||
(declare-function org-kill-line "org" (&optional arg))
|
||||
(declare-function org-kill-note-or-show-branches "org" ())
|
||||
(declare-function org-list-make-subtree "org" ())
|
||||
(declare-function org-list-make-subtree "org-list" ())
|
||||
(declare-function org-mark-element "org" ())
|
||||
(declare-function org-mark-ring-goto "org" (&optional n))
|
||||
(declare-function org-mark-ring-push "org" (&optional pos buffer))
|
||||
|
|
@ -148,27 +148,29 @@
|
|||
(declare-function org-narrow-to-element "org" ())
|
||||
(declare-function org-narrow-to-subtree "org" (&optional element))
|
||||
(declare-function org-next-block "org" (arg &optional backward block-regexp))
|
||||
(declare-function org-next-link "org" (&optional search-backward))
|
||||
(declare-function org-next-link "ol" (&optional search-backward))
|
||||
(declare-function org-next-visible-heading "org" (arg))
|
||||
(declare-function org-open-at-mouse "org" (ev))
|
||||
(declare-function org-open-at-point "org" (&optional arg reference-buffer))
|
||||
(declare-function org-open-at-point "org" (&optional arg))
|
||||
(declare-function org-open-line "org" (n))
|
||||
(declare-function org-paste-special "org" (arg))
|
||||
(declare-function org-plot/gnuplot "org-plot" (&optional params))
|
||||
(declare-function org-previous-block "org" (arg &optional block-regexp))
|
||||
(declare-function org-previous-link "org" ())
|
||||
(declare-function org-previous-link "ol" ())
|
||||
(declare-function org-previous-visible-heading "org" (arg))
|
||||
(declare-function org-priority "org" (&optional action show))
|
||||
(defvar org-priority-highest)
|
||||
(defvar org-priority-default)
|
||||
(defvar org-priority-lowest)
|
||||
(declare-function org-promote-subtree "org" ())
|
||||
(declare-function org-redisplay-inline-images "org" ())
|
||||
(declare-function org-refile "org-refile" (&optional arg1 default-buffer rfloc msg))
|
||||
(declare-function org-refile-copy "org-refile" ())
|
||||
(declare-function org-refile-reverse "org-refile" (&optional arg default-buffer rfloc msg))
|
||||
(declare-function org-reftex-citation "org" ())
|
||||
(declare-function org-reload "org" (&optional arg1))
|
||||
(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-return "org" (&optional indent))
|
||||
(declare-function org-resolve-clocks "org-clock" (&optional only-dangling-p prompt-fn last-valid))
|
||||
(declare-function org-return "org" (&optional indent arg interactive))
|
||||
(declare-function org-return-and-maybe-indent "org" ())
|
||||
(declare-function org-fold-reveal "org-fold" (&optional siblings))
|
||||
(declare-function org-schedule "org" (arg &optional time))
|
||||
|
|
@ -190,36 +192,36 @@
|
|||
(declare-function org-shiftright "org" (&optional arg))
|
||||
(declare-function org-shifttab "org" (&optional arg))
|
||||
(declare-function org-shiftup "org" (&optional arg))
|
||||
(declare-function org-fold-show-all "org-fold" (&optional types))
|
||||
(declare-function org-fold-show-children "org-fold" (&optional level))
|
||||
(declare-function org-fold-show-subtree "org-fold" ())
|
||||
(declare-function org-sort "org" (&optional with-case))
|
||||
(declare-function org-sparse-tree "org" (&optional arg type))
|
||||
(declare-function org-table-copy-down "org" (n))
|
||||
(declare-function org-table-create-or-convert-from-region "org" (arg))
|
||||
(declare-function org-table-copy-down "org-table" (n))
|
||||
(declare-function org-table-create-or-convert-from-region "org-table" (arg))
|
||||
(declare-function org-table-create-with-table\.el "org-table" ())
|
||||
(declare-function org-table-edit-field "org" (arg))
|
||||
(declare-function org-table-eval-formula "org" (&optional arg equation suppress-align suppress-const suppress-store suppress-analysis))
|
||||
(declare-function org-table-field-info "org" (arg))
|
||||
(declare-function org-table-rotate-recalc-marks "org" (&optional newchar))
|
||||
(declare-function org-table-sum "org" (&optional beg end nlast))
|
||||
(declare-function org-table-toggle-coordinate-overlays "org" ())
|
||||
(declare-function org-table-toggle-formula-debugger "org" ())
|
||||
(declare-function org-table-edit-field "org-table" (arg))
|
||||
(declare-function org-table-eval-formula "org-table" (&optional arg equation suppress-align suppress-const suppress-store suppress-analysis))
|
||||
(declare-function org-table-field-info "org-table" (arg))
|
||||
(declare-function org-table-rotate-recalc-marks "org-table" (&optional newchar))
|
||||
(declare-function org-table-sum "org-table" (&optional beg end nlast))
|
||||
(declare-function org-table-toggle-coordinate-overlays "org-table" ())
|
||||
(declare-function org-table-toggle-formula-debugger "org-table" ())
|
||||
(declare-function org-timestamp "org" (arg &optional inactive))
|
||||
(declare-function org-timestamp-inactive "org" (&optional arg))
|
||||
(declare-function org-timer "org" (&optional restart no-insert))
|
||||
(declare-function org-timer-item "org" (&optional arg))
|
||||
(declare-function org-timer-pause-or-continue "org" (&optional stop))
|
||||
(declare-function org-timer-set-timer "org" (&optional opt))
|
||||
(declare-function org-timer-start "org" (&optional offset))
|
||||
(declare-function org-timer-stop "org" ())
|
||||
(declare-function org-timer "org-timer" (&optional restart no-insert))
|
||||
(declare-function org-timer-item "org-timer" (&optional arg))
|
||||
(declare-function org-timer-pause-or-continue "org-timer" (&optional stop))
|
||||
(declare-function org-timer-set-timer "org-timer" (&optional opt))
|
||||
(declare-function org-timer-start "org-timer" (&optional offset))
|
||||
(declare-function org-timer-stop "org-timer" ())
|
||||
(declare-function org-todo "org" (&optional arg1))
|
||||
(declare-function org-toggle-archive-tag "org" (&optional find-done))
|
||||
(declare-function org-toggle-checkbox "org" (&optional toggle-presence))
|
||||
(declare-function org-toggle-radio-button "org" (&optional arg))
|
||||
(declare-function org-toggle-archive-tag "org-archive" (&optional find-done))
|
||||
(declare-function org-toggle-checkbox "org-list" (&optional toggle-presence))
|
||||
(declare-function org-toggle-radio-button "org-list" (&optional arg))
|
||||
(declare-function org-toggle-comment "org" ())
|
||||
(declare-function org-toggle-fixed-width "org" ())
|
||||
(declare-function org-toggle-inline-images "org" (&optional include-linked beg end))
|
||||
(declare-function org-link-preview "ol" (&optional arg beg end))
|
||||
(declare-function org-link-preview-refresh "ol" ())
|
||||
(declare-function org-latex-preview "org" (&optional arg))
|
||||
(declare-function org-toggle-narrow-to-subtree "org" ())
|
||||
(declare-function org-toggle-ordered-property "org" ())
|
||||
|
|
@ -233,6 +235,7 @@
|
|||
(declare-function org-update-statistics-cookies "org" (all))
|
||||
(declare-function org-yank "org" (&optional arg))
|
||||
(declare-function orgtbl-ascii-plot "org-table" (&optional ask))
|
||||
(declare-function outline-up-heading "outline" (arg &optional invisible-ok))
|
||||
|
||||
|
||||
|
||||
|
|
@ -390,9 +393,9 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
|
|||
;;; Global bindings
|
||||
|
||||
;;;; Outline functions
|
||||
(define-key org-mode-map [menu-bar headings] 'undefined)
|
||||
(define-key org-mode-map [menu-bar hide] 'undefined)
|
||||
(define-key org-mode-map [menu-bar show] 'undefined)
|
||||
(define-key org-mode-map [menu-bar headings] #'undefined)
|
||||
(define-key org-mode-map [menu-bar hide] #'undefined)
|
||||
(define-key org-mode-map [menu-bar show] #'undefined)
|
||||
|
||||
(define-key org-mode-map [remap outline-mark-subtree] #'org-mark-subtree)
|
||||
(define-key org-mode-map [remap outline-show-subtree] #'org-fold-show-subtree)
|
||||
|
|
@ -410,6 +413,8 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
|
|||
(define-key org-mode-map [remap outline-previous-visible-heading]
|
||||
#'org-previous-visible-heading)
|
||||
(define-key org-mode-map [remap outline-show-children] #'org-fold-show-children)
|
||||
(defalias 'org-up-heading #'outline-up-heading)
|
||||
(define-key org-mode-map [remap outline-up-heading] #'org-up-heading)
|
||||
|
||||
;;;; Make `C-c C-x' a prefix key
|
||||
(org-defkey org-mode-map (kbd "C-c C-x") (make-sparse-keymap))
|
||||
|
|
@ -463,6 +468,37 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
|
|||
(org-defkey org-mode-map (kbd "C-S-<up>") #'org-shiftcontrolup)
|
||||
(org-defkey org-mode-map (kbd "C-S-<down>") #'org-shiftcontroldown)
|
||||
|
||||
;;; Repeat-mode map.
|
||||
(defvar org-navigation-repeat-map (make-sparse-keymap)
|
||||
"Repeat keymap for navigation commands.")
|
||||
(org-defkey org-navigation-repeat-map (kbd "b") #'org-backward-heading-same-level)
|
||||
(org-defkey org-navigation-repeat-map (kbd "f") #'org-forward-heading-same-level)
|
||||
(org-defkey org-navigation-repeat-map (kbd "n") #'org-next-visible-heading)
|
||||
(org-defkey org-navigation-repeat-map (kbd "p") #'org-previous-visible-heading)
|
||||
(org-defkey org-navigation-repeat-map (kbd "u") #'org-up-heading)
|
||||
(map-keymap
|
||||
(lambda (_key cmd)
|
||||
(put cmd 'repeat-map 'org-navigation-repeat-map))
|
||||
org-navigation-repeat-map)
|
||||
|
||||
(defvar org-link-navigation-repeat-map (make-sparse-keymap)
|
||||
"Repeat keymap for link navigation commands.")
|
||||
(org-defkey org-link-navigation-repeat-map (kbd "n") #'org-next-link)
|
||||
(org-defkey org-link-navigation-repeat-map (kbd "p") #'org-previous-link)
|
||||
(map-keymap
|
||||
(lambda (_ cmd)
|
||||
(put cmd 'repeat-map 'org-link-navigation-repeat-map))
|
||||
org-link-navigation-repeat-map)
|
||||
|
||||
(defvar org-block-navigation-repeat-map (make-sparse-keymap)
|
||||
"Repeat keymap for block navigation commands.")
|
||||
(org-defkey org-block-navigation-repeat-map (kbd "f") #'org-next-block)
|
||||
(org-defkey org-block-navigation-repeat-map (kbd "b") #'org-previous-block)
|
||||
(map-keymap
|
||||
(lambda (_ cmd)
|
||||
(put cmd 'repeat-map 'org-block-navigation-repeat-map))
|
||||
org-block-navigation-repeat-map)
|
||||
|
||||
;;;; Extra keys for TTY access.
|
||||
|
||||
;; We only set them when really needed because otherwise the
|
||||
|
|
@ -619,8 +655,8 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
|
|||
(org-defkey org-mode-map (kbd "C-c C-x x") #'org-dynamic-block-insert-dblock)
|
||||
(org-defkey org-mode-map (kbd "C-c C-x C-u") #'org-dblock-update)
|
||||
(org-defkey org-mode-map (kbd "C-c C-x C-l") #'org-latex-preview)
|
||||
(org-defkey org-mode-map (kbd "C-c C-x C-v") #'org-toggle-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 C-v") #'org-link-preview)
|
||||
(org-defkey org-mode-map (kbd "C-c C-x C-M-v") #'org-link-preview-refresh)
|
||||
(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-r") #'org-toggle-radio-button)
|
||||
|
|
@ -655,8 +691,13 @@ commands should be active.
|
|||
For example, to activate speed commands when the point is on any
|
||||
star at the beginning of the headline, you can do this:
|
||||
|
||||
(setq org-use-speed-commands
|
||||
(lambda () (and (looking-at org-outline-regexp) (looking-back \"^\\**\"))))"
|
||||
(setopt org-use-speed-commands
|
||||
(lambda ()
|
||||
(and (looking-at org-outline-regexp)
|
||||
(looking-back \"^\\\\**\"))))
|
||||
|
||||
Note that prior to Emacs 29, `setopt' is unavailable, and
|
||||
`custom-set-variables' or `setq' is used instead."
|
||||
:group 'org-structure
|
||||
:type '(choice
|
||||
(const :tag "Never" nil)
|
||||
|
|
@ -719,10 +760,10 @@ hook. The default setting is `org-speed-command-activate'."
|
|||
("Meta Data Editing")
|
||||
("t" . org-todo)
|
||||
("," . (org-priority))
|
||||
("0" . (org-priority ?\ ))
|
||||
("1" . (org-priority ?A))
|
||||
("2" . (org-priority ?B))
|
||||
("3" . (org-priority ?C))
|
||||
("0" . (org-priority 'remove))
|
||||
("1" . (org-priority org-priority-highest))
|
||||
("2" . (org-priority org-priority-default))
|
||||
("3" . (org-priority org-priority-lowest))
|
||||
(":" . org-set-tags-command)
|
||||
("e" . org-set-effort)
|
||||
("E" . org-inc-effort)
|
||||
|
|
@ -748,7 +789,7 @@ interpreted as a descriptive headline that will be added when
|
|||
listing the speed commands in the Help buffer using the `?' speed
|
||||
command."
|
||||
:group 'org-structure
|
||||
:package-version '(Org . "9.5")
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(repeat :value ("k" . ignore)
|
||||
(choice :value ("k" . ignore)
|
||||
(list :tag "Descriptive Headline" (string :tag "Headline"))
|
||||
|
|
@ -756,7 +797,8 @@ command."
|
|||
(string :tag "Command letter")
|
||||
(choice
|
||||
(function)
|
||||
(sexp))))))
|
||||
(sexp)))))
|
||||
:risky t)
|
||||
|
||||
(defun org--print-speed-command (speed-command)
|
||||
"Print information about SPEED-COMMAND in help buffer.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
;; Checks currently implemented report the following:
|
||||
|
||||
;; - duplicates CUSTOM_ID properties,
|
||||
;; - duplicate CUSTOM_ID properties,
|
||||
;; - duplicate NAME values,
|
||||
;; - duplicate targets,
|
||||
;; - duplicate footnote definitions,
|
||||
|
|
@ -159,6 +159,16 @@ checker. Currently, two properties are supported:
|
|||
(seq-remove (lambda (c) (eq name (org-lint-checker-name c)))
|
||||
org-lint--checkers))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-lint-remove-checker (name &rest names)
|
||||
"Remove checker(s) from linter.
|
||||
NAME is the unique check identifier, as a non-nil symbol. NAMES
|
||||
are additional check identifiers to be removed."
|
||||
(let ((removelist (cons name names)))
|
||||
(setq org-lint--checkers
|
||||
(seq-remove (lambda (c) (memq (org-lint-checker-name c) removelist))
|
||||
org-lint--checkers))))
|
||||
|
||||
|
||||
;;; Reports UI
|
||||
|
||||
|
|
@ -470,7 +480,10 @@ Example:
|
|||
(when (= (org-element-post-blank keyword) 0)
|
||||
(let ((next-element (org-with-point-at (org-element-end keyword)
|
||||
(org-element-at-point))))
|
||||
(when (< (org-element-begin next-element) (org-element-post-affiliated next-element))
|
||||
(when (and
|
||||
;; KEYWORD being the last in the file is OK.
|
||||
(not (equal (org-element-begin next-element) (org-element-begin keyword)))
|
||||
(< (org-element-begin next-element) (org-element-post-affiliated next-element)))
|
||||
;; A keyword followed without blank lines by an element with affiliated keywords.
|
||||
;; The keyword may be confused with affiliated keywords.
|
||||
(list (org-element-begin keyword)
|
||||
|
|
@ -553,9 +566,8 @@ Use :header-args: instead"
|
|||
(lambda (b)
|
||||
(when-let* ((lang (org-element-property :language b)))
|
||||
(unless (or (functionp (intern (format "org-babel-execute:%s" lang)))
|
||||
;; No babel backend, but there is corresponding
|
||||
;; major mode.
|
||||
(fboundp (org-src-get-lang-mode lang)))
|
||||
;; No Babel backend, but relevant major mode is bound.
|
||||
(org-src-get-lang-mode-if-bound lang))
|
||||
(list (org-element-property :post-affiliated b)
|
||||
(format "Unknown source block language: '%s'" lang)))))))
|
||||
|
||||
|
|
@ -718,6 +730,10 @@ Use :header-args: instead"
|
|||
(pcase type
|
||||
((or "attachment" "file")
|
||||
(let* ((path (org-element-property :path l))
|
||||
(path (if (and (equal type "attachment")
|
||||
(string-match "::\\(.*\\)\\'" path))
|
||||
(substring path 0 (match-beginning 0))
|
||||
path))
|
||||
(file (if (string= type "file")
|
||||
path
|
||||
(org-with-point-at (org-element-begin l)
|
||||
|
|
@ -837,7 +853,6 @@ Use \"export %s\" instead"
|
|||
|
||||
(defun org-lint-export-option-keywords (ast)
|
||||
"Check for options keyword properties without EXPORT in AST."
|
||||
(require 'ox)
|
||||
(let (options reports common-options options-alist)
|
||||
(dolist (opt org-export-options-alist)
|
||||
(when (stringp (nth 1 opt))
|
||||
|
|
@ -872,6 +887,7 @@ Use \"export %s\" instead"
|
|||
reports))
|
||||
|
||||
(defun org-lint-invalid-macro-argument-and-template (ast)
|
||||
"Check for invalid macro arguments in AST."
|
||||
(let* ((reports nil)
|
||||
(extract-placeholders
|
||||
(lambda (template)
|
||||
|
|
@ -934,7 +950,7 @@ Use \"export %s\" instead"
|
|||
name))
|
||||
reports))))))))
|
||||
;; Check arguments for macros.
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-initialize-templates org-export-global-macros)
|
||||
(let ((templates (append
|
||||
(mapcar (lambda (m) (cons m "$1"))
|
||||
'("author" "date" "email" "title" "results"))
|
||||
|
|
@ -1236,7 +1252,7 @@ Use \"export %s\" instead"
|
|||
(funcall verify
|
||||
datum
|
||||
nil
|
||||
(cl-mapcan #'org-babel-parse-header-arguments
|
||||
(cl-mapcan (lambda (s) (org-babel-parse-header-arguments s 'no-eval))
|
||||
(list
|
||||
(org-element-property :inside-header datum)
|
||||
(org-element-property :end-header datum)))))
|
||||
|
|
@ -1245,7 +1261,8 @@ Use \"export %s\" instead"
|
|||
datum
|
||||
(org-element-property :language datum)
|
||||
(org-babel-parse-header-arguments
|
||||
(org-element-property :parameters datum))))
|
||||
(org-element-property :parameters datum)
|
||||
'no-eval)))
|
||||
(`keyword
|
||||
(when (string= (org-element-property :key datum) "PROPERTY")
|
||||
(let ((value (org-element-property :value datum)))
|
||||
|
|
@ -1257,7 +1274,8 @@ Use \"export %s\" instead"
|
|||
datum
|
||||
(match-string 1 value)
|
||||
(org-babel-parse-header-arguments
|
||||
(substring value (match-end 0))))))))
|
||||
(substring value (match-end 0))
|
||||
'no-eval))))))
|
||||
(`node-property
|
||||
(let ((key (org-element-property :key datum)))
|
||||
(when (let ((case-fold-search t))
|
||||
|
|
@ -1269,12 +1287,13 @@ Use \"export %s\" instead"
|
|||
datum
|
||||
(match-string 1 key)
|
||||
(org-babel-parse-header-arguments
|
||||
(org-element-property :value datum))))))
|
||||
(org-element-property :value datum)
|
||||
'no-eval)))))
|
||||
(`src-block
|
||||
(funcall verify
|
||||
datum
|
||||
(org-element-property :language datum)
|
||||
(cl-mapcan #'org-babel-parse-header-arguments
|
||||
(cl-mapcan (lambda (s) (org-babel-parse-header-arguments s 'no-eval))
|
||||
(cons (org-element-property :parameters datum)
|
||||
(org-element-property :header datum))))))))
|
||||
reports))
|
||||
|
|
@ -1339,7 +1358,8 @@ Use \"export %s\" instead"
|
|||
(concat
|
||||
(org-element-property :inside-header datum)
|
||||
" "
|
||||
(org-element-property :end-header datum))))))))
|
||||
(org-element-property :end-header datum)))))
|
||||
'no-eval)))
|
||||
(dolist (header datum-header-values)
|
||||
(let ((allowed-values
|
||||
(cdr (assoc-string (substring (symbol-name (car header)) 1)
|
||||
|
|
@ -1395,7 +1415,10 @@ Use \"export %s\" instead"
|
|||
(org-export-resolve-link (car result) `(:parse-tree ,ast))
|
||||
(org-link-broken nil))
|
||||
(org-export-get-previous-element el nil))))
|
||||
(when (org-element-type-p origin-block 'src-block)
|
||||
(when (and (org-element-type-p origin-block 'src-block)
|
||||
(pcase-let ((`(,_ ,_ ,args . ,_)
|
||||
(org-babel-get-src-block-info 'light origin-block)))
|
||||
(not (member (alist-get :exports args) '("results" "both")))))
|
||||
(list (org-element-begin el)
|
||||
(format "Links to \"%s\" will not be valid during export unless the parent source block has :exports results or both" result-name)))))))
|
||||
|
||||
|
|
@ -1483,6 +1506,32 @@ Use \"export %s\" instead"
|
|||
(format "Bullet counter \"%s\" is not the same with item position %d. Consider adding manual [@%d] counter."
|
||||
bullet (car (last true-number)) bullet-number))))))))
|
||||
|
||||
(defun org-lint-priority (ast)
|
||||
"Report out-of-bounds, invalid, and malformed priorities.
|
||||
Raise warnings on headlines containing out-of-bounds, invalid (e.g.,
|
||||
`[#-1]', `[#AA]'), or malformed (e.g., `[#1', `[#A') priorities."
|
||||
(let ((bad-priority-rx (rx line-start ?\[ ?#
|
||||
(group (zero-or-more (not (in ?\[ ?\]))))
|
||||
(group (zero-or-more ?\])))))
|
||||
(org-element-map ast 'headline
|
||||
(lambda (headline)
|
||||
(if-let* ((priority (org-element-property :priority headline)))
|
||||
(when (and (not (org-priority-valid-value-p priority))
|
||||
(org-priority-valid-value-p priority t))
|
||||
(list (org-element-begin headline)
|
||||
(format "Out-of-bounds priority '%s'"
|
||||
(org-priority-to-string priority))))
|
||||
(when-let* ((headline-value (org-element-property
|
||||
:raw-value headline))
|
||||
(matches (string-match bad-priority-rx
|
||||
headline-value)))
|
||||
(list (org-element-begin headline)
|
||||
(if (string-empty-p (match-string 2 headline-value))
|
||||
(format "Malformed priority '%s'"
|
||||
(match-string 0 headline-value))
|
||||
(format "Invalid priority '%s'"
|
||||
(match-string 1 headline-value))))))))))
|
||||
|
||||
(defun org-lint-LaTeX-$ (ast)
|
||||
"Report semi-obsolete $...$ LaTeX fragments.
|
||||
AST is the buffer parse tree."
|
||||
|
|
@ -1491,6 +1540,7 @@ AST is the buffer parse tree."
|
|||
(and (string-match-p "^[$][^$]" (org-element-property :value fragment))
|
||||
(list (org-element-begin fragment)
|
||||
"Potentially confusing LaTeX fragment format. Prefer using more reliable \\(...\\)")))))
|
||||
|
||||
(defun org-lint-LaTeX-$-ambiguous (_)
|
||||
"Report LaTeX fragment-like text.
|
||||
AST is the buffer parse tree."
|
||||
|
|
@ -1507,6 +1557,7 @@ AST is the buffer parse tree."
|
|||
"$ symbol potentially matching LaTeX fragment boundary. Consider using \\dollar entity.")
|
||||
report)))
|
||||
report)))
|
||||
|
||||
(defun org-lint-timestamp-syntax (ast)
|
||||
"Report malformed timestamps.
|
||||
AST is the buffer parse tree."
|
||||
|
|
@ -1519,6 +1570,23 @@ AST is the buffer parse tree."
|
|||
(unless (equal expected actual)
|
||||
(list (org-element-property :begin timestamp)
|
||||
(format "Potentially malformed timestamp %s. Parsed as: %s" actual expected)))))))
|
||||
|
||||
(defun org-lint-clock-syntax (ast)
|
||||
"Report malformed clocks.
|
||||
AST is the buffer parse tree."
|
||||
(org-element-map ast 'clock
|
||||
(lambda (clock)
|
||||
(let ((expected (string-trim-right (org-element-interpret-data clock)))
|
||||
(actual (string-trim
|
||||
(buffer-substring-no-properties
|
||||
(org-element-property :begin clock)
|
||||
(org-element-property :end clock)))))
|
||||
(unless (equal expected actual)
|
||||
(list (org-element-property :begin clock)
|
||||
(format "Potentially malformed CLOCK: line
|
||||
%s
|
||||
Parsed as: %s" actual expected)))))))
|
||||
|
||||
(defun org-lint-inactive-planning (ast)
|
||||
"Report inactive timestamp in SCHEDULED/DEADLINE.
|
||||
AST is the buffer parse tree."
|
||||
|
|
@ -1553,7 +1621,7 @@ AST is the buffer parse tree."
|
|||
#'org-lint-misplaced-heading :trust 'low)
|
||||
|
||||
(org-lint-add-checker 'duplicate-custom-id
|
||||
"Report duplicates CUSTOM_ID properties"
|
||||
"Report duplicate CUSTOM_ID properties"
|
||||
#'org-lint-duplicate-custom-id
|
||||
:categories '(link))
|
||||
|
||||
|
|
@ -1822,6 +1890,11 @@ AST is the buffer parse tree."
|
|||
#'org-lint-item-number
|
||||
:categories '(plain-list))
|
||||
|
||||
(org-lint-add-checker 'priority
|
||||
"Report out-of-bounds, invalid, and malformed priorities."
|
||||
#'org-lint-priority
|
||||
:categories '(markup))
|
||||
|
||||
(org-lint-add-checker 'LaTeX-$
|
||||
"Report potentially confusing $...$ LaTeX markup."
|
||||
#'org-lint-LaTeX-$
|
||||
|
|
@ -1838,6 +1911,10 @@ AST is the buffer parse tree."
|
|||
"Report malformed timestamps."
|
||||
#'org-lint-timestamp-syntax
|
||||
:categories '(timestamp) :trust 'low)
|
||||
(org-lint-add-checker 'clock-syntax
|
||||
"Report malformed clocks."
|
||||
#'org-lint-clock-syntax
|
||||
:categories '(timestamp) :trust 'low)
|
||||
(org-lint-add-checker 'planning-inactive
|
||||
"Report inactive timestamps in SCHEDULED/DEADLINE."
|
||||
#'org-lint-inactive-planning
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@
|
|||
|
||||
(declare-function org-at-heading-p "org" (&optional invisible-ok))
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-back-to-heading-or-point-min "org" (&optional invisible-ok))
|
||||
(declare-function org-before-first-heading-p "org" ())
|
||||
(declare-function org-current-level "org" ())
|
||||
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
|
||||
|
|
@ -113,8 +114,8 @@
|
|||
(declare-function org-element-interpret-data "org-element" (data))
|
||||
(declare-function org-element-lineage "org-element-ast" (blob &optional types with-self))
|
||||
(declare-function org-element-macro-interpreter "org-element" (macro ##))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated))
|
||||
(declare-function org-element-normalize-string "org-element" (s))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated no-undefer))
|
||||
(declare-function org-element-normalize-string "org-element" (s &optional keep-newlines))
|
||||
(declare-function org-element-parse-buffer "org-element" (&optional granularity visible-only keep-deferred))
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
(declare-function org-element-begin "org-element" (node))
|
||||
|
|
@ -125,7 +126,7 @@
|
|||
(declare-function org-element-post-blank "org-element" (node))
|
||||
(declare-function org-element-parent "org-element-ast" (node))
|
||||
(declare-function org-element-put-property "org-element-ast" (node property value))
|
||||
(declare-function org-element-set "org-element-ast" (old new))
|
||||
(declare-function org-element-set "org-element-ast" (old new &optional keep-props))
|
||||
(declare-function org-element-type-p "org-element-ast" (node types))
|
||||
(declare-function org-element-update-syntax "org-element" ())
|
||||
(declare-function org-end-of-meta-data "org" (&optional full))
|
||||
|
|
@ -147,9 +148,9 @@
|
|||
(declare-function org-mode "org" ())
|
||||
(declare-function org-narrow-to-subtree "org" (&optional element))
|
||||
(declare-function org-outline-level "org" ())
|
||||
(declare-function org-previous-line-empty-p "org" ())
|
||||
(declare-function org-reduced-level "org" (L))
|
||||
(declare-function org-set-tags "org" (tags))
|
||||
(declare-function org--deactivate-mark "org" ())
|
||||
(declare-function org-fold-show-subtree "org-fold" ())
|
||||
(declare-function org-fold-region "org-fold" (from to flag &optional spec))
|
||||
(declare-function org-sort-remove-invisible "org" (S))
|
||||
|
|
@ -1858,7 +1859,10 @@ Initial position of cursor is restored after the changes."
|
|||
(shift-body-ind
|
||||
;; Shift the indentation between END and BEG by DELTA.
|
||||
;; Start from the line before END.
|
||||
(lambda (end beg delta)
|
||||
;; Take care not to shift to or before IND, which is the
|
||||
;; containg list item indentation. (otherwise, we are going
|
||||
;; to break the list structure)
|
||||
(lambda (end beg delta ind)
|
||||
(goto-char end)
|
||||
(skip-chars-backward " \r\t\n")
|
||||
(forward-line 0)
|
||||
|
|
@ -1871,7 +1875,8 @@ Initial position of cursor is restored after the changes."
|
|||
(org-inlinetask-goto-beginning))
|
||||
;; Shift only non-empty lines.
|
||||
((looking-at-p "^[ \t]*\\S-")
|
||||
(indent-line-to (+ (org-current-text-indentation) delta))))
|
||||
(indent-line-to (max (+ (org-current-text-indentation) delta)
|
||||
(if ind (1+ ind) -1)))))
|
||||
(forward-line -1))))
|
||||
(modify-item
|
||||
;; Replace ITEM first line elements with new elements from
|
||||
|
|
@ -1933,7 +1938,7 @@ Initial position of cursor is restored after the changes."
|
|||
(ind-shift (- (+ ind-pos (length bul-pos))
|
||||
(+ ind-old (length bul-old))))
|
||||
(end-pos (org-list-get-item-end pos old-struct)))
|
||||
(push (cons pos ind-shift) itm-shift)
|
||||
(push (list pos ind-shift ind-pos) itm-shift)
|
||||
(unless (assq end-pos old-struct)
|
||||
;; To determine real ind of an ending position that
|
||||
;; is not at an item, we have to find the item it
|
||||
|
|
@ -1955,7 +1960,7 @@ Initial position of cursor is restored after the changes."
|
|||
(down (car all-ends))
|
||||
(itemp (assq up struct))
|
||||
(delta
|
||||
(if itemp (cdr (assq up itm-shift))
|
||||
(if itemp (nth 1 (assq up itm-shift))
|
||||
;; If we're not at an item, there's a child of the
|
||||
;; item point belongs to above. Make sure the less
|
||||
;; indented line in this slice has the same column
|
||||
|
|
@ -1981,7 +1986,7 @@ Initial position of cursor is restored after the changes."
|
|||
down t)))))
|
||||
(forward-line)))
|
||||
(- ind min-ind)))))
|
||||
(push (list down up delta) sliced-struct)))
|
||||
(push (list down up delta (when itemp (nth 2 (assq up itm-shift)))) sliced-struct)))
|
||||
;; 3. Shift each slice in buffer, provided delta isn't 0, from
|
||||
;; end to beginning. Take a special action when beginning is
|
||||
;; at item bullet.
|
||||
|
|
@ -2358,7 +2363,7 @@ is an integer, 0 means `-', 1 means `+' etc. If WHICH is
|
|||
(define-minor-mode org-list-checkbox-radio-mode
|
||||
"When turned on, use list checkboxes as radio buttons."
|
||||
:lighter " CheckBoxRadio"
|
||||
(unless (eq major-mode 'org-mode)
|
||||
(unless (derived-mode-p 'org-mode)
|
||||
(user-error "Cannot turn this mode outside org-mode buffers")))
|
||||
|
||||
(defun org-toggle-radio-button (&optional arg)
|
||||
|
|
@ -2541,10 +2546,6 @@ portion of the buffer."
|
|||
(let* ((cookie-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)")
|
||||
(box-re "^[ \t]*\\([-+*]\\|\\([0-9]+\\|[A-Za-z]\\)[.)]\\)[ \t]+\
|
||||
\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?\\(\\[[- X]\\]\\)")
|
||||
(cookie-data (or (org-entry-get nil "COOKIE_DATA") ""))
|
||||
(recursivep
|
||||
(or (not org-checkbox-hierarchical-statistics)
|
||||
(string-match-p "\\<recursive\\>" cookie-data)))
|
||||
(within-inlinetask (and (not all)
|
||||
(featurep 'org-inlinetask)
|
||||
(org-inlinetask-in-task-p)))
|
||||
|
|
@ -2582,14 +2583,18 @@ portion of the buffer."
|
|||
;; Move to start.
|
||||
(cond (all (goto-char (point-min)))
|
||||
(within-inlinetask (org-back-to-heading t))
|
||||
(t (org-with-limited-levels (outline-previous-heading))))
|
||||
(t (org-with-limited-levels (org-back-to-heading-or-point-min t))))
|
||||
;; Build an alist for each cookie found. The key is the position
|
||||
;; at beginning of cookie and values ending position, format of
|
||||
;; cookie, number of checked boxes to report and total number of
|
||||
;; boxes.
|
||||
(while (re-search-forward cookie-re end t)
|
||||
(let ((context (save-excursion (backward-char)
|
||||
(save-match-data (org-element-context)))))
|
||||
(let* ((context (save-excursion (backward-char)
|
||||
(save-match-data (org-element-context))))
|
||||
(cookie-data (save-match-data (or (org-entry-get nil "COOKIE_DATA") "")))
|
||||
(recursivep
|
||||
(or (not org-checkbox-hierarchical-statistics)
|
||||
(string-match-p "\\<recursive\\>" cookie-data))))
|
||||
(when (and (org-element-type-p context 'statistics-cookie)
|
||||
(not (string-match-p "\\<todo\\>" cookie-data)))
|
||||
(push
|
||||
|
|
@ -2725,8 +2730,7 @@ Return t if successful."
|
|||
(no-subtree (1+ (line-beginning-position)))
|
||||
(t (org-list-get-item-end (line-beginning-position) struct))))))
|
||||
(let* ((beg (marker-position org-last-indent-begin-marker))
|
||||
(end (marker-position org-last-indent-end-marker))
|
||||
(deactivate-mark nil))
|
||||
(end (marker-position org-last-indent-end-marker)))
|
||||
(cond
|
||||
;; Special case: moving top-item with indent rule.
|
||||
(specialp
|
||||
|
|
@ -2773,6 +2777,7 @@ Return t if successful."
|
|||
(org-list-struct-indent beg end struct parents prevs))))
|
||||
(org-list-write-struct struct new-parents old-struct))
|
||||
(org-update-checkbox-count-maybe))))))
|
||||
(setq deactivate-mark (org--deactivate-mark))
|
||||
t)
|
||||
|
||||
(defun org-outdent-item ()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2013-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
|
||||
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Keywords: outlines, hypermedia, calendar, text
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
|
@ -55,9 +56,8 @@
|
|||
(require 'org-compat)
|
||||
|
||||
(declare-function org-collect-keywords "org" (keywords &optional unique directory))
|
||||
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
|
||||
(declare-function org-element-context "org-element" (&optional element))
|
||||
(declare-function org-element-copy "org-element-ast" (datum))
|
||||
(declare-function org-element-copy "org-element-ast" (datum &optional keep-contents))
|
||||
(declare-function org-element-macro-parser "org-element" ())
|
||||
(declare-function org-element-keyword-parser "org-element" (limit affiliated))
|
||||
(declare-function org-element-put-property "org-element-ast" (node property value))
|
||||
|
|
@ -69,10 +69,8 @@
|
|||
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
|
||||
(declare-function org-element-type-p "org-element-ast" (node types))
|
||||
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
|
||||
(declare-function org-file-contents "org" (file &optional noerror nocache))
|
||||
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance element))
|
||||
(declare-function org-link-search "ol" (s &optional avoid-pos stealth))
|
||||
(declare-function org-mode "org" ())
|
||||
(declare-function org-link-search "ol" (s &optional avoid-pos stealth new-heading-container))
|
||||
(declare-function vc-backend "vc-hooks" (f))
|
||||
(declare-function vc-call "vc-hooks" (fun file &rest args) t)
|
||||
(declare-function vc-exec-after "vc-dispatcher" (code &optional success))
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2004-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
|
||||
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Keywords: outlines, hypermedia, calendar, text
|
||||
;; URL: https://orgmode.org
|
||||
;;
|
||||
|
|
@ -33,6 +34,7 @@
|
|||
|
||||
(require 'cl-lib)
|
||||
(require 'format-spec)
|
||||
(eval-when-compile (require 'subr-x)) ; For `when-let*', Emacs < 29
|
||||
|
||||
;;; Org version verification.
|
||||
|
||||
|
|
@ -80,7 +82,16 @@ Version mismatch is commonly encountered in the following situations:
|
|||
It is recommended to set `load-path' as early in the config as
|
||||
possible.
|
||||
|
||||
3. New Org version is loaded using straight.el package manager and
|
||||
3. New Org version is loaded while an old Org version is partially
|
||||
loaded during compilation or M-x package-upgrade. This usually
|
||||
should not happen (at least, a number of attemps have been made
|
||||
to avoid this problem in package.el), but sometimes it does anyway.
|
||||
|
||||
You can manually delete Org installation from ~/.emacs.d/elpa/ and
|
||||
try installing again, possibly from emacs -Q without any
|
||||
configuration loaded.
|
||||
|
||||
4. New Org version is loaded using straight.el package manager and
|
||||
other package depending on Org is loaded before straight triggers
|
||||
loading of the newer Org version.
|
||||
|
||||
|
|
@ -93,7 +104,7 @@ Version mismatch is commonly encountered in the following situations:
|
|||
sufficient if the corresponding `use-package' statement is
|
||||
deferring the loading.
|
||||
|
||||
4. A new Org version is synchronized with Emacs git repository and
|
||||
5. A new Org version is synchronized with Emacs git repository and
|
||||
stale .elc files are still left from the previous build.
|
||||
|
||||
It is recommended to remove .elc files from lisp/org directory and
|
||||
|
|
@ -108,10 +119,8 @@ Version mismatch is commonly encountered in the following situations:
|
|||
(declare-function org-mode "org" ())
|
||||
(declare-function org-agenda-files "org" (&optional unrestricted archives))
|
||||
(declare-function org-time-string-to-seconds "org" (s))
|
||||
(declare-function org-fold-show-context "org-fold" (&optional key))
|
||||
(declare-function org-fold-save-outline-visibility "org-fold" (use-markers &rest body))
|
||||
(declare-function org-fold-next-visibility-change "org-fold" (&optional pos limit ignore-hidden-p previous-p))
|
||||
(declare-function org-fold-core-with-forced-fontification "org-fold" (&rest body))
|
||||
(declare-function org-fold-folded-p "org-fold" (&optional pos limit ignore-hidden-p previous-p))
|
||||
(declare-function org-time-convert-to-list "org-compat" (time))
|
||||
(declare-function org-buffer-text-pixel-width "org-compat" ())
|
||||
|
|
@ -246,26 +255,37 @@ This function is only useful when called from Agenda buffer."
|
|||
(defmacro org-preserve-local-variables (&rest body)
|
||||
"Execute BODY while preserving local variables."
|
||||
(declare (debug (body)))
|
||||
`(let ((local-variables
|
||||
(org-with-gensyms (local-variables tick-counter-before)
|
||||
`(org-with-undo-amalgamate
|
||||
(let ((,local-variables
|
||||
(org-with-wide-buffer
|
||||
(goto-char (point-max))
|
||||
(let ((case-fold-search t))
|
||||
(and (re-search-backward "^[ \t]*# +Local Variables:"
|
||||
(and (re-search-backward
|
||||
,(rx-let ((prefix
|
||||
(seq line-start (zero-or-more whitespace)
|
||||
"#" (one-or-more whitespace))))
|
||||
(rx prefix "Local Variables:"
|
||||
(one-or-more anychar)
|
||||
prefix "End:"
|
||||
(zero-or-more whitespace) (optional "\n")))
|
||||
(max (- (point) 3000) 1)
|
||||
t)
|
||||
(let ((buffer-undo-list t))
|
||||
(delete-and-extract-region (point) (point-max)))))))
|
||||
(tick-counter-before (buffer-modified-tick)))
|
||||
(cons (match-beginning 0)
|
||||
(delete-and-extract-region (match-beginning 0)
|
||||
(match-end 0)))))))
|
||||
(,tick-counter-before (buffer-modified-tick)))
|
||||
(unwind-protect (progn ,@body)
|
||||
(when local-variables
|
||||
(when ,local-variables
|
||||
(org-with-wide-buffer
|
||||
(let ((modified (< ,tick-counter-before (buffer-modified-tick))))
|
||||
(if (not modified)
|
||||
(goto-char (car ,local-variables))
|
||||
(goto-char (point-max))
|
||||
(unless (bolp) (insert "\n"))
|
||||
(let ((modified (< tick-counter-before (buffer-modified-tick)))
|
||||
(buffer-undo-list t))
|
||||
(insert local-variables)
|
||||
(unless (bolp) (insert "\n")))
|
||||
(insert (cdr ,local-variables))
|
||||
(unless modified
|
||||
(restore-buffer-modified-p nil))))))))
|
||||
(restore-buffer-modified-p nil))))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro org-element-with-disabled-cache (&rest body)
|
||||
|
|
@ -274,6 +294,16 @@ This function is only useful when called from Agenda buffer."
|
|||
`(cl-letf (((symbol-function #'org-element--cache-active-p) (lambda (&rest _) nil)))
|
||||
,@body))
|
||||
|
||||
(defmacro org-with-syntax-table (table &rest body)
|
||||
"Evaluate BODY with syntax table of current buffer set to TABLE.
|
||||
|
||||
This is the same as `with-syntax-table' except that it also binds
|
||||
`parse-sexp-lookup-properties' to nil."
|
||||
(declare (debug t) (indent 1))
|
||||
`(with-syntax-table ,table
|
||||
(let ((parse-sexp-lookup-properties nil))
|
||||
,@body)))
|
||||
|
||||
|
||||
;;; Buffer and windows
|
||||
|
||||
|
|
@ -672,7 +702,14 @@ ones and overrule settings in the other lists."
|
|||
org-element--cache-diagnostics-ring-size
|
||||
org-element--cache-sync-keys
|
||||
org-element--cache-sync-requests
|
||||
org-element--cache-sync-timer)
|
||||
org-element--cache-sync-timer
|
||||
;; FIXME: Avoid copying `buffer-file-name' - when closing a
|
||||
;; temporary buffer, org-persist badly interacts with multiple
|
||||
;; _different_ buffers with the same `buffer-file-name' and may
|
||||
;; modify (via `org-element--cache-persist-before-write' by side
|
||||
;; effect the cache in a _different_ buffer (whatever comes first
|
||||
;; in `get-file-buffer').
|
||||
buffer-file-name)
|
||||
"List of local variables that cannot be transferred to another buffer.")
|
||||
|
||||
(defun org-get-local-variables ()
|
||||
|
|
@ -1142,6 +1179,9 @@ delimiting S."
|
|||
((= cursor end) 0)
|
||||
(t (string-width (substring s cursor end)))))))
|
||||
|
||||
(defvar org-string-width--old-emacs (version< emacs-version "28")
|
||||
"When non-nil, use fallback behavior, primarily for old Emacs versions.")
|
||||
|
||||
(defun org--string-width-1 (string)
|
||||
"Return width of STRING when displayed in the current buffer.
|
||||
Unlike `string-width', this function takes into consideration
|
||||
|
|
@ -1151,29 +1191,10 @@ Results may be off sometimes if it cannot handle a given
|
|||
`display' value."
|
||||
(org--string-from-props string 'display 0 (length string)))
|
||||
|
||||
(defun org-string-width (string &optional pixels default-face)
|
||||
"Return width of STRING when displayed in the current buffer.
|
||||
Return width in pixels when PIXELS is non-nil.
|
||||
When PIXELS is nil, DEFAULT-FACE is the face used to calculate relative
|
||||
STRING width. When REFERENCE-FACE is nil, `default' face is used."
|
||||
(if (and (version< emacs-version "28") (not pixels))
|
||||
;; FIXME: Fallback to old limited version, because
|
||||
;; `window-pixel-width' is buggy in older Emacs.
|
||||
(org--string-width-1 string)
|
||||
;; Wrap/line prefix will make `window-text-pixel-size' return too
|
||||
;; large value including the prefix.
|
||||
(remove-text-properties 0 (length string)
|
||||
'(wrap-prefix t line-prefix t)
|
||||
string)
|
||||
;; Face should be removed to make sure that all the string symbols
|
||||
;; are using default face with constant width. Constant char width
|
||||
;; is critical to get right string width from pixel width (not needed
|
||||
;; when PIXELS are requested though).
|
||||
(unless pixels
|
||||
(put-text-property 0 (length string) 'face (or default-face 'default) string))
|
||||
(let (;; We need to remove the folds to make sure that folded table
|
||||
(defun org-string-width-invisibility-spec ()
|
||||
"Return the invisibility spec of this buffer without folds and ellipses."
|
||||
;; We need to remove the folds to make sure that folded table
|
||||
;; alignment is not messed up.
|
||||
(current-invisibility-spec
|
||||
(or (and (not (listp buffer-invisibility-spec))
|
||||
buffer-invisibility-spec)
|
||||
(let (result)
|
||||
|
|
@ -1187,24 +1208,47 @@ STRING width. When REFERENCE-FACE is nil, `default' face is used."
|
|||
'(org-fold-drawer
|
||||
org-fold-block
|
||||
org-fold-outline))))
|
||||
(push el result)))
|
||||
result)))
|
||||
(current-char-property-alias-alist char-property-alias-alist))
|
||||
(with-current-buffer (get-buffer-create " *Org string width*")
|
||||
(setq-local display-line-numbers nil)
|
||||
(setq-local line-prefix nil)
|
||||
(setq-local wrap-prefix nil)
|
||||
(setq-local buffer-invisibility-spec
|
||||
(if (listp current-invisibility-spec)
|
||||
(mapcar (lambda (el)
|
||||
(push
|
||||
;; Consider ellipsis to have 0 width.
|
||||
;; It is what Emacs 28+ does, but we have
|
||||
;; to force it in earlier Emacs versions.
|
||||
(if (and (consp el) (cdr el))
|
||||
(list (car el))
|
||||
el))
|
||||
el)
|
||||
result)))
|
||||
result)))
|
||||
|
||||
(defun org-string-width (string &optional pixels default-face invisibility-spec)
|
||||
"Return width of STRING when displayed in the current buffer.
|
||||
Return width in pixels when PIXELS is non-nil.
|
||||
When PIXELS is nil, DEFAULT-FACE is the face used to calculate relative
|
||||
STRING width. When REFERENCE-FACE is nil, `default' face is used.
|
||||
Use INVISIBILITY-SPEC when non-nil, otherwise construct one without
|
||||
folds and ellipses."
|
||||
(if (and org-string-width--old-emacs (not pixels))
|
||||
;; FIXME: Fallback to old limited version, because
|
||||
;; `window-pixel-width' is buggy in older Emacs.
|
||||
(org--string-width-1 string)
|
||||
;; Wrap/line prefix will make `window-text-pixel-size' return too
|
||||
;; large value including the prefix.
|
||||
(setq string (copy-sequence string)) ; do not modify STRING object
|
||||
(remove-text-properties 0 (length string)
|
||||
'(wrap-prefix t line-prefix t)
|
||||
string)
|
||||
;; Face should be removed to make sure that all the string symbols
|
||||
;; are using default face with constant width. Constant char width
|
||||
;; is critical to get right string width from pixel width (not needed
|
||||
;; when PIXELS are requested though).
|
||||
(unless pixels
|
||||
(put-text-property 0 (length string) 'face (or default-face 'default) string))
|
||||
(let ((current-invisibility-spec (or invisibility-spec (org-string-width-invisibility-spec)))
|
||||
(current-char-property-alias-alist char-property-alias-alist))
|
||||
(with-current-buffer (get-buffer-create " *Org string width*" t)
|
||||
(setq-local display-line-numbers nil)
|
||||
(setq-local line-prefix nil)
|
||||
(setq-local wrap-prefix nil)
|
||||
(setq-local buffer-invisibility-spec
|
||||
current-invisibility-spec)
|
||||
current-invisibility-spec))
|
||||
(setq-local char-property-alias-alist
|
||||
current-char-property-alias-alist)
|
||||
(let (pixel-width symbol-width)
|
||||
|
|
@ -1218,7 +1262,7 @@ STRING width. When REFERENCE-FACE is nil, `default' face is used."
|
|||
(setq symbol-width (org-buffer-text-pixel-width))))
|
||||
(if pixels
|
||||
pixel-width
|
||||
(ceiling pixel-width symbol-width)))))))
|
||||
(round pixel-width symbol-width)))))))
|
||||
|
||||
(defmacro org-current-text-column ()
|
||||
"Like `current-column' but ignore display properties.
|
||||
|
|
@ -1228,7 +1272,9 @@ This function forces `tab-width' value because it is used as a part of
|
|||
the parser, to ensure parser consistency when calculating list
|
||||
indentation."
|
||||
`(progn
|
||||
(unless (= 8 tab-width) (error "Tab width in Org files must be 8, not %d. Please adjust your `tab-width' settings for Org mode" tab-width))
|
||||
(unless (= 8 tab-width)
|
||||
(org--set-tab-width)
|
||||
(warn "Tab width in Org files must be 8, not %d. Setting back to 8. Please adjust your `tab-width' settings for Org mode" tab-width))
|
||||
(string-width (buffer-substring-no-properties
|
||||
(line-beginning-position) (point)))))
|
||||
|
||||
|
|
@ -1701,18 +1747,33 @@ it for output."
|
|||
(file-relative-name source pwd))
|
||||
source))
|
||||
(log-buf (and log-buf (get-buffer-create log-buf)))
|
||||
(time (file-attribute-modification-time (file-attributes output))))
|
||||
(time (file-attribute-modification-time (file-attributes output)))
|
||||
exit-status (did-error nil))
|
||||
(save-window-excursion
|
||||
(dolist (command commands)
|
||||
(cond
|
||||
((functionp command)
|
||||
;; We could treat return value of the function
|
||||
;; as return code in shell command, but that would be
|
||||
;; a breaking changed compared to historical behavior.
|
||||
;; Functions might still take care to remove the target file
|
||||
;; (if it already exists) to mark failure.
|
||||
(funcall command (shell-quote-argument relname)))
|
||||
((stringp command)
|
||||
(let ((shell-command-dont-erase-buffer t))
|
||||
(shell-command command log-buf))))))
|
||||
(setq exit-status (shell-command command log-buf))
|
||||
(when (and (numberp exit-status) (> exit-status 0))
|
||||
(setq did-error t)))))))
|
||||
;; Check for process failure. Output file is expected to be
|
||||
;; located in the same directory as SOURCE.
|
||||
(unless (org-file-newer-than-p output time)
|
||||
;; Sometimes, the (LaTeX) process fails still producing output.
|
||||
;; Then, assume compilation success. It is way too common for
|
||||
;; LaTeX to throw non-0 exit code yet producing perfectly usable
|
||||
;; pdfs.
|
||||
(when (or (not (file-exists-p output))
|
||||
;; non-0 exit code and output not updated.
|
||||
(and did-error
|
||||
(not (org-file-newer-than-p output time))))
|
||||
(ignore (defvar org-batch-test))
|
||||
;; Display logs when running tests.
|
||||
(when (bound-and-true-p org-batch-test)
|
||||
|
|
@ -1812,6 +1873,15 @@ indirectly called by the latter."
|
|||
(eq (window-frame) (window-frame window))))
|
||||
(window--display-buffer buffer window 'reuse alist))))
|
||||
|
||||
(defun org-base-buffer-file-name (&optional buffer)
|
||||
"Resolve the base file name for the provided BUFFER.
|
||||
If BUFFER is not provided, default to the current buffer. If
|
||||
BUFFER does not have a file name associated with it (e.g. a
|
||||
transient buffer) then return nil."
|
||||
(if-let* ((base-buffer (buffer-base-buffer buffer)))
|
||||
(buffer-file-name base-buffer)
|
||||
(buffer-file-name buffer)))
|
||||
|
||||
(provide 'org-macs)
|
||||
|
||||
;; Local variables:
|
||||
|
|
|
|||
|
|
@ -1035,13 +1035,13 @@ be returned that indicates what went wrong."
|
|||
((eq what 'priority)
|
||||
(let ((case-fold-search nil))
|
||||
(when (looking-at org-complex-heading-regexp)
|
||||
(let ((current (and (match-end 3) (substring (match-string 3) 2 3))))
|
||||
(let ((current (and (match-end 3) (substring (match-string 3) 2 -1))))
|
||||
(cond
|
||||
((equal current new) t) ;no action required
|
||||
((or (equal current old)
|
||||
(eq org-mobile-force-mobile-change t)
|
||||
(memq 'tags org-mobile-force-mobile-change))
|
||||
(org-priority (and new (string-to-char new))))
|
||||
(org-priority (and new (org-priority-to-value new))))
|
||||
(t (error "Priority was expected to be %s, but is %s"
|
||||
old current)))))))
|
||||
|
||||
|
|
|
|||
|
|
@ -427,13 +427,13 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
|
|||
(let ((tags (org-get-tags nil t)))
|
||||
(org-mouse-keyword-menu
|
||||
(sort (mapcar #'car (org-get-buffer-tags))
|
||||
(or org-tags-sort-function #'org-string<))
|
||||
#'org-tags-sort)
|
||||
(lambda (tag)
|
||||
(org-mouse-set-tags
|
||||
(sort (if (member tag tags)
|
||||
(delete tag tags)
|
||||
(cons tag tags))
|
||||
(or org-tags-sort-function #'org-string<))))
|
||||
#'org-tags-sort)))
|
||||
(lambda (tag) (member tag tags))
|
||||
))
|
||||
'("--"
|
||||
|
|
@ -491,7 +491,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
|
|||
`("Main Menu"
|
||||
["Show Overview" org-mouse-show-overview t]
|
||||
["Show Headlines" org-mouse-show-headlines t]
|
||||
["Show All" org-show-all t]
|
||||
["Show All" org-fold-show-all t]
|
||||
["Remove Highlights" org-remove-occur-highlights
|
||||
:visible org-occur-highlights]
|
||||
"--"
|
||||
|
|
@ -504,7 +504,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
|
|||
("Check Tags"
|
||||
,@(org-mouse-keyword-menu
|
||||
(sort (mapcar #'car (org-get-buffer-tags))
|
||||
(or org-tags-sort-function #'org-string<))
|
||||
#'org-tags-sort)
|
||||
(lambda (tag) (org-tags-sparse-tree nil tag)))
|
||||
"--"
|
||||
["Custom Tag ..." org-tags-sparse-tree t])
|
||||
|
|
@ -515,7 +515,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
|
|||
("Display Tags"
|
||||
,@(org-mouse-keyword-menu
|
||||
(sort (mapcar #'car (org-get-buffer-tags))
|
||||
(or org-tags-sort-function #'org-string<))
|
||||
#'org-tags-sort)
|
||||
(lambda (tag) (org-tags-view nil tag)))
|
||||
"--"
|
||||
["Custom Tag ..." org-tags-view t])
|
||||
|
|
@ -627,7 +627,7 @@ This means, between the beginning of line and the point."
|
|||
["Sparse Tree" (org-occur ',region-string)]
|
||||
["Find in Buffer" (occur ',region-string)]
|
||||
["Grep in Current Dir"
|
||||
(grep (format "grep -rnH -e '%s' *" ',region-string))]
|
||||
(grep (format "grep -rnH -e '%s' ./*" ',region-string))]
|
||||
["Grep in Parent Dir"
|
||||
(grep (format "grep -rnH -e '%s' ../*" ',region-string))]
|
||||
"--"
|
||||
|
|
@ -887,7 +887,7 @@ This means, between the beginning of line and the point."
|
|||
(when (memq 'activate-stars org-mouse-features)
|
||||
(font-lock-add-keywords
|
||||
nil
|
||||
`((,org-outline-regexp
|
||||
`((,org-outline-regexp-bol
|
||||
0 `(face org-link mouse-face highlight keymap ,org-mouse-map)
|
||||
'prepend))
|
||||
t))
|
||||
|
|
|
|||
|
|
@ -76,10 +76,6 @@
|
|||
(defvar org-n-level-faces)
|
||||
(defvar org-odd-levels-only)
|
||||
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
|
||||
(declare-function org-reduced-level "org" (l))
|
||||
|
||||
|
||||
;;; Customization
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
(require 'org-compat)
|
||||
(require 'pcomplete)
|
||||
|
||||
(declare-function org-at-heading-p "org" (&optional ignored))
|
||||
(declare-function org-load-export-backends "org" ())
|
||||
(declare-function org-babel-combine-header-arg-lists "ob-core" (original &rest others))
|
||||
(declare-function org-babel-get-src-block-info "ob-core" (&optional no-eval datum))
|
||||
(declare-function org-before-first-heading-p "org" ())
|
||||
|
|
@ -51,15 +51,14 @@
|
|||
(declare-function org-export-backend-options "ox" (cl-x) t)
|
||||
(declare-function org-get-buffer-tags "org" ())
|
||||
(declare-function org-get-export-keywords "org" ())
|
||||
(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-link-heading-search-string "ol" (&optional string))
|
||||
(declare-function org-tag-alist-to-string "org" (alist &optional skip-key))
|
||||
(declare-function org-time-stamp-format "org" (&optional with-time inactive custom))
|
||||
(declare-function org-priority-to-string "org" (priority))
|
||||
|
||||
(defvar org-babel-common-header-args-w-values)
|
||||
(defvar org-current-tag-alist)
|
||||
(defvar org-priority-default)
|
||||
(defvar org-drawer-regexp)
|
||||
(defvar org-element-affiliated-keywords)
|
||||
(defvar org-entities)
|
||||
|
|
@ -68,9 +67,10 @@
|
|||
(defvar org-export-select-tags)
|
||||
(defvar org-file-tags)
|
||||
(defvar org-priority-highest)
|
||||
(defvar org-priority-default)
|
||||
(defvar org-priority-lowest)
|
||||
(defvar org-link-abbrev-alist)
|
||||
(defvar org-link-abbrev-alist-local)
|
||||
(defvar org-priority-lowest)
|
||||
(defvar org-options-keywords)
|
||||
(defvar org-outline-regexp)
|
||||
(defvar org-property-re)
|
||||
|
|
@ -157,6 +157,26 @@ The return value is a string naming the thing at point."
|
|||
(while (setq e (pop list))
|
||||
(setq res (cons (downcase e) (cons (upcase e) res))))
|
||||
(nreverse res)))
|
||||
|
||||
;; Variables and constants
|
||||
|
||||
(defconst org-block-keywords
|
||||
(let (block-names)
|
||||
(dolist (name
|
||||
'("CENTER" "COMMENT" "EXAMPLE" "EXPORT" "QUOTE" "SRC"
|
||||
"VERSE")
|
||||
block-names)
|
||||
(push (format "END_%s" name) block-names)
|
||||
(push (concat "BEGIN_"
|
||||
name
|
||||
;; Since language is compulsory in
|
||||
;; export blocks source blocks, add
|
||||
;; a space.
|
||||
(and (member name '("EXPORT" "SRC")) " "))
|
||||
block-names)
|
||||
(push (concat "ATTR_" name ": ") block-names))
|
||||
block-names)
|
||||
"Keywords related to blocks.")
|
||||
|
||||
|
||||
;;; Completion API
|
||||
|
|
@ -219,20 +239,7 @@ When completing for #+STARTUP, for example, this function returns
|
|||
org-options-keywords)
|
||||
(mapcar (lambda (keyword) (concat keyword ": "))
|
||||
org-element-affiliated-keywords)
|
||||
(let (block-names)
|
||||
(dolist (name
|
||||
'("CENTER" "COMMENT" "EXAMPLE" "EXPORT" "QUOTE" "SRC"
|
||||
"VERSE")
|
||||
block-names)
|
||||
(push (format "END_%s" name) block-names)
|
||||
(push (concat "BEGIN_"
|
||||
name
|
||||
;; Since language is compulsory in
|
||||
;; export blocks source blocks, add
|
||||
;; a space.
|
||||
(and (member name '("EXPORT" "SRC")) " "))
|
||||
block-names)
|
||||
(push (format "ATTR_%s: " name) block-names)))
|
||||
org-block-keywords
|
||||
(mapcar (lambda (keyword) (concat keyword ": "))
|
||||
(org-get-export-keywords))))
|
||||
(substring pcomplete-stub 2)))
|
||||
|
|
@ -269,10 +276,11 @@ When completing for #+STARTUP, for example, this function returns
|
|||
|
||||
(defun pcomplete/org-mode/file-option/priorities ()
|
||||
"Complete arguments for the #+PRIORITIES file option."
|
||||
(pcomplete-here (list (format "%c %c %c"
|
||||
org-priority-highest
|
||||
org-priority-lowest
|
||||
org-priority-default))))
|
||||
(pcomplete-here
|
||||
(list (format "%s %s %s"
|
||||
(org-priority-to-string org-priority-highest)
|
||||
(org-priority-to-string org-priority-lowest)
|
||||
(org-priority-to-string org-priority-default)))))
|
||||
|
||||
(defun pcomplete/org-mode/file-option/select_tags ()
|
||||
"Complete arguments for the #+SELECT_TAGS file option."
|
||||
|
|
@ -311,6 +319,7 @@ When completing for #+STARTUP, for example, this function returns
|
|||
|
||||
(defun pcomplete/org-mode/file-option/options ()
|
||||
"Complete arguments for the #+OPTIONS file option."
|
||||
(org-load-export-backends)
|
||||
(while (pcomplete-here
|
||||
(pcomplete-uniquify-list
|
||||
(append
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2021-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
|
||||
;; Keywords: cache, storage
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
|
@ -58,7 +59,8 @@
|
|||
;; has been removed.
|
||||
;;
|
||||
;; 3. Temporarily cache a file, including TRAMP path to disk:
|
||||
;; (org-persist-write 'file "/path/to/file")
|
||||
;; (org-persist-write `(file "/path/to/file"))
|
||||
;; (org-persist-read `(file "/path/to/file")) ; => get path to the cached file copy
|
||||
;;
|
||||
;; 4. Cache file or URL while some other file exists.
|
||||
;; (org-persist-register '(url "https://static.fsf.org/common/img/logo-new.png") '(:file "/path to the other file") :expiry 'never :write-immediately t)
|
||||
|
|
@ -262,10 +264,6 @@
|
|||
(require 'org-id)
|
||||
(require 'xdg nil t)
|
||||
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-next-visible-heading "org" (arg))
|
||||
(declare-function org-at-heading-p "org" (&optional invisible-not-ok))
|
||||
|
||||
;; Silence byte-compiler (used in `org-persist--write-elisp-file').
|
||||
(defvar pp-use-max-width)
|
||||
|
||||
|
|
@ -396,6 +394,9 @@ message is displayed.
|
|||
When the value is a non-nil non-number, always display the message.
|
||||
When the value is nil, never display the message.")
|
||||
|
||||
(defvar org-persist--wrote-to-disk nil
|
||||
"Whether we wrote to disk during current Emacs session.")
|
||||
|
||||
;;;; Common functions
|
||||
|
||||
(defun org-persist--display-time (duration format &rest args)
|
||||
|
|
@ -448,7 +449,11 @@ FORMAT and ARGS are passed to `message'."
|
|||
;; FIXME: `pp' is very slow when writing even moderately large datasets
|
||||
;; We should probably drop it or find some fast formatter.
|
||||
(defun org-persist--write-elisp-file (file data &optional no-circular pp)
|
||||
"Write elisp DATA to FILE."
|
||||
"Write to index and then write elisp DATA to FILE.
|
||||
When optional argument NO-CIRCULAR is non-nil, do not bind
|
||||
`print-circle' to t.
|
||||
When optional argument PP is non-nil, pretty-print the data (slow on
|
||||
moderately large data)."
|
||||
;; Fsync slightly reduces the chance of an incomplete filesystem
|
||||
;; write, however on modern hardware its effectiveness is
|
||||
;; questionable and it is insufficient to guarantee complete writes.
|
||||
|
|
@ -472,20 +477,22 @@ FORMAT and ARGS are passed to `message'."
|
|||
(print-escape-nonascii t)
|
||||
(print-continuous-numbering t)
|
||||
print-number-table
|
||||
(start-time (float-time)))
|
||||
(start-time (float-time))
|
||||
(tmp-file (make-temp-file "org-persist-")))
|
||||
(unless (file-exists-p (file-name-directory file))
|
||||
(make-directory (file-name-directory file) t))
|
||||
;; Force writing even when the file happens to be opened by
|
||||
;; another Emacs process.
|
||||
(cl-letf (((symbol-function #'ask-user-about-lock)
|
||||
;; FIXME: Emacs 27 does not yet have `always'.
|
||||
(lambda (&rest _) t)))
|
||||
(with-temp-file file
|
||||
;; Do not write to FILE directly. Another Emacs instance may be
|
||||
;; doing the same at the same time. Instead, write to new
|
||||
;; temporary file and then rename it (renaming is atomic
|
||||
;; operation that does not create data races).
|
||||
;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=75209#35
|
||||
(with-temp-file tmp-file
|
||||
(insert ";; -*- mode: lisp-data; -*-\n")
|
||||
(if pp
|
||||
(let ((pp-use-max-width nil)) ; Emacs bug#58687
|
||||
(pp data (current-buffer)))
|
||||
(prin1 data (current-buffer)))))
|
||||
(prin1 data (current-buffer))))
|
||||
(rename-file tmp-file file 'overwrite)
|
||||
(org-persist--display-time
|
||||
(- (float-time) start-time)
|
||||
"Writing to %S" file)))
|
||||
|
|
@ -533,13 +540,26 @@ BODY is executed in a context with the following additional variables:
|
|||
(org-persist-collection-let collection
|
||||
(and org-persist--index-hash
|
||||
(catch :found
|
||||
(dolist (cont (cons container container))
|
||||
(dolist (cont
|
||||
(if (listp (car container)) ; container group
|
||||
(cons container container)
|
||||
(list container)))
|
||||
(let ((r (or (gethash (cons cont associated) org-persist--index-hash)
|
||||
(and path (gethash (cons cont (list :file path)) org-persist--index-hash))
|
||||
(and inode (gethash (cons cont (list :inode inode)) org-persist--index-hash))
|
||||
(and hash (gethash (cons cont (list :hash hash)) org-persist--index-hash))
|
||||
(and key (gethash (cons cont (list :key key)) org-persist--index-hash)))))
|
||||
(when r (throw :found r))))))))
|
||||
(when (and r
|
||||
;; Every element in container group of
|
||||
;; COLLECTION matches returned CONTAINER.
|
||||
(seq-every-p
|
||||
(lambda (cont)
|
||||
(org-persist-collection-let r
|
||||
(member cont container)))
|
||||
(if (listp (car container))
|
||||
container
|
||||
(list container))))
|
||||
(throw :found r))))))))
|
||||
|
||||
(defun org-persist--add-to-index (collection &optional hash-only)
|
||||
"Add or update COLLECTION in `org-persist--index'.
|
||||
|
|
@ -557,7 +577,10 @@ Return PLIST."
|
|||
existing)
|
||||
(unless hash-only (push collection org-persist--index))
|
||||
(unless org-persist--index-hash (setq org-persist--index-hash (make-hash-table :test 'equal)))
|
||||
(dolist (cont (cons container container))
|
||||
(dolist (cont
|
||||
(if (listp (car container)) ; container group
|
||||
(cons container container)
|
||||
(list container)))
|
||||
(puthash (cons cont associated) collection org-persist--index-hash)
|
||||
(when path (puthash (cons cont (list :file path)) collection org-persist--index-hash))
|
||||
(when inode (puthash (cons cont (list :inode inode)) collection org-persist--index-hash))
|
||||
|
|
@ -579,7 +602,10 @@ Return PLIST."
|
|||
(let ((existing (org-persist--find-index collection)))
|
||||
(when existing
|
||||
(org-persist-collection-let collection
|
||||
(dolist (cont (cons container container))
|
||||
(dolist (cont
|
||||
(if (listp (car container)) ; container group
|
||||
(cons container container)
|
||||
(list container)))
|
||||
(unless (listp (car container))
|
||||
(org-persist-gc:generic cont collection)
|
||||
(dolist (afile (org-persist-associated-files:generic cont collection))
|
||||
|
|
@ -599,7 +625,6 @@ or file-path, (:inode inode), (:hash hash), or or (:key key).
|
|||
MISC, if non-nil will be appended to the collection. It must be a plist."
|
||||
(unless (and (listp container) (listp (car container)))
|
||||
(setq container (list container)))
|
||||
(setq associated (org-persist--normalize-associated associated))
|
||||
(when (and misc (or (not (listp misc)) (cl-oddp (length misc))))
|
||||
(error "org-persist: Not a plist: %S" misc))
|
||||
(or (org-persist--find-index
|
||||
|
|
@ -609,7 +634,8 @@ MISC, if non-nil will be appended to the collection. It must be a plist."
|
|||
(nconc
|
||||
(list :container (org-persist--normalize-container container)
|
||||
:persist-file
|
||||
(replace-regexp-in-string "^.." "\\&/" (org-id-uuid))
|
||||
(let ((uuid (org-id-uuid)))
|
||||
(concat (substring uuid 0 2) "/" (substring uuid 2)))
|
||||
:associated associated)
|
||||
misc))))
|
||||
|
||||
|
|
@ -635,9 +661,10 @@ When INNER is non-nil, do not try to match as list of containers."
|
|||
(defvar org-persist--associated-buffer-cache (make-hash-table :weakness 'key)
|
||||
"Buffer hash cache.")
|
||||
|
||||
(defun org-persist--normalize-associated (associated)
|
||||
(defsubst org-persist--normalize-associated (associated)
|
||||
"Normalize ASSOCIATED representation into (:type value)."
|
||||
(pcase associated
|
||||
(`nil nil)
|
||||
((or (pred stringp) `(:file ,_))
|
||||
(unless (stringp associated)
|
||||
(setq associated (cadr associated)))
|
||||
|
|
@ -729,7 +756,7 @@ COLLECTION is the plist holding data collection."
|
|||
|
||||
(defun org-persist-read:index (cont index-file _)
|
||||
"Read index container CONT from INDEX-FILE."
|
||||
(when (file-exists-p index-file)
|
||||
(when (and (file-exists-p index-file) (file-readable-p index-file))
|
||||
(let ((index (org-persist--read-elisp-file index-file)))
|
||||
(when index
|
||||
(catch :found
|
||||
|
|
@ -785,9 +812,10 @@ COLLECTION is the plist holding data collection."
|
|||
(when (file-exists-p org-persist-directory)
|
||||
(dolist (file (directory-files org-persist-directory 'absolute
|
||||
"\\`[^.][^.]"))
|
||||
(when (file-writable-p file)
|
||||
(if (file-directory-p file)
|
||||
(delete-directory file t)
|
||||
(delete-file file))))
|
||||
(delete-file file)))))
|
||||
(plist-put (org-persist--get-collection container) :expiry 'never))))
|
||||
|
||||
(defun org-persist--load-index ()
|
||||
|
|
@ -827,6 +855,12 @@ COLLECTION is the plist holding data collection."
|
|||
(when (boundp (cadr container))
|
||||
(symbol-value (cadr container))))
|
||||
(`nil
|
||||
;; FIXME: Here and in other places, we use `get-file-buffer'
|
||||
;; assuming that all the buffers with the same
|
||||
;; `buffer-file-name' are same. However, this may not
|
||||
;; necessarily be the case in general and we may initiate
|
||||
;; writing cache in one buffer, but `get-file-buffer' may then
|
||||
;; return _another_ buffer (with the same `buffer-file-name').
|
||||
(if-let* ((buf (and (plist-get (plist-get collection :associated) :file)
|
||||
(get-file-buffer (plist-get (plist-get collection :associated) :file)))))
|
||||
;; FIXME: There is `buffer-local-boundp' introduced in Emacs 28.
|
||||
|
|
@ -906,7 +940,7 @@ Otherwise, return t."
|
|||
(let ((index-file
|
||||
(org-file-name-concat org-persist-directory org-persist-index-file)))
|
||||
(org-persist--merge-index-with-disk)
|
||||
(org-persist--write-elisp-file index-file org-persist--index t)
|
||||
(org-persist--write-elisp-file index-file org-persist--index t nil)
|
||||
(setq org-persist--index-age
|
||||
(file-attribute-modification-time (file-attributes index-file)))
|
||||
index-file)))
|
||||
|
|
@ -918,6 +952,7 @@ Otherwise, return t."
|
|||
|
||||
(defun org-persist--merge-index-with-disk ()
|
||||
"Merge `org-persist--index' with the current index file on disk."
|
||||
(org-persist--load-index)
|
||||
(let* ((index-file
|
||||
(org-file-name-concat org-persist-directory org-persist-index-file))
|
||||
(disk-index
|
||||
|
|
@ -929,13 +964,17 @@ Otherwise, return t."
|
|||
(when disk-index
|
||||
(setq org-persist--index combined-index
|
||||
org-persist--index-age
|
||||
(file-attribute-modification-time (file-attributes index-file))))))
|
||||
(file-attribute-modification-time (file-attributes index-file)))
|
||||
;; Store newly added entries in the index hash.
|
||||
(mapc (lambda (collection) (org-persist--add-to-index collection 'hash))
|
||||
org-persist--index))))
|
||||
|
||||
(defun org-persist--merge-index (base other)
|
||||
"Attempt to merge new index items in OTHER into BASE.
|
||||
Items with different details are considered too difficult, and skipped."
|
||||
(if other
|
||||
(let ((new (cl-set-difference other base :test #'equal))
|
||||
(if (not base) other
|
||||
(let ((new (cl-set-difference other base :key #'org-persist--find-index))
|
||||
(base-files (mapcar (lambda (s) (plist-get s :persist-file)) base))
|
||||
(combined (reverse base)))
|
||||
(dolist (item (nreverse new))
|
||||
|
|
@ -945,12 +984,13 @@ Items with different details are considered too difficult, and skipped."
|
|||
(plist-get item :persist-file))))
|
||||
(member (plist-get item :persist-file) base-files))
|
||||
(push item combined)))
|
||||
(nreverse combined))
|
||||
(nreverse combined)))
|
||||
base))
|
||||
|
||||
;;;; Public API
|
||||
|
||||
(cl-defun org-persist-register (container &optional associated &rest misc
|
||||
(cl-defun org-persist-register
|
||||
( container &optional associated &rest misc
|
||||
&key inherit
|
||||
&key (expiry org-persist-default-expiry)
|
||||
&key (write-immediately nil)
|
||||
|
|
@ -969,8 +1009,11 @@ MISC will be appended to the collection. It must be alternating :KEY
|
|||
VALUE pairs.
|
||||
When WRITE-IMMEDIATELY is non-nil, the return value will be the same
|
||||
with `org-persist-write'."
|
||||
(unless org-persist--index (org-persist--load-index))
|
||||
;; Sync cache with disk, dropping conflicting items between multiple
|
||||
;; Emacsen.
|
||||
(org-persist--merge-index-with-disk)
|
||||
(setq container (org-persist--normalize-container container))
|
||||
(setq associated (org-persist--normalize-associated associated))
|
||||
(when inherit
|
||||
(setq inherit (org-persist--normalize-container inherit))
|
||||
(let ((inherited-collection (org-persist--get-collection inherit associated))
|
||||
|
|
@ -996,7 +1039,9 @@ with `org-persist-write'."
|
|||
When ASSOCIATED is `all', unregister CONTAINER everywhere.
|
||||
When REMOVE-RELATED is non-nil, remove all the containers stored with
|
||||
the CONTAINER as well."
|
||||
(unless org-persist--index (org-persist--load-index))
|
||||
;; Sync cache with disk, dropping conflicting items between multiple
|
||||
;; Emacsen.
|
||||
(org-persist--merge-index-with-disk)
|
||||
(setq container (org-persist--normalize-container container))
|
||||
(if (eq associated 'all)
|
||||
(mapc (lambda (collection)
|
||||
|
|
@ -1012,10 +1057,6 @@ the CONTAINER as well."
|
|||
(remove container (plist-get collection :container)))
|
||||
(org-persist--add-to-index collection))))))
|
||||
|
||||
(defvar org-persist--write-cache (make-hash-table :test #'equal)
|
||||
"Hash table storing as-written data objects.
|
||||
|
||||
This data is used to avoid reading the data multiple times.")
|
||||
(cl-defun org-persist-read (container &optional associated hash-must-match load &key read-related)
|
||||
"Restore CONTAINER data for ASSOCIATED.
|
||||
When HASH-MUST-MATCH is non-nil, do not restore data if hash for
|
||||
|
|
@ -1037,7 +1078,9 @@ CONTAINER as well. For example:
|
|||
(org-persist-read \"My data\") ; => \"My data\"
|
||||
(org-persist-read \"My data\" nil nil nil
|
||||
:read-related t) ; => (\"My data\" \"test\")"
|
||||
(unless org-persist--index (org-persist--load-index))
|
||||
;; Sync cache with disk, dropping conflicting items between multiple
|
||||
;; Emacsen.
|
||||
(org-persist--merge-index-with-disk)
|
||||
(setq associated (org-persist--normalize-associated associated))
|
||||
(setq container (org-persist--normalize-container container))
|
||||
(let* ((collection (org-persist--find-index `(:container ,container :associated ,associated)))
|
||||
|
|
@ -1063,8 +1106,7 @@ CONTAINER as well. For example:
|
|||
(unless (seq-find (lambda (v)
|
||||
(run-hook-with-args-until-success 'org-persist-before-read-hook v associated))
|
||||
(plist-get collection :container))
|
||||
(setq data (or (gethash persist-file org-persist--write-cache)
|
||||
(org-persist--read-elisp-file persist-file)))
|
||||
(setq data (org-persist--read-elisp-file persist-file))
|
||||
(when data
|
||||
(cl-loop for c in (plist-get collection :container)
|
||||
with result = nil
|
||||
|
|
@ -1086,7 +1128,9 @@ have the same meaning as in `org-persist-read'."
|
|||
|
||||
(defun org-persist-load-all (&optional associated)
|
||||
"Restore all the persistent data associated with ASSOCIATED."
|
||||
(unless org-persist--index (org-persist--load-index))
|
||||
;; Sync cache with disk, dropping conflicting items between multiple
|
||||
;; Emacsen.
|
||||
(org-persist--merge-index-with-disk)
|
||||
(setq associated (org-persist--normalize-associated associated))
|
||||
(let (all-containers)
|
||||
(dolist (collection org-persist--index)
|
||||
|
|
@ -1113,6 +1157,7 @@ The return value is nil when writing fails and the written value (as
|
|||
returned by `org-persist-read') on success.
|
||||
When IGNORE-RETURN is non-nil, just return t on success without calling
|
||||
`org-persist-read'."
|
||||
(setq org-persist--wrote-to-disk t)
|
||||
(setq associated (org-persist--normalize-associated associated))
|
||||
;; Update hash
|
||||
(when (and (plist-get associated :file)
|
||||
|
|
@ -1131,18 +1176,18 @@ When IGNORE-RETURN is non-nil, just return t on success without calling
|
|||
(seq-find (lambda (v)
|
||||
(run-hook-with-args-until-success 'org-persist-before-write-hook v associated))
|
||||
(plist-get collection :container)))
|
||||
(when (or (file-exists-p org-persist-directory) (org-persist--save-index))
|
||||
(let ((file (org-file-name-concat org-persist-directory (plist-get collection :persist-file)))
|
||||
(data (mapcar (lambda (c) (cons c (org-persist-write:generic c collection)))
|
||||
(plist-get collection :container))))
|
||||
(puthash file data org-persist--write-cache)
|
||||
(org-persist--write-elisp-file file data)
|
||||
(or ignore-return (org-persist-read container associated)))))))
|
||||
(or ignore-return (org-persist-read container associated))))))
|
||||
|
||||
(defun org-persist-write-all (&optional associated)
|
||||
"Save all the persistent data.
|
||||
When ASSOCIATED is non-nil, only save the matching data."
|
||||
(unless org-persist--index (org-persist--load-index))
|
||||
;; Sync cache with disk, dropping conflicting items between multiple
|
||||
;; Emacsen.
|
||||
(org-persist--merge-index-with-disk)
|
||||
(setq associated (org-persist--normalize-associated associated))
|
||||
(if
|
||||
(and (equal 1 (length org-persist--index))
|
||||
|
|
@ -1220,6 +1265,7 @@ Do nothing in an indirect buffer."
|
|||
(defun org-persist--refresh-gc-lock ()
|
||||
"Refresh session timestamp in `org-persist-gc-lock-file'.
|
||||
Remove expired sessions timestamps."
|
||||
(when org-persist--wrote-to-disk
|
||||
(let* ((file (org-file-name-concat org-persist-directory org-persist-gc-lock-file))
|
||||
(alist (when (file-exists-p file) (org-persist--read-elisp-file file)))
|
||||
new-alist)
|
||||
|
|
@ -1229,7 +1275,7 @@ Remove expired sessions timestamps."
|
|||
(when (< (- (float-time (cdr record)) (float-time (current-time)))
|
||||
org-persist-gc-lock-expiry)
|
||||
(push record new-alist)))
|
||||
(org-persist--write-elisp-file file new-alist)))
|
||||
(ignore-errors (org-persist--write-elisp-file file new-alist)))))
|
||||
|
||||
(defun org-persist--gc-orphan-p ()
|
||||
"Return non-nil, when orphan files should be garbage-collected.
|
||||
|
|
@ -1237,16 +1283,16 @@ Remove current sessions from `org-persist-gc-lock-file'."
|
|||
(let* ((file (org-file-name-concat org-persist-directory org-persist-gc-lock-file))
|
||||
(alist (when (file-exists-p file) (org-persist--read-elisp-file file))))
|
||||
(setq alist (org-assoc-delete-all before-init-time alist))
|
||||
(org-persist--write-elisp-file file alist)
|
||||
(ignore-errors (org-persist--write-elisp-file file alist))
|
||||
;; Only GC orphan files when there are no active sessions.
|
||||
(not alist)))
|
||||
|
||||
(defun org-persist-gc ()
|
||||
"Remove expired or unregistered containers and orphaned files.
|
||||
Also, remove containers associated with non-existing files."
|
||||
(if org-persist--index
|
||||
;; Sync cache with disk, dropping conflicting items between multiple
|
||||
;; Emacsen.
|
||||
(org-persist--merge-index-with-disk)
|
||||
(org-persist--load-index))
|
||||
(let (new-index
|
||||
(remote-files-num 0)
|
||||
(orphan-files
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
(require 'org)
|
||||
(require 'org-table)
|
||||
|
||||
(declare-function gnuplot-delchar-or-maybe-eof "ext:gnuplot" (arg))
|
||||
(declare-function gnuplot-mode "ext:gnuplot" ())
|
||||
(declare-function gnuplot-send-buffer-to-gnuplot "ext:gnuplot" ())
|
||||
|
||||
|
|
@ -48,7 +47,9 @@
|
|||
(:ind . 0))
|
||||
"Default options to gnuplot used by `org-plot/gnuplot'.")
|
||||
|
||||
(defvar org-plot-timestamp-fmt nil)
|
||||
(defvar org-plot-timestamp-fmt "%Y-%m-%d-%H:%M:%S"
|
||||
"Default time format to be passed to Gnuplot.
|
||||
Can be changed via timefmt plot option.")
|
||||
|
||||
(defun org-plot/add-options-to-plist (p options)
|
||||
"Parse an OPTIONS line and set values in the property list P.
|
||||
|
|
@ -130,14 +131,17 @@ will be added. Returns the resulting property list."
|
|||
Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE."
|
||||
(with-temp-file
|
||||
data-file
|
||||
(setq-local org-plot-timestamp-fmt (or
|
||||
(let ((org-plot-timestamp-fmt
|
||||
(or
|
||||
(plist-get params :timefmt)
|
||||
"%Y-%m-%d-%H:%M:%S"))
|
||||
org-plot-timestamp-fmt
|
||||
"%Y-%m-%d-%H:%M:%S")))
|
||||
(insert (orgtbl-to-generic
|
||||
table
|
||||
(org-combine-plists
|
||||
'(:sep "\t" :fmt org-plot-quote-tsv-field)
|
||||
params))))
|
||||
'( :sep "\t" :fmt org-plot-quote-tsv-field
|
||||
:with-special-rows nil)
|
||||
params)))))
|
||||
nil)
|
||||
|
||||
(defun org-plot/gnuplot-to-grid-data (table data-file params)
|
||||
|
|
@ -302,9 +306,10 @@ When NORMALIZE is non-nil, the count is divided by the number of values."
|
|||
(defcustom org-plot/gnuplot-script-preamble ""
|
||||
"String of function to be inserted before the gnuplot plot command is run.
|
||||
|
||||
Note that this is in addition to, not instead of other content generated in
|
||||
`org-plot/gnuplot-script'. If a function, it is called with the plot type as
|
||||
the argument, and must return a string to be used."
|
||||
Note that this is in addition to, not instead of other content generated
|
||||
in `org-plot/gnuplot-script'. If a function, it is called with the
|
||||
parameters used by the current plot type (see
|
||||
`org-plot/preset-plot-types'), and must return a string to be used."
|
||||
:group 'org-plot
|
||||
:type '(choice string function))
|
||||
|
||||
|
|
@ -349,7 +354,7 @@ the argument, and must return a string to be used."
|
|||
(grid :plot-cmd "splot"
|
||||
:plot-pre (lambda (_table _data-file _num-cols params _plot-str)
|
||||
(if (plist-get params :map) "set pm3d map" "set map"))
|
||||
:data-dump (lambda (table data-file params _num-cols)
|
||||
:data-dump (lambda (table data-file _num-cols params)
|
||||
(let ((y-labels (org-plot/gnuplot-to-grid-data
|
||||
table data-file params)))
|
||||
(when y-labels (plist-put params :ylabels y-labels))))
|
||||
|
|
@ -391,8 +396,8 @@ be set.
|
|||
- :data-dump - Function to dump the table to a datafile for ease of
|
||||
use.
|
||||
|
||||
Accepts lambda function. Default lambda body:
|
||||
(org-plot/gnuplot-to-data table data-file params)
|
||||
Accepts function with arguments:
|
||||
(table data-file num-cols params)
|
||||
|
||||
- :plot-pre - Gnuplot code to be inserted early into the script, just
|
||||
after term and output have been set.
|
||||
|
|
@ -400,7 +405,9 @@ be set.
|
|||
Accepts string, nil, or lambda function which returns string
|
||||
or nil. Defaults to nil."
|
||||
:group 'org-plot
|
||||
:type 'alist)
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'alist
|
||||
:risky t)
|
||||
|
||||
(defvar org--plot/radar-template
|
||||
"### spider plot/chart with gnuplot
|
||||
|
|
@ -541,7 +548,8 @@ EOD
|
|||
"String or function which provides the extra term options.
|
||||
E.g. a value of \"size 1050,650\" would cause
|
||||
\"set term ... size 1050,650\" to be used.
|
||||
If a function, it is called with the plot type as the argument."
|
||||
If a function, it is called with the parameters used by the current plot
|
||||
type, see `org-plot/preset-plot-types'."
|
||||
:group 'org-plot
|
||||
:type '(choice string function))
|
||||
|
||||
|
|
@ -627,7 +635,7 @@ manner suitable for prepending to a user-specified script."
|
|||
|
||||
(defun org-plot/redisplay-img-in-buffer (img-file)
|
||||
"Find any overlays for IMG-FILE in the current Org buffer, and refresh them."
|
||||
(dolist (img-overlay org-inline-image-overlays)
|
||||
(dolist (img-overlay org-link-preview-overlays)
|
||||
(when (string= img-file (plist-get (cdr (overlay-get img-overlay 'display)) :file))
|
||||
(when (and (file-exists-p img-file)
|
||||
(fboundp 'image-flush))
|
||||
|
|
@ -662,8 +670,7 @@ line directly before or after the table."
|
|||
(looking-at "[[:space:]]*#\\+"))
|
||||
(setf params (org-plot/collect-options params))))
|
||||
;; collect table and table information
|
||||
(let* ((data-file (make-temp-file "org-plot"))
|
||||
(table (let ((tbl (save-excursion
|
||||
(let* ((table (let ((tbl (save-excursion
|
||||
(org-plot/goto-nearest-table)
|
||||
(org-table-to-lisp))))
|
||||
(when (pcase (plist-get params :transpose)
|
||||
|
|
@ -679,14 +686,13 @@ line directly before or after the table."
|
|||
tbl))
|
||||
(num-cols (length (if (eq (nth 0 table) 'hline) (nth 1 table)
|
||||
(nth 0 table))))
|
||||
(type (assoc (plist-get params :plot-type)
|
||||
org-plot/preset-plot-types))
|
||||
gnuplot-script)
|
||||
(type (cdr (assoc (plist-get params :plot-type)
|
||||
org-plot/preset-plot-types)))
|
||||
gnuplot-script data-file)
|
||||
|
||||
(unless type
|
||||
(user-error "Org-plot type `%s' is undefined" (plist-get params :plot-type)))
|
||||
|
||||
(run-with-idle-timer 0.1 nil #'delete-file data-file)
|
||||
(when (eq (cadr table) 'hline)
|
||||
(setf params
|
||||
(plist-put params :labels (car table))) ; headers to labels
|
||||
|
|
@ -695,8 +701,18 @@ line directly before or after the table."
|
|||
(save-excursion (while (and (equal 0 (forward-line -1))
|
||||
(looking-at "[[:space:]]*#\\+"))
|
||||
(setf params (org-plot/collect-options params))))
|
||||
;; Ensure that the user can override any plot parameter, and
|
||||
;; that the parameters set by the plot type in
|
||||
;; `org-plot/preset-plot-types' is respected.
|
||||
(setq params (org-combine-plists type params))
|
||||
;; Dump table to datafile
|
||||
(let ((dump-func (plist-get type :data-dump)))
|
||||
;; Use a stable temporary file to ensure that 'replot' upon
|
||||
;; resizing a GUI gnuplot terminal window works.
|
||||
(setq data-file (org-babel-temp-stable-file
|
||||
(list (or dump-func 'org-plot/gnuplot-to-data)
|
||||
table num-cols params)
|
||||
"org-plot"))
|
||||
(if dump-func
|
||||
(funcall dump-func table data-file num-cols params)
|
||||
(org-plot/gnuplot-to-data table data-file params)))
|
||||
|
|
|
|||
|
|
@ -101,15 +101,15 @@
|
|||
;; new URLSearchParams({
|
||||
;; url: location.href,
|
||||
;; title: document.title,
|
||||
;; body: window.getSelection()})
|
||||
;; body: window.getSelection()});void(0)
|
||||
;;
|
||||
;; Alternatively use the following expression that encodes space as \"%20\"
|
||||
;; instead of \"+\", so it is compatible with Org versions from 9.0 to 9.4:
|
||||
;;
|
||||
;; location.href='org-protocol://sub-protocol?url='+
|
||||
;; javascript:location.href='org-protocol://sub-protocol?url='+
|
||||
;; encodeURIComponent(location.href)+'&title='+
|
||||
;; encodeURIComponent(document.title)+'&body='+
|
||||
;; encodeURIComponent(window.getSelection())
|
||||
;; encodeURIComponent(window.getSelection());void(0)
|
||||
;;
|
||||
;; The handler for the sub-protocol \"capture\" detects an optional template
|
||||
;; char that, if present, triggers the use of a special template.
|
||||
|
|
@ -437,14 +437,14 @@ also recognized.
|
|||
The location for a browser's bookmark may look like this:
|
||||
|
||||
javascript:location.href = \\='org-protocol://store-link?\\=' +
|
||||
new URLSearchParams({url:location.href, title:document.title});
|
||||
new URLSearchParams({url:location.href, title:document.title});void(0);
|
||||
|
||||
or to keep compatibility with Org versions from 9.0 to 9.4 it may be:
|
||||
|
||||
javascript:location.href = \\
|
||||
\\='org-protocol://store-link?url=\\=' + \\
|
||||
encodeURIComponent(location.href) + \\='&title=\\=' + \\
|
||||
encodeURIComponent(document.title);
|
||||
encodeURIComponent(document.title);void(0);
|
||||
|
||||
Don't use `escape()'! Use `encodeURIComponent()' instead. The
|
||||
title of the page could contain slashes and the location
|
||||
|
|
@ -482,20 +482,21 @@ by `/'. The location for a browser's bookmark looks like this:
|
|||
new URLSearchParams({
|
||||
url: location.href,
|
||||
title: document.title,
|
||||
body: window.getSelection()})
|
||||
body: window.getSelection()});void(0)
|
||||
|
||||
or to keep compatibility with Org versions from 9.0 to 9.4:
|
||||
|
||||
javascript:location.href = \\='org-protocol://capture?url=\\='+ \\
|
||||
encodeURIComponent(location.href) + \\='&title=\\=' + \\
|
||||
encodeURIComponent(document.title) + \\='&body=\\=' + \\
|
||||
encodeURIComponent(window.getSelection())
|
||||
encodeURIComponent(window.getSelection());void(0)
|
||||
|
||||
By default, it uses the character `org-protocol-default-template-key',
|
||||
which should be associated with a template in `org-capture-templates'.
|
||||
You may specify the template with a template= query parameter, like this:
|
||||
|
||||
javascript:location.href = \\='org-protocol://capture?template=b\\='+ ...
|
||||
javascript:location.href
|
||||
= \\='org-protocol://capture?template=b\\='+ ...;void(0)
|
||||
|
||||
Now template ?b will be used."
|
||||
(let* ((parts
|
||||
|
|
@ -556,13 +557,13 @@ in `org-protocol-project-alist'.
|
|||
The location for a browser's bookmark should look like this:
|
||||
|
||||
javascript:location.href = \\='org-protocol://open-source?\\=' +
|
||||
new URLSearchParams({url: location.href})
|
||||
new URLSearchParams({url: location.href});void(0)
|
||||
|
||||
or if you prefer to keep compatibility with older Org versions (9.0 to 9.4),
|
||||
consider the following expression:
|
||||
|
||||
javascript:location.href = \\='org-protocol://open-source?url=\\=' + \\
|
||||
encodeURIComponent(location.href)"
|
||||
encodeURIComponent(location.href);void(0)"
|
||||
;; As we enter this function for a match on our protocol, the return value
|
||||
;; defaults to nil.
|
||||
(let (;; (result nil)
|
||||
|
|
|
|||
|
|
@ -72,9 +72,10 @@ This is a list of cons cells. Each cell contains:
|
|||
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.
|
||||
headlines in the current buffer.
|
||||
- A specification of how to find candidate refile targets. This may be
|
||||
any of:
|
||||
- t to indicate that all headlines should be considered.
|
||||
- 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.
|
||||
|
|
@ -104,13 +105,15 @@ are used, equivalent to the value `((nil . (:level . 1)))'."
|
|||
(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))))))
|
||||
(function) (variable) (file) (repeat (file)))
|
||||
(choice :tag "Target headlines"
|
||||
(const :tag "All" t)
|
||||
(cons :tag "Tagged with" (const :value :tag) (string))
|
||||
(cons :tag "With the TODO keyword" (const :value :todo) (string))
|
||||
(cons :tag "Matching the regexp" (const :value :regexp) (regexp))
|
||||
(cons :tag "At level" (const :value :level) (integer))
|
||||
(cons :tag "Up through level" (const :value :maxlevel) (integer)))))
|
||||
:package-version '(Org . "9.8"))
|
||||
|
||||
(defcustom org-refile-target-verify-function nil
|
||||
"Function to verify if the headline at point should be a refile target.
|
||||
|
|
@ -289,10 +292,12 @@ When `org-refile-use-cache' is nil, just return POS."
|
|||
(setq files (symbol-value files))))
|
||||
(when (stringp files) (setq files (list files)))
|
||||
;; Allow commonly used (FILE :maxlevel N) and similar values.
|
||||
(when (and (listp (cdr desc)) (null (cddr desc)))
|
||||
(when (and (listp desc) (listp (cdr desc)) (null (cddr desc)))
|
||||
(setq desc (cons (car desc) (cadr desc))))
|
||||
(condition-case err
|
||||
(cond
|
||||
((eq desc t)
|
||||
(setq descre (concat "^\\*+[ \t]")))
|
||||
((eq (car desc) :tag)
|
||||
(setq descre (concat "^\\*+[ \t]+.*?:" (regexp-quote (cdr desc)) ":")))
|
||||
((eq (car desc) :todo)
|
||||
|
|
@ -341,25 +346,7 @@ When `org-refile-use-cache' is nil, just return POS."
|
|||
(org-with-wide-buffer
|
||||
(goto-char (point-min))
|
||||
(setq org-outline-path-cache nil)
|
||||
(while (re-search-forward descre nil t)
|
||||
(forward-line 0)
|
||||
(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
|
||||
(let ((base (pcase org-refile-use-outline-path
|
||||
(`file (list
|
||||
(and (buffer-file-name (buffer-base-buffer))
|
||||
(file-name-nondirectory
|
||||
|
|
@ -375,7 +362,27 @@ When `org-refile-use-cache' is nil, just return POS."
|
|||
(`buffer-name
|
||||
(list (buffer-name
|
||||
(buffer-base-buffer))))
|
||||
(_ nil))
|
||||
(_ nil))))
|
||||
(while (re-search-forward descre nil t)
|
||||
(forward-line 0)
|
||||
(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)
|
||||
(org-link-display-format heading)
|
||||
(mapconcat
|
||||
#'identity
|
||||
(append
|
||||
base
|
||||
(mapcar (lambda (s) (replace-regexp-in-string
|
||||
"/" "\\/" s nil t))
|
||||
(org-get-outline-path t t)))
|
||||
|
|
@ -384,7 +391,7 @@ When `org-refile-use-cache' is nil, just return POS."
|
|||
tgs)))
|
||||
(when (= (point) begin)
|
||||
;; Verification function has not moved point.
|
||||
(end-of-line)))))))
|
||||
(end-of-line))))))))
|
||||
(when org-refile-use-cache
|
||||
(org-refile-cache-put tgs (buffer-file-name) descre))
|
||||
(setq targets (append tgs targets))))))
|
||||
|
|
@ -482,7 +489,7 @@ prefix argument (\\`C-u C-u C-u C-c C-w')."
|
|||
(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)
|
||||
pos it nbuf file level reversed tree)
|
||||
(setq last-command nil)
|
||||
(when regionp
|
||||
(goto-char region-start)
|
||||
|
|
@ -544,6 +551,7 @@ prefix argument (\\`C-u C-u C-u C-c C-w')."
|
|||
(setq nbuf (find-file-noselect file 'nowarn))
|
||||
(if (and arg (not (equal arg 3)))
|
||||
(progn
|
||||
(org-mark-ring-push)
|
||||
(pop-to-buffer-same-window nbuf)
|
||||
(goto-char (cond (pos)
|
||||
((org-notes-order-reversed-p) (point-min))
|
||||
|
|
@ -551,9 +559,10 @@ prefix argument (\\`C-u C-u C-u C-c C-w')."
|
|||
(org-fold-show-context 'org-goto))
|
||||
(if regionp
|
||||
(progn
|
||||
(org-kill-new (buffer-substring region-start region-end))
|
||||
(setq tree (buffer-substring region-start region-end))
|
||||
(org-kill-new tree)
|
||||
(org-save-markers-in-region region-start region-end))
|
||||
(org-copy-subtree 1 nil t))
|
||||
(setq tree (org-copy-subtree 1 nil t)))
|
||||
(let ((origin (point-marker)))
|
||||
;; Handle special case when we refile to exactly same
|
||||
;; location with tree promotion/demotion. Point marker
|
||||
|
|
@ -580,7 +589,7 @@ prefix argument (\\`C-u C-u C-u C-c C-w')."
|
|||
(goto-char (point-min))
|
||||
(or (outline-next-heading) (goto-char (point-max)))))
|
||||
(unless (bolp) (newline))
|
||||
(org-paste-subtree level nil nil t)
|
||||
(org-paste-subtree level tree 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.
|
||||
|
|
@ -634,6 +643,7 @@ prefix argument (\\`C-u C-u C-u C-c C-w')."
|
|||
(defun org-refile-goto-last-stored ()
|
||||
"Go to the location where the last refile was stored."
|
||||
(interactive)
|
||||
(org-mark-ring-push)
|
||||
(bookmark-jump (plist-get org-bookmark-names-plist :last-refile))
|
||||
(message "This is the location of the last refile"))
|
||||
|
||||
|
|
@ -777,9 +787,7 @@ this function appends the default value from
|
|||
(all-completions string thetable predicate))))
|
||||
((eq (car-safe flag) 'boundaries)
|
||||
;; See `completion-file-name-table'.
|
||||
(let ((start (or (and (string-match "/" string)
|
||||
(match-beginning 0))
|
||||
(length string)))
|
||||
(let ((start 0)
|
||||
(end (and (string-match "/" (cdr flag))
|
||||
(match-beginning 0))))
|
||||
`(boundaries ,start . ,end)))
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
(declare-function org--get-expected-indentation "org" (element contentsp))
|
||||
(declare-function org-mode "org" ())
|
||||
(declare-function org--get-expected-indentation "org" (element contentsp))
|
||||
(declare-function org-fold-region "org-fold" (from to flag &optional spec-or-alias))
|
||||
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
|
||||
(declare-function org-element-class "org-element" (datum &optional parent))
|
||||
(declare-function org-element-context "org-element" (&optional element))
|
||||
|
|
@ -128,17 +127,21 @@ When this variable is nil, while indenting with `\\[org-indent-block]'
|
|||
or after editing with `\\[org-edit-src-code]', the minimum (across-lines)
|
||||
number of leading whitespace characters are removed from all lines,
|
||||
and the code block is uniformly indented according to the value of
|
||||
`org-edit-src-content-indentation'."
|
||||
`org-src-content-indentation'."
|
||||
:group 'org-edit-structure
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom org-edit-src-content-indentation 2
|
||||
(defcustom org-src-content-indentation 2
|
||||
"Indentation for the content of a source code block.
|
||||
|
||||
This should be the number of spaces added to the indentation of the #+begin
|
||||
line in order to compute the indentation of the block content after
|
||||
editing it with `\\[org-edit-src-code]'.
|
||||
|
||||
This customization also affects how the source code and example blocks
|
||||
are printed - when interpreting Org AST (during export), during
|
||||
detangling, and indentation.
|
||||
|
||||
It has no effect if `org-src-preserve-indentation' is non-nil."
|
||||
:group 'org-edit-structure
|
||||
:type 'integer
|
||||
|
|
@ -220,7 +223,7 @@ The shells are associated with `sh-mode'."
|
|||
("cpp" . c++)
|
||||
("ditaa" . artist)
|
||||
("desktop" . conf-desktop)
|
||||
("dot" . fundamental)
|
||||
("dot" . graphviz-dot)
|
||||
("elisp" . emacs-lisp)
|
||||
("ocaml" . tuareg)
|
||||
("screen" . shell-script)
|
||||
|
|
@ -238,11 +241,12 @@ not the case, this variable provides a way to simplify things on
|
|||
the user side. For example, there is no `ocaml-mode' in Emacs,
|
||||
but the mode to use is `tuareg-mode'."
|
||||
:group 'org-edit-structure
|
||||
:package-version '(Org . "9.7")
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(repeat
|
||||
(cons
|
||||
(string :tag "Language name")
|
||||
(symbol :tag "Major mode"))))
|
||||
(symbol :tag "Major mode")))
|
||||
:safe #'listp)
|
||||
|
||||
(defcustom org-src-block-faces nil
|
||||
"Alist of faces to be used for source-block.
|
||||
|
|
@ -339,10 +343,14 @@ Return nil if there is no such buffer."
|
|||
(dolist (b (buffer-list))
|
||||
(with-current-buffer b
|
||||
(and (org-src-edit-buffer-p)
|
||||
(= beg org-src--beg-marker)
|
||||
(eq (marker-buffer beg) (marker-buffer org-src--beg-marker))
|
||||
(= end org-src--end-marker)
|
||||
(eq (marker-buffer end) (marker-buffer org-src--end-marker))
|
||||
;; Do it after comparing buffers. In some scenarios
|
||||
;; (namely, when Org buffer is generated as a copy and
|
||||
;; the source buffer gets killed), these markers may
|
||||
;; point nowhere making `=' throw an error.
|
||||
(= beg org-src--beg-marker)
|
||||
(= end org-src--end-marker)
|
||||
(throw 'exit b))))))
|
||||
|
||||
(defun org-src--coordinates (pos beg end)
|
||||
|
|
@ -585,7 +593,7 @@ Leave point in edit buffer."
|
|||
(org--get-expected-indentation
|
||||
(org-element-parent datum) nil))
|
||||
(t (org-current-text-indentation)))))
|
||||
(content-ind org-edit-src-content-indentation)
|
||||
(content-ind org-src-content-indentation)
|
||||
(preserve-ind (org-src-preserve-indentation-p datum))
|
||||
;; Store relative positions of mark (if any) and point
|
||||
;; within the edited area.
|
||||
|
|
@ -605,7 +613,10 @@ Leave point in edit buffer."
|
|||
;; Insert contents.
|
||||
(insert contents)
|
||||
(remove-text-properties (point-min) (point-max)
|
||||
'(display nil invisible nil intangible nil))
|
||||
'( display nil
|
||||
invisible nil
|
||||
intangible nil
|
||||
syntax-table nil ))
|
||||
(let ((lf (eq type 'latex-fragment)))
|
||||
(unless preserve-ind (org-do-remove-indentation (and lf block-ind) lf)))
|
||||
(set-buffer-modified-p nil)
|
||||
|
|
@ -665,11 +676,10 @@ Leave point in edit buffer."
|
|||
"Fontify code block between START and END using LANG's syntax.
|
||||
This function is called by Emacs's automatic fontification, as long
|
||||
as `org-src-fontify-natively' is non-nil."
|
||||
(let ((modified (buffer-modified-p))
|
||||
(native-tab-width tab-width))
|
||||
(let ((modified (buffer-modified-p)) native-tab-width)
|
||||
(remove-text-properties start end '(face nil))
|
||||
(let ((lang-mode (org-src-get-lang-mode lang)))
|
||||
(when (fboundp lang-mode)
|
||||
(when-let* ((lang-mode (org-src-get-lang-mode-if-bound lang)))
|
||||
(condition-case nil
|
||||
(let ((string (buffer-substring-no-properties start end))
|
||||
(org-buffer (current-buffer)))
|
||||
(with-current-buffer
|
||||
|
|
@ -693,7 +703,7 @@ as `org-src-fontify-natively' is non-nil."
|
|||
;; space and the remapping between 'font-lock-face and 'face
|
||||
;; text properties may thus not be set. See commit
|
||||
;; 453d634bc.
|
||||
(dolist (prop (append '(font-lock-face face) font-lock-extra-managed-props))
|
||||
(dolist (prop (append '(font-lock-face face syntax-table) font-lock-extra-managed-props))
|
||||
(let ((new-prop (get-text-property pos prop)))
|
||||
(when new-prop
|
||||
(if (not (eq prop 'invisible))
|
||||
|
|
@ -734,27 +744,39 @@ as `org-src-fontify-natively' is non-nil."
|
|||
'org-src-invisible new-prop
|
||||
org-buffer)))))))
|
||||
(setq pos next)))
|
||||
(set-buffer-modified-p nil)))))
|
||||
(let ((new-table (syntax-table)))
|
||||
(alter-text-property
|
||||
start end 'syntax-table
|
||||
(lambda (old-table) (or old-table new-table))
|
||||
org-buffer))
|
||||
(set-buffer-modified-p nil)))
|
||||
(error
|
||||
(message "Native code fontification error in %S at pos%d\n Error: %S"
|
||||
(current-buffer) start
|
||||
(when (and (fboundp 'backtrace-get-frames)
|
||||
(fboundp 'backtrace-to-string))
|
||||
(backtrace-to-string (backtrace-get-frames 'backtrace)))))))
|
||||
;; Add Org faces.
|
||||
(let ((src-face (nth 1 (assoc-string lang org-src-block-faces t))))
|
||||
(when (or (facep src-face) (listp src-face))
|
||||
(font-lock-append-text-property start end 'face src-face))
|
||||
(font-lock-append-text-property start end 'face 'org-block))
|
||||
;; Display native tab indentation characters as spaces
|
||||
(when native-tab-width
|
||||
(save-excursion
|
||||
(goto-char start)
|
||||
(let ((indent-offset
|
||||
(if (org-src-preserve-indentation-p) 0
|
||||
(+ (progn (backward-char)
|
||||
(org-current-text-indentation))
|
||||
org-edit-src-content-indentation))))
|
||||
org-src-content-indentation))))
|
||||
(while (re-search-forward "^[ ]*\t" end t)
|
||||
(let* ((b (and (eq indent-offset (move-to-column indent-offset))
|
||||
(point)))
|
||||
(e (progn (skip-chars-forward "\t") (point)))
|
||||
(s (and b (make-string (* (- e b) native-tab-width) ? ))))
|
||||
(when (and b (< b e)) (add-text-properties b e `(display ,s)))
|
||||
(forward-char)))))
|
||||
(forward-char))))))
|
||||
(add-text-properties
|
||||
start end
|
||||
'(font-lock-fontified t fontified t font-lock-multiline t))
|
||||
|
|
@ -970,12 +992,31 @@ Org-babel commands."
|
|||
|
||||
(defun org-src-get-lang-mode (lang)
|
||||
"Return major mode that should be used for LANG.
|
||||
LANG is a string, and the returned major mode is a symbol."
|
||||
(intern
|
||||
LANG is a string, and the returned value is a symbol."
|
||||
(let ((mode (intern
|
||||
(concat
|
||||
(let ((l (or (cdr (assoc lang org-src-lang-modes)) lang)))
|
||||
(if (symbolp l) (symbol-name l) l))
|
||||
"-mode")))
|
||||
"-mode"))))
|
||||
(cond
|
||||
((fboundp 'major-mode-remap) (major-mode-remap mode))
|
||||
((boundp 'major-mode-remap-alist)
|
||||
(or (cdr (assq mode major-mode-remap-alist)) mode))
|
||||
(t mode))))
|
||||
|
||||
(defun org-src-get-lang-mode-if-bound (lang &optional fallback fallback-message-p)
|
||||
"Return major mode for LANG, if bound, and FALLBACK otherwise.
|
||||
LANG is a string. FALLBACK and the returned value are both symbols. If
|
||||
FALLBACK-MESSAGE-P and FALLBACK are both non-nil, display a message when
|
||||
falling back to a major mode different from that for LANG."
|
||||
(let ((mode (org-src-get-lang-mode lang)))
|
||||
(if (functionp mode)
|
||||
mode
|
||||
(when (and fallback
|
||||
fallback-message-p
|
||||
(not (eq fallback mode)))
|
||||
(message "%s not available, falling back to %s" mode fallback))
|
||||
fallback)))
|
||||
|
||||
(defun org-src-edit-buffer-p (&optional buffer)
|
||||
"Non-nil when current buffer is a source editing buffer.
|
||||
|
|
@ -1236,16 +1277,21 @@ Throw an error when not at an export block."
|
|||
(unless (and (org-element-type-p element 'export-block)
|
||||
(org-src--on-datum-p element))
|
||||
(user-error "Not in an export block"))
|
||||
(let* ((type (downcase (or (org-element-property :type element)
|
||||
;; Missing export-block type. Fallback
|
||||
;; to default mode.
|
||||
"fundamental")))
|
||||
(mode (org-src-get-lang-mode type)))
|
||||
(unless (functionp mode) (error "No such language mode: %s" mode))
|
||||
(let* ((lang-f-fallback #'fundamental-mode)
|
||||
(lang (or (if-let* ((lang
|
||||
(org-element-property :type element)))
|
||||
(downcase lang))
|
||||
(replace-regexp-in-string
|
||||
"-mode$" ""
|
||||
(symbol-name lang-f-fallback))))
|
||||
(lang-f (org-src-get-lang-mode-if-bound
|
||||
lang
|
||||
lang-f-fallback
|
||||
t)))
|
||||
(org-src--edit-element
|
||||
element
|
||||
(org-src--construct-edit-buffer-name (buffer-name) type)
|
||||
mode
|
||||
(org-src--construct-edit-buffer-name (buffer-name) lang)
|
||||
lang-f
|
||||
(lambda () (org-escape-code-in-region (point-min) (point-max)))))
|
||||
t))
|
||||
|
||||
|
|
@ -1282,8 +1328,9 @@ original code in the Org buffer, and replace it with the edited
|
|||
version. See `org-src-window-setup' to configure the display of
|
||||
windows containing the Org buffer and the code buffer.
|
||||
|
||||
When optional argument CODE is a string, edit it in a dedicated
|
||||
buffer instead.
|
||||
When optional argument CODE is a string, edit it in a read-only buffer
|
||||
instead. The contents of that buffer will *not* be written back to
|
||||
the source of example block at point.
|
||||
|
||||
When optional argument EDIT-BUFFER-NAME is non-nil, use it as the
|
||||
name of the sub-editing buffer."
|
||||
|
|
@ -1296,12 +1343,12 @@ name of the sub-editing buffer."
|
|||
(let* ((lang
|
||||
(if (eq type 'src-block) (org-element-property :language element)
|
||||
"example"))
|
||||
(lang-f (and (eq type 'src-block) (org-src-get-lang-mode lang)))
|
||||
(lang-f (and (eq type 'src-block)
|
||||
(org-src-get-lang-mode-if-bound
|
||||
lang #'fundamental-mode lang)))
|
||||
(babel-info (and (eq type 'src-block)
|
||||
(org-babel-get-src-block-info 'no-eval)))
|
||||
deactivate-mark)
|
||||
(when (and (eq type 'src-block) (not (functionp lang-f)))
|
||||
(error "No such language mode: %s" lang-f))
|
||||
(org-src--edit-element
|
||||
element
|
||||
(or edit-buffer-name
|
||||
|
|
@ -1331,10 +1378,9 @@ name of the sub-editing buffer."
|
|||
(org-src--on-datum-p context))
|
||||
(user-error "Not on inline source code"))
|
||||
(let* ((lang (org-element-property :language context))
|
||||
(lang-f (org-src-get-lang-mode lang))
|
||||
(lang-f (org-src-get-lang-mode-if-bound lang #'fundamental-mode t))
|
||||
(babel-info (org-babel-get-src-block-info 'no-eval))
|
||||
deactivate-mark)
|
||||
(unless (functionp lang-f) (error "No such language mode: %s" lang-f))
|
||||
(org-src--edit-element
|
||||
context
|
||||
(org-src--construct-edit-buffer-name (buffer-name) lang)
|
||||
|
|
@ -1409,15 +1455,22 @@ EVENT is passed to `mouse-set-point'."
|
|||
(overlay org-src--overlay))
|
||||
(org-src--contents-for-write-back write-back-buf)
|
||||
(with-current-buffer (org-src-source-buffer)
|
||||
;; Note: be careful to not move point here to make sure that
|
||||
;; point motion does not get recorded into the undo list,
|
||||
;; leading to unexpected results.
|
||||
;; https://orgmode.org/list/XF_7mLNCUN8XKtnd7G-NUoAF5Vq0DDafaDdF0v53eFlhQ35N-H3bPA0VkYyDrbEWE-0PEQg8iiyB7NatUtvPEQe6SQyJaTE5vW0CwoUKzqs=@proton.me
|
||||
(undo-boundary)
|
||||
(goto-char beg)
|
||||
;; Temporarily disable read-only features of OVERLAY in order to
|
||||
;; insert new contents.
|
||||
(delete-overlay overlay)
|
||||
(let ((expecting-bol (bolp)))
|
||||
(goto-char end)
|
||||
(org-replace-region-contents beg end write-back-buf 0.1 nil)
|
||||
(cl-assert (= (point) (+ beg (buffer-size write-back-buf))))
|
||||
(let ((expecting-bol (save-excursion (goto-char beg) (bolp))))
|
||||
(if (version< emacs-version "27.1")
|
||||
(progn (delete-region beg end)
|
||||
(insert (with-current-buffer write-back-buf (buffer-string))))
|
||||
(save-restriction
|
||||
(narrow-to-region beg end)
|
||||
(org-replace-buffer-contents write-back-buf 0.1 nil)
|
||||
(goto-char (point-max))))
|
||||
(when (and expecting-bol (not (bolp))) (insert "\n")))
|
||||
(kill-buffer write-back-buf)
|
||||
(save-buffer)
|
||||
|
|
@ -1455,12 +1508,20 @@ EVENT is passed to `mouse-set-point'."
|
|||
(not (equal (buffer-substring beg end)
|
||||
(with-current-buffer write-back-buf
|
||||
(buffer-string)))))
|
||||
;; Note: be careful to not move point here to make sure that
|
||||
;; point motion does not get recorded into the undo list,
|
||||
;; leading to unexpected results.
|
||||
;; https://orgmode.org/list/XF_7mLNCUN8XKtnd7G-NUoAF5Vq0DDafaDdF0v53eFlhQ35N-H3bPA0VkYyDrbEWE-0PEQg8iiyB7NatUtvPEQe6SQyJaTE5vW0CwoUKzqs=@proton.me
|
||||
(undo-boundary)
|
||||
(goto-char beg)
|
||||
(let ((expecting-bol (bolp)))
|
||||
(goto-char end)
|
||||
(org-replace-region-contents beg end write-back-buf 0.1 nil)
|
||||
(cl-assert (= (point) (+ beg (buffer-size write-back-buf))))
|
||||
(let ((expecting-bol (save-excursion (goto-char beg) (bolp))))
|
||||
(if (version< emacs-version "27.1")
|
||||
(progn (delete-region beg end)
|
||||
(insert (with-current-buffer write-back-buf
|
||||
(buffer-string))))
|
||||
(save-restriction
|
||||
(narrow-to-region beg end)
|
||||
(org-replace-buffer-contents write-back-buf 0.1 nil)
|
||||
(goto-char (point-max))))
|
||||
(when (and expecting-bol (not (bolp))) (insert "\n")))))
|
||||
(when write-back-buf (kill-buffer write-back-buf))
|
||||
;; If we are to return to source buffer, put point at an
|
||||
|
|
@ -1470,7 +1531,7 @@ EVENT is passed to `mouse-set-point'."
|
|||
(goto-char beg)
|
||||
(cond
|
||||
;; Block is hidden; move at start of block.
|
||||
((org-fold-folded-p nil 'block) (forward-line -1))
|
||||
((org-invisible-p) (forward-line -1))
|
||||
(write-back (org-src--goto-coordinates coordinates beg end))))
|
||||
;; Clean up left-over markers and restore window configuration.
|
||||
(set-marker beg nil)
|
||||
|
|
|
|||
|
|
@ -44,42 +44,32 @@
|
|||
(require 'org-fold-core)
|
||||
|
||||
(declare-function calc-eval "calc" (str &optional separator &rest args))
|
||||
(declare-function face-remap-remove-relative "face-remap" (cookie))
|
||||
(declare-function face-remap-add-relative "face-remap" (face &rest specs))
|
||||
(declare-function org-at-timestamp-p "org" (&optional extended))
|
||||
(declare-function org-delete-backward-char "org" (N))
|
||||
(declare-function org-mode "org" ())
|
||||
(declare-function org-duration-p "org-duration" (duration &optional canonical))
|
||||
(declare-function org-duration-p "org-duration" (duration))
|
||||
(declare-function org-duration-to-minutes "org-duration" (duration &optional canonical))
|
||||
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
|
||||
(declare-function org-element-contents "org-element-ast" (node))
|
||||
(declare-function org-element-extract "org-element-ast" (node))
|
||||
(declare-function org-element-interpret-data "org-element" (data))
|
||||
(declare-function org-element-lineage "org-element-ast" (blob &optional types with-self))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated))
|
||||
(declare-function org-element-parse-buffer "org-element" (&optional granularity visible-only keep-deferred))
|
||||
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated no-undefer))
|
||||
(declare-function org-element-property "org-element-ast" (property node))
|
||||
(declare-function org-element-end "org-element" (node))
|
||||
(declare-function org-element-post-affiliated "org-element" (node))
|
||||
(declare-function org-element-type-p "org-element-ast" (node types))
|
||||
(declare-function org-element-cache-reset "org-element" (&optional all no-persistence))
|
||||
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
|
||||
(declare-function org-export-create-backend "ox" (&rest rest) t)
|
||||
(declare-function org-export-data-with-backend "ox" (data backend info))
|
||||
(declare-function org-export-filter-apply-functions "ox" (filters value info))
|
||||
(declare-function org-export-first-sibling-p "ox" (blob info))
|
||||
(declare-function org-export-get-backend "ox" (name))
|
||||
(declare-function org-export-get-environment "ox" (&optional backend subtreep ext-plist))
|
||||
(declare-function org-export-install-filters "ox" (info))
|
||||
(declare-function org-export-table-has-special-column-p "ox" (table))
|
||||
(declare-function org-export-table-row-is-special-p "ox" (table-row info))
|
||||
(declare-function org-forward-paragraph "org" (&optional arg))
|
||||
(declare-function org-id-find "org-id" (id &optional markerp))
|
||||
(declare-function org-indent-line "org" ())
|
||||
(declare-function org-load-modules-maybe "org" (&optional force))
|
||||
(declare-function org-restart-font-lock "org" ())
|
||||
(declare-function org-sort-remove-invisible "org" (s))
|
||||
(declare-function org-time-stamp-format "org" (&optional long inactive))
|
||||
(declare-function org-time-stamp-format "org" (&optional long inactive custom))
|
||||
(declare-function org-time-string-to-absolute "org" (s &optional daynr prefer buffer pos))
|
||||
(declare-function org-time-string-to-time "org" (s))
|
||||
(declare-function org-timestamp-up-day "org" (&optional arg))
|
||||
|
|
@ -344,11 +334,11 @@ The `U' flag in a table formula will select this specific format for
|
|||
a single formula."
|
||||
:group 'org-table-calculation
|
||||
:version "24.1"
|
||||
:type '(choice (symbol :tag "Seconds" 'seconds)
|
||||
(symbol :tag "Minutes" 'minutes)
|
||||
(symbol :tag "Hours " 'hours)
|
||||
(symbol :tag "Days " 'days)
|
||||
(symbol :tag "HH:MM " 'hh:mm)))
|
||||
:type '(choice (const :tag "Seconds" seconds)
|
||||
(const :tag "Minutes" minutes)
|
||||
(const :tag "Hours " hours)
|
||||
(const :tag "Days " days)
|
||||
(const :tag "HH:MM " hh:mm)))
|
||||
|
||||
(defcustom org-table-duration-hour-zero-padding t
|
||||
"Non-nil means hours in table duration computations should be zero-padded.
|
||||
|
|
@ -521,7 +511,7 @@ This may be useful when columns have been shrunk."
|
|||
(define-minor-mode org-table-header-line-mode
|
||||
"Display the first row of the table at point in the header line."
|
||||
:lighter " TblHeader"
|
||||
(unless (eq major-mode 'org-mode)
|
||||
(unless (derived-mode-p 'org-mode)
|
||||
(user-error "Cannot turn org table header mode outside org-mode buffers"))
|
||||
(if org-table-header-line-mode
|
||||
(add-hook 'post-command-hook #'org-table-header-set-header nil t)
|
||||
|
|
@ -586,7 +576,7 @@ This works for both table types.")
|
|||
"Match a reference that needs translation, for reference display.")
|
||||
|
||||
(defconst org-table--separator-space-pre
|
||||
(propertize " " 'display '(space :relative-width 1))
|
||||
(propertize " " 'display '(space :relative-width 1) 'rear-nonsticky t)
|
||||
"Space used in front of fields when aligning the table.
|
||||
This space serves as a segment separator for the purposes of the
|
||||
bidirectional reordering.
|
||||
|
|
@ -929,8 +919,8 @@ nil When nil, the command tries to be smart and figure out the
|
|||
(cond
|
||||
((looking-at "^") (insert "| "))
|
||||
((looking-at "[ \t]*$") (replace-match " |") (forward-line 1))
|
||||
((looking-at "[ \t]*\"\\([^\"\n]*\\)\"")
|
||||
(replace-match "\\1")
|
||||
((looking-at "[ \t]*\"\\([^\"]*\\)\"")
|
||||
(replace-match (replace-regexp-in-string "\n" " " (match-string 1)) t t)
|
||||
(if (looking-at "\"") (insert "\"")))
|
||||
((looking-at "[^,\n]+") (goto-char (match-end 0)))
|
||||
((looking-at "[ \t]*,") (replace-match " | "))
|
||||
|
|
@ -1118,7 +1108,7 @@ Before doing so, re-align the table if necessary."
|
|||
(when (looking-at "| ?")
|
||||
(goto-char (match-end 0))))
|
||||
|
||||
(defun org-table-beginning-of-field (&optional n)
|
||||
(defun org-table-beginning-of-field (n)
|
||||
"Move to the beginning of the current table field.
|
||||
If already at or before the beginning, move to the beginning of the
|
||||
previous field.
|
||||
|
|
@ -1134,7 +1124,7 @@ With numeric argument N, move N-1 fields backward first."
|
|||
(and (looking-at " ") (forward-char 1)))
|
||||
(when (>= (point) pos) (org-table-beginning-of-field 2))))
|
||||
|
||||
(defun org-table-end-of-field (&optional n)
|
||||
(defun org-table-end-of-field (n)
|
||||
"Move to the end of the current table field.
|
||||
If already at or after the end, move to the end of the next table field.
|
||||
With numeric argument N, move N-1 fields forward first."
|
||||
|
|
@ -2966,6 +2956,7 @@ known that the table will be realigned a little later anyway."
|
|||
beg end eqlcol eqlfield)
|
||||
;; Insert constants in all formulas.
|
||||
(when eqlist
|
||||
(org-fold-core-ignore-modifications
|
||||
(org-table-with-shrunk-columns
|
||||
(org-table-save-field
|
||||
;; Expand equations, then split the equation list between
|
||||
|
|
@ -3014,6 +3005,7 @@ existing formula for column %s"
|
|||
(t nil)))
|
||||
(setq beg (line-beginning-position)
|
||||
end (copy-marker (line-beginning-position 2))))
|
||||
(org-combine-change-calls beg end
|
||||
(goto-char beg)
|
||||
;; Mark named fields untouchable. Also check if several
|
||||
;; field/range formulas try to set the same field.
|
||||
|
|
@ -3098,7 +3090,7 @@ existing formula for column %s"
|
|||
"Missing columns in the table. Aborting"))))))
|
||||
(org-table-eval-formula nil formula t t t t)))
|
||||
;; Clean up marker.
|
||||
(set-marker end nil)))
|
||||
(set-marker end nil)))))
|
||||
(unless noalign
|
||||
(when org-table-may-need-update (org-table-align))
|
||||
(when all
|
||||
|
|
@ -3142,7 +3134,7 @@ with the prefix ARG."
|
|||
;; the way.
|
||||
(org-table-recalculate t t)
|
||||
(org-table-align))
|
||||
t)))
|
||||
t 'org)))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-table-iterate-buffer-tables ()
|
||||
|
|
@ -3156,7 +3148,9 @@ with the prefix ARG."
|
|||
(catch 'exit
|
||||
(while (> i 0)
|
||||
(setq i (1- i))
|
||||
(org-table-map-tables (lambda () (org-table-recalculate t t)) t)
|
||||
(org-table-map-tables
|
||||
(lambda () (org-table-recalculate t t))
|
||||
t 'org)
|
||||
(if (equal checksum (setq c1 (md5 (buffer-string))))
|
||||
(progn
|
||||
(org-table-map-tables #'org-table-align t)
|
||||
|
|
@ -3323,8 +3317,8 @@ Parameters get priority."
|
|||
(org-defkey map [(shift right)] 'org-table-fedit-ref-right)
|
||||
(org-defkey map [(meta up)] 'org-table-fedit-scroll-down)
|
||||
(org-defkey map [(meta down)] 'org-table-fedit-scroll)
|
||||
(org-defkey map [(meta tab)] 'lisp-complete-symbol)
|
||||
(org-defkey map "\M-\C-i" 'lisp-complete-symbol)
|
||||
(org-defkey map [(meta tab)] 'completion-at-point)
|
||||
(org-defkey map "\M-\C-i" 'completion-at-point)
|
||||
(org-defkey map [(tab)] 'org-table-fedit-lisp-indent)
|
||||
(org-defkey map "\C-i" 'org-table-fedit-lisp-indent)
|
||||
(org-defkey map "\C-c\C-r" 'org-table-fedit-toggle-ref-type)
|
||||
|
|
@ -3338,7 +3332,7 @@ Parameters get priority."
|
|||
["Abort" org-table-fedit-abort t]
|
||||
"--"
|
||||
["Pretty-Print Lisp Formula" org-table-fedit-lisp-indent t]
|
||||
["Complete Lisp Symbol" lisp-complete-symbol t]
|
||||
["Complete Lisp Symbol" completion-at-point t]
|
||||
"--"
|
||||
"Shift Reference at Point"
|
||||
["Up" org-table-fedit-ref-up t]
|
||||
|
|
@ -3397,6 +3391,9 @@ Parameters get priority."
|
|||
(setq-local org-table--fedit-source source)
|
||||
(setq-local org-window-configuration wc)
|
||||
(setq-local org-selected-window sel-win)
|
||||
;; Use completion from `emacs-lisp-mode'
|
||||
(add-hook 'completion-at-point-functions
|
||||
#'elisp-completion-at-point nil 'local)
|
||||
(use-local-map org-table-fedit-map)
|
||||
(add-hook 'post-command-hook #'org-table-fedit-post-command t t)
|
||||
(setq startline (org-current-line))
|
||||
|
|
@ -3427,7 +3424,7 @@ Edit formulas, finish with `\\[org-ctrl-c-ctrl-c]' or `\\[org-edit-special]'. \
|
|||
See menu for more commands.")))))
|
||||
|
||||
(defun org-table-fedit-post-command ()
|
||||
(when (not (memq this-command '(lisp-complete-symbol)))
|
||||
(when (not (memq this-command '(lisp-complete-symbol completion-at-point)))
|
||||
(let ((win (selected-window)))
|
||||
(save-excursion
|
||||
(ignore-errors (org-table-show-reference))
|
||||
|
|
@ -4292,12 +4289,16 @@ beginning and end position of the current table."
|
|||
;;; Generic Tools
|
||||
|
||||
;;;###autoload
|
||||
(defun org-table-map-tables (f &optional quietly)
|
||||
"Apply function F to the start of all tables in the buffer."
|
||||
(defun org-table-map-tables (f &optional quietly type)
|
||||
"Apply function F to the start of all tables in the buffer.
|
||||
When TYPE is non-nil, only consider Org tables of that type (symbol
|
||||
`org' or symbol `table.el'."
|
||||
(org-with-point-at 1
|
||||
(while (re-search-forward org-table-line-regexp nil t)
|
||||
(let ((table (org-element-lineage (org-element-at-point) 'table t)))
|
||||
(when table
|
||||
(when (and table
|
||||
(or (not type)
|
||||
(eq type (org-element-property :type table))))
|
||||
(unless quietly
|
||||
(message "Mapping tables: %d%%"
|
||||
(floor (* 100.0 (point)) (buffer-size))))
|
||||
|
|
@ -4375,11 +4376,12 @@ extension of the given file name, and finally on the variable
|
|||
(user-error "TABLE_EXPORT_FORMAT invalid")))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-table--align-field (field width align)
|
||||
(defun org-table--align-field (field width align &optional field-width)
|
||||
"Format FIELD according to column WIDTH and alignment ALIGN.
|
||||
FIELD is a string. WIDTH is a number. ALIGN is either \"c\",
|
||||
\"l\" or\"r\"."
|
||||
(let* ((spaces (- width (org-string-width field nil 'org-table)))
|
||||
\"l\" or\"r\". If FIELD-WIDTH is non-nil, then it's used as
|
||||
FIELD's width. Otherwise, it's calculated."
|
||||
(let* ((spaces (- width (or field-width (org-string-width field nil 'org-table))))
|
||||
(prefix (pcase align
|
||||
("l" "")
|
||||
("r" (make-string spaces ?\s))
|
||||
|
|
@ -4408,7 +4410,16 @@ FIELD is a string. WIDTH is a number. ALIGN is either \"c\",
|
|||
(rows (remq 'hline table))
|
||||
(widths nil)
|
||||
(alignments nil)
|
||||
(columns-number 1))
|
||||
(columns-number 1)
|
||||
(invisibility-spec (org-string-width-invisibility-spec))
|
||||
(cell-width-cache (make-hash-table :test 'equal))
|
||||
(get-or-compute-cell-width
|
||||
(lambda (cell)
|
||||
(or (gethash cell cell-width-cache)
|
||||
(puthash
|
||||
cell
|
||||
(org-string-width cell nil 'org-table invisibility-spec)
|
||||
cell-width-cache)))))
|
||||
(if (null rows)
|
||||
;; Table contains only horizontal rules. Compute the
|
||||
;; number of columns anyway, and choose an arbitrary width
|
||||
|
|
@ -4428,7 +4439,7 @@ FIELD is a string. WIDTH is a number. ALIGN is either \"c\",
|
|||
(non-empty 0))
|
||||
(dolist (row rows)
|
||||
(let ((cell (or (nth i row) "")))
|
||||
(setq max-width (max max-width (org-string-width cell nil 'org-table)))
|
||||
(setq max-width (max max-width (funcall get-or-compute-cell-width cell)))
|
||||
(cond (fixed-align? nil)
|
||||
((equal cell "") nil)
|
||||
((string-match "\\`<\\([lrc]\\)[0-9]*>\\'" cell)
|
||||
|
|
@ -4451,6 +4462,8 @@ FIELD is a string. WIDTH is a number. ALIGN is either \"c\",
|
|||
(setq org-table-last-column-widths widths)
|
||||
;; Build new table rows. Only replace rows that actually
|
||||
;; changed.
|
||||
(org-fold-core-ignore-modifications
|
||||
(org-combine-change-calls beg end
|
||||
(let ((rule (and (memq 'hline table)
|
||||
(mapconcat (lambda (w) (make-string (+ 2 w) ?-))
|
||||
widths
|
||||
|
|
@ -4467,7 +4480,13 @@ FIELD is a string. WIDTH is a number. ALIGN is either \"c\",
|
|||
(append row
|
||||
(make-list offset "")))))
|
||||
(mapconcat #'identity
|
||||
(cl-mapcar #'org-table--align-field
|
||||
(cl-mapcar
|
||||
(lambda (field width alignment)
|
||||
(org-table--align-field
|
||||
field
|
||||
width
|
||||
alignment
|
||||
(funcall get-or-compute-cell-width field)))
|
||||
fields
|
||||
widths
|
||||
alignments)
|
||||
|
|
@ -4476,7 +4495,7 @@ FIELD is a string. WIDTH is a number. ALIGN is either \"c\",
|
|||
(if (equal new previous)
|
||||
(forward-line)
|
||||
(insert new "\n")
|
||||
(delete-region (point) (line-beginning-position 2))))))
|
||||
(delete-region (point) (line-beginning-position 2))))))))
|
||||
(set-marker end nil)
|
||||
(when org-table-overlay-coordinates (org-table-overlay-coordinates))
|
||||
(setq org-table-may-need-update nil))))))
|
||||
|
|
@ -5653,6 +5672,42 @@ First element has index 0, or I0 if given."
|
|||
(insert txt)
|
||||
(goto-char pos)))
|
||||
|
||||
(defun orgtbl--skip (ast _ info)
|
||||
"Extract first X table rows from AST.
|
||||
X is taken from :skip property in INFO plist.
|
||||
Return the modified AST."
|
||||
(when-let* ((skip (plist-get info :skip)))
|
||||
(unless (wholenump skip) (user-error "Wrong :skip value"))
|
||||
(let ((n 0))
|
||||
(org-element-map ast 'table-row
|
||||
(lambda (row)
|
||||
(if (>= n skip) t
|
||||
(org-element-extract row)
|
||||
(cl-incf n)
|
||||
nil))
|
||||
nil t)))
|
||||
ast)
|
||||
|
||||
(defun orgtbl--skipcols (ast _ info)
|
||||
"Extract first X table columns from AST.
|
||||
X is taken from :skipcols property in INFO plist.
|
||||
Special columns are always ignored.
|
||||
Return the modified AST."
|
||||
(when-let* ((skipcols (plist-get info :skipcols)))
|
||||
(unless (consp skipcols) (user-error "Wrong :skipcols value"))
|
||||
(org-element-map ast 'table
|
||||
(lambda (table)
|
||||
(let ((specialp (org-export-table-has-special-column-p table)))
|
||||
(dolist (row (org-element-contents table))
|
||||
(when (eq (org-element-property :type row) 'standard)
|
||||
(let ((c 1))
|
||||
(dolist (cell (nthcdr (if specialp 1 0)
|
||||
(org-element-contents row)))
|
||||
(when (memq c skipcols)
|
||||
(org-element-extract cell))
|
||||
(cl-incf c)))))))))
|
||||
ast)
|
||||
|
||||
;;;###autoload
|
||||
(defun orgtbl-to-generic (table params)
|
||||
"Convert the `orgtbl-mode' TABLE to some other format.
|
||||
|
|
@ -5664,7 +5719,8 @@ a horizontal separator line, or a list of fields for that
|
|||
line. PARAMS is a property list of parameters that can
|
||||
influence the conversion.
|
||||
|
||||
Valid parameters are:
|
||||
Valid parameters are all the export options understood by the export
|
||||
backend and also:
|
||||
|
||||
:backend, :raw
|
||||
|
||||
|
|
@ -5773,84 +5829,55 @@ This may be either a string or a function of two arguments:
|
|||
;; regular backend has a transcoder for them. We
|
||||
;; provide one so they are not ignored, but displayed
|
||||
;; as-is instead.
|
||||
(macro . (lambda (m c i) (org-element-macro-interpreter m nil))))))
|
||||
data info)
|
||||
(macro . (lambda (m c i) (org-element-macro-interpreter m nil)))
|
||||
;; Only export the actual table. Do nothing with the
|
||||
;; containing section regardless what backend think about
|
||||
;; it. (It is somewhat like BODY-ONLY argument in
|
||||
;; `org-export-as', but skips not only transcoding the
|
||||
;; full document, but also section containing the table.
|
||||
(section . (lambda (_ contents _) contents))))))
|
||||
;; Store TABLE as Org syntax in DATA. Tolerate non-string cells.
|
||||
;; Initialize communication channel in INFO.
|
||||
(with-temp-buffer
|
||||
(let ((org-inhibit-startup t)) (org-mode))
|
||||
(org-fold-core-ignore-modifications
|
||||
(let ((standard-output (current-buffer))
|
||||
(org-element-use-cache nil))
|
||||
(let ((standard-output (current-buffer)))
|
||||
(dolist (e table)
|
||||
(cond ((eq e 'hline) (princ "|--\n"))
|
||||
((consp e)
|
||||
(princ "| ") (dolist (c e) (princ c) (princ " |"))
|
||||
(princ "\n")))))
|
||||
(org-element-cache-reset)
|
||||
;; Add backend specific filters, but not user-defined ones. In
|
||||
;; particular, make sure to call parse-tree filters on the
|
||||
;; table.
|
||||
(setq info
|
||||
(let ((org-export-filters-alist nil))
|
||||
(org-export-install-filters
|
||||
(org-combine-plists
|
||||
(org-export-get-environment backend nil params)
|
||||
`(:back-end ,(org-export-get-backend backend))))))
|
||||
(setq data
|
||||
(org-export-filter-apply-functions
|
||||
(plist-get info :filter-parse-tree)
|
||||
(org-element-map (org-element-parse-buffer) 'table
|
||||
#'identity nil t)
|
||||
info))
|
||||
(let ((org-inhibit-startup t)) (org-mode))
|
||||
(defvar org-export-before-processing-functions) ; ox.el
|
||||
(defvar org-export-process-citations) ; ox.el
|
||||
(defvar org-export-expand-links) ; ox.el
|
||||
(defvar org-export-filter-parse-tree-functions) ; ox.el
|
||||
(defvar org-export-filters-alist) ; ox.el
|
||||
(defvar org-export-replace-macros) ; ox.el
|
||||
(declare-function
|
||||
org-export-as "ox"
|
||||
(backend &optional subtreep visible-only body-only ext-plist))
|
||||
;; We disable the usual pre-processing and post-processing,
|
||||
;; i.e., hooks, Babel code evaluation, and macro expansion.
|
||||
;; Only backend specific filters are retained.
|
||||
;; We _do not_ disable `org-export-filter-parse-tree-functions'
|
||||
;; (historically).
|
||||
(let ((org-export-before-processing-functions nil)
|
||||
(org-export-replace-macros nil)
|
||||
(org-export-use-babel nil)
|
||||
(org-export-before-parsing-functions nil)
|
||||
(org-export-process-citations nil)
|
||||
(org-export-expand-links nil)
|
||||
(org-export-filter-parse-tree-functions
|
||||
(append
|
||||
'(orgtbl--skip orgtbl--skipcols)
|
||||
org-export-filter-parse-tree-functions))
|
||||
(org-export-filters-alist
|
||||
'((:filter-parse-tree . org-export-filter-parse-tree-functions))))
|
||||
(when (or (not backend) (plist-get params :raw)) (require 'ox-org))
|
||||
(when (and backend (symbolp backend) (not (org-export-get-backend backend)))
|
||||
(user-error "Unknown :backend value"))))
|
||||
(when (or (not backend) (plist-get info :raw)) (require 'ox-org))
|
||||
;; Handle :skip parameter.
|
||||
(let ((skip (plist-get info :skip)))
|
||||
(when skip
|
||||
(unless (wholenump skip) (user-error "Wrong :skip value"))
|
||||
(let ((n 0))
|
||||
(org-element-map data 'table-row
|
||||
(lambda (row)
|
||||
(if (>= n skip) t
|
||||
(org-element-extract row)
|
||||
(cl-incf n)
|
||||
nil))
|
||||
nil t))))
|
||||
;; Handle :skipcols parameter.
|
||||
(let ((skipcols (plist-get info :skipcols)))
|
||||
(when skipcols
|
||||
(unless (consp skipcols) (user-error "Wrong :skipcols value"))
|
||||
(org-element-map data 'table
|
||||
(lambda (table)
|
||||
(let ((specialp (org-export-table-has-special-column-p table)))
|
||||
(dolist (row (org-element-contents table))
|
||||
(when (eq (org-element-property :type row) 'standard)
|
||||
(let ((c 1))
|
||||
(dolist (cell (nthcdr (if specialp 1 0)
|
||||
(org-element-contents row)))
|
||||
(when (memq c skipcols)
|
||||
(org-element-extract cell))
|
||||
(cl-incf c))))))))))
|
||||
;; Since we are going to export using a low-level mechanism,
|
||||
;; ignore special column and special rows manually.
|
||||
(let ((special? (org-export-table-has-special-column-p data))
|
||||
ignore)
|
||||
(org-element-map data (if special? '(table-cell table-row) 'table-row)
|
||||
(lambda (datum)
|
||||
(when (if (org-element-type-p datum 'table-row)
|
||||
(org-export-table-row-is-special-p datum nil)
|
||||
(org-export-first-sibling-p datum nil))
|
||||
(push datum ignore))))
|
||||
(setq info (plist-put info :ignore-list ignore)))
|
||||
;; We use a low-level mechanism to export DATA so as to skip all
|
||||
;; usual pre-processing and post-processing, i.e., hooks, Babel
|
||||
;; code evaluation, include keywords and macro expansion. Only
|
||||
;; backend specific filters are retained.
|
||||
(let ((output (org-export-data-with-backend data custom-backend info)))
|
||||
(user-error "Unknown :backend value: %S" backend))
|
||||
(let ((output (org-export-as custom-backend nil nil 'body-only params)))
|
||||
;; Remove final newline.
|
||||
(if (org-string-nw-p output) (substring-no-properties output 0 -1) ""))))
|
||||
(if (org-string-nw-p output) (substring-no-properties output 0 -1) ""))))))
|
||||
|
||||
(defun org-table--generic-apply (value name &optional with-cons &rest args)
|
||||
(cond ((null value) nil)
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@
|
|||
(require 'cl-lib)
|
||||
(require 'org-clock)
|
||||
|
||||
(declare-function org-agenda-error "org-agenda" ())
|
||||
|
||||
(defvar org-timer-start-time nil
|
||||
"Start time for the running timer.")
|
||||
|
||||
|
|
@ -108,7 +106,8 @@ nil current timer is not displayed"
|
|||
"Hook run after countdown timer is set.")
|
||||
|
||||
(defvar org-timer-done-hook nil
|
||||
"Hook run after countdown timer reaches zero.")
|
||||
"Hook run after countdown timer reaches zero.
|
||||
The hook is run before the timer is actually stopped.")
|
||||
|
||||
;;;###autoload
|
||||
(defun org-timer-start (&optional offset)
|
||||
|
|
@ -426,7 +425,8 @@ using three \\[universal-argument] prefix arguments."
|
|||
org-timer-default-timer))
|
||||
(effort-minutes
|
||||
(cond ((derived-mode-p 'org-agenda-mode)
|
||||
(org-get-at-bol 'effort-minutes))
|
||||
(when-let* ((effort (org-get-at-bol 'effort-minutes)))
|
||||
(floor effort)))
|
||||
((derived-mode-p 'org-mode)
|
||||
(let ((effort (org-entry-get nil org-effort-property)))
|
||||
(when (org-string-nw-p effort)
|
||||
|
|
@ -470,11 +470,11 @@ time is up."
|
|||
(sound org-clock-sound))
|
||||
(run-with-timer
|
||||
secs nil (lambda ()
|
||||
(setq org-timer-countdown-timer nil
|
||||
org-timer-start-time nil)
|
||||
(org-notify msg sound)
|
||||
(org-timer-set-mode-line 'off)
|
||||
(run-hooks 'org-timer-done-hook)))))
|
||||
(run-hooks 'org-timer-done-hook)
|
||||
(setq org-timer-countdown-timer nil
|
||||
org-timer-start-time nil)))))
|
||||
|
||||
(defun org-timer--get-timer-title ()
|
||||
"Construct timer title.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
(defun org-release ()
|
||||
"The release version of Org.
|
||||
Inserted by installing Org mode or when a release is made."
|
||||
(let ((org-release "9.7.11"))
|
||||
(let ((org-release "9.8.1"))
|
||||
org-release))
|
||||
;;;###autoload
|
||||
(defun org-git-version ()
|
||||
"The Git version of Org mode.
|
||||
Inserted by installing Org or when a release is made."
|
||||
(let ((org-git-version "release_9.7.11"))
|
||||
(let ((org-git-version "release_9.8.1"))
|
||||
org-git-version))
|
||||
|
||||
(provide 'org-version)
|
||||
|
|
|
|||
1706
lisp/org/org.el
1706
lisp/org/org.el
File diff suppressed because it is too large
Load diff
|
|
@ -37,9 +37,6 @@
|
|||
;;; Function Declarations
|
||||
|
||||
(declare-function aa2u "ext:ascii-art-to-unicode" ())
|
||||
(declare-function org-at-heading-p "org" (&optional _))
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-next-visible-heading "org" (arg))
|
||||
|
||||
;;; Define Backend
|
||||
;;
|
||||
|
|
@ -688,8 +685,8 @@ possible. It doesn't apply to `inlinetask' elements."
|
|||
(org-make-tag-string tag-list)))))
|
||||
(priority
|
||||
(and (plist-get info :with-priority)
|
||||
(let ((char (org-element-property :priority element)))
|
||||
(and char (format "(#%c) " char)))))
|
||||
(let ((priority-value (org-element-property :priority element)))
|
||||
(and priority-value (format "(#%s) " (org-priority-to-string priority-value))))))
|
||||
(first-part (concat numbers todo priority text)))
|
||||
(concat
|
||||
first-part
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ through `org-beamer-environments-extra' variable.")
|
|||
("example" "e" "\\begin{example}%a[%h]%l" "\\end{example}")
|
||||
("exampleblock" "E" "\\begin{exampleblock}%a{%h}%l" "\\end{exampleblock}")
|
||||
("proof" "p" "\\begin{proof}%a[%h]" "\\end{proof}")
|
||||
("onlyenv" "O" "\\begin{onlyenv}%a" "\\end{onlyenv}")
|
||||
("beamercolorbox" "o" "\\begin{beamercolorbox}%o{%h}" "\\end{beamercolorbox}"))
|
||||
"Environments triggered by properties in Beamer export.
|
||||
These are the defaults - for user definitions, see
|
||||
|
|
@ -500,6 +501,15 @@ used as a communication channel."
|
|||
(if (and env (equal (downcase env) "fullframe")) ""
|
||||
(org-export-data
|
||||
(org-element-property :title headline) info))))
|
||||
;; Subtitle
|
||||
(when-let* ((subtitle
|
||||
(org-element-property :BEAMER_SUBTITLE headline)))
|
||||
(format "{%s}"
|
||||
(org-export-data
|
||||
(org-element-parse-secondary-string
|
||||
subtitle
|
||||
(org-element-restriction 'keyword))
|
||||
info)))
|
||||
"\n"
|
||||
;; The following workaround is required in fragile frames
|
||||
;; as Beamer will append "\par" to the beginning of the
|
||||
|
|
|
|||
|
|
@ -43,12 +43,7 @@
|
|||
|
||||
;;; Function Declarations
|
||||
|
||||
(declare-function org-id-find-id-file "org-id" (id))
|
||||
(declare-function htmlize-region "ext:htmlize" (beg end))
|
||||
(declare-function mm-url-decode-entities "mm-url" ())
|
||||
(declare-function org-at-heading-p "org" (&optional _))
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-next-visible-heading "org" (arg))
|
||||
|
||||
(defvar htmlize-css-name-prefix)
|
||||
(defvar htmlize-output-type)
|
||||
|
|
@ -161,7 +156,7 @@
|
|||
(:html-postamble-format nil nil org-html-postamble-format)
|
||||
(:html-preamble-format nil nil org-html-preamble-format)
|
||||
(:html-prefer-user-labels nil nil org-html-prefer-user-labels)
|
||||
(:html-self-link-headlines nil nil org-html-self-link-headlines)
|
||||
(:html-self-link-headlines nil "html-self-link-headlines" org-html-self-link-headlines)
|
||||
(:html-table-align-individual-fields
|
||||
nil nil org-html-table-align-individual-fields)
|
||||
(:html-table-caption-above nil nil org-html-table-caption-above)
|
||||
|
|
@ -233,10 +228,10 @@ For blocks that should contain headlines, use the HTML_CONTAINER
|
|||
property on the headline itself.")
|
||||
|
||||
(defconst org-html-special-string-regexps
|
||||
'(("\\\\-" . "­") ; shy
|
||||
("---\\([^-]\\)" . "—\\1") ; mdash
|
||||
("--\\([^-]\\)" . "–\\1") ; ndash
|
||||
("\\.\\.\\." . "…")) ; hellip
|
||||
'(("\\\\-" . "­")
|
||||
("---\\([^-]\\)" . "—\\1")
|
||||
("--\\([^-]\\)" . "–\\1")
|
||||
("\\.\\.\\." . "…"))
|
||||
"Regular expressions for special string conversion.")
|
||||
|
||||
(defvar org-html--id-attr-prefix "ID-"
|
||||
|
|
@ -318,6 +313,7 @@ This affects IDs that are determined from the ID property.")
|
|||
pre.src-asymptote:before { content: 'Asymptote'; }
|
||||
pre.src-awk:before { content: 'Awk'; }
|
||||
pre.src-authinfo::before { content: 'Authinfo'; }
|
||||
pre.src-c:before { content: 'C'; }
|
||||
pre.src-C:before { content: 'C'; }
|
||||
/* pre.src-C++ doesn't work in CSS */
|
||||
pre.src-clojure:before { content: 'Clojure'; }
|
||||
|
|
@ -332,7 +328,7 @@ This affects IDs that are determined from the ID property.")
|
|||
pre.src-haskell:before { content: 'Haskell'; }
|
||||
pre.src-hledger:before { content: 'hledger'; }
|
||||
pre.src-java:before { content: 'Java'; }
|
||||
pre.src-js:before { content: 'Javascript'; }
|
||||
pre.src-js:before { content: 'JavaScript'; }
|
||||
pre.src-latex:before { content: 'LaTeX'; }
|
||||
pre.src-ledger:before { content: 'Ledger'; }
|
||||
pre.src-lisp:before { content: 'Lisp'; }
|
||||
|
|
@ -459,8 +455,9 @@ You can use `org-html-head' and `org-html-head-extra' to add to
|
|||
this style. If you don't want to include this default style,
|
||||
customize `org-html-head-include-default-style'."
|
||||
:group 'org-export-html
|
||||
:package-version '(Org . "9.5")
|
||||
:type 'string)
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'string
|
||||
:safe #'stringp)
|
||||
|
||||
|
||||
;;; User Configuration Variables
|
||||
|
|
@ -1130,7 +1127,7 @@ org-info.js for your website."
|
|||
((on . "☑") (off . "☐") (trans . "☐")))
|
||||
(ascii .
|
||||
((on . "<code>[X]</code>")
|
||||
(off . "<code>[ ]</code>")
|
||||
(off . "<code>[ ]</code>")
|
||||
(trans . "<code>[-]</code>")))
|
||||
(html .
|
||||
((on . "<input type='checkbox' checked='checked' />")
|
||||
|
|
@ -1168,6 +1165,20 @@ See `format-time-string' for more information on its components."
|
|||
:package-version '(Org . "8.0")
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-html-datetime-formats '("%F" . "%FT%T")
|
||||
"Formats used for the timestamp added as metadata to the time HTML element.
|
||||
This only has an effect when `org-html-html5-fancy' is enabled, but
|
||||
does not affect how the timestamp is displayed. The format in CAR
|
||||
represents the timestamp used for timestamps without a time component,
|
||||
CDR the one for the full date and time. Note that the HTML standard
|
||||
restricts what timestamp formats are considered valid for the datetime
|
||||
attribute. See `format-time-string' for more information on its
|
||||
components."
|
||||
:type '(cons string string)
|
||||
:group 'org-export-html
|
||||
:package-version '(Org . "9.8")
|
||||
:safe #'consp)
|
||||
|
||||
;;;; Template :: Mathjax
|
||||
|
||||
(defcustom org-html-mathjax-options
|
||||
|
|
@ -1531,7 +1542,8 @@ style information."
|
|||
This variable can contain the full HTML structure to provide a
|
||||
style, including the surrounding HTML tags. You can consider
|
||||
including definitions for the following classes: title, todo,
|
||||
done, timestamp, timestamp-kwd, tag, target.
|
||||
done, timestamp, timestamp-kwd, tag, target. Can be a string, or
|
||||
a function that accepts the INFO plist and returns a string.
|
||||
|
||||
For example, a valid value would be:
|
||||
|
||||
|
|
@ -1554,21 +1566,25 @@ header.
|
|||
You can set this on a per-file basis using #+HTML_HEAD:,
|
||||
or for publication projects using the :html-head property."
|
||||
:group 'org-export-html
|
||||
:version "24.4"
|
||||
:package-version '(Org . "8.0")
|
||||
:type 'string)
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(choice (string :tag "Literal text to insert")
|
||||
(function :tag "Function evaluating to a string"))
|
||||
:safe #'stringp)
|
||||
;;;###autoload
|
||||
(put 'org-html-head 'safe-local-variable 'stringp)
|
||||
|
||||
(defcustom org-html-head-extra ""
|
||||
"More head information to add in the HTML output.
|
||||
|
||||
You can set this on a per-file basis using #+HTML_HEAD_EXTRA:,
|
||||
or for publication projects using the :html-head-extra property."
|
||||
You can set this on a per-file basis using #+HTML_HEAD_EXTRA:, or
|
||||
for publication projects using the :html-head-extra property.
|
||||
Can be a string, or a function that accepts the INFO plist and returns
|
||||
a string."
|
||||
:group 'org-export-html
|
||||
:version "24.4"
|
||||
:package-version '(Org . "8.0")
|
||||
:type 'string)
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(choice (string :tag "Literal text to insert")
|
||||
(function :tag "Function evaluating to a string"))
|
||||
:safe #'stringp)
|
||||
;;;###autoload
|
||||
(put 'org-html-head-extra 'safe-local-variable 'stringp)
|
||||
|
||||
|
|
@ -1648,7 +1664,7 @@ https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag"
|
|||
selector_eval_scheme: '.src-scheme',
|
||||
selector: '.src-clojure',
|
||||
selector_eval_ruby: '.src-ruby'};"
|
||||
"Javascript snippet to activate klipse."
|
||||
"JavaScript snippet to activate klipse."
|
||||
:group 'org-export-html
|
||||
:package-version '(Org . "9.1")
|
||||
:type 'string)
|
||||
|
|
@ -1804,6 +1820,29 @@ is meant to be used as a predicate for `org-export-get-ordinal' or
|
|||
a value to `org-html-standalone-image-predicate'."
|
||||
(org-element-property :caption element))
|
||||
|
||||
(defun org-html--format-timestamp (timestamp info)
|
||||
"Format given TIMESTAMP for inclusion in an HTML document.
|
||||
INFO is a plist used as a communication channel. Formatted timestamp
|
||||
will be wrapped in an element with class timestamp."
|
||||
(let ((html-tag (if (org-html--html5-fancy-p info) "time" "span"))
|
||||
(html-attrs (concat "class=\"timestamp\""
|
||||
(when (org-html--html5-fancy-p info)
|
||||
(format " datetime=\"%s\""
|
||||
(org-format-timestamp
|
||||
timestamp
|
||||
(if (org-timestamp-has-time-p timestamp)
|
||||
(cdr org-html-datetime-formats)
|
||||
(car org-html-datetime-formats))))))))
|
||||
(replace-regexp-in-string
|
||||
"--"
|
||||
"–"
|
||||
(format "<%s %s>%s</%s>"
|
||||
html-tag
|
||||
html-attrs
|
||||
(org-html-plain-text (org-timestamp-translate timestamp)
|
||||
info)
|
||||
html-tag))))
|
||||
|
||||
;;;; Table
|
||||
|
||||
(defun org-html-htmlize-region-for-paste (beg end)
|
||||
|
|
@ -2001,6 +2040,15 @@ INFO is a plist used as a communication channel."
|
|||
org-html-meta-tags))
|
||||
""))))
|
||||
|
||||
(defun org-html-normalize-string-or-function (input &rest args)
|
||||
"Normalize INPUT function or string.
|
||||
If INPUT is a string, it is passed to
|
||||
`org-element-normalize-string'. If INPUT is a function, it is
|
||||
applied to arguments ARGS, and the result is passed to
|
||||
`org-element-normalize-string'."
|
||||
(let ((s (if (functionp input) (format "%s" (apply input args)) input)))
|
||||
(org-element-normalize-string s)))
|
||||
|
||||
(defun org-html--build-head (info)
|
||||
"Return information for the <head>..</head> of the HTML output.
|
||||
INFO is a plist used as a communication channel."
|
||||
|
|
@ -2008,8 +2056,9 @@ INFO is a plist used as a communication channel."
|
|||
(concat
|
||||
(when (plist-get info :html-head-include-default-style)
|
||||
(org-element-normalize-string org-html-style-default))
|
||||
(org-element-normalize-string (plist-get info :html-head))
|
||||
(org-element-normalize-string (plist-get info :html-head-extra))
|
||||
(org-html-normalize-string-or-function (plist-get info :html-head) info)
|
||||
(org-html-normalize-string-or-function (plist-get info :html-head-extra)
|
||||
info)
|
||||
(when (and (plist-get info :html-htmlized-css-url)
|
||||
(eq org-html-htmlize-output-type 'css))
|
||||
(org-html-close-tag "link"
|
||||
|
|
@ -2318,7 +2367,8 @@ INFO is the info plist."
|
|||
"Format a priority into HTML.
|
||||
PRIORITY is the character code of the priority or nil. INFO is
|
||||
a plist containing export options."
|
||||
(and priority (format "<span class=\"priority\">[%c]</span>" priority)))
|
||||
(and priority (format "<span class=\"priority\">[%s]</span>"
|
||||
(org-priority-to-string priority))))
|
||||
|
||||
;;;; Tags
|
||||
|
||||
|
|
@ -2333,7 +2383,7 @@ INFO is a plist containing export options."
|
|||
(concat (plist-get info :html-tag-class-prefix)
|
||||
(org-html-fix-class-name tag))
|
||||
tag))
|
||||
tags " "))))
|
||||
tags " "))))
|
||||
|
||||
;;;; Src Code
|
||||
|
||||
|
|
@ -2355,8 +2405,7 @@ is the language used for CODE, as a string, or nil."
|
|||
(org-html-encode-plain-text code))
|
||||
(t
|
||||
;; Map language
|
||||
(setq lang (or (assoc-default lang org-src-lang-modes) lang))
|
||||
(let* ((lang-mode (and lang (intern (format "%s-mode" lang)))))
|
||||
(let* ((lang-mode (and lang (org-src-get-lang-mode lang))))
|
||||
(cond
|
||||
;; Case 1: Language is not associated with any Emacs mode
|
||||
((not (functionp lang-mode))
|
||||
|
|
@ -2471,7 +2520,7 @@ of contents as a string, or nil if it is empty."
|
|||
(let* ((toc-id-counter (plist-get info :org-html--toc-counter))
|
||||
(toc (concat (format "<div id=\"text-table-of-contents%s\" role=\"doc-toc\">"
|
||||
(if toc-id-counter (format "-%d" toc-id-counter) ""))
|
||||
(org-html--toc-text toc-entries)
|
||||
(org-html--toc-text toc-entries scope)
|
||||
"</div>\n")))
|
||||
(plist-put info :org-html--toc-counter (1+ (or toc-id-counter 0)))
|
||||
(if scope toc
|
||||
|
|
@ -2489,11 +2538,14 @@ of contents as a string, or nil if it is empty."
|
|||
toc
|
||||
(format "</%s>\n" outer-tag))))))))
|
||||
|
||||
(defun org-html--toc-text (toc-entries)
|
||||
(defun org-html--toc-text (toc-entries &optional scope)
|
||||
"Return innards of a table of contents, as a string.
|
||||
|
||||
TOC-ENTRIES is an alist where key is an entry title, as a string,
|
||||
and value is its relative level, as an integer."
|
||||
(let* ((prev-level (1- (cdar toc-entries)))
|
||||
and value is its relative level, as an integer. Optional SCOPE,
|
||||
when non-nil, indicates a TOC for a subtree, which affects the
|
||||
initial nesting level."
|
||||
(let* ((prev-level (if scope (1- (cdar toc-entries)) 0))
|
||||
(start-level prev-level))
|
||||
(concat
|
||||
(mapconcat
|
||||
|
|
@ -2639,17 +2691,17 @@ holding contextual information."
|
|||
|
||||
;;;; Clock
|
||||
|
||||
(defun org-html-clock (clock _contents _info)
|
||||
(defun org-html-clock (clock _contents info)
|
||||
"Transcode a CLOCK element from Org to HTML.
|
||||
CONTENTS is nil. INFO is a plist used as a communication
|
||||
channel."
|
||||
(format "<p>
|
||||
<span class=\"timestamp-wrapper\">
|
||||
<span class=\"timestamp-kwd\">%s</span> <span class=\"timestamp\">%s</span>%s
|
||||
<span class=\"timestamp-kwd\">%s</span> %s%s
|
||||
</span>
|
||||
</p>"
|
||||
org-clock-string
|
||||
(org-timestamp-translate (org-element-property :value clock))
|
||||
(org-html--format-timestamp (org-element-property :value clock) info)
|
||||
(let ((time (org-element-property :duration clock)))
|
||||
(and time (format " <span class=\"timestamp\">(%s)</span>" time)))))
|
||||
|
||||
|
|
@ -2860,7 +2912,7 @@ description of TODO, PRIORITY, TEXT, TAGS, and INFO arguments."
|
|||
(concat todo (and todo " ")
|
||||
priority (and priority " ")
|
||||
text
|
||||
(and tags "   ") tags)))
|
||||
(and tags "  ") tags)))
|
||||
|
||||
(defun org-html--container (headline info)
|
||||
"Return HTML container name for HEADLINE as a string.
|
||||
|
|
@ -3051,7 +3103,7 @@ INFO is a plist containing export properties."
|
|||
(concat (file-name-as-directory org-preview-latex-image-directory)
|
||||
(file-name-sans-extension
|
||||
(file-name-nondirectory bfn)))
|
||||
cache-dir (file-name-directory bfn))
|
||||
cache-dir (file-name-directory (plist-get info :output-file)))
|
||||
;; Re-create LaTeX environment from original buffer in
|
||||
;; temporary buffer so that dvipng/imagemagick can properly
|
||||
;; turn the fragment into an image.
|
||||
|
|
@ -3085,6 +3137,8 @@ Math environments match the regular expression defined in
|
|||
`org-latex-math-environments-re'. This function is meant to be
|
||||
used as a predicate for `org-export-get-ordinal' or a value to
|
||||
`org-html-standalone-image-predicate'."
|
||||
(require 'ox-latex)
|
||||
(defvar org-latex-math-environments-re) ; defined in ox-latex.el
|
||||
(string-match-p org-latex-math-environments-re
|
||||
(org-element-property :value element)))
|
||||
|
||||
|
|
@ -3328,7 +3382,7 @@ INFO is a plist holding contextual information. See
|
|||
(let ((destination (org-export-resolve-radio-link link info)))
|
||||
(if (not destination) desc
|
||||
(format "<a href=\"#%s\"%s>%s</a>"
|
||||
(org-export-get-reference destination info)
|
||||
(org-html--reference destination info)
|
||||
attributes
|
||||
desc))))
|
||||
;; Links pointing to a headline: Find destination and build
|
||||
|
|
@ -3373,6 +3427,8 @@ INFO is a plist holding contextual information. See
|
|||
(format "<a href=\"#%s\"%s>%s</a>" href attributes desc)))
|
||||
;; Fuzzy link points to a target or an element.
|
||||
(_
|
||||
(require 'ox-latex)
|
||||
(declare-function org-latex--environment-type "ox-latex" (latex-environment))
|
||||
(if (and destination
|
||||
(memq (plist-get info :with-latex) '(mathjax t))
|
||||
(org-element-type-p destination 'latex-environment)
|
||||
|
|
@ -3565,10 +3621,9 @@ channel."
|
|||
(when timestamp
|
||||
(let ((string (car pair)))
|
||||
(format "<span class=\"timestamp-kwd\">%s</span> \
|
||||
<span class=\"timestamp\">%s</span> "
|
||||
%s "
|
||||
string
|
||||
(org-html-plain-text (org-timestamp-translate timestamp)
|
||||
info))))))
|
||||
(org-html--format-timestamp timestamp info))))))
|
||||
`((,org-closed-string . ,(org-element-property :closed planning))
|
||||
(,org-deadline-string . ,(org-element-property :deadline planning))
|
||||
(,org-scheduled-string . ,(org-element-property :scheduled planning)))
|
||||
|
|
@ -3697,7 +3752,7 @@ contextual information."
|
|||
" data-editor-type=\"html\""
|
||||
"")
|
||||
code)
|
||||
(format "<pre class=\"src src-%s\"%s>%s</pre>"
|
||||
(format "<pre class=\"src src-%s\"%s><code>%s</code></pre>"
|
||||
;; Lang being nil is OK.
|
||||
lang label code))))))
|
||||
|
||||
|
|
@ -3751,7 +3806,7 @@ channel."
|
|||
" align=\"%s\"" " class=\"org-%s\"")
|
||||
(org-export-table-cell-alignment table-cell info)))))
|
||||
(when (or (not contents) (string= "" (org-trim contents)))
|
||||
(setq contents " "))
|
||||
(setq contents " "))
|
||||
(cond
|
||||
((and (org-export-table-has-header-p table info)
|
||||
(= 1 (org-export-table-row-group table-row info)))
|
||||
|
|
@ -3837,7 +3892,6 @@ INFO is a plist used as a communication channel."
|
|||
"Format table.el TABLE into HTML.
|
||||
INFO is a plist used as a communication channel."
|
||||
(when (eq (org-element-property :type table) 'table.el)
|
||||
(require 'table)
|
||||
(let ((outbuf (with-current-buffer
|
||||
(get-buffer-create "*org-export-table*")
|
||||
(erase-buffer) (current-buffer))))
|
||||
|
|
@ -3920,9 +3974,16 @@ information."
|
|||
"Transcode a TIMESTAMP object from Org to HTML.
|
||||
CONTENTS is nil. INFO is a plist holding contextual
|
||||
information."
|
||||
(let ((value (org-html-plain-text (org-timestamp-translate timestamp) info)))
|
||||
(format "<span class=\"timestamp-wrapper\"><span class=\"timestamp\">%s</span></span>"
|
||||
(replace-regexp-in-string "--" "–" value))))
|
||||
(let (
|
||||
;; Strip :post-blank
|
||||
;; It will be handled as a part of generic transcoder code
|
||||
;; so we should avoid double-counting post-blank.
|
||||
(timestamp-no-blank
|
||||
(org-element-put-property
|
||||
(org-element-copy timestamp t)
|
||||
:post-blank 0)))
|
||||
(format "<span class=\"timestamp-wrapper\">%s</span>"
|
||||
(org-html--format-timestamp timestamp-no-blank info))))
|
||||
|
||||
;;;; Underline
|
||||
|
||||
|
|
@ -3952,7 +4013,7 @@ contextual information."
|
|||
(format "<p class=\"verse\">\n%s</p>"
|
||||
;; Replace leading white spaces with non-breaking spaces.
|
||||
(replace-regexp-in-string
|
||||
"^[ \t]+" (lambda (m) (org-html--make-string (length m) " "))
|
||||
"^[ \t]+" (lambda (m) (org-html--make-string (length m) " "))
|
||||
;; Replace each newline character with line break. Also
|
||||
;; remove any trailing "br" close-tag so as to avoid
|
||||
;; duplicates.
|
||||
|
|
|
|||
|
|
@ -39,9 +39,6 @@
|
|||
(require 'org-agenda)
|
||||
(require 'ox-ascii)
|
||||
(declare-function org-bbdb-anniv-export-ical "ol-bbdb" nil)
|
||||
(declare-function org-at-heading-p "org" (&optional _))
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-next-visible-heading "org" (arg))
|
||||
|
||||
|
||||
|
||||
|
|
@ -202,18 +199,28 @@ This is a list of symbols, the following are valid:
|
|||
(defcustom org-icalendar-with-timestamps 'active
|
||||
"Non-nil means make an event from plain time stamps.
|
||||
|
||||
It can be set to `active', `inactive', t or nil, in order to make
|
||||
an event from, respectively, only active timestamps, only
|
||||
inactive ones, all of them or none.
|
||||
It can be set to `active', `active-exclude-diary', `inactive', t
|
||||
or nil, in order to make an event from, respectively, only active
|
||||
timestamps (with/without diary timestamps), only inactive ones,
|
||||
all of them or none.
|
||||
|
||||
This variable has the same options as
|
||||
`org-export-with-timestamps', and takes precedence over it.
|
||||
However, note that this variable applies to all timestamps within
|
||||
an entry, whereas `org-export-with-timestamps' only applies to
|
||||
timestamps isolated in a paragraph containing only timestamps.
|
||||
|
||||
This variable has precedence over `org-export-with-timestamps'.
|
||||
It can also be set with the #+OPTIONS line, e.g. \"<:t\"."
|
||||
:group 'org-export-icalendar
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(choice
|
||||
(const :tag "All timestamps" t)
|
||||
(const :tag "Only active timestamps" active)
|
||||
(const :tag "Active timestamps, including diary timestamps" active)
|
||||
(const :tag "Active timestamps, excluding diary timestamps"
|
||||
active-exclude-diary)
|
||||
(const :tag "Only inactive timestamps" inactive)
|
||||
(const :tag "No timestamp" nil)))
|
||||
(const :tag "No timestamp" nil))
|
||||
:safe (lambda (x) (memq x '(t nil active active-exclude-diary inactive))))
|
||||
|
||||
(defcustom org-icalendar-include-todo nil
|
||||
"Non-nil means create VTODO components from TODO items.
|
||||
|
|
@ -744,11 +751,9 @@ inlinetask within the section."
|
|||
(org-element-contents inside))
|
||||
'timestamp
|
||||
(lambda (ts)
|
||||
(when (let ((type (org-element-property :type ts)))
|
||||
(cl-case (plist-get info :with-timestamps)
|
||||
(active (memq type '(active active-range)))
|
||||
(inactive (memq type '(inactive inactive-range)))
|
||||
((t) t)))
|
||||
(unless (org-export--skip-timestamp-p
|
||||
(plist-get info :with-timestamps)
|
||||
(org-element-property :type ts))
|
||||
(let ((uid (format "TS%d-%s" (cl-incf counter) uid)))
|
||||
(org-icalendar--vevent
|
||||
entry ts uid summary loc desc cat tz class))))
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@
|
|||
(:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t)
|
||||
(:latex-header "LATEX_HEADER" nil nil newline)
|
||||
(:latex-header-extra "LATEX_HEADER_EXTRA" nil nil newline)
|
||||
(:latex-class-pre "LATEX_CLASS_PRE" nil nil newline)
|
||||
(:description "DESCRIPTION" nil nil parse)
|
||||
(:keywords "KEYWORDS" nil nil parse)
|
||||
(:subtitle "SUBTITLE" nil nil parse)
|
||||
|
|
@ -170,6 +171,7 @@
|
|||
(:latex-title-command nil nil org-latex-title-command)
|
||||
(:latex-toc-command nil nil org-latex-toc-command)
|
||||
(:latex-compiler "LATEX_COMPILER" nil org-latex-compiler)
|
||||
(:latex-use-sans nil "latex-use-sans" org-latex-use-sans)
|
||||
;; Redefine regular options.
|
||||
(:date "DATE" nil "\\today" parse)))
|
||||
|
||||
|
|
@ -588,6 +590,7 @@ like that: \"%%\".
|
|||
Setting :latex-title-command in publishing projects will take
|
||||
precedence over this variable."
|
||||
:group 'org-export-latex
|
||||
:safe #'stringp
|
||||
:type '(string :tag "Format string"))
|
||||
|
||||
(defcustom org-latex-subtitle-format "\\\\\\medskip\n\\large %s"
|
||||
|
|
@ -597,6 +600,7 @@ which is replaced with the subtitle."
|
|||
:group 'org-export-latex
|
||||
:version "26.1"
|
||||
:package-version '(Org . "8.3")
|
||||
:safe #'stringp
|
||||
:type '(string :tag "Format string"))
|
||||
|
||||
(defcustom org-latex-subtitle-separate nil
|
||||
|
|
@ -604,6 +608,7 @@ which is replaced with the subtitle."
|
|||
:group 'org-export-latex
|
||||
:version "26.1"
|
||||
:package-version '(Org . "8.3")
|
||||
:safe #'booleanp
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom org-latex-toc-command "\\tableofcontents\n\n"
|
||||
|
|
@ -616,7 +621,7 @@ the #+TOC keyword."
|
|||
|
||||
(defcustom org-latex-hyperref-template
|
||||
"\\hypersetup{\n pdfauthor={%a},\n pdftitle={%t},\n pdfkeywords={%k},
|
||||
pdfsubject={%d},\n pdfcreator={%c}, \n pdflang={%L}}\n"
|
||||
pdfsubject={%d},\n pdfcreator={%c},\n pdflang={%L}}\n"
|
||||
"Template for hyperref package options.
|
||||
|
||||
This format string may contain these elements:
|
||||
|
|
@ -643,7 +648,8 @@ precedence over this variable."
|
|||
:version "26.1"
|
||||
:package-version '(Org . "8.3")
|
||||
:type '(choice (const :tag "No template" nil)
|
||||
(string :tag "Format string")))
|
||||
(string :tag "Format string"))
|
||||
:safe #'string-or-null-p)
|
||||
|
||||
;;;; Headline
|
||||
|
||||
|
|
@ -675,6 +681,7 @@ command like \"\\sidenote{%s%s}\" that you want to use.
|
|||
The value will be passed as an argument to `format' as the following
|
||||
(format org-latex-default-footnote-command
|
||||
footnote-description footnote-label)"
|
||||
|
||||
:group 'org-export-latex
|
||||
:package-version '(Org . "9.7")
|
||||
:type 'string)
|
||||
|
|
@ -698,17 +705,17 @@ The value will be passed as an argument to `format' as the following
|
|||
;;;; Timestamps
|
||||
|
||||
(defcustom org-latex-active-timestamp-format "\\textit{%s}"
|
||||
"A printf format string to be applied to active timestamps."
|
||||
"A `format' string to be applied to active timestamps."
|
||||
:group 'org-export-latex
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-latex-inactive-timestamp-format "\\textit{%s}"
|
||||
"A printf format string to be applied to inactive timestamps."
|
||||
"A `format' string to be applied to inactive timestamps."
|
||||
:group 'org-export-latex
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-latex-diary-timestamp-format "\\textit{%s}"
|
||||
"A printf format string to be applied to diary timestamps."
|
||||
"A `format' string to be applied to diary timestamps."
|
||||
:group 'org-export-latex
|
||||
:type 'string)
|
||||
|
||||
|
|
@ -956,13 +963,13 @@ The first two options provide basic syntax
|
|||
highlighting (listings), or none at all (verbatim).
|
||||
|
||||
When using listings, you also need to make use of LaTeX package
|
||||
\"listings\". The \"color\" LaTeX package is also needed if you
|
||||
would like color too. These can simply be added to
|
||||
\"listings\". The \"xcolor\" LaTeX package is also needed for
|
||||
color management. These can simply be added to
|
||||
`org-latex-packages-alist', using customize or something like:
|
||||
|
||||
(require \\='ox-latex)
|
||||
(add-to-list \\='org-latex-packages-alist \\='(\"\" \"listings\"))
|
||||
(add-to-list \\='org-latex-packages-alist \\='(\"\" \"color\"))
|
||||
(add-to-list \\='org-latex-packages-alist \\='(\"\" \"xcolor\"))
|
||||
|
||||
There are two further options for more comprehensive
|
||||
fontification. The first can be set with,
|
||||
|
|
@ -983,7 +990,7 @@ In addition, it is necessary to install pygments
|
|||
passed to pdflatex.
|
||||
|
||||
The minted choice has possible repercussions on the preview of
|
||||
latex fragments (see `org-preview-latex-fragment'). If you run
|
||||
latex fragments (see `org-latex-preview'). If you run
|
||||
into previewing problems, please consult
|
||||
URL `https://orgmode.org/worg/org-tutorials/org-latex-preview.html'.
|
||||
|
||||
|
|
@ -1409,6 +1416,10 @@ See also `org-latex-compiler'."
|
|||
:version "26.1"
|
||||
:package-version '(Org . "9.0"))
|
||||
|
||||
(defconst org-latex-compilers '("pdflatex" "xelatex" "lualatex")
|
||||
"Known LaTeX compilers.
|
||||
See also `org-latex-compiler'.")
|
||||
|
||||
(defcustom org-latex-compiler "pdflatex"
|
||||
"LaTeX compiler to use.
|
||||
|
||||
|
|
@ -1422,11 +1433,12 @@ Can also be set in buffers via #+LATEX_COMPILER. See also
|
|||
(const :tag "LuaLaTeX" "lualatex")
|
||||
(const :tag "Unset" ""))
|
||||
:version "26.1"
|
||||
:package-version '(Org . "9.0"))
|
||||
|
||||
(defconst org-latex-compilers '("pdflatex" "xelatex" "lualatex")
|
||||
"Known LaTeX compilers.
|
||||
See also `org-latex-compiler'.")
|
||||
:package-version '(Org . "9.0")
|
||||
:safe (lambda (s)
|
||||
(and (stringp s) ; must be a string
|
||||
;; either an empty string or one of the supported compilers
|
||||
(or (length= s 0)
|
||||
(member s org-latex-compilers)))))
|
||||
|
||||
(defcustom org-latex-bib-compiler "bibtex"
|
||||
"Command to process a LaTeX file's bibliography.
|
||||
|
|
@ -1443,7 +1455,7 @@ A better approach is to use a compiler suit such as `latexmk'."
|
|||
:package-version '(Org . "9.0"))
|
||||
|
||||
(defcustom org-latex-pdf-process
|
||||
(if (executable-find "latexmk")
|
||||
(if (and (executable-find "latexmk") (executable-find "perl"))
|
||||
'("latexmk -f -pdf -%latex -interaction=nonstopmode -output-directory=%o %f")
|
||||
'("%latex -interaction nonstopmode -output-directory %o %f"
|
||||
"%latex -interaction nonstopmode -output-directory %o %f"
|
||||
|
|
@ -1522,7 +1534,7 @@ logfiles to remove, set `org-latex-logfiles-extensions'."
|
|||
("Underfull \\hbox" . "[underfull hbox]")
|
||||
("Overfull \\hbox" . "[overfull hbox]")
|
||||
("Citation.*?undefined" . "[undefined citation]")
|
||||
("^!.+Unicode character" . "[unicode character(s) not set up for use with pdflatex. You can run lualatex or xelatex instead]")
|
||||
("^!.+Unicode character" . "[unicode character(s) not supported by pdflatex. Set org-latex-compiler to lualatex or xelatex instead]")
|
||||
("Missing character: There is no" . "[Missing character(s): please load an appropriate font with the fontspec package]")
|
||||
("Undefined control sequence" . "[undefined control sequence]"))
|
||||
"Alist of regular expressions and associated messages for the user.
|
||||
|
|
@ -1537,6 +1549,18 @@ calling `org-latex-compile'."
|
|||
(string :tag "Message"))))
|
||||
|
||||
|
||||
(defcustom org-latex-toc-include-unnumbered nil
|
||||
"Whether to include unnumbered headings in the table of contents.
|
||||
|
||||
The default behaviour is to include numbered headings only, as it is
|
||||
usually the case in LaTeX (but different from other Org exporters).
|
||||
To include an unnumbered heading, set the `:UNNUMBERED:'
|
||||
property to `toc'"
|
||||
:group 'org-export-latex
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'boolean
|
||||
:safe #'booleanp)
|
||||
|
||||
|
||||
;;; Internal Functions
|
||||
|
||||
|
|
@ -1926,16 +1950,24 @@ INFO is a plist used as a communication channel."
|
|||
;; Here the actual name of the LANGUAGE or LANG is used.
|
||||
(or (plist-get plist :lang-name)
|
||||
lang))))
|
||||
`((?a . ,(org-export-data (plist-get info :author) info))
|
||||
(?t . ,(org-export-data (plist-get info :title) info))
|
||||
(?s . ,(org-export-data (plist-get info :subtitle) info))
|
||||
`((?a . ,(if (plist-get info :with-author)
|
||||
(org-export-data (plist-get info :author) info)
|
||||
""))
|
||||
(?t . ,(if (plist-get info :with-title)
|
||||
(org-export-data (plist-get info :title) info)
|
||||
""))
|
||||
(?s . ,(if (plist-get info :with-title)
|
||||
(org-export-data (plist-get info :subtitle) info)
|
||||
""))
|
||||
(?k . ,(org-export-data (org-latex--wrap-latex-math-block
|
||||
(plist-get info :keywords) info)
|
||||
info))
|
||||
(?d . ,(org-export-data (org-latex--wrap-latex-math-block
|
||||
(plist-get info :description) info)
|
||||
info))
|
||||
(?c . ,(plist-get info :creator))
|
||||
(?c . ,(if (plist-get info :with-creator)
|
||||
(plist-get info :creator)
|
||||
""))
|
||||
(?l . ,language)
|
||||
(?L . ,(capitalize language))
|
||||
(?D . ,(org-export-data (org-export-get-date info) info)))))
|
||||
|
|
@ -1948,6 +1980,15 @@ INFO is a plist used as a communication channel."
|
|||
(member (or compiler "") org-latex-compilers)
|
||||
(format org-latex-compiler-file-string compiler))))
|
||||
|
||||
(defcustom org-latex-use-sans nil
|
||||
"Whether to typeset the document with the Sans font family.
|
||||
|
||||
The default behaviour is to typeset with the Roman font family."
|
||||
:group 'org-export-latex
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'boolean
|
||||
:safe #'booleanp)
|
||||
|
||||
|
||||
;;; Filters
|
||||
|
||||
|
|
@ -1985,10 +2026,15 @@ specified in `org-latex-default-packages-alist' or
|
|||
(let* ((class-options (plist-get info :latex-class-options))
|
||||
(header (nth 1 (assoc class (plist-get info :latex-classes)))))
|
||||
(and (stringp header)
|
||||
(mapconcat #'org-element-normalize-string
|
||||
(list
|
||||
(and (not snippet?)
|
||||
(plist-get info :latex-class-pre))
|
||||
(if (not class-options) header
|
||||
(replace-regexp-in-string
|
||||
"^[ \t]*\\\\documentclass\\(\\(\\[[^]]*\\]\\)?\\)"
|
||||
class-options header t nil 1))))
|
||||
class-options header t nil 1)))
|
||||
nil)))
|
||||
(user-error "Unknown LaTeX class `%s'" class))))
|
||||
(org-latex-guess-polyglossia-language
|
||||
(org-latex-guess-babel-language
|
||||
|
|
@ -2002,7 +2048,11 @@ specified in `org-latex-default-packages-alist' or
|
|||
(mapconcat #'org-element-normalize-string
|
||||
(list (plist-get info :latex-header)
|
||||
(and (not snippet?)
|
||||
(plist-get info :latex-header-extra)))
|
||||
(plist-get info :latex-header-extra))
|
||||
(and (not snippet?)
|
||||
(plist-get info :latex-use-sans)
|
||||
"\\renewcommand*\\familydefault{\\sfdefault}"))
|
||||
|
||||
""))))
|
||||
info)
|
||||
info)))
|
||||
|
|
@ -2237,11 +2287,10 @@ CONTENTS is nil. INFO is a plist holding contextual information."
|
|||
(org-export-get-footnote-definition footnote-reference info)
|
||||
info t)))
|
||||
;; Use \footnotemark if reference is within another footnote
|
||||
;; reference, footnote definition, table cell, verse block, or
|
||||
;; item's tag.
|
||||
;; reference, footnote definition, table cell, or item's tag.
|
||||
((or (org-element-lineage footnote-reference
|
||||
'(footnote-reference footnote-definition
|
||||
table-cell verse-block))
|
||||
'( footnote-reference footnote-definition
|
||||
table-cell))
|
||||
(org-element-type-p
|
||||
(org-element-parent-element footnote-reference) 'item))
|
||||
"\\footnotemark")
|
||||
|
|
@ -2269,18 +2318,13 @@ CONTENTS is nil. INFO is a plist holding contextual information."
|
|||
|
||||
;;;; Headline
|
||||
|
||||
(defun org-latex-headline (headline contents info)
|
||||
"Transcode a HEADLINE element from Org to LaTeX.
|
||||
CONTENTS holds the contents of the headline. INFO is a plist
|
||||
holding contextual information."
|
||||
(unless (org-element-property :footnote-section-p headline)
|
||||
(defun org-latex--get-section-format (headline info)
|
||||
"Get section format for HEADLINE.
|
||||
INFO is the communication plist."
|
||||
(let* ((class (plist-get info :latex-class))
|
||||
(level (org-export-get-relative-level headline info))
|
||||
(numberedp (org-export-numbered-headline-p headline info))
|
||||
(class-sectioning (assoc class (plist-get info :latex-classes)))
|
||||
;; Section formatting will set two placeholders: one for
|
||||
;; the title and the other for the contents.
|
||||
(section-fmt
|
||||
(class-sectioning (assoc class (plist-get info :latex-classes))))
|
||||
(let ((sec (if (functionp (nth 2 class-sectioning))
|
||||
(funcall (nth 2 class-sectioning) level numberedp)
|
||||
(nth (1+ level) class-sectioning))))
|
||||
|
|
@ -2299,10 +2343,9 @@ holding contextual information."
|
|||
;; (num-in num-out no-num-in no-num-out)
|
||||
((= (length sec) 4)
|
||||
(if numberedp (concat (car sec) "\n%s" (nth 1 sec))
|
||||
(concat (nth 2 sec) "\n%s" (nth 3 sec)))))))
|
||||
;; Create a temporary export backend that hard-codes
|
||||
;; "\underline" within "\section" and alike.
|
||||
(section-backend
|
||||
(concat (nth 2 sec) "\n%s" (nth 3 sec))))))))
|
||||
|
||||
(defconst org-latex--section-backend
|
||||
(org-export-create-backend
|
||||
:parent 'latex
|
||||
:transcoders
|
||||
|
|
@ -2312,23 +2355,45 @@ holding contextual information."
|
|||
;; So, within headings it's a good idea to replace any instances of \verb
|
||||
;; with \texttt.
|
||||
(code . (lambda (o _ _) (org-latex--protect-texttt (org-element-property :value o))))
|
||||
(verbatim . (lambda (o _ _) (org-latex--protect-texttt (org-element-property :value o)))))))
|
||||
;; Create a temporary export backend that strips footnotes from title.
|
||||
;; Footnotes are not allowed in \section and similar
|
||||
;; commands that contribute to TOC and footers.
|
||||
;; See https://orgmode.org/list/691643eb-49d0-45c3-ab7f-a1edbd093bef@gmail.com
|
||||
;; https://texfaq.org/FAQ-ftnsect
|
||||
(section-no-footnote-backend
|
||||
(verbatim . (lambda (o _ _) (org-latex--protect-texttt (org-element-property :value o))))))
|
||||
"Export backend that hard-codes \\underline within \\section and alike.")
|
||||
|
||||
(defconst org-latex--section-no-footnote-backend
|
||||
(org-export-create-backend
|
||||
:parent section-backend
|
||||
:parent org-latex--section-backend
|
||||
:transcoders
|
||||
`((footnote-reference . ignore))))
|
||||
`((footnote-reference . ignore)))
|
||||
"Export backend that strips footnotes from title.
|
||||
|
||||
Footnotes are not allowed in \\section and similar commands that
|
||||
contribute to TOC and footers.
|
||||
See https://orgmode.org/list/691643eb-49d0-45c3-ab7f-a1edbd093bef@gmail.com
|
||||
https://texfaq.org/FAQ-ftnsect")
|
||||
|
||||
(defun org-latex-headline (headline contents info)
|
||||
"Transcode a HEADLINE element from Org to LaTeX.
|
||||
CONTENTS holds the contents of the headline. INFO is a plist
|
||||
holding contextual information."
|
||||
(unless (org-element-property :footnote-section-p headline)
|
||||
(let* ((level (org-export-get-relative-level headline info))
|
||||
;; "LaTeX TOC handling"
|
||||
;; :unnumbered: toc will add the heading to the ToC
|
||||
;; "Org TOC handling"
|
||||
;; :unnumbered: notoc to suppress heading from the ToC
|
||||
;; else include all headings (including unnumbered) like other modes
|
||||
(unnumbered-type (org-export-get-node-property :UNNUMBERED headline t))
|
||||
(numberedp (org-export-numbered-headline-p headline info))
|
||||
;; Section formatting will set two placeholders: one for
|
||||
;; the title and the other for the contents.
|
||||
(section-fmt (org-latex--get-section-format headline info))
|
||||
(text
|
||||
(org-export-data-with-backend
|
||||
(org-element-property :title headline) section-backend info))
|
||||
(org-element-property :title headline)
|
||||
org-latex--section-backend info))
|
||||
(text-no-footnote
|
||||
(org-export-data-with-backend
|
||||
(org-element-property :title headline) section-no-footnote-backend info))
|
||||
(org-element-property :title headline)
|
||||
org-latex--section-no-footnote-backend info))
|
||||
(todo
|
||||
(and (plist-get info :with-todo-keywords)
|
||||
(let ((todo (org-element-property :todo-keyword headline)))
|
||||
|
|
@ -2382,8 +2447,10 @@ holding contextual information."
|
|||
(funcall (plist-get info :latex-format-headline-function)
|
||||
todo todo-type priority
|
||||
(org-export-data-with-backend
|
||||
;; Returns alternative title when provided or
|
||||
;; title itself.
|
||||
(org-export-get-alt-title headline info)
|
||||
section-backend info)
|
||||
org-latex--section-backend info)
|
||||
(and (eq (plist-get info :with-tags) t) tags)
|
||||
info))
|
||||
;; Maybe end local TOC (see `org-latex-keyword').
|
||||
|
|
@ -2402,25 +2469,80 @@ holding contextual information."
|
|||
(string-match-p "\\<local\\>" v)
|
||||
(format "\\stopcontents[level-%d]" level)))))
|
||||
info t)))))
|
||||
(if (and (or (and opt-title (not (equal opt-title full-text)))
|
||||
;; Heading contains footnotes. Add optional title
|
||||
;; version without footnotes to avoid footnotes in
|
||||
;; TOC/footers.
|
||||
(and (not (equal full-text-no-footnote full-text))
|
||||
(setq opt-title full-text-no-footnote)))
|
||||
(string-match "\\`\\\\\\(.+?\\){" section-fmt))
|
||||
(format (replace-match "\\1[%s]" nil nil section-fmt 1)
|
||||
;; When do we need to explicitly specify a heading for TOC?
|
||||
;; 1. On numbered section with footnotes in title or alt_title
|
||||
;; 2. On an unnumbered section if :UNNUMBERED: allows it regardless of footnotes
|
||||
;; This applies to anything that may go into the ToC.
|
||||
;; Specifically for paragraphs, see first answer of
|
||||
;; https://tex.stackexchange.com/questions/288072/footnotes-within-paragraph
|
||||
(let ((section-kw
|
||||
(and (string-match "\\`\\\\\\(.+?\\){" section-fmt)
|
||||
(match-string 1 section-fmt)))
|
||||
need-alternative-toc-title)
|
||||
(if (not section-kw)
|
||||
;; We only know how to add \SECTION-KW{...} to TOC.
|
||||
(setq need-alternative-toc-title nil)
|
||||
(if (string-suffix-p "*" section-kw)
|
||||
;; FIXME: In theory, user may customize section-fmt
|
||||
;; to use, e.g. \section{...} for unnumbered headings
|
||||
;; We do not handle such scenario.
|
||||
(progn ;; unnumbered sections (ending with *)
|
||||
;; Then we need to obey what the :UNNUMBERED: property says
|
||||
(if org-latex-toc-include-unnumbered
|
||||
;; Treat the ToC closer to what other exporters do
|
||||
;; Include unnumbered section into TOC unless
|
||||
;; explicitly requested not to.
|
||||
(if (string= unnumbered-type "notoc")
|
||||
(setq need-alternative-toc-title nil)
|
||||
(setq need-alternative-toc-title t))
|
||||
;; Ignore unnumbered headings in ToC - as in LaTeX
|
||||
;; unless explicitly requested to include.
|
||||
(if (string= unnumbered-type "toc")
|
||||
(setq need-alternative-toc-title t)
|
||||
(setq need-alternative-toc-title nil))))
|
||||
;; Numbered sections
|
||||
;; Specify special TOC title only when there is
|
||||
;; opt-title or when title contains footnotes.
|
||||
(if (and (string= full-text full-text-no-footnote) ;; no footnotes
|
||||
;; opt-title is either ALT_TITLE or title itself
|
||||
;; as returned by `org-export-get-alt-title'
|
||||
(string= full-text opt-title)) ;; same alternative title
|
||||
(setq need-alternative-toc-title nil)
|
||||
(setq need-alternative-toc-title t))))
|
||||
;; In all cases
|
||||
;; Get rid of the footnotes in opt-title
|
||||
(when (and (not (string= full-text-no-footnote full-text)) ;; when we have footnotess
|
||||
(string= full-text opt-title)) ;; And we do not impose an alternative title
|
||||
(setq opt-title full-text-no-footnote))
|
||||
(if need-alternative-toc-title
|
||||
(let ((new-format section-fmt)
|
||||
(new-extra "")) ;; put the addcontentsline here
|
||||
(if (string-suffix-p "*" section-kw)
|
||||
;; Subsection that needs alternative title:
|
||||
;; Keep section format, use \\addcontentsline
|
||||
(setq new-extra
|
||||
(format "\\addcontentsline{toc}{%s}{%s}\n"
|
||||
(string-remove-suffix "*" section-kw)
|
||||
opt-title))
|
||||
;; section... we need the brackets
|
||||
(let*
|
||||
;; Replace square brackets with parenthesis
|
||||
;; since square brackets are not supported in
|
||||
;; optional arguments.
|
||||
(replace-regexp-in-string
|
||||
"\\[" "(" (replace-regexp-in-string "\\]" ")" opt-title))
|
||||
((un-bracketed-alt (replace-regexp-in-string
|
||||
"\\[" "(" (replace-regexp-in-string "\\]" ")" opt-title)))
|
||||
(replacement-re (concat
|
||||
"\\1["
|
||||
(replace-regexp-in-string (rx "\\") "\\\\" un-bracketed-alt nil t)
|
||||
"]")))
|
||||
(setq new-format (replace-match replacement-re nil nil section-fmt 1))))
|
||||
(format new-format
|
||||
full-text
|
||||
(concat headline-label pre-blanks contents))
|
||||
;; Impossible to add an alternative heading. Fallback to
|
||||
;; regular sectioning format string.
|
||||
(concat headline-label new-extra pre-blanks contents)))
|
||||
;; Don't need or cannot have alternative heading.
|
||||
;; Use regular sectioning format string.
|
||||
(format section-fmt full-text
|
||||
(concat headline-label pre-blanks contents))))))))
|
||||
(concat headline-label pre-blanks contents)))))))))
|
||||
|
||||
(defun org-latex-format-headline-default-function
|
||||
(todo _todo-type priority text tags _info)
|
||||
|
|
@ -2428,7 +2550,7 @@ holding contextual information."
|
|||
See `org-latex-format-headline-function' for details."
|
||||
(concat
|
||||
(and todo (format "{\\bfseries\\sffamily %s} " todo))
|
||||
(and priority (format "\\framebox{\\#%c} " priority))
|
||||
(and priority (format "\\framebox{\\#%s} " (org-priority-to-string priority)))
|
||||
text
|
||||
(and tags
|
||||
(format "\\hfill{}\\textsc{%s}"
|
||||
|
|
@ -2534,7 +2656,7 @@ holding contextual information."
|
|||
See `org-latex-format-inlinetask-function' for details."
|
||||
(let ((full-title
|
||||
(concat (when todo (format "\\textbf{\\textsf{\\textsc{%s}}} " todo))
|
||||
(when priority (format "\\framebox{\\#%c} " priority))
|
||||
(when priority (format "\\framebox{\\#%s} " (org-priority-to-string priority)))
|
||||
title
|
||||
(when tags
|
||||
(format "\\hfill{}\\textsc{%s}"
|
||||
|
|
@ -3119,6 +3241,8 @@ contextual information."
|
|||
"{[}"
|
||||
output
|
||||
nil nil 1))
|
||||
;; When inside verse block, use special rules.
|
||||
(setq output (org-latex--plain-text-verse-block output text))
|
||||
;; Return value.
|
||||
output))
|
||||
|
||||
|
|
@ -4188,39 +4312,27 @@ channel."
|
|||
|
||||
;;;; Verse Block
|
||||
|
||||
(defun org-latex-verse-block (verse-block contents info)
|
||||
"Transcode a VERSE-BLOCK element from Org to LaTeX.
|
||||
CONTENTS is verse block contents. INFO is a plist holding
|
||||
contextual information."
|
||||
(defun org-latex--plain-text-verse-block (contents plain-text)
|
||||
"Format CONTENTS if PLAIN-TEXT is inside verse environment.
|
||||
INFO is the communication plist.
|
||||
Return CONTENTS unchanged when TEXT is not inside verse environment or
|
||||
when TEXT is a part of footnote reference.
|
||||
|
||||
In a verse environment, add a line break to each newline character and
|
||||
change each white space at beginning of a line into a normal space,
|
||||
calculated with `\\fontdimen2\\font'. One or more blank lines between
|
||||
lines are exported as a single blank line. If the `:lines' attribute
|
||||
is used, the last verse of each stanza ends with the string `\\!',
|
||||
according to the syntax of the `verse' package. The separation between
|
||||
stanzas can be controlled with the length `\\stanzaskip', of the
|
||||
aforementioned package. If the `:literal' attribute is used, all
|
||||
blank lines are preserved and exported as `\\vspace*{\\baselineskip}',
|
||||
including the blank lines before or after CONTENTS."
|
||||
(if-let* ((verse-block (org-element-lineage plain-text 'verse-block))
|
||||
;; VALUEFORM
|
||||
((not (org-element-lineage plain-text 'footnote-reference))))
|
||||
(let* ((lin (org-export-read-attribute :attr_latex verse-block :lines))
|
||||
(latcode (org-export-read-attribute :attr_latex verse-block :latexcode))
|
||||
(cent (org-export-read-attribute :attr_latex verse-block :center))
|
||||
(lit (org-export-read-attribute :attr_latex verse-block :literal))
|
||||
(attr (concat
|
||||
(if cent "[\\versewidth]" "")
|
||||
(if lin (format "\n\\poemlines{%s}" lin) "")
|
||||
(if latcode (format "\n%s" latcode) "")))
|
||||
(versewidth (org-export-read-attribute :attr_latex verse-block :versewidth))
|
||||
(vwidth (if versewidth (format "\\settowidth{\\versewidth}{%s}\n" versewidth) ""))
|
||||
(linreset (if lin "\n\\poemlines{0}" "")))
|
||||
(concat
|
||||
(org-latex--wrap-label
|
||||
verse-block
|
||||
;; In a verse environment, add a line break to each newline
|
||||
;; character and change each white space at beginning of a line
|
||||
;; into a normal space, calculated with `\fontdimen2\font'. One
|
||||
;; or more blank lines between lines are exported as a single
|
||||
;; blank line. If the `:lines' attribute is used, the last
|
||||
;; verse of each stanza ends with the string `\\!', according to
|
||||
;; the syntax of the `verse' package. The separation between
|
||||
;; stanzas can be controlled with the length `\stanzaskip', of
|
||||
;; the aforementioned package. If the `:literal' attribute is
|
||||
;; used, all blank lines are preserved and exported as
|
||||
;; `\vspace*{\baselineskip}', including the blank lines before
|
||||
;; or after CONTENTS.
|
||||
(format "%s\\begin{verse}%s\n%s\\end{verse}%s"
|
||||
vwidth
|
||||
attr
|
||||
(lit (org-export-read-attribute :attr_latex verse-block :literal)))
|
||||
(replace-regexp-in-string
|
||||
"^[ \t]+" (lambda (m) (format "\\hspace*{%d\\fontdimen2\\font}" (length m)))
|
||||
(replace-regexp-in-string
|
||||
|
|
@ -4235,17 +4347,41 @@ contextual information."
|
|||
(replace-regexp-in-string
|
||||
"\\([ \t]*\\\\\\\\\\)?[ \t]*\n"
|
||||
"\\\\\n"
|
||||
contents
|
||||
nil t)
|
||||
nil t)
|
||||
nil t))
|
||||
;; Not in verse block, return CONTENTS unchanged.
|
||||
contents))
|
||||
|
||||
(defun org-latex-verse-block (verse-block contents info)
|
||||
"Transcode a VERSE-BLOCK element from Org to LaTeX.
|
||||
CONTENTS is verse block contents. INFO is a plist holding
|
||||
contextual information."
|
||||
(let* ((lin (org-export-read-attribute :attr_latex verse-block :lines))
|
||||
(latcode (org-export-read-attribute :attr_latex verse-block :latexcode))
|
||||
(cent (org-export-read-attribute :attr_latex verse-block :center))
|
||||
(attr (concat
|
||||
(if cent "[\\versewidth]" "")
|
||||
(if lin (format "\n\\poemlines{%s}" lin) "")
|
||||
(if latcode (format "\n%s" latcode) "")))
|
||||
(lit (org-export-read-attribute :attr_latex verse-block :literal))
|
||||
(versewidth (org-export-read-attribute :attr_latex verse-block :versewidth))
|
||||
(vwidth (if versewidth (format "\\settowidth{\\versewidth}{%s}\n" versewidth) ""))
|
||||
(linreset (if lin "\n\\poemlines{0}" "")))
|
||||
(org-latex--wrap-label
|
||||
verse-block
|
||||
(format "%s\\begin{verse}%s\n%s\\end{verse}%s"
|
||||
vwidth attr
|
||||
;; If the `:literal' attribute is used, all blank lines
|
||||
;; are preserved and exported as
|
||||
;; `\\vspace*{\\baselineskip}', including the blank lines
|
||||
;; before or after CONTENTS.
|
||||
(if (not lit)
|
||||
(concat (org-trim contents t) "\n")
|
||||
contents)
|
||||
nil t)
|
||||
nil t)
|
||||
nil t)
|
||||
linreset)
|
||||
info)
|
||||
;; Insert footnote definitions, if any, after the environment, so
|
||||
;; the special formatting above is not applied to them.
|
||||
(org-latex--delayed-footnotes-definitions verse-block info))))
|
||||
info)))
|
||||
|
||||
|
||||
;;; End-user functions
|
||||
|
|
@ -4282,11 +4418,16 @@ Export is done in a buffer named \"*Org LATEX Export*\", which
|
|||
will be displayed when `org-export-show-temporary-export-buffer'
|
||||
is non-nil."
|
||||
(interactive)
|
||||
(defvar TeX-parse-self) ;; defined in tex.el
|
||||
(let (;; FIXME: Working around LaTeX-mode being broken in non-file buffers.
|
||||
;; To be removed once we drop Emacs 30 and earlier, where the problem
|
||||
;; is not yet fixed.
|
||||
(TeX-parse-self nil))
|
||||
(org-export-to-buffer 'latex "*Org LATEX Export*"
|
||||
async subtreep visible-only body-only ext-plist
|
||||
(if (fboundp 'major-mode-remap)
|
||||
(major-mode-remap 'latex-mode)
|
||||
#'LaTeX-mode)))
|
||||
#'LaTeX-mode))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-latex-convert-region-to-latex ()
|
||||
|
|
|
|||
|
|
@ -33,7 +33,11 @@
|
|||
;; See ox.el for more details on how this exporter works.
|
||||
;;
|
||||
;; It introduces one new buffer keywords:
|
||||
;; "MAN_CLASS_OPTIONS".
|
||||
;; "MAN_CLASS_OPTIONS" that accepts the following options:
|
||||
;; - `:section-id', the section, a string (eg. ':section-id "2"');
|
||||
;; - `:release', the footer middle, a string (eg. ':release "Emacs 13"');
|
||||
;; - `:header', the header middle, a string (eg. ':header "GNU"').
|
||||
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
|
@ -101,6 +105,7 @@
|
|||
(underline . org-man-underline)
|
||||
(verbatim . org-man-verbatim)
|
||||
(verse-block . org-man-verse-block))
|
||||
:filters-alist '((:filter-parse-tree . org-man--remove-blank))
|
||||
:menu-entry
|
||||
'(?M "Export to MAN"
|
||||
((?m "As MAN file" org-man-export-to-man)
|
||||
|
|
@ -300,6 +305,17 @@ This function shouldn't be used for floats. See
|
|||
;; backslash) cannot be used as per the same man page.
|
||||
(replace-regexp-in-string "\\\\" "\\e" text nil t))
|
||||
|
||||
|
||||
;;; Filters
|
||||
|
||||
(defun org-man--remove-blank (tree _backend info)
|
||||
"Remove :post-blank from TREE elements.
|
||||
INFO is the communication plist.
|
||||
Avoiding blank lines is adviced by groff_man_style(7) man page."
|
||||
(org-element-map tree org-element-all-elements
|
||||
(lambda (el) (setf (org-element-post-blank el) 0))
|
||||
info)
|
||||
tree)
|
||||
|
||||
|
||||
;;; Template
|
||||
|
|
@ -315,19 +331,25 @@ holding export options."
|
|||
#'identity
|
||||
(list (plist-get info :man-class-options))
|
||||
" "))))
|
||||
(section-item (plist-get attr :section-id)))
|
||||
|
||||
(section-item (plist-get attr :section-id))
|
||||
(release (plist-get attr :release))
|
||||
(header (plist-get attr :header))
|
||||
;; Note: groff linter suggests date to be the third argument
|
||||
;; of .TH
|
||||
(date (and (plist-get info :with-date)
|
||||
(org-export-data (org-export-get-date info) info))))
|
||||
(concat
|
||||
|
||||
(cond
|
||||
((and title (stringp section-item))
|
||||
(format ".TH \"%s\" \"%s\" \n" title section-item))
|
||||
((and (string= "" title) (stringp section-item))
|
||||
(format ".TH \"%s\" \"%s\" \n" " " section-item))
|
||||
(title
|
||||
(format ".TH \"%s\" \"1\" \n" title))
|
||||
(t
|
||||
".TH \" \" \"1\" "))
|
||||
(format ".TH \"%s\" \"%s\"" ;; only two required by groff_man(7).
|
||||
(if title title " ")
|
||||
(if (stringp section-item) section-item "1"))
|
||||
(if date (format " \"%s\"" date)
|
||||
" \"\"") ;; in case later options are present.
|
||||
(if release (format " \"%s\"" release)
|
||||
" \"\"") ;; in case later options are present.
|
||||
;; Do not write an empty footer-outside, otherwise man(1) will
|
||||
;; no longer generate its content, see groff_man(7).
|
||||
(if header (format " \"%s\"" header))
|
||||
" \n"
|
||||
contents)))
|
||||
|
||||
|
||||
|
|
@ -535,7 +557,7 @@ contextual information."
|
|||
(delete-file in-file)
|
||||
(delete-file out-file)
|
||||
code-block)
|
||||
(format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE\n"
|
||||
(format ".RS\n.nf\n\\fC%s\\m[]\\fP\n.fi\n.RE\n"
|
||||
(org-man--protect-example code)))))
|
||||
|
||||
;; Do not use a special package: transcode it verbatim.
|
||||
|
|
@ -755,7 +777,7 @@ holding contextual information."
|
|||
CONTENTS holds the contents of the item. INFO is a plist holding
|
||||
contextual information."
|
||||
(if (not (plist-get info :man-source-highlight))
|
||||
(format ".RS\n.nf\n\\fC%s\\fP\n.fi\n.RE\n\n"
|
||||
(format ".RS\n.nf\n\\fC%s\\fP\n.fi\n.RE\n"
|
||||
(org-man--protect-example (org-export-format-code-default src-block info)))
|
||||
(let* ((tmpdir temporary-file-directory)
|
||||
(in-file (make-temp-name (expand-file-name "srchilite" tmpdir)))
|
||||
|
|
@ -779,7 +801,7 @@ contextual information."
|
|||
(delete-file in-file)
|
||||
(delete-file out-file)
|
||||
code-block)
|
||||
(format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE" (org-man--protect-example code))))))
|
||||
(format ".RS\n.nf\n\\fC%s\\m[]\\fP\n.fi\n.RE" (org-man--protect-example code))))))
|
||||
|
||||
|
||||
;;; Statistics Cookie
|
||||
|
|
@ -1125,6 +1147,8 @@ file-local settings.
|
|||
Return PDF file's name."
|
||||
(interactive)
|
||||
(let ((outfile (org-export-output-file-name ".man" subtreep)))
|
||||
(require 'ox-latex)
|
||||
(declare-function org-latex-compile "ox-latex" (texfile &optional snippet))
|
||||
(org-export-to-file 'man outfile
|
||||
async subtreep visible-only body-only ext-plist
|
||||
#'org-latex-compile)))
|
||||
|
|
|
|||
|
|
@ -93,6 +93,22 @@ headings for its own use."
|
|||
;; Avoid `natnum' because that's not available until Emacs 28.1.
|
||||
:type 'integer)
|
||||
|
||||
(defcustom org-md-link-org-files-as-md t
|
||||
"Non-nil means make file links to \"file.org\" point to \"file.md\".
|
||||
|
||||
When Org mode is exporting an Org file to markdown, links to
|
||||
non-markdown files are directly put into a \"href\" tag in
|
||||
markdown. However, links to other Org files \(recognized by the
|
||||
extension \".org\") should become links to the corresponding
|
||||
markdown file, assuming that the linked Org file will also be
|
||||
converted to markdown.
|
||||
|
||||
When nil, the links still point to the plain \".org\" file."
|
||||
:group 'org-export-md
|
||||
:package-version '(Org . "9.8")
|
||||
:type 'boolean
|
||||
:safe #'booleanp)
|
||||
|
||||
|
||||
|
||||
;;; Define Backend
|
||||
|
|
@ -144,7 +160,8 @@ headings for its own use."
|
|||
'((:md-footnote-format nil nil org-md-footnote-format)
|
||||
(:md-footnotes-section nil nil org-md-footnotes-section)
|
||||
(:md-headline-style nil nil org-md-headline-style)
|
||||
(:md-toplevel-hlevel nil nil org-md-toplevel-hlevel)))
|
||||
(:md-toplevel-hlevel nil nil org-md-toplevel-hlevel)
|
||||
(:md-link-org-files-as-md nil nil org-md-link-org-files-as-md)))
|
||||
|
||||
|
||||
;;; Filters
|
||||
|
|
@ -393,8 +410,8 @@ a communication channel."
|
|||
(concat " " (org-make-tag-string tag-list))))))
|
||||
(priority
|
||||
(and (plist-get info :with-priority)
|
||||
(let ((char (org-element-property :priority headline)))
|
||||
(and char (format "[#%c] " char)))))
|
||||
(let ((priority-value (org-element-property :priority headline)))
|
||||
(and priority-value (format "[#%s] " (org-priority-to-string priority-value))))))
|
||||
;; Headline text without tags.
|
||||
(heading (concat todo priority title))
|
||||
(style (plist-get info :md-headline-style)))
|
||||
|
|
@ -540,17 +557,19 @@ channel."
|
|||
DESC is the description part of the link, or the empty string.
|
||||
INFO is a plist holding contextual information. See
|
||||
`org-export-data'."
|
||||
(let* ((link-org-files-as-md
|
||||
(let* ((link-org-files-as-md-maybe
|
||||
(lambda (raw-path)
|
||||
;; Treat links to `file.org' as links to `file.md'.
|
||||
(if (string= ".org" (downcase (file-name-extension raw-path ".")))
|
||||
(if (and
|
||||
(plist-get info :md-link-org-files-as-md)
|
||||
(string= ".org" (downcase (file-name-extension raw-path "."))))
|
||||
(concat (file-name-sans-extension raw-path) ".md")
|
||||
raw-path)))
|
||||
(type (org-element-property :type link))
|
||||
(raw-path (org-element-property :path link))
|
||||
(path (cond
|
||||
((string-equal type "file")
|
||||
(org-export-file-uri (funcall link-org-files-as-md raw-path)))
|
||||
(org-export-file-uri (funcall link-org-files-as-md-maybe raw-path)))
|
||||
(t (concat type ":" raw-path)))))
|
||||
(cond
|
||||
;; Link type is handled by a special function.
|
||||
|
|
@ -561,7 +580,7 @@ INFO is a plist holding contextual information. See
|
|||
(org-export-resolve-id-link link info))))
|
||||
(pcase (org-element-type destination)
|
||||
(`plain-text ; External file.
|
||||
(let ((path (funcall link-org-files-as-md destination)))
|
||||
(let ((path (funcall link-org-files-as-md-maybe destination)))
|
||||
(if (not desc) (format "<%s>" path)
|
||||
(format "[%s](%s)" desc path))))
|
||||
(`headline
|
||||
|
|
|
|||
|
|
@ -35,10 +35,6 @@
|
|||
(require 'ox)
|
||||
(require 'table nil 'noerror)
|
||||
|
||||
(declare-function org-at-heading-p "org" (&optional _))
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-next-visible-heading "org" (arg))
|
||||
|
||||
;;; Define Backend
|
||||
|
||||
(org-export-define-backend 'odt
|
||||
|
|
@ -91,10 +87,12 @@
|
|||
(verbatim . org-odt-verbatim)
|
||||
(verse-block . org-odt-verse-block))
|
||||
:filters-alist '((:filter-parse-tree
|
||||
. (org-odt--translate-latex-fragments
|
||||
. (org-odt--strip-trailing-newlines
|
||||
org-odt--translate-latex-fragments
|
||||
org-odt--translate-description-lists
|
||||
org-odt--translate-list-tables
|
||||
org-odt--translate-image-links)))
|
||||
org-odt--translate-image-links))
|
||||
(:filter-final-output . org-odt--remove-forbidden))
|
||||
:menu-entry
|
||||
'(?o "Export to ODT"
|
||||
((?o "As ODT file" org-odt-export-to-odt)
|
||||
|
|
@ -108,6 +106,7 @@
|
|||
(:keywords "KEYWORDS" nil nil space)
|
||||
(:subtitle "SUBTITLE" nil nil parse)
|
||||
;; Other variables.
|
||||
(:odt-with-forbidden-chars nil nil org-odt-with-forbidden-chars)
|
||||
(:odt-content-template-file nil nil org-odt-content-template-file)
|
||||
(:odt-display-outline-level nil nil org-odt-display-outline-level)
|
||||
(:odt-fontify-srcblocks nil nil org-odt-fontify-srcblocks)
|
||||
|
|
@ -170,6 +169,14 @@ Use this to infer values of `org-odt-styles-dir' and
|
|||
("\\.\\.\\." . "…")) ; hellip
|
||||
"Regular expressions for special string conversion.")
|
||||
|
||||
(defconst org-odt-forbidden-char-re
|
||||
(rx (not (in ?\N{U+9} ?\N{U+A} ?\N{U+D}
|
||||
(?\N{U+20} . ?\N{U+D7FF})
|
||||
(?\N{U+E000} . ?\N{U+FFFD})
|
||||
(?\N{U+10000} . ?\N{U+10FFFF}))))
|
||||
"Regexp matching forbidden XML1.0 characters.
|
||||
https://www.w3.org/TR/REC-xml/#charsets")
|
||||
|
||||
(defconst org-odt-schema-dir-list
|
||||
(list (expand-file-name "./schema/" org-odt-data-dir))
|
||||
"List of directories to search for OpenDocument schema files.
|
||||
|
|
@ -364,6 +371,20 @@ the entity. See `org-odt--enumerate'.")
|
|||
:tag "Org Export ODT"
|
||||
:group 'org-export)
|
||||
|
||||
(defcustom org-odt-with-forbidden-chars ""
|
||||
"String to replace forbidden XML characters.
|
||||
When set to t, forbidden characters are left as-is.
|
||||
When set to nil, an error is thrown.
|
||||
See `org-odt-forbidden-char-re' for the list of forbidden characters
|
||||
that cannot occur inside ODT documents.
|
||||
|
||||
You may also consider export filters to perform more fine-grained
|
||||
replacements. See info node `(org)Advanced Export Configuration'."
|
||||
:package-version '(Org . "9.8")
|
||||
:type '(choice (const :tag "Leave forbidden characters as-is" t)
|
||||
(const :tag "Err when forbidden characters encountered" nil)
|
||||
(string :tag "Replacement string"))
|
||||
:safe #'always)
|
||||
|
||||
;;;; Debugging
|
||||
|
||||
|
|
@ -699,26 +720,31 @@ When set, the exporter will process LaTeX environments and
|
|||
fragments.
|
||||
|
||||
This option can also be set with the +OPTIONS line,
|
||||
e.g. \"tex:mathjax\". Allowed values are:
|
||||
e.g. \"tex:dvipng\". Allowed values are:
|
||||
|
||||
nil Ignore math snippets.
|
||||
`verbatim' Keep everything in verbatim
|
||||
`dvipng' Process the LaTeX fragments to images. This will also
|
||||
include processing of non-math environments.
|
||||
`imagemagick' Convert the LaTeX fragments to pdf files and use
|
||||
imagemagick to convert pdf files to png files.
|
||||
`mathjax' Do MathJax preprocessing and arrange for MathJax.js to
|
||||
be loaded.
|
||||
t, `mathml' Convert the LaTeX fragments to MathML if the
|
||||
`org-latex-to-mathml-convert-command' is usable.
|
||||
SYMBOL Convert the LaTeX fragments to images using any symbol
|
||||
defined in `org-preview-latex-process-alist', e.g.,
|
||||
`dvipng'.
|
||||
`verbatim' Keep everything in verbatim.
|
||||
|
||||
Any other symbol is a synonym for `mathjax'."
|
||||
:version "24.4"
|
||||
:package-version '(Org . "8.0")
|
||||
:type '(choice
|
||||
If the desired converter is not available or any other symbol is
|
||||
provided, process as `verbatim'."
|
||||
:package-version '(Org . "9.8")
|
||||
:type `(choice
|
||||
(const :tag "Do not process math in any way" nil)
|
||||
(const :tag "Leave math verbatim" verbatim)
|
||||
(const :tag "Use dvipng to make images" dvipng)
|
||||
(const :tag "Use imagemagick to make images" imagemagick)
|
||||
(other :tag "Use MathJax to display math" mathjax)))
|
||||
(choice :tag "Convert fragments to MathML" :value t
|
||||
(const t)
|
||||
(const mathml))
|
||||
(restricted-sexp :tag "Convert fragments to images"
|
||||
:value ,(caar org-preview-latex-process-alist)
|
||||
:match-alternatives
|
||||
(,(lambda (v)
|
||||
(assq v org-preview-latex-process-alist))))
|
||||
(const :tag "Leave math verbatim" verbatim))
|
||||
:safe #'always)
|
||||
|
||||
|
||||
;;;; Links
|
||||
|
|
@ -1097,8 +1123,9 @@ specifying the depth of the table."
|
|||
(format "<text:span text:style-name=\"%s\">%s</text:span> "
|
||||
style todo)))
|
||||
(when priority
|
||||
(let* ((style (format "OrgPriority-%s" priority))
|
||||
(priority (format "[#%c]" priority)))
|
||||
(let* ((priority-string (org-priority-to-string priority))
|
||||
(style (format "OrgPriority-%s" priority-string))
|
||||
(priority (format "[#%s]" priority-string)))
|
||||
(format "<text:span text:style-name=\"%s\">%s</text:span> "
|
||||
style priority)))
|
||||
;; Title.
|
||||
|
|
@ -1369,7 +1396,11 @@ original parsed data. INFO is a plist holding export options."
|
|||
;; Ensure we have write permissions to this file.
|
||||
(set-file-modes (concat org-odt-zip-dir "styles.xml") #o600)
|
||||
|
||||
(let ((styles-xml (concat org-odt-zip-dir "styles.xml")))
|
||||
(let ((styles-xml (concat org-odt-zip-dir "styles.xml"))
|
||||
;; Capture the current (possibly buffer-local) values for priorities
|
||||
;; because these get reset to global values when we use `with-temp-buffer'
|
||||
(priority-high org-priority-highest)
|
||||
(priority-low org-priority-lowest))
|
||||
(with-temp-buffer
|
||||
(when (file-exists-p styles-xml)
|
||||
(insert-file-contents styles-xml))
|
||||
|
|
@ -1401,6 +1432,16 @@ original parsed data. INFO is a plist holding export options."
|
|||
(if (wholenump sec-num) (<= level sec-num) sec-num))
|
||||
(replace-match replacement t nil))))
|
||||
|
||||
;; Update styles.xml with priority styles for the current valid priority range
|
||||
(when (plist-get info :with-priority)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "<style:style style:name=\"OrgPriority\" style:family=\"text\"/>" nil t)
|
||||
(goto-char (match-end 0))
|
||||
(insert "\n <!-- Org Priority Styles -->\n")
|
||||
(dolist (priority (number-sequence priority-high priority-low))
|
||||
(insert (format " <style:style style:name=\"OrgPriority-%s\" style:family=\"text\" style:parent-style-name=\"OrgPriority\"/>\n"
|
||||
(org-priority-to-string priority))))))
|
||||
|
||||
;; Write back the new contents.
|
||||
(write-region nil nil styles-xml))))
|
||||
;; Update content.xml.
|
||||
|
|
@ -1838,8 +1879,9 @@ See `org-odt-format-headline-function' for details."
|
|||
(let ((style (if (eq todo-type 'done) "OrgDone" "OrgTodo")))
|
||||
(format "<text:span text:style-name=\"%s\">%s</text:span> " style todo)))
|
||||
(when priority
|
||||
(let* ((style (format "OrgPriority-%c" priority))
|
||||
(priority (format "[#%c]" priority)))
|
||||
(let* ((priority-string (org-priority-to-string priority))
|
||||
(style (format "OrgPriority-%s" priority-string))
|
||||
(priority (format "[#%s]" priority-string)))
|
||||
(format "<text:span text:style-name=\"%s\">%s</text:span> "
|
||||
style priority)))
|
||||
;; Title.
|
||||
|
|
@ -2209,9 +2251,10 @@ SHORT-CAPTION are strings."
|
|||
;; Use Imagemagick.
|
||||
(and (executable-find "identify")
|
||||
(let ((size-in-pixels
|
||||
(let ((dim (shell-command-to-string
|
||||
(format "identify -format \"%%w:%%h\" \"%s\""
|
||||
file))))
|
||||
(let ((dim (with-temp-buffer
|
||||
(call-process "identify" nil `(,(current-buffer) nil) nil
|
||||
"-format" "%w:%h" (format "%s" file))
|
||||
(buffer-string))))
|
||||
(when (string-match "\\([0-9]+\\):\\([0-9]+\\)" dim)
|
||||
(cons (string-to-number (match-string 1 dim))
|
||||
(string-to-number (match-string 2 dim)))))))
|
||||
|
|
@ -2892,6 +2935,32 @@ contextual information."
|
|||
(format " <text:s text:c=\"%d\"/>" (1- (length s)))))
|
||||
line))
|
||||
|
||||
(defun org-odt--remove-forbidden (text _backend info)
|
||||
"Remove forbidden and discouraged characters from TEXT.
|
||||
INFO is the communication plist"
|
||||
(pcase-exhaustive (plist-get info :odt-with-forbidden-chars)
|
||||
((and (pred stringp) rep)
|
||||
(let ((replacements (make-hash-table :test 'equal)))
|
||||
(with-temp-buffer
|
||||
(insert text)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-odt-forbidden-char-re nil t)
|
||||
(cl-incf (gethash (match-string 0) replacements 0))
|
||||
(replace-match rep))
|
||||
(cl-loop for forbidden being the hash-keys of replacements
|
||||
using (hash-values count)
|
||||
do (display-warning
|
||||
'(ox-odt ox-odt-with-forbidden-chars)
|
||||
(format "Replaced forbidden character '%s' with '%s' %d times"
|
||||
forbidden rep count)))
|
||||
(buffer-string))))
|
||||
(`nil
|
||||
(if (string-match org-odt-forbidden-char-re text)
|
||||
(error "Forbidden character '%s' found. See `org-odt-with-forbidden-chars'"
|
||||
(match-string 0 text))
|
||||
text))
|
||||
('t text)))
|
||||
|
||||
(defun org-odt--encode-plain-text (text &optional no-whitespace-filling)
|
||||
(dolist (pair '(("&" . "&") ("<" . "<") (">" . ">")))
|
||||
(setq text (replace-regexp-in-string (car pair) (cdr pair) text t t)))
|
||||
|
|
@ -2925,7 +2994,11 @@ contextual information."
|
|||
;; FIXME: The unnecessary spacing may still remain when a newline
|
||||
;; is at a boundary between Org objects (e.g. italics markup
|
||||
;; followed by newline).
|
||||
(when (org-string-nw-p output) ; blank string needs not to be re-filled
|
||||
(when (and (org-string-nw-p output) ; blank string needs not to be re-filled
|
||||
;; Plain text inside verse blocks gotta preserve newlines
|
||||
;; and spaces.
|
||||
(not (org-element-lineage text '(verse-block)))
|
||||
)
|
||||
(setq output
|
||||
(with-temp-buffer
|
||||
(save-match-data
|
||||
|
|
@ -3116,8 +3189,7 @@ and prefix with \"OrgSrc\". For example,
|
|||
|
||||
(defun org-odt-do-format-code
|
||||
(code info &optional lang refs retain-labels num-start)
|
||||
(let* ((lang (or (assoc-default lang org-src-lang-modes) lang))
|
||||
(lang-mode (if lang (intern (format "%s-mode" lang)) #'ignore))
|
||||
(let* ((lang-mode (if lang (org-src-get-lang-mode lang) #'ignore))
|
||||
(code-lines (org-split-string code "\n"))
|
||||
(code-length (length code-lines))
|
||||
(use-htmlfontify-p (and (functionp lang-mode)
|
||||
|
|
@ -3711,14 +3783,38 @@ contextual information."
|
|||
(replace-regexp-in-string
|
||||
;; Replace leading tabs and spaces.
|
||||
"^[ \t]+" #'org-odt--encode-tabs-and-spaces
|
||||
;; Add line breaks to each line of verse.
|
||||
(replace-regexp-in-string
|
||||
"\\(<text:line-break/>\\)?[ \t]*$" "<text:line-break/>" contents))))
|
||||
;; Remove newlines after line breaks.
|
||||
"<text:line-break/>[\n]" "<text:line-break/>"
|
||||
(replace-regexp-in-string
|
||||
;; Add line breaks to each line of verse.
|
||||
"\\(<text:line-break/>\\)?[ \t]*$" "<text:line-break/>" contents)))))
|
||||
|
||||
|
||||
|
||||
;;; Filters
|
||||
|
||||
;;; Plain text
|
||||
|
||||
;; Trailing newlines appear as spaces in ODT.
|
||||
;; We do not want that in, for example, in paragraphs where
|
||||
;; end of paragraph is already signaled by ODT tag.
|
||||
(defun org-odt--strip-trailing-newlines (data _backend info)
|
||||
"Strip trailing newlines in DATA at the end of contents.
|
||||
INFO is the communication channel."
|
||||
(org-element-map data org-element-all-elements
|
||||
(lambda (el)
|
||||
(when-let* ((last-child (car (last (org-element-contents el)))))
|
||||
(when (and (org-element-type-p last-child 'plain-text)
|
||||
(string-suffix-p "\n" last-child))
|
||||
(when (length> last-child 1)
|
||||
(org-element-insert-before
|
||||
(substring last-child 0 (1- (length last-child)))
|
||||
last-child))
|
||||
(org-element-extract last-child))))
|
||||
info nil nil t)
|
||||
data)
|
||||
|
||||
;;; Images
|
||||
|
||||
(defun org-odt--translate-image-links (data _backend info)
|
||||
|
|
@ -3728,26 +3824,35 @@ contextual information."
|
|||
|
||||
(defun org-odt--translate-latex-fragments (tree _backend info)
|
||||
(let ((processing-type (plist-get info :with-latex))
|
||||
(preview-symbols (mapcar #'car org-preview-latex-process-alist))
|
||||
(count 0)
|
||||
(warning nil))
|
||||
;; Normalize processing-type to one of dvipng, mathml or verbatim.
|
||||
;; If the desired converter is not available, force verbatim
|
||||
;; processing.
|
||||
(cl-case processing-type
|
||||
((t mathml)
|
||||
;; Normalize processing-type to one of mathml, verbatim, or a
|
||||
;; symbol in org-preview-latex-process-alist. If the desired
|
||||
;; converter is not available, force verbatim processing.
|
||||
(pcase processing-type
|
||||
((or 't 'mathml)
|
||||
(if (and (fboundp 'org-format-latex-mathml-available-p)
|
||||
(org-format-latex-mathml-available-p))
|
||||
(setq processing-type 'mathml)
|
||||
(setq warning "`org-odt-with-latex': LaTeX to MathML converter not available. Falling back to verbatim.")
|
||||
(setq processing-type 'verbatim)))
|
||||
((dvipng imagemagick)
|
||||
(unless (and (org-check-external-command "latex" "" t)
|
||||
(org-check-external-command
|
||||
(if (eq processing-type 'dvipng) "dvipng" "convert") "" t))
|
||||
(setq warning "`org-odt-with-latex': LaTeX to PNG converter not available. Falling back to verbatim.")
|
||||
(setq processing-type 'verbatim)))
|
||||
(verbatim) ;; nothing to do
|
||||
(otherwise
|
||||
((and s (guard (memq s preview-symbols)))
|
||||
(let* ((ext-commands (plist-get
|
||||
(cdr (assq s org-preview-latex-process-alist))
|
||||
:programs))
|
||||
(ext-commands-available
|
||||
(seq-reduce (lambda (result cmd)
|
||||
(and result
|
||||
(not
|
||||
(null
|
||||
(org-check-external-command cmd "" t)))))
|
||||
ext-commands t)))
|
||||
(unless ext-commands-available
|
||||
(setq warning "`org-odt-with-latex': LaTeX to image converter not available. Falling back to verbatim.")
|
||||
(setq processing-type 'verbatim))))
|
||||
('verbatim) ;; nothing to do
|
||||
(_
|
||||
(setq warning "`org-odt-with-latex': Unknown LaTeX option. Forcing verbatim.")
|
||||
(setq processing-type 'verbatim)))
|
||||
|
||||
|
|
@ -3764,34 +3869,32 @@ contextual information."
|
|||
(message "Formatting LaTeX using %s" processing-type)
|
||||
|
||||
;; Convert `latex-fragment's and `latex-environment's.
|
||||
(when (memq processing-type '(mathml dvipng imagemagick))
|
||||
(when (memq processing-type (append '(mathml) preview-symbols))
|
||||
(org-element-map tree '(latex-fragment latex-environment)
|
||||
(lambda (latex-*)
|
||||
(cl-incf count)
|
||||
(let* ((latex-frag (org-element-property :value latex-*))
|
||||
(input-file (plist-get info :input-file))
|
||||
(is-image (memq processing-type preview-symbols))
|
||||
(cache-dir (file-name-directory input-file))
|
||||
(cache-subdir (concat
|
||||
(cl-case processing-type
|
||||
((dvipng imagemagick)
|
||||
org-preview-latex-image-directory)
|
||||
(mathml "ltxmathml/"))
|
||||
(if is-image
|
||||
org-preview-latex-image-directory
|
||||
org-latex-mathml-directory)
|
||||
(file-name-sans-extension
|
||||
(file-name-nondirectory input-file))))
|
||||
(display-msg
|
||||
(cl-case processing-type
|
||||
((dvipng imagemagick)
|
||||
(format "Creating LaTeX Image %d..." count))
|
||||
(mathml (format "Creating MathML snippet %d..." count))))
|
||||
;; Get an Org-style link to PNG image or the MathML
|
||||
;; file.
|
||||
(if is-image
|
||||
(format "Creating LaTeX image %d..." count)
|
||||
(format "Creating MathML snippet %d..." count)))
|
||||
;; Get an Org-style link to image or the MathML file.
|
||||
(link
|
||||
(with-temp-buffer
|
||||
(insert latex-frag)
|
||||
(delay-mode-hooks (let ((org-inhibit-startup t)) (org-mode)))
|
||||
;; When converting to a PNG image, make sure to
|
||||
;; copy all LaTeX header specifications from the
|
||||
;; Org source.
|
||||
;; When converting to an image, make sure to copy
|
||||
;; all LaTeX header specifications from the Org
|
||||
;; source.
|
||||
(unless (eq processing-type 'mathml)
|
||||
(let ((h (plist-get info :latex-header)))
|
||||
(when h
|
||||
|
|
@ -4033,7 +4136,11 @@ contextual information."
|
|||
(kill-buffer buf)))))
|
||||
;; Delete temporary directory and also other embedded
|
||||
;; files that get copied there.
|
||||
(delete-directory org-odt-zip-dir t))))
|
||||
(delete-directory org-odt-zip-dir t)))
|
||||
;; We specify UTF-8 in `org-odt-template'. Enforce it even
|
||||
;; when the buffer text has different encoding.
|
||||
(coding-system-for-write 'utf-8)
|
||||
(save-buffer-coding-system 'utf-8))
|
||||
(condition-case-unless-debug err
|
||||
(progn
|
||||
(unless (executable-find "zip")
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ a communication channel."
|
|||
;; them are included in the result.
|
||||
(let ((footnotes
|
||||
(org-element-map
|
||||
(list (org-element-lineage section 'headline) section)
|
||||
(list (or (org-element-lineage section 'headline) "") section)
|
||||
'footnote-reference
|
||||
(lambda (fn)
|
||||
(and (eq (org-element-property :type fn) 'standard)
|
||||
|
|
@ -337,10 +337,13 @@ is the property list for the given project. PUB-DIR is the
|
|||
publishing directory.
|
||||
|
||||
Return output file name."
|
||||
(require 'ox-publish)
|
||||
(declare-function org-publish-org-to "ox-publish" (backend filename extension plist &optional pub-dir))
|
||||
(org-publish-org-to 'org filename ".org" plist pub-dir)
|
||||
(when (plist-get plist :htmlized-source)
|
||||
(org-require-package 'htmlize)
|
||||
(require 'ox-html)
|
||||
(defvar org-html-extension) ; defined in ox-html.el
|
||||
(let* ((org-inhibit-startup t)
|
||||
(htmlize-output-type 'css)
|
||||
(html-ext (concat "." (or (plist-get plist :html-extension)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue