Update to Org 9.4.1
This commit is contained in:
parent
6aa9fe3e1b
commit
f22856a5c5
118 changed files with 9010 additions and 6270 deletions
1216
doc/misc/org.texi
1216
doc/misc/org.texi
File diff suppressed because it is too large
Load diff
593
etc/ORG-NEWS
593
etc/ORG-NEWS
|
@ -10,6 +10,546 @@ See the end of the file for license conditions.
|
|||
|
||||
Please send Org bug reports to mailto:emacs-orgmode@gnu.org.
|
||||
|
||||
* Version 9.4
|
||||
** Incompatible changes
|
||||
*** Possibly broken internal file links: please check and fix
|
||||
|
||||
A bug has been affecting internal links to headlines, like
|
||||
|
||||
: [[*Headline][A link to a headline]]
|
||||
|
||||
Storing a link to a headline may have been broken in your setup and
|
||||
those links may appear as
|
||||
|
||||
: [[*TODO Headline][A link to a headline]]
|
||||
|
||||
Following the link above will result in an error: the TODO keyword
|
||||
should not be part of internal file links.
|
||||
|
||||
You can use the following command to fix links in an Org buffer:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun org-fix-links ()
|
||||
"Fix ill-formatted internal links.
|
||||
E.g. replace [[*TODO Headline][headline]] by [[*Headline][headline]].
|
||||
Go through the buffer and ask for the replacement."
|
||||
(interactive)
|
||||
(visible-mode 1)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let ((regexp (format "\\[\\[\\*%s\\s-+"
|
||||
(regexp-opt org-todo-keywords-1 t))))
|
||||
(while (re-search-forward regexp nil t)
|
||||
(when (and (save-excursion
|
||||
(goto-char (match-beginning 0))
|
||||
(looking-at-p org-link-bracket-re))
|
||||
(y-or-n-p "Fix link (remove TODO keyword)? "))
|
||||
(replace-match "[[*")))))
|
||||
(visible-mode -1))
|
||||
#+end_src
|
||||
|
||||
*** Calling conventions changes when opening or exporting custom links
|
||||
|
||||
This changes affects export back-ends, and libraries providing new
|
||||
link types.
|
||||
|
||||
Function used in ~:follow~ link parameter is required to accept a
|
||||
second argument. Likewise, function used in ~:export~ parameter needs
|
||||
to accept a fourth argument. See ~org-link-set-parameters~ for
|
||||
details.
|
||||
|
||||
Eventually, the function ~org-export-custom-protocol-maybe~ is now
|
||||
called with a fourth argument. Even though the 3-arguments definition
|
||||
is still supported, at least for now, we encourage back-end developers
|
||||
to switch to the new signature.
|
||||
|
||||
*** Python session return values must be top-level expression statements
|
||||
|
||||
Python blocks with ~:session :results value~ header arguments now only
|
||||
return a value if the last line is a top-level expression statement.
|
||||
Also, when a None value is returned, "None" will be printed under
|
||||
"#+RESULTS:", as it already did with ~:results value~ for non-session
|
||||
blocks.
|
||||
|
||||
*** In HTML export, change on how outline-container-* is set
|
||||
|
||||
When the headline has a =CUSTOM_ID=, use this custom id to build the
|
||||
div id. For example, if you have =:CUSTOM_ID: my-headline= then the
|
||||
resulting <div> will be ~<div id="outline-container-my-headline">~.
|
||||
|
||||
You may want to check whether your HTML files are rendered differently
|
||||
after this change.
|
||||
|
||||
*** New keybinding =<C-c C-TAB>= for ~org-force-cycle-archived~
|
||||
|
||||
~org-force-cycle-archived~ used to be associated with =<C-TAB>= but
|
||||
this keybinding is used in Emacs for navigating tabs in Emacs. The
|
||||
new keybinding is =<C-c C-TAB>=.
|
||||
|
||||
** New default settings for some options
|
||||
|
||||
These options now default to =t=:
|
||||
|
||||
- ~org-loop-over-headlines-in-active-region~
|
||||
- ~org-fontify-done-headline~
|
||||
- ~org-src-tab-acts-natively~
|
||||
|
||||
You may want to read the docstrings of these options to understand the
|
||||
consequences of this change.
|
||||
|
||||
Also, ~org-startup-folded~ now defaults to ~showeverything~.
|
||||
|
||||
** New features
|
||||
|
||||
*** Looping agenda commands over headlines
|
||||
|
||||
~org-agenda-loop-over-headlines-in-active-region~ allows you to loop
|
||||
agenda commands over the active region.
|
||||
|
||||
When set to =t= (the default), loop over all headlines. When set to
|
||||
='start-level=, loop over headlines with the same level as the first
|
||||
headline in the region. When set to a string, loop over lines
|
||||
matching this regular expression.
|
||||
|
||||
*** New minor mode ~org-table-header-line-mode~
|
||||
|
||||
Turn on the display of the first data row of the table at point in the
|
||||
window header line when this first row is not visible anymore in the
|
||||
buffer.
|
||||
|
||||
You can activate this minor mode by default by setting the option
|
||||
~org-table-header-line-p~ to =t=. You can also change the face for
|
||||
the header line by customizing the ~org-table-header~ face.
|
||||
|
||||
*** New minor mode ~org-list-checkbox-radio-mode~
|
||||
|
||||
When this minor mode is on, checkboxes behave as radio buttons: if a
|
||||
checkbox is turned on, other checkboxes at the same level are turned
|
||||
off.
|
||||
|
||||
If you want to occasionally toggle a checkbox as a radio button
|
||||
without turning this minor mode on, you can use =<C-c C-x C-r>= to
|
||||
call ~org-toggle-radio-button~.
|
||||
|
||||
You can also add =#+ATTR_ORG: :radio t= right before the list to tell
|
||||
Org to use radio buttons for this list only.
|
||||
|
||||
*** New allowed value for ~org-adapt-indentation~
|
||||
|
||||
~org-adapt-indentation~ now accepts a new value, ='headline-data=.
|
||||
|
||||
When set to this value, Org will only adapt indentation of headline
|
||||
data lines, such as planning/clock lines and property/logbook drawers.
|
||||
Also, with this setting, =org-indent-mode= will keep these data lines
|
||||
correctly aligned with the headline above.
|
||||
|
||||
*** Numeric priorities are now allowed (up to 65)
|
||||
|
||||
You can now set ~org-priority-highest/lowest/default~ to integers to
|
||||
use numeric priorities globally or set, for example
|
||||
|
||||
#+PRIORITIES: 1 10 5
|
||||
|
||||
to define a buffer-local range and default for priorities. Priority
|
||||
commands should work as usual. You cannot use numbers superior to 64
|
||||
for numeric priorities, as it would clash with priorities like [#A]
|
||||
where the "A" is internally converted to its numeric value of 65.
|
||||
|
||||
*** Property drawers allowed before first headline
|
||||
|
||||
Property drawers are now allowed before the first headline.
|
||||
|
||||
Org mode is moving more towards making things before the first
|
||||
headline behave just as if it was at outline level 0. Inheritance for
|
||||
properties will work also for this level. In other words: defining
|
||||
things in a property drawer before the first headline will make them
|
||||
"inheritable" for all headlines.
|
||||
|
||||
*** Refinement in window behavior on exiting Org source buffer
|
||||
|
||||
After editing a source block, Org will restore the window layout when
|
||||
~org-src-window-setup~ is set to a value that modifies the layout.
|
||||
|
||||
*** Display remote inline images
|
||||
|
||||
Org now knows how to display remote images inline.
|
||||
|
||||
Whether the images are actually displayed is controlled by the new
|
||||
option ~org-display-remote-inline-images~.
|
||||
|
||||
*** New option to resolve open clock at a provided time
|
||||
|
||||
~org-resolve-clocks~ now has a `t' option, which works just like the
|
||||
`k' option, but the user specifies a time of day, not a number of
|
||||
minutes.
|
||||
|
||||
*** New step value =semimonth= accepted for clock tables
|
||||
|
||||
*** Allow text rescaling in column view
|
||||
|
||||
You can now use =C-x C-+= in column view: the columns face size will
|
||||
increase or decrease, together with the column header size.
|
||||
|
||||
*** New startup option =#+startup: num=
|
||||
|
||||
When this startup option is set, display headings as numerated.
|
||||
|
||||
Use =#+startup: nonum= to turn this off.
|
||||
|
||||
*** New tool for custom links
|
||||
|
||||
Org provides a new tool ~org-link-open-as-file~, useful when defining
|
||||
new link types similar to "file"-type links. See docstring for
|
||||
details.
|
||||
|
||||
*** New optional numeric argument for ~org-return~
|
||||
|
||||
In situations where ~org-return~ calls ~newline~, multiple newlines
|
||||
can now be inserted with this prefix argument.
|
||||
|
||||
*** New source code block header argument =:file-mode=
|
||||
|
||||
Source code block header argument =:file-mode= can set file
|
||||
permissions if =:file= argument is provided.
|
||||
|
||||
*** =RET= and =C-j= now obey ~electric-indent-mode~
|
||||
|
||||
Since Emacs 24.4, ~electric-indent-mode~ is enabled by default. In
|
||||
most major modes, this causes =RET= to reindent the current line and
|
||||
indent the new line, and =C-j= to insert a newline without indenting.
|
||||
|
||||
Org mode now obeys this minor mode: when ~electric-indent-mode~ is
|
||||
enabled, and point is neither in a table nor on a timestamp or a link:
|
||||
|
||||
- =RET= (bound to ~org-return~) reindents the current line and indents
|
||||
the new line;
|
||||
- =C-j= (bound to the new command ~org-return-and-maybe-indent~)
|
||||
merely inserts a newline.
|
||||
|
||||
To get the previous behaviour back, disable ~electric-indent-mode~
|
||||
explicitly:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(add-hook 'org-mode-hook (lambda () (electric-indent-local-mode -1)))
|
||||
#+end_src
|
||||
|
||||
Alternatively, if you wish to keep =RET= as the "smart-return" key,
|
||||
but dislike Org's default indentation of sections, you may prefer to
|
||||
customize ~org-adapt-indentation~ to either =nil= or ='headline-data=.
|
||||
|
||||
*** =ob-C.el= allows the inclusion of non-system header files
|
||||
|
||||
In C and C++ blocks, ~:includes~ arguments that do not start with a
|
||||
~<~ character will now be formatted as double-quoted ~#include~
|
||||
statements.
|
||||
|
||||
*** =ob-clojure.el= supports inf-clojure.el and ClojureScript evaluation
|
||||
|
||||
You can now set ~(setq org-babel-clojure-backend 'inf-clojure)~ and
|
||||
evaluate Clojure source blocks using [[https://github.com/clojure-emacs/inf-clojure][inf-clojure]]. With a header
|
||||
argument like =:alias "alias"= the Clojure REPL will boot with
|
||||
=clojure -Aalias=. Otherwise Clojure will boot with =lein=, =boot= or
|
||||
=tools.deps=, depending on whether the current directory contains a
|
||||
=project.clj=, =build.boot= or =deps.edn=, falling back on
|
||||
~inf-clojure-generic-cmd~ in case no such file is present.
|
||||
|
||||
Also, when using [[https://github.com/clojure-emacs/cider][cider]], you can now use =#+begin_src clojurescript= to
|
||||
execute ClojureScript code from Org files. Note that this works only
|
||||
if your Org file is associated with a cider session that knows how to
|
||||
run ClojureScript code. A bare =lein repl= session outside of a
|
||||
directory configured for ClojureScript will /not/ work.
|
||||
|
||||
*** =ob-java.el= supports Java command line arguments
|
||||
|
||||
Babel Java blocks recognize header argument =:cmdargs= and pass its
|
||||
value in call to =java=.
|
||||
|
||||
*** =ob-screen.el= now accepts =:screenrc= header argument
|
||||
|
||||
Screen blocks now recognize the =:screenrc= header argument and pass
|
||||
its value to the screen command via the "-c" option. The default
|
||||
remains =/dev/null= (i.e. a clean screen session)
|
||||
|
||||
*** =ob-plantuml=: now supports using PlantUML executable to generate diagrams
|
||||
|
||||
Set =org-plantuml-exec-mode= to ='plantuml= in order to use the
|
||||
executable instead of JAR. When using an executable it is also
|
||||
possible to configure executable location as well as arguments via:
|
||||
=org-plantuml-executable-path= and =org-plantuml-executable-args=.
|
||||
|
||||
** New commands
|
||||
*** ~org-table-header-line-mode~
|
||||
|
||||
Turn on a minor mode to display the first data row of the table at
|
||||
point in the header-line when the beginning of the table is invisible.
|
||||
|
||||
*** ~org-agenda-ctrl-c-ctrl-c~
|
||||
|
||||
Hitting =<C-c C-c>= in an agenda view now calls ~org-agenda-set-tags~.
|
||||
|
||||
*** ~org-hide-entry~
|
||||
|
||||
This command is the counterpart of ~org-show-entry~.
|
||||
|
||||
*** ~org-columns-toggle-or-columns-quit~
|
||||
|
||||
=<C-c C-c>= bound to ~org-columns-toggle-or-columns-quit~ replaces the
|
||||
recent ~org-columns-set-tags-or-toggle~. Tag setting is still
|
||||
possible via column view value edit or with =<C-c C-q>=.
|
||||
|
||||
*** ~org-datetree-find-month-create~
|
||||
|
||||
Find or create a month entry for a date.
|
||||
|
||||
** New options and settings
|
||||
*** New option ~org-html-prefer-user-labels~
|
||||
|
||||
When non-nil, use =NAME= affiliated keyword, or raw target values, to
|
||||
generate anchor's ID. Otherwise, consistently use internal naming
|
||||
scheme.
|
||||
|
||||
=CUSTOM_ID= values are still always used, when available.
|
||||
*** New option for using tabs in ~org-agenda-window-setup~
|
||||
|
||||
Choosing ~other-tab~ for ~org-agenda-window-setup~ will open the
|
||||
agenda view in a new tab. This will work with versions of Emacs since
|
||||
27.1 when ~tab-bar-mode~ was introduced.
|
||||
|
||||
*** New option ~org-table-header-line-p~
|
||||
|
||||
Setting this option to =t= will activate ~org-table-header-line-mode~
|
||||
in org-mode buffers.
|
||||
|
||||
*** New option ~org-startup-numerated~
|
||||
|
||||
When this option is =t=, Org files will start using ~(org-num-mode 1)~
|
||||
and headings will be visually numerated.
|
||||
|
||||
You can turn this on/off on a per-file basis with =#+startup: num= or
|
||||
=#+startup: nonum=.
|
||||
|
||||
*** New option ~org-clock-auto-clockout-timer~
|
||||
|
||||
When this option is set to a number and the user configuration
|
||||
contains =(org-clock-auto-clockout-insinuate)=, Org will clock out the
|
||||
currently clocked in task after that number of seconds of idle time.
|
||||
|
||||
This is useful when you often forget to clock out before being idle
|
||||
and don't want to have to manually set the clocking time to take into
|
||||
account.
|
||||
|
||||
*** New option to group captured datetime entries by month
|
||||
|
||||
A new `:tree-type month' option was added to org-capture-templates to
|
||||
group new datetime entries by month.
|
||||
|
||||
*** New option to show source buffers using "plain" display-buffer
|
||||
|
||||
There is a new option ~plain~ to ~org-src-window-setup~ to show source
|
||||
buffers using ~display-buffer~. This allows users to control how
|
||||
source buffers are displayed by modifying ~display-buffer-alist~ or
|
||||
~display-buffer-base-action~.
|
||||
|
||||
*** New option ~org-archive-subtree-save-file-p~
|
||||
|
||||
Archiving a subtree used to always save the target archive buffer.
|
||||
Commit [[https://code.orgmode.org/bzg/org-mode/commit/b186d1d7][b186d1d7]] changed this behavior by always not saving the target
|
||||
buffer, because batch archiving from agenda could take too much time.
|
||||
|
||||
This new option ~org-archive-subtree-save-file-p~ defaults to the
|
||||
value =from-org= so that archiving a subtree will save the target
|
||||
buffer when done from an org-mode buffer, but not from the agenda.
|
||||
You can also set this option to =t= or to =from-agenda=.
|
||||
|
||||
*** New option ~org-show-notification-timeout~
|
||||
|
||||
This option will add a timeout to notifications.
|
||||
|
||||
*** New option ~org-latex-to-html-convert-command~
|
||||
|
||||
This new option allows you to convert a LaTeX fragment directly into
|
||||
HTML.
|
||||
|
||||
*** New option ~org-babel-shell-results-defaults-to-output~
|
||||
|
||||
By default, source code blocks are executed in "functional mode": it
|
||||
means that the results of executing them are the value of their last
|
||||
statement (see [[https://orgmode.org/manual/Results-of-Evaluation.html][the documentation]].)
|
||||
|
||||
The value of a shell script's execution is its exit code. But most
|
||||
users expect the results of executing a shell script to be its output,
|
||||
not its exit code.
|
||||
|
||||
So we introduced this option, that you can set to =nil= if you want
|
||||
to stick using ~:results value~ as the implicit header.
|
||||
|
||||
In all Babel libraries, the absence of a ~:results~ header should
|
||||
produce the same result than setting ~:results value~, unless there is
|
||||
an option to explicitly create an exception.
|
||||
|
||||
See [[https://orgmode.org/list/CA+A2iZaziAfMeGpBqL6qGrzrWEVvLvC0DUw++T4gCF3NGuW-DQ@mail.gmail.com/][this thread]] for more context.
|
||||
|
||||
*** New option in ~org-attach-store-link-p~
|
||||
|
||||
~org-attach-store-link-p~ has a new option to store a file link to the
|
||||
attachment.
|
||||
*** New option ~org-fontify-todo-headline~
|
||||
|
||||
This feature is the same as ~org-fontify-done-headline~, but for TODO
|
||||
headlines instead. This allows you to distinguish TODO headlines from
|
||||
normal headlines. The face can be customized via ~org-headline-todo~.
|
||||
|
||||
*** New default value for ~org-file-apps~
|
||||
|
||||
The new value uses Emacs as the application for opening directory.
|
||||
|
||||
*** New hook ~org-agenda-filter-hook~
|
||||
|
||||
Functions in this hook are run after ~org-agenda-filter~ is called.
|
||||
|
||||
** Removed or renamed functions and variables
|
||||
*** Deprecated ~org-flag-drawer~ function
|
||||
|
||||
Use ~org-hide-drawer-toggle~ instead.
|
||||
|
||||
*** Deprecated ~org-hide-block-toggle-maybe~ function
|
||||
|
||||
Use ~org-hide-block-toggle~ instead.
|
||||
|
||||
*** Deprecated ~org-hide-block-toggle-all~ function
|
||||
|
||||
This function was not used in the code base, and has no clear use
|
||||
either. It has been marked for future removal. Please contact the
|
||||
mailing list if you use this function.
|
||||
|
||||
*** Deprecated ~org-return-indent~ function
|
||||
|
||||
In Elisp code, use ~(org-return t)~ instead. Interactively, =C-j= is
|
||||
now bound to ~org-return-and-maybe-indent~, which indents the new line
|
||||
when ~electric-indent-mode~ is disabled.
|
||||
|
||||
*** Removed ~org-maybe-keyword-time-regexp~
|
||||
|
||||
The variable was not used in the code base.
|
||||
|
||||
*** Removed ~org-export-special-keywords~
|
||||
|
||||
The variable was not used in the code base.
|
||||
|
||||
*** Renamed ~org-at-property-block-p~
|
||||
|
||||
The new name is ~org-at-property-drawer-p~, which is less confusing.
|
||||
|
||||
*** Renamed ~org-columns-set-tags-or-toggle~
|
||||
|
||||
See [[*~org-columns-toggle-or-columns-quit~]].
|
||||
|
||||
*** Renamed priority options
|
||||
|
||||
From ~org-lowest-priority~ to ~org-priority-lowest~.
|
||||
From ~org-default-priority~ to ~org-priority-default~.
|
||||
From ~org-highest-priority~ to ~org-priority-highest~.
|
||||
From ~org-enable-priority-commands~ to ~org-priority-enable-commands~.
|
||||
From ~org-show-priority~ to ~org-priority-show~.
|
||||
|
||||
** Miscellaneous
|
||||
*** =ob-screen.el= now respects screen =:session= name
|
||||
|
||||
Screen babel session are now named based on the =:session= header
|
||||
argument (defaults to ~default~).
|
||||
|
||||
Previously all session names had ~org-babel-session-~ prepended.
|
||||
|
||||
*** Forward/backward paragraph functions in line with the rest of Emacs
|
||||
|
||||
~org-forward-paragraph~ and ~org-backward-paragraph~, bound to
|
||||
~<C-UP>~ and ~<C-DOWN>~ functions mimic more closely behaviour of
|
||||
~forward-paragraph~ and ~backward-paragraph~ functions when
|
||||
available.
|
||||
|
||||
They also accept an optional argument for multiple calls.
|
||||
|
||||
See their docstring for details.
|
||||
*** ~org-table-to-lisp~ no longer checks if point is at a table
|
||||
|
||||
The caller is now responsible for the check. It can use, e.g.,
|
||||
~org-at-table-p~.
|
||||
|
||||
The function is also much more efficient than it used to be, even on
|
||||
very large tables.
|
||||
|
||||
*** New function ~org-collect-keywords~
|
||||
*** Drawers' folding use an API similar to block's
|
||||
|
||||
Tooling for folding drawers interactively or programmatically is now
|
||||
on par with block folding. In particular, ~org-hide-drawer-toggle~,
|
||||
a new function, is the central place for drawer folding.
|
||||
|
||||
*** Duration can be read and written in compact form
|
||||
|
||||
~org-duration-to-minutes~ understands =1d3h5min= as a duration,
|
||||
whereas ~org-duration-from-minutes~ can output this compact form if
|
||||
the duration format contains the symbol ~compact~.
|
||||
|
||||
*** C-n, C-p, SPC and DEL in agenda commands dispatch window
|
||||
|
||||
You can now use =<C-n>=, =<C-p>=, =<SPC>= and =<DEL>= key to scroll up
|
||||
and down the agenda and attach dispatch window.
|
||||
|
||||
*** =<C-c C-c>= in agenda calls ~org-agenda-set-tags~
|
||||
|
||||
Both =<C-c C-q>= and =<C-c C-c>= set the tags of the headline in the
|
||||
Org buffer. Both keybindings are now available from the agenda too.
|
||||
|
||||
*** Allow to use an empty HTML extension
|
||||
|
||||
Using =(setq org-html-extension "")= or setting the HTML extension in
|
||||
any fashion will produce the expected output, with no trailing period
|
||||
to the resulting HTML file.
|
||||
|
||||
*** Handle repeated tasks with =.+= type and hours step
|
||||
|
||||
A task using a =.+= repeater and hours step is repeated starting from
|
||||
now. E.g.,
|
||||
|
||||
#+begin_example
|
||||
,,** TODO Wash my hands
|
||||
DEADLINE: <2019-04-05 08:00 Sun .+1h>
|
||||
Marking this DONE shifts the date to exactly one hour from now.
|
||||
#+end_example
|
||||
|
||||
*** The format of equation reference in HTML export can now be specified
|
||||
|
||||
By default, HTML (via MathJax) and LaTeX export equation references
|
||||
using different commands. LaTeX must use ~\ref{%s}~ because it is used
|
||||
for all labels; however, HTML (via MathJax) uses ~\eqref{%s}~ for
|
||||
equations producing inconsistent output. New option
|
||||
~org-html-equation-reference-format~ sets the command used in HTML
|
||||
export.
|
||||
|
||||
*** =ob-haskell.el= supports compilation with =:compile= header argument
|
||||
|
||||
By default, Haskell blocks are interpreted. By adding =:compile yes=
|
||||
to a Haskell source block, it will be compiled, executed and the
|
||||
results will be displayed.
|
||||
|
||||
*** Support for ~org-edit-special~ with LaTeX fragments
|
||||
|
||||
Calling ~org-edit-special~ on an inline LaTeX fragment calls a new
|
||||
function, ~org-edit-latex-fragment~. This functions in a comparable
|
||||
manner to editing inline source blocks, bringing up a minibuffer set
|
||||
to LaTeX mode. The math-mode deliminators are read only.
|
||||
|
||||
*** ~org-capture-current-plist~ is now accessible during ~org-capture-mode-hook~
|
||||
*** New =org-refile.el= file
|
||||
|
||||
Org refile variables and functions have been moved to a new file.
|
||||
|
||||
*** The end of a 7 years old bug
|
||||
|
||||
This bug [[https://lists.gnu.org/archive/html/emacs-orgmode/2013-08/msg00072.html][originally reported]] by Matt Lundin and investigated by Andrew
|
||||
Hyatt has been fixed. Thanks to both of them.
|
||||
|
||||
* Version 9.3
|
||||
|
||||
** Incompatible changes
|
||||
|
@ -19,15 +559,11 @@ Org used to percent-encode sensitive characters in the URI part of the
|
|||
bracket links.
|
||||
|
||||
Now, escaping mechanism uses the usual backslash character, according
|
||||
to the following rules, applied in order:
|
||||
to the following rules:
|
||||
|
||||
1. All consecutive =\= characters at the end of the link must be
|
||||
escaped;
|
||||
2. Any =]= character at the very end of the link must be escaped;
|
||||
3. All consecutive =\= characters preceding =][= or =]]= patterns must
|
||||
be escaped;
|
||||
4. Any =]= character followed by either =[= or =]= must be escaped;
|
||||
5. Others =]= and =\= characters need not be escaped.
|
||||
1. All =[= and =]= characters in the URI must be escaped;
|
||||
2. Every =\= character preceding either =[= or =]= must be escaped;
|
||||
3. Every =\= character at the end of the URI must be escaped.
|
||||
|
||||
When in doubt, use the function ~org-link-escape~ in order to turn
|
||||
a link string into its properly escaped form.
|
||||
|
@ -141,7 +677,7 @@ Export ignore done tasks with a deadline when
|
|||
Likewise, scheduled done tasks are also ignored when
|
||||
~org-icalendar-use-scheduled~ contains the same symbol.
|
||||
|
||||
*** Add split-window-right option for src block edit window placement
|
||||
*** Add ~split-window-right~ option for src block edit window placement
|
||||
|
||||
Given the increasing popularity of wide screen monitors, splitting
|
||||
horizontally may make more sense than splitting vertically. An
|
||||
|
@ -364,7 +900,6 @@ the headline to use for making the table of contents.
|
|||
,* Another section
|
||||
,#+TOC: headlines 1 :target "#TargetSection"
|
||||
#+end_example
|
||||
|
||||
** New functions
|
||||
*** ~org-dynamic-block-insert-dblock~
|
||||
|
||||
|
@ -474,6 +1009,16 @@ I.e. treat the whole file as if it was a subtree.
|
|||
|
||||
*** Respect narrowing when agenda command is restricted to buffer
|
||||
|
||||
*** ~org-table-insert-column~ inserts the column at point position
|
||||
|
||||
Before, the new column was inserted to the right of the column at
|
||||
point position.
|
||||
|
||||
*** Table column deletion now consistent with row deletion
|
||||
|
||||
Point stays in the column at deletion, except when deleting the
|
||||
rightmost column.
|
||||
|
||||
* Version 9.2
|
||||
** Incompatible changes
|
||||
*** Removal of OrgStruct mode mode and radio lists
|
||||
|
@ -484,7 +1029,7 @@ and ~org-list-radio-lists-templates~) are removed from the code base.
|
|||
Note that only radio /lists/ have been removed, not radio tables.
|
||||
|
||||
If you want to manipulate lists like in Org in other modes, we suggest
|
||||
to use orgalist.el, which you can install from GNU ELPA.
|
||||
to use =orgalist.el=, which you can install from GNU ELPA.
|
||||
|
||||
If you want to use Org folding outside of Org buffers, you can have a
|
||||
look at the outshine package in the MELPA repository.
|
||||
|
@ -1276,9 +1821,9 @@ removed from Gnus circa September 2010.
|
|||
|
||||
*** ~org-agenda-repeating-timestamp-show-all~ is removed.
|
||||
|
||||
For an equivalent to a ~nil~ value, set
|
||||
For an equivalent to a =nil= value, set
|
||||
~org-agenda-show-future-repeats~ to nil and
|
||||
~org-agenda-prefer-last-repeat~ to ~t~.
|
||||
~org-agenda-prefer-last-repeat~ to =t=.
|
||||
|
||||
*** ~org-gnus-nnimap-query-article-no-from-file~ is removed.
|
||||
|
||||
|
@ -1296,7 +1841,7 @@ equivalent to the removed format string.
|
|||
|
||||
*** ~org-enable-table-editor~ is removed.
|
||||
|
||||
Setting it to a ~nil~ value broke some other features (e.g., speed
|
||||
Setting it to a =nil= value broke some other features (e.g., speed
|
||||
keys).
|
||||
|
||||
*** ~org-export-use-babel~ cannot be set to ~inline-only~
|
||||
|
@ -1377,16 +1922,20 @@ is now obsolete.
|
|||
|
||||
Now ~=...=~ markup uses ~@samp{}~ instead of ~@verb{}~. You can use
|
||||
~@verb{}~ again by customizing the variable.
|
||||
|
||||
*** Texinfo exports example blocks as ~@example~
|
||||
*** Texinfo exports inline source blocks as ~@code{}~
|
||||
*** Texinfo default table markup is ~@asis~
|
||||
|
||||
It used to be ~@samp~ but ~@asis~ is neutral and, therefore, more
|
||||
suitable as a default value.
|
||||
|
||||
*** Texinfo default process includes ~--no-split~ option
|
||||
*** New entities : ~\dollar~ and ~\USD~
|
||||
*** Support for date style URLs in =org-protocol://open-source=
|
||||
URLs like =https://cool-blog.com/2017/05/20/cool-post/= are
|
||||
covered by rewrite rules.
|
||||
|
||||
URLs like =https://cool-blog.com/2017/05/20/cool-post/= are covered by
|
||||
rewrite rules.
|
||||
|
||||
*** Add (C) =COMMENT= support to ~org-structure-template-alist~
|
||||
|
||||
|
@ -1476,7 +2025,7 @@ Moreover, ~:export-block~ keyword used in ~org-export-define-backend~ and
|
|||
~org-export-define-derived-backend~ is no longer used and needs to be
|
||||
removed.
|
||||
|
||||
*** Footnotes
|
||||
*** Footnotes changes
|
||||
|
||||
**** [1]-like constructs are not valid footnotes
|
||||
|
||||
|
@ -2216,7 +2765,7 @@ without changing the headline.
|
|||
|
||||
*** Hierarchies of tags
|
||||
|
||||
The functionality of nesting tags in hierarchies is added to org-mode.
|
||||
The functionality of nesting tags in hierarchies is added to Org mode.
|
||||
This is the generalization of what was previously called "Tag groups"
|
||||
in the manual. That term is now changed to "Tag hierarchy".
|
||||
|
||||
|
@ -4105,7 +4654,7 @@ See https://orgmode.org/elpa/
|
|||
|
||||
You can temporarily activate continuous clocking with =C-u C-u
|
||||
C-u M-x= [[doc::org-clock-in][org-clock-in]] =RET= (three universal prefix arguments)
|
||||
and =C-u C-u M-x= [[org-clock-in-last][org-clock-in-last]] =RET= (two universal prefix
|
||||
and =C-u C-u M-x= [[doc::org-clock-in-last][org-clock-in-last]] =RET= (two universal prefix
|
||||
arguments).
|
||||
|
||||
|
||||
|
@ -4581,7 +5130,7 @@ that Calc formulas can operate on them.
|
|||
|
||||
The new system has a technically cleaner implementation and more
|
||||
possibilities for capturing different types of data. See
|
||||
[[http://thread.gmane.org/gmane.emacs.orgmode/26441/focus%3D26441][Carsten's announcement]] for more details.
|
||||
[[https://orgmode.org/list/C46F10DC-DE51-43D4-AFFE-F71E440D1E1F@gmail.com][Carsten's announcement]] for more details.
|
||||
|
||||
To switch over to the new system:
|
||||
|
||||
|
@ -4712,7 +5261,7 @@ that Calc formulas can operate on them.
|
|||
|
||||
**** Modified link escaping
|
||||
|
||||
David Maus worked on `org-link-escape'. See [[http://article.gmane.org/gmane.emacs.orgmode/37888][his message]]:
|
||||
David Maus worked on `org-link-escape'. See [[https://orgmode.org/list/87k4gysacq.wl%dmaus@ictsoc.de][his message]]:
|
||||
|
||||
: Percent escaping is used in Org mode to escape certain characters
|
||||
: in links that would either break the parser (e.g. square brackets
|
||||
|
@ -5151,7 +5700,7 @@ that Calc formulas can operate on them.
|
|||
|
||||
Thanks to Nicolas Goaziou for coding these changes.
|
||||
|
||||
**** A property value of "nil" now means to unset a property
|
||||
**** A property value of =nil= now means to unset a property
|
||||
|
||||
This can be useful in particular with property inheritance, if
|
||||
some upper level has the property, and some grandchild of it
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
% Reference Card for Org Mode
|
||||
\def\orgversionnumber{9.3}
|
||||
\def\orgversionnumber{9.4.1}
|
||||
\def\versionyear{2019} % latest update
|
||||
\input emacsver.tex
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
|||
\pdflayout=(0l)
|
||||
|
||||
% Nothing else needs to be changed below this line.
|
||||
% Copyright (C) 1987, 1993, 1996--1997, 2001--2020 Free Software
|
||||
% Copyright (C) 1987, 1993, 1996-1997, 2001-2020 Free Software
|
||||
% Foundation, Inc.
|
||||
|
||||
% This document is free software: you can redistribute it and/or modify
|
||||
|
@ -79,6 +79,9 @@
|
|||
\centerline{Released under the terms of the GNU General Public License}
|
||||
\centerline{version 3 or later.}
|
||||
|
||||
\centerline{For more Emacs documentation, and the \TeX{} source for this card, see}
|
||||
\centerline{the Emacs distribution, or {\tt https://www.gnu.org/software/emacs}}
|
||||
|
||||
\endgroup}
|
||||
|
||||
% make \bye not \outer so that the \def\bye in the \else clause below
|
||||
|
@ -515,7 +518,7 @@ \section{Properties and Column View}
|
|||
\key{special commands in property lines}{C-c C-c}
|
||||
\key{next/previous allowed value}{S-LEFT/RIGHT}
|
||||
\key{turn on column view}{C-c C-x C-c}
|
||||
\key{capture columns view in dynamic block}{C-c C-x i}
|
||||
\key{capture columns view in dynamic block}{C-c C-x x}
|
||||
|
||||
\key{quit column view}{q}
|
||||
\key{show full value}{v}
|
||||
|
@ -558,7 +561,7 @@ \section{Timestamps}
|
|||
\key{stop/cancel clock on current item}{C-c C-x C-o/x}
|
||||
\key{display total subtree times}{C-c C-x C-d}
|
||||
\key{remove displayed times}{C-c C-c}
|
||||
\key{insert/update table with clock report}{C-c C-x C-r}
|
||||
\key{insert/update table with clock report}{C-c C-x C-x}
|
||||
|
||||
\section{Agenda Views}
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ or `org-babel-execute:C++' or `org-babel-execute:D'."
|
|||
cmdline)))
|
||||
"")))
|
||||
(when results
|
||||
(setq results (org-trim (org-remove-indentation results)))
|
||||
(setq results (org-remove-indentation results))
|
||||
(org-babel-reassemble-table
|
||||
(org-babel-result-cond (cdr (assq :result-params params))
|
||||
(org-babel-read results t)
|
||||
|
@ -232,7 +232,13 @@ its header arguments."
|
|||
(list
|
||||
;; includes
|
||||
(mapconcat
|
||||
(lambda (inc) (format "#include %s" inc))
|
||||
(lambda (inc)
|
||||
;; :includes '(<foo> <bar>) gives us a list of
|
||||
;; symbols; convert those to strings.
|
||||
(when (symbolp inc) (setq inc (symbol-name inc)))
|
||||
(if (string-prefix-p "<" inc)
|
||||
(format "#include %s" inc)
|
||||
(format "#include \"%s\"" inc)))
|
||||
includes "\n")
|
||||
;; defines
|
||||
(mapconcat
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2011-2020 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Oleh Krehel
|
||||
;; Maintainer: Joseph Novakovich <josephnovakovich@gmail.com>
|
||||
;; Keywords: literate programming, reproducible research
|
||||
;; Homepage: https://orgmode.org
|
||||
|
||||
|
@ -76,6 +77,8 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(message "executing J source code block")
|
||||
(let* ((processed-params (org-babel-process-params params))
|
||||
(sessionp (cdr (assq :session params)))
|
||||
(sit-time (let ((sit (assq :sit params)))
|
||||
(if sit (cdr sit) .1)))
|
||||
(full-body (org-babel-expand-body:J
|
||||
body params processed-params))
|
||||
(tmp-script-file (org-babel-temp-file "J-src")))
|
||||
|
@ -86,9 +89,9 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(with-temp-file tmp-script-file
|
||||
(insert full-body))
|
||||
(org-babel-eval (format "%s < %s" org-babel-J-command tmp-script-file) ""))
|
||||
(org-babel-J-eval-string full-body)))))
|
||||
(org-babel-J-eval-string full-body sit-time)))))
|
||||
|
||||
(defun org-babel-J-eval-string (str)
|
||||
(defun org-babel-J-eval-string (str sit-time)
|
||||
"Sends STR to the `j-console-cmd' session and executes it."
|
||||
(let ((session (j-console-ensure-session)))
|
||||
(with-current-buffer (process-buffer session)
|
||||
|
@ -96,7 +99,7 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(insert (format "\n%s\n" str))
|
||||
(let ((beg (point)))
|
||||
(comint-send-input)
|
||||
(sit-for .1)
|
||||
(sit-for sit-time)
|
||||
(buffer-substring-no-properties
|
||||
beg (point-max))))))
|
||||
|
||||
|
|
|
@ -193,7 +193,8 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(org-babel-comint-in-buffer session
|
||||
(mapc (lambda (var)
|
||||
(end-of-line 1) (insert var) (comint-send-input nil t)
|
||||
(org-babel-comint-wait-for-output session)) var-lines))
|
||||
(org-babel-comint-wait-for-output session))
|
||||
var-lines))
|
||||
session))
|
||||
|
||||
(defun org-babel-load-session:R (session body params)
|
||||
|
@ -459,11 +460,11 @@ last statement in BODY, as elisp."
|
|||
"R-specific processing of return value.
|
||||
Insert hline if column names in output have been requested."
|
||||
(if column-names-p
|
||||
(cons (car result) (cons 'hline (cdr result)))
|
||||
(condition-case nil
|
||||
(cons (car result) (cons 'hline (cdr result)))
|
||||
(error "Could not parse R result"))
|
||||
result))
|
||||
|
||||
(provide 'ob-R)
|
||||
|
||||
|
||||
|
||||
;;; ob-R.el ends here
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
;; Author: William Waites
|
||||
;; Keywords: literate programming, music
|
||||
;; Homepage: http://www.tardis.ed.ac.uk/wwaites
|
||||
;; Version: 0.01
|
||||
;; Homepage: https://www.tardis.ed.ac.uk/~wwaites
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
|
@ -87,4 +86,5 @@
|
|||
(error "ABC does not support sessions"))
|
||||
|
||||
(provide 'ob-abc)
|
||||
|
||||
;;; ob-abc.el ends here
|
||||
|
|
|
@ -134,6 +134,4 @@ Otherwise, it is either `real', if some elements are floats, or
|
|||
|
||||
(provide 'ob-asymptote)
|
||||
|
||||
|
||||
|
||||
;;; ob-asymptote.el ends here
|
||||
|
|
|
@ -106,6 +106,4 @@ This function is called by `org-babel-execute-src-block'."
|
|||
|
||||
(provide 'ob-awk)
|
||||
|
||||
|
||||
|
||||
;;; ob-awk.el ends here
|
||||
|
|
|
@ -105,6 +105,4 @@
|
|||
|
||||
(provide 'ob-calc)
|
||||
|
||||
|
||||
|
||||
;;; ob-calc.el ends here
|
||||
|
|
|
@ -30,80 +30,70 @@
|
|||
|
||||
;; - clojure (at least 1.2.0)
|
||||
;; - clojure-mode
|
||||
;; - either cider or SLIME
|
||||
;; - inf-clojure, cider or SLIME
|
||||
|
||||
;; For Cider, see https://github.com/clojure-emacs/cider
|
||||
;; For clojure-mode, see https://github.com/clojure-emacs/clojure-mode
|
||||
;; For cider, see https://github.com/clojure-emacs/cider
|
||||
;; For inf-clojure, see https://github.com/clojure-emacs/cider
|
||||
|
||||
;; For SLIME, the best way to install these components is by following
|
||||
;; the directions as set out by Phil Hagelberg (Technomancy) on the
|
||||
;; web page: http://technomancy.us/126
|
||||
|
||||
;;; Code:
|
||||
(require 'cl-lib)
|
||||
(require 'ob)
|
||||
(require 'org-macs)
|
||||
|
||||
(declare-function cider-jack-in "ext:cider" (&optional prompt-project cljs-too))
|
||||
(declare-function cider-current-connection "ext:cider-client" (&optional type))
|
||||
(declare-function cider-current-ns "ext:cider-client" ())
|
||||
(declare-function cider-repls "ext:cider-connection" (&optional type ensure))
|
||||
(declare-function nrepl--merge "ext:nrepl-client" (dict1 dict2))
|
||||
(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))
|
||||
(declare-function inf-clojure-project-type "ext:inf-clojure" ())
|
||||
(declare-function nrepl-dict-get "ext:nrepl-client" (dict key))
|
||||
(declare-function nrepl-dict-put "ext:nrepl-client" (dict key value))
|
||||
(declare-function nrepl-request:eval "ext:nrepl-client" (input callback connection &optional ns line column additional-params tooling))
|
||||
(declare-function nrepl-sync-request:eval "ext:nrepl-client" (input connection &optional ns tooling))
|
||||
(declare-function sesman-start-session "ext:sesman" (system))
|
||||
(declare-function slime-eval "ext:slime" (sexp &optional package))
|
||||
|
||||
(defvar nrepl-sync-request-timeout)
|
||||
(defvar cider-buffer-ns)
|
||||
(defvar sesman-system)
|
||||
(defvar cider-version)
|
||||
|
||||
(defvar org-babel-tangle-lang-exts)
|
||||
(add-to-list 'org-babel-tangle-lang-exts '("clojure" . "clj"))
|
||||
(add-to-list 'org-babel-tangle-lang-exts '("clojurescript" . "cljs"))
|
||||
|
||||
(defvar org-babel-default-header-args:clojure '())
|
||||
(defvar org-babel-header-args:clojure '((ns . :any)
|
||||
(package . :any)))
|
||||
(defvar org-babel-header-args:clojure '((ns . :any) (package . :any)))
|
||||
(defvar org-babel-default-header-args:clojurescript '())
|
||||
(defvar org-babel-header-args:clojurescript '((package . :any)))
|
||||
|
||||
(defcustom org-babel-clojure-sync-nrepl-timeout 10
|
||||
"Timeout value, in seconds, of a Clojure sync call.
|
||||
If the value is nil, timeout is disabled."
|
||||
:group 'org-babel
|
||||
:type 'integer
|
||||
:version "26.1"
|
||||
:package-version '(Org . "9.1")
|
||||
:safe #'wholenump)
|
||||
|
||||
(defcustom org-babel-clojure-backend
|
||||
(cond ((featurep 'cider) 'cider)
|
||||
(t 'slime))
|
||||
(defcustom org-babel-clojure-backend nil
|
||||
"Backend used to evaluate Clojure code blocks."
|
||||
:group 'org-babel
|
||||
:type '(choice
|
||||
(const :tag "inf-clojure" inf-clojure)
|
||||
(const :tag "cider" cider)
|
||||
(const :tag "SLIME" slime)))
|
||||
(const :tag "slime" slime)
|
||||
(const :tag "Not configured yet" nil)))
|
||||
|
||||
(defcustom org-babel-clojure-default-ns "user"
|
||||
"Default Clojure namespace for source block when finding ns failed."
|
||||
:type 'string
|
||||
:group 'org-babel)
|
||||
|
||||
(defun org-babel-clojure-cider-current-ns ()
|
||||
"Like `cider-current-ns' except `cider-find-ns'."
|
||||
(or cider-buffer-ns
|
||||
(let ((repl-buf (cider-current-connection)))
|
||||
(and repl-buf (buffer-local-value 'cider-buffer-ns repl-buf)))
|
||||
org-babel-clojure-default-ns))
|
||||
|
||||
(defun org-babel-expand-body:clojure (body params)
|
||||
"Expand BODY according to PARAMS, return the expanded body."
|
||||
(let* ((vars (org-babel--get-vars params))
|
||||
(ns (or (cdr (assq :ns params))
|
||||
(org-babel-clojure-cider-current-ns)))
|
||||
(if (eq org-babel-clojure-backend 'cider)
|
||||
(or cider-buffer-ns
|
||||
(let ((repl-buf (cider-current-connection)))
|
||||
(and repl-buf (buffer-local-value
|
||||
'cider-buffer-ns repl-buf))))
|
||||
org-babel-clojure-default-ns)))
|
||||
(result-params (cdr (assq :result-params params)))
|
||||
(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.
|
||||
|
@ -113,7 +103,7 @@ If the value is nil, timeout is disabled."
|
|||
(format "(let [%s]\n%s)"
|
||||
(mapconcat
|
||||
(lambda (var)
|
||||
(format "%S (quote %S)" (car var) (cdr var)))
|
||||
(format "%S %S" (car var) (cdr var)))
|
||||
vars
|
||||
"\n ")
|
||||
body))))))
|
||||
|
@ -122,161 +112,141 @@ If the value is nil, timeout is disabled."
|
|||
(format "(clojure.pprint/pprint (do %s))" body)
|
||||
body)))
|
||||
|
||||
(defun org-babel-execute:clojure (body params)
|
||||
"Execute a block of Clojure code with Babel.
|
||||
The underlying process performed by the code block can be output
|
||||
using the :show-process parameter."
|
||||
(let* ((expanded (org-babel-expand-body:clojure body params))
|
||||
(response (list 'dict))
|
||||
result)
|
||||
(cl-case org-babel-clojure-backend
|
||||
(cider
|
||||
(require 'cider)
|
||||
(let ((result-params (cdr (assq :result-params params)))
|
||||
(show (cdr (assq :show-process params))))
|
||||
(if (member show '(nil "no"))
|
||||
;; Run code without showing the process.
|
||||
(progn
|
||||
(setq response
|
||||
(let ((nrepl-sync-request-timeout
|
||||
org-babel-clojure-sync-nrepl-timeout))
|
||||
(nrepl-sync-request:eval expanded
|
||||
(cider-current-connection))))
|
||||
(setq result
|
||||
(concat
|
||||
(nrepl-dict-get response
|
||||
(if (or (member "output" result-params)
|
||||
(member "pp" result-params))
|
||||
"out"
|
||||
"value"))
|
||||
(nrepl-dict-get response "ex")
|
||||
(nrepl-dict-get response "root-ex")
|
||||
(nrepl-dict-get response "err"))))
|
||||
;; Show the process in an output buffer/window.
|
||||
(let ((process-buffer (switch-to-buffer-other-window
|
||||
"*Clojure Show Process Sub Buffer*"))
|
||||
status)
|
||||
;; Run the Clojure code in nREPL.
|
||||
(nrepl-request:eval
|
||||
expanded
|
||||
(lambda (resp)
|
||||
(when (member "out" resp)
|
||||
;; Print the output of the nREPL in the output buffer.
|
||||
(princ (nrepl-dict-get resp "out") process-buffer))
|
||||
(when (member "ex" resp)
|
||||
;; In case there is an exception, then add it to the
|
||||
;; output buffer as well.
|
||||
(princ (nrepl-dict-get resp "ex") process-buffer)
|
||||
(princ (nrepl-dict-get resp "root-ex") process-buffer))
|
||||
(when (member "err" resp)
|
||||
;; In case there is an error, then add it to the
|
||||
;; output buffer as well.
|
||||
(princ (nrepl-dict-get resp "err") process-buffer))
|
||||
(nrepl--merge response resp)
|
||||
;; Update the status of the nREPL output session.
|
||||
(setq status (nrepl-dict-get response "status")))
|
||||
(cider-current-connection))
|
||||
(defvar ob-clojure-inf-clojure-filter-out)
|
||||
(defvar ob-clojure-inf-clojure-tmp-output)
|
||||
(defun ob-clojure-inf-clojure-output (s)
|
||||
"Store a trimmed version of S in a variable and return S."
|
||||
(let ((s0 (org-trim
|
||||
(replace-regexp-in-string
|
||||
ob-clojure-inf-clojure-filter-out "" s))))
|
||||
(push s0 ob-clojure-inf-clojure-tmp-output))
|
||||
s)
|
||||
|
||||
;; Wait until the nREPL code finished to be processed.
|
||||
(while (not (member "done" status))
|
||||
(nrepl-dict-put response "status" (remove "need-input" status))
|
||||
(accept-process-output nil 0.01)
|
||||
(redisplay))
|
||||
(defmacro ob-clojure-with-temp-expanded (expanded params &rest body)
|
||||
"Run BODY on EXPANDED code block with PARAMS."
|
||||
(declare (debug (body)) (indent 2))
|
||||
`(with-temp-buffer
|
||||
(insert ,expanded)
|
||||
(goto-char (point-min))
|
||||
(while (not (looking-at "\\s-*\\'"))
|
||||
(let* ((beg (point))
|
||||
(end (progn (forward-sexp) (point)))
|
||||
(exp (org-babel-expand-body:clojure
|
||||
(buffer-substring beg end) ,params)))
|
||||
(sit-for .1)
|
||||
,@body))))
|
||||
|
||||
;; Delete the show buffer & window when the processing is
|
||||
;; finalized.
|
||||
(mapc #'delete-window
|
||||
(get-buffer-window-list process-buffer nil t))
|
||||
(kill-buffer process-buffer)
|
||||
(defsubst ob-clojure-string-or-list (l)
|
||||
"Convert list L into a string or a list of list."
|
||||
(if (and (listp l) (= (length l) 1))
|
||||
(car l)
|
||||
(mapcar #'list l)))
|
||||
|
||||
;; Put the output or the value in the result section of
|
||||
;; the code block.
|
||||
(setq result
|
||||
(concat
|
||||
(nrepl-dict-get response
|
||||
(if (or (member "output" result-params)
|
||||
(member "pp" result-params))
|
||||
"out"
|
||||
"value"))
|
||||
(defvar inf-clojure-buffer)
|
||||
(defvar comint-prompt-regexp)
|
||||
(defvar inf-clojure-comint-prompt-regexp)
|
||||
(defun ob-clojure-eval-with-inf-clojure (expanded params)
|
||||
"Evaluate EXPANDED code block with PARAMS using inf-clojure."
|
||||
(condition-case nil (require 'inf-clojure)
|
||||
(user-error "inf-clojure not available"))
|
||||
;; Maybe initiate the inf-clojure session
|
||||
(unless (and inf-clojure-buffer
|
||||
(buffer-live-p (get-buffer inf-clojure-buffer)))
|
||||
(save-window-excursion
|
||||
(let* ((alias (cdr (assq :alias params)))
|
||||
(cmd0 (inf-clojure-cmd (inf-clojure-project-type)))
|
||||
(cmd (if alias (replace-regexp-in-string
|
||||
"clojure" (format "clojure -A%s" alias)
|
||||
cmd0)
|
||||
cmd0)))
|
||||
(setq comint-prompt-regexp inf-clojure-comint-prompt-regexp)
|
||||
(funcall-interactively #'inf-clojure cmd)
|
||||
(goto-char (point-max))))
|
||||
(sit-for 1))
|
||||
;; Now evaluate the code
|
||||
(setq ob-clojure-inf-clojure-filter-out
|
||||
(concat "^nil\\|nil$\\|\\s-*"
|
||||
(or (cdr (assq :ns params))
|
||||
org-babel-clojure-default-ns)
|
||||
"=>\\s-*"))
|
||||
(add-hook 'comint-preoutput-filter-functions
|
||||
#'ob-clojure-inf-clojure-output)
|
||||
(setq ob-clojure-inf-clojure-tmp-output nil)
|
||||
(ob-clojure-with-temp-expanded expanded nil
|
||||
(inf-clojure-eval-string exp))
|
||||
(sit-for .5)
|
||||
(remove-hook 'comint-preoutput-filter-functions
|
||||
#'ob-clojure-inf-clojure-output)
|
||||
;; And return the result
|
||||
(ob-clojure-string-or-list
|
||||
(delete nil
|
||||
(mapcar
|
||||
(lambda (s)
|
||||
(unless (or (equal "" s)
|
||||
(string-match-p "^Clojure" s))
|
||||
s))
|
||||
(reverse ob-clojure-inf-clojure-tmp-output)))))
|
||||
|
||||
(defun ob-clojure-eval-with-cider (expanded params)
|
||||
"Evaluate EXPANDED code block with PARAMS using cider."
|
||||
(condition-case nil (require 'cider)
|
||||
(user-error "cider not available"))
|
||||
(let ((connection (cider-current-connection (cdr (assq :target params))))
|
||||
(result-params (cdr (assq :result-params params)))
|
||||
result0)
|
||||
(unless connection (sesman-start-session 'CIDER))
|
||||
(if (not connection)
|
||||
;; Display in the result instead of using `user-error'
|
||||
(setq result0 "Please reevaluate when nREPL is connected")
|
||||
(ob-clojure-with-temp-expanded expanded params
|
||||
(let ((response (nrepl-sync-request:eval exp connection)))
|
||||
(push (or (nrepl-dict-get response "root-ex")
|
||||
(nrepl-dict-get response "ex")
|
||||
(nrepl-dict-get response "root-ex")
|
||||
(nrepl-dict-get response "err")))))))
|
||||
(slime
|
||||
(require 'slime)
|
||||
(with-temp-buffer
|
||||
(insert expanded)
|
||||
(setq result
|
||||
(slime-eval
|
||||
`(swank:eval-and-grab-output
|
||||
,(buffer-substring-no-properties (point-min) (point-max)))
|
||||
(cdr (assq :package params)))))))
|
||||
(org-babel-result-cond (cdr (assq :result-params params))
|
||||
(nrepl-dict-get
|
||||
response (if (or (member "output" result-params)
|
||||
(member "pp" result-params))
|
||||
"out"
|
||||
"value")))
|
||||
result0)))
|
||||
(ob-clojure-string-or-list
|
||||
(reverse (delete "" (mapcar (lambda (r)
|
||||
(replace-regexp-in-string "nil" "" r))
|
||||
result0)))))))
|
||||
|
||||
(defun ob-clojure-eval-with-slime (expanded params)
|
||||
"Evaluate EXPANDED code block with PARAMS using slime."
|
||||
(condition-case nil (require 'slime)
|
||||
(user-error "slime not available"))
|
||||
(with-temp-buffer
|
||||
(insert expanded)
|
||||
(slime-eval
|
||||
`(swank:eval-and-grab-output
|
||||
,(buffer-substring-no-properties (point-min) (point-max)))
|
||||
(cdr (assq :package params)))))
|
||||
|
||||
(defun org-babel-execute:clojure (body params)
|
||||
"Execute a block of Clojure code with Babel."
|
||||
(unless org-babel-clojure-backend
|
||||
(user-error "You need to customize org-babel-clojure-backend"))
|
||||
(let* ((expanded (org-babel-expand-body:clojure body params))
|
||||
(result-params (cdr (assq :result-params params)))
|
||||
result)
|
||||
(setq result
|
||||
(cond
|
||||
((eq org-babel-clojure-backend 'inf-clojure)
|
||||
(ob-clojure-eval-with-inf-clojure expanded params))
|
||||
((eq org-babel-clojure-backend 'cider)
|
||||
(ob-clojure-eval-with-cider expanded params))
|
||||
((eq org-babel-clojure-backend 'slime)
|
||||
(ob-clojure-eval-with-slime expanded params))))
|
||||
(org-babel-result-cond result-params
|
||||
result
|
||||
(condition-case nil (org-babel-script-escape result)
|
||||
(error result)))))
|
||||
|
||||
(defun org-babel-clojure-initiate-session (&optional session _params)
|
||||
"Initiate a session named SESSION according to PARAMS."
|
||||
(when (and session (not (string= session "none")))
|
||||
(save-window-excursion
|
||||
(cond
|
||||
((org-babel-comint-buffer-livep session) nil)
|
||||
;; CIDER jack-in to the Clojure project directory.
|
||||
((eq org-babel-clojure-backend 'cider)
|
||||
(require 'cider)
|
||||
(let ((session-buffer
|
||||
(save-window-excursion
|
||||
(if (version< cider-version "0.18.0")
|
||||
;; Older CIDER (without sesman) still need to use
|
||||
;; old way.
|
||||
(cider-jack-in nil) ;jack-in without project
|
||||
;; New CIDER (with sesman to manage sessions).
|
||||
(unless (cider-repls)
|
||||
(let ((sesman-system 'CIDER))
|
||||
(call-interactively 'sesman-link-with-directory))))
|
||||
(current-buffer))))
|
||||
(when (org-babel-comint-buffer-livep session-buffer)
|
||||
(sit-for .25)
|
||||
session-buffer)))
|
||||
((eq org-babel-clojure-backend 'slime)
|
||||
(error "Session evaluation with SLIME is not supported"))
|
||||
(t
|
||||
(error "Session initiate failed")))
|
||||
(get-buffer session))))
|
||||
|
||||
(defun org-babel-prep-session:clojure (session params)
|
||||
"Prepare SESSION according to the header arguments specified in PARAMS."
|
||||
(let ((session (org-babel-clojure-initiate-session session))
|
||||
(var-lines (org-babel-variable-assignments:clojure params)))
|
||||
(when session
|
||||
(org-babel-comint-in-buffer session
|
||||
(dolist (var var-lines)
|
||||
(insert var)
|
||||
(comint-send-input nil t)
|
||||
(org-babel-comint-wait-for-output session)
|
||||
(sit-for .1)
|
||||
(goto-char (point-max)))))
|
||||
session))
|
||||
|
||||
(defun org-babel-clojure-var-to-clojure (var)
|
||||
"Convert src block's VAR to Clojure variable."
|
||||
(cond
|
||||
((listp var)
|
||||
(replace-regexp-in-string "(" "'(" var))
|
||||
((stringp var)
|
||||
;; Wrap Babel passed-in header argument value with quotes in Clojure.
|
||||
(format "\"%s\"" var))
|
||||
(t
|
||||
(format "%S" var))))
|
||||
|
||||
(defun org-babel-variable-assignments:clojure (params)
|
||||
"Return a list of Clojure statements assigning the block's variables in PARAMS."
|
||||
(mapcar
|
||||
(lambda (pair)
|
||||
(format "(def %s %s)"
|
||||
(car pair)
|
||||
(org-babel-clojure-var-to-clojure (cdr pair))))
|
||||
(org-babel--get-vars params)))
|
||||
(defun org-babel-execute:clojurescript (body params)
|
||||
"Evaluate BODY with PARAMS as ClojureScript code."
|
||||
(org-babel-execute:clojure body (cons '(:target . "cljs") params)))
|
||||
|
||||
(provide 'ob-clojure)
|
||||
|
||||
|
|
|
@ -151,6 +151,4 @@ FILE exists at end of evaluation."
|
|||
|
||||
(provide 'ob-comint)
|
||||
|
||||
|
||||
|
||||
;;; ob-comint.el ends here
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
;; session evaluation is supported. Requires both coq.el and
|
||||
;; coq-inferior.el, both of which are distributed with Coq.
|
||||
;;
|
||||
;; http://coq.inria.fr/
|
||||
;; https://coq.inria.fr/
|
||||
|
||||
;;; Code:
|
||||
(require 'ob)
|
||||
|
@ -76,3 +76,5 @@ create one. Return the initialized session."
|
|||
(get-buffer org-babel-coq-buffer))
|
||||
|
||||
(provide 'ob-coq)
|
||||
|
||||
;;; ob-coq.el ends here
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
(defvar org-link-file-path-type)
|
||||
(defvar org-src-lang-modes)
|
||||
(defvar org-src-preserve-indentation)
|
||||
(defvar org-babel-tangle-uncomment-comments)
|
||||
|
||||
(declare-function org-at-item-p "org-list" ())
|
||||
(declare-function org-at-table-p "org" (&optional table-type))
|
||||
|
@ -59,6 +60,7 @@
|
|||
(declare-function org-element-type "org-element" (element))
|
||||
(declare-function org-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-indent-line "org" ())
|
||||
(declare-function org-list-get-list-end "org-list" (item struct prevs))
|
||||
|
@ -67,7 +69,6 @@
|
|||
(declare-function org-list-to-generic "org-list" (LIST PARAMS))
|
||||
(declare-function org-list-to-lisp "org-list" (&optional delete))
|
||||
(declare-function org-macro-escape-arguments "org-macro" (&rest args))
|
||||
(declare-function org-make-options-regexp "org" (kwds &optional extra))
|
||||
(declare-function org-mark-ring-push "org" (&optional pos buffer))
|
||||
(declare-function org-narrow-to-subtree "org" ())
|
||||
(declare-function org-next-block "org" (arg &optional backward block-regexp))
|
||||
|
@ -78,6 +79,7 @@
|
|||
(declare-function org-src-coderef-regexp "org-src" (fmt &optional label))
|
||||
(declare-function org-src-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))
|
||||
|
@ -164,7 +166,6 @@ This string must include a \"%s\" which will be replaced by the results."
|
|||
"Non-nil means show the time the code block was evaluated in the result hash."
|
||||
:group 'org-babel
|
||||
:type 'boolean
|
||||
:version "26.1"
|
||||
:package-version '(Org . "9.0")
|
||||
:safe #'booleanp)
|
||||
|
||||
|
@ -238,7 +239,8 @@ should be asked whether to allow evaluation."
|
|||
(if (functionp org-confirm-babel-evaluate)
|
||||
(funcall org-confirm-babel-evaluate
|
||||
;; Language, code block body.
|
||||
(nth 0 info) (nth 1 info))
|
||||
(nth 0 info)
|
||||
(org-babel--expand-body info))
|
||||
org-confirm-babel-evaluate))))
|
||||
(cond
|
||||
(noeval nil)
|
||||
|
@ -400,6 +402,7 @@ then run `org-babel-switch-to-session'."
|
|||
(file . :any)
|
||||
(file-desc . :any)
|
||||
(file-ext . :any)
|
||||
(file-mode . ((#o755 #o555 #o444 :any)))
|
||||
(hlines . ((no yes)))
|
||||
(mkdirp . ((yes no)))
|
||||
(no-expand)
|
||||
|
@ -487,11 +490,21 @@ For the format of SAFE-LIST, see `org-babel-safe-header-args'."
|
|||
"Regexp matching a NAME keyword.")
|
||||
|
||||
(defconst org-babel-result-regexp
|
||||
(format "^[ \t]*#\\+%s\\(?:\\[\\(?:%s \\)?\\([[:alnum:]]+\\)\\]\\)?:[ \t]*"
|
||||
org-babel-results-keyword
|
||||
;; <%Y-%m-%d %H:%M:%S>
|
||||
"<\\(?:[0-9]\\{4\\}-[0-1][0-9]-[0-3][0-9] \
|
||||
[0-2][0-9]\\(?::[0-5][0-9]\\)\\{2\\}\\)>")
|
||||
(rx (seq bol
|
||||
(zero-or-more (any "\t "))
|
||||
"#+results"
|
||||
(opt "["
|
||||
;; Time stamp part.
|
||||
(opt "("
|
||||
(= 4 digit) (= 2 "-" (= 2 digit))
|
||||
" "
|
||||
(= 2 digit) (= 2 ":" (= 2 digit))
|
||||
") ")
|
||||
;; SHA1 hash.
|
||||
(group (one-or-more hex-digit))
|
||||
"]")
|
||||
":"
|
||||
(zero-or-more (any "\t "))))
|
||||
"Regular expression used to match result lines.
|
||||
If the results are associated with a hash key then the hash will
|
||||
be saved in match group 1.")
|
||||
|
@ -622,6 +635,17 @@ a list with the following pattern:
|
|||
(setf (nth 2 info) (org-babel-generate-file-param name (nth 2 info)))
|
||||
info))))
|
||||
|
||||
(defun org-babel--expand-body (info)
|
||||
"Expand noweb references in body and remove any coderefs."
|
||||
(let ((coderef (nth 6 info))
|
||||
(expand
|
||||
(if (org-babel-noweb-p (nth 2 info) :eval)
|
||||
(org-babel-expand-noweb-references info)
|
||||
(nth 1 info))))
|
||||
(if (not coderef) expand
|
||||
(replace-regexp-in-string
|
||||
(org-src-coderef-regexp coderef) "" expand nil nil 1))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-babel-execute-src-block (&optional arg info params)
|
||||
"Execute the current source code block.
|
||||
|
@ -667,17 +691,7 @@ block."
|
|||
((org-babel-confirm-evaluate info)
|
||||
(let* ((lang (nth 0 info))
|
||||
(result-params (cdr (assq :result-params params)))
|
||||
;; Expand noweb references in BODY and remove any
|
||||
;; coderef.
|
||||
(body
|
||||
(let ((coderef (nth 6 info))
|
||||
(expand
|
||||
(if (org-babel-noweb-p params :eval)
|
||||
(org-babel-expand-noweb-references info)
|
||||
(nth 1 info))))
|
||||
(if (not coderef) expand
|
||||
(replace-regexp-in-string
|
||||
(org-src-coderef-regexp coderef) "" expand nil nil 1))))
|
||||
(body (org-babel--expand-body info))
|
||||
(dir (cdr (assq :dir params)))
|
||||
(mkdirp (cdr (assq :mkdirp params)))
|
||||
(default-directory
|
||||
|
@ -721,7 +735,11 @@ block."
|
|||
(with-temp-file file
|
||||
(insert (org-babel-format-result
|
||||
result
|
||||
(cdr (assq :sep params))))))
|
||||
(cdr (assq :sep params)))))
|
||||
;; Set file permissions if header argument
|
||||
;; `:file-mode' is provided.
|
||||
(when (assq :file-mode params)
|
||||
(set-file-modes file (cdr (assq :file-mode params)))))
|
||||
(setq result file))
|
||||
;; Possibly perform post process provided its
|
||||
;; appropriate. Dynamically bind "*this*" to the
|
||||
|
@ -1301,10 +1319,9 @@ CONTEXT specifies the context of evaluation. It can be `:eval',
|
|||
"Return the current in-buffer hash."
|
||||
(let ((result (org-babel-where-is-src-block-result nil info)))
|
||||
(when result
|
||||
(org-with-wide-buffer
|
||||
(goto-char result)
|
||||
(looking-at org-babel-result-regexp)
|
||||
(match-string-no-properties 1)))))
|
||||
(org-with-point-at result
|
||||
(let ((case-fold-search t)) (looking-at org-babel-result-regexp))
|
||||
(match-string-no-properties 1)))))
|
||||
|
||||
(defun org-babel-hide-hash ()
|
||||
"Hide the hash in the current results line.
|
||||
|
@ -1312,7 +1329,8 @@ Only the initial `org-babel-hash-show' characters of the hash
|
|||
will remain visible."
|
||||
(add-to-invisibility-spec '(org-babel-hide-hash . t))
|
||||
(save-excursion
|
||||
(when (and (re-search-forward org-babel-result-regexp nil t)
|
||||
(when (and (let ((case-fold-search t))
|
||||
(re-search-forward org-babel-result-regexp nil t))
|
||||
(match-string 1))
|
||||
(let* ((start (match-beginning 1))
|
||||
(hide-start (+ org-babel-hash-show start))
|
||||
|
@ -1330,11 +1348,12 @@ Only the initial `org-babel-hash-show' characters of each hash
|
|||
will remain visible. This function should be called as part of
|
||||
the `org-mode-hook'."
|
||||
(save-excursion
|
||||
(while (and (not org-babel-hash-show-time)
|
||||
(re-search-forward org-babel-result-regexp nil t))
|
||||
(goto-char (match-beginning 0))
|
||||
(org-babel-hide-hash)
|
||||
(goto-char (match-end 0)))))
|
||||
(let ((case-fold-search t))
|
||||
(while (and (not org-babel-hash-show-time)
|
||||
(re-search-forward org-babel-result-regexp nil t))
|
||||
(goto-char (match-beginning 0))
|
||||
(org-babel-hide-hash)
|
||||
(goto-char (match-end 0))))))
|
||||
(add-hook 'org-mode-hook 'org-babel-hide-all-hashes)
|
||||
|
||||
(defun org-babel-hash-at-point (&optional point)
|
||||
|
@ -1363,9 +1382,10 @@ portions of results lines."
|
|||
(interactive)
|
||||
(org-babel-show-result-all)
|
||||
(save-excursion
|
||||
(while (re-search-forward org-babel-result-regexp nil t)
|
||||
(save-excursion (goto-char (match-beginning 0))
|
||||
(org-babel-hide-result-toggle-maybe)))))
|
||||
(let ((case-fold-search t))
|
||||
(while (re-search-forward org-babel-result-regexp nil t)
|
||||
(save-excursion (goto-char (match-beginning 0))
|
||||
(org-babel-hide-result-toggle-maybe))))))
|
||||
|
||||
(defun org-babel-show-result-all ()
|
||||
"Unfold all results in the current buffer."
|
||||
|
@ -1377,52 +1397,50 @@ portions of results lines."
|
|||
"Toggle visibility of result at point."
|
||||
(interactive)
|
||||
(let ((case-fold-search t))
|
||||
(if (save-excursion
|
||||
(beginning-of-line 1)
|
||||
(looking-at org-babel-result-regexp))
|
||||
(progn (org-babel-hide-result-toggle)
|
||||
t) ;; to signal that we took action
|
||||
nil))) ;; to signal that we did not
|
||||
(and (org-match-line org-babel-result-regexp)
|
||||
(progn (org-babel-hide-result-toggle) t))))
|
||||
|
||||
(defun org-babel-hide-result-toggle (&optional force)
|
||||
"Toggle the visibility of the current result."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(if (re-search-forward org-babel-result-regexp nil t)
|
||||
(let ((start (progn (beginning-of-line 2) (- (point) 1)))
|
||||
(end (progn
|
||||
(while (looking-at org-babel-multi-line-header-regexp)
|
||||
(forward-line 1))
|
||||
(goto-char (- (org-babel-result-end) 1)) (point)))
|
||||
ov)
|
||||
(if (memq t (mapcar (lambda (overlay)
|
||||
(eq (overlay-get overlay 'invisible)
|
||||
'org-babel-hide-result))
|
||||
(overlays-at start)))
|
||||
(when (or (not force) (eq force 'off))
|
||||
(mapc (lambda (ov)
|
||||
(when (member ov org-babel-hide-result-overlays)
|
||||
(setq org-babel-hide-result-overlays
|
||||
(delq ov org-babel-hide-result-overlays)))
|
||||
(when (eq (overlay-get ov 'invisible)
|
||||
'org-babel-hide-result)
|
||||
(delete-overlay ov)))
|
||||
(overlays-at start)))
|
||||
(setq ov (make-overlay start end))
|
||||
(overlay-put ov 'invisible 'org-babel-hide-result)
|
||||
;; make the block accessible to isearch
|
||||
(overlay-put
|
||||
ov 'isearch-open-invisible
|
||||
(lambda (ov)
|
||||
(when (member ov org-babel-hide-result-overlays)
|
||||
(setq org-babel-hide-result-overlays
|
||||
(delq ov org-babel-hide-result-overlays)))
|
||||
(when (eq (overlay-get ov 'invisible)
|
||||
'org-babel-hide-result)
|
||||
(delete-overlay ov))))
|
||||
(push ov org-babel-hide-result-overlays)))
|
||||
(error "Not looking at a result line"))))
|
||||
(let ((case-fold-search t))
|
||||
(unless (re-search-forward org-babel-result-regexp nil t)
|
||||
(error "Not looking at a result line")))
|
||||
(let ((start (progn (beginning-of-line 2) (1- (point))))
|
||||
(end (progn
|
||||
(while (looking-at org-babel-multi-line-header-regexp)
|
||||
(forward-line 1))
|
||||
(goto-char (1- (org-babel-result-end)))
|
||||
(point)))
|
||||
ov)
|
||||
(if (memq t (mapcar (lambda (overlay)
|
||||
(eq (overlay-get overlay 'invisible)
|
||||
'org-babel-hide-result))
|
||||
(overlays-at start)))
|
||||
(when (or (not force) (eq force 'off))
|
||||
(mapc (lambda (ov)
|
||||
(when (member ov org-babel-hide-result-overlays)
|
||||
(setq org-babel-hide-result-overlays
|
||||
(delq ov org-babel-hide-result-overlays)))
|
||||
(when (eq (overlay-get ov 'invisible)
|
||||
'org-babel-hide-result)
|
||||
(delete-overlay ov)))
|
||||
(overlays-at start)))
|
||||
(setq ov (make-overlay start end))
|
||||
(overlay-put ov 'invisible 'org-babel-hide-result)
|
||||
;; make the block accessible to isearch
|
||||
(overlay-put
|
||||
ov 'isearch-open-invisible
|
||||
(lambda (ov)
|
||||
(when (member ov org-babel-hide-result-overlays)
|
||||
(setq org-babel-hide-result-overlays
|
||||
(delq ov org-babel-hide-result-overlays)))
|
||||
(when (eq (overlay-get ov 'invisible)
|
||||
'org-babel-hide-result)
|
||||
(delete-overlay ov))))
|
||||
(push ov org-babel-hide-result-overlays)))))
|
||||
|
||||
;; org-tab-after-check-for-cycling-hook
|
||||
(add-hook 'org-tab-first-hook 'org-babel-hide-result-toggle-maybe)
|
||||
|
@ -1654,7 +1672,8 @@ Note: this function removes any hlines in TABLE."
|
|||
(mapcar (lambda (row)
|
||||
(if (listp row)
|
||||
(cons (or (pop rownames) "") row)
|
||||
row)) table)
|
||||
row))
|
||||
table)
|
||||
table))
|
||||
|
||||
(defun org-babel-pick-name (names selector)
|
||||
|
@ -1879,9 +1898,9 @@ region is not active then the point is demarcated."
|
|||
(block (and start (match-string 0)))
|
||||
(headers (and start (match-string 4)))
|
||||
(stars (concat (make-string (or (org-current-level) 1) ?*) " "))
|
||||
(lower-case-p (and block
|
||||
(upper-case-p (and block
|
||||
(let (case-fold-search)
|
||||
(string-match-p "#\\+begin_src" block)))))
|
||||
(string-match-p "#\\+BEGIN_SRC" block)))))
|
||||
(if info
|
||||
(mapc
|
||||
(lambda (place)
|
||||
|
@ -1895,9 +1914,9 @@ region is not active then the point is demarcated."
|
|||
(delete-region (point-at-bol) (point-at-eol)))
|
||||
(insert (concat
|
||||
(if (looking-at "^") "" "\n")
|
||||
indent (funcall (if lower-case-p 'downcase 'upcase) "#+end_src\n")
|
||||
indent (if upper-case-p "#+END_SRC\n" "#+end_src\n")
|
||||
(if arg stars indent) "\n"
|
||||
indent (funcall (if lower-case-p 'downcase 'upcase) "#+begin_src ")
|
||||
indent (if upper-case-p "#+BEGIN_SRC " "#+begin_src ")
|
||||
lang
|
||||
(if (> (length headers) 1)
|
||||
(concat " " headers) headers)
|
||||
|
@ -1918,14 +1937,16 @@ region is not active then the point is demarcated."
|
|||
(if (org-region-active-p) (mark) (point)) (point))))
|
||||
(insert (concat (if (looking-at "^") "" "\n")
|
||||
(if arg (concat stars "\n") "")
|
||||
(funcall (if lower-case-p 'downcase 'upcase) "#+begin_src ")
|
||||
lang "\n"
|
||||
body
|
||||
(if upper-case-p "#+BEGIN_SRC " "#+begin_src ")
|
||||
lang "\n" body
|
||||
(if (or (= (length body) 0)
|
||||
(string-suffix-p "\r" body)
|
||||
(string-suffix-p "\n" body)) "" "\n")
|
||||
(funcall (if lower-case-p 'downcase 'upcase) "#+end_src\n")))
|
||||
(goto-char start) (move-end-of-line 1)))))
|
||||
(string-suffix-p "\n" body))
|
||||
""
|
||||
"\n")
|
||||
(if upper-case-p "#+END_SRC\n" "#+end_src\n")))
|
||||
(goto-char start)
|
||||
(move-end-of-line 1)))))
|
||||
|
||||
(defun org-babel--insert-results-keyword (name hash)
|
||||
"Insert RESULTS keyword with NAME value at point.
|
||||
|
@ -1938,7 +1959,7 @@ the results hash, or nil. Leave point before the keyword."
|
|||
(cond ((not hash) nil)
|
||||
(org-babel-hash-show-time
|
||||
(format "[%s %s]"
|
||||
(format-time-string "<%F %T>")
|
||||
(format-time-string "(%F %T)")
|
||||
hash))
|
||||
(t (format "[%s]" hash)))
|
||||
":"
|
||||
|
@ -1964,7 +1985,7 @@ point, along with related contents. Do nothing if HASH is nil.
|
|||
Return a non-nil value if results were cleared. In this case,
|
||||
leave point where new results should be inserted."
|
||||
(when hash
|
||||
(looking-at org-babel-result-regexp)
|
||||
(let ((case-fold-search t)) (looking-at org-babel-result-regexp))
|
||||
(unless (string= (match-string 1) hash)
|
||||
(let* ((e (org-element-at-point))
|
||||
(post (copy-marker (org-element-property :post-affiliated e))))
|
||||
|
@ -2371,13 +2392,58 @@ INFO may provide the values of these header arguments (in the
|
|||
(org-babel-chomp result "\n"))))
|
||||
(t (goto-char beg) (insert result)))
|
||||
(setq end (copy-marker (point) t))
|
||||
;; possibly wrap result
|
||||
;; Possibly wrap result.
|
||||
(cond
|
||||
((assq :wrap (nth 2 info))
|
||||
(let ((name (or (cdr (assq :wrap (nth 2 info))) "results")))
|
||||
(funcall wrap (concat "#+begin_" name)
|
||||
(concat "#+end_" (car (split-string name)))
|
||||
nil nil (concat "{{{results(@@" name ":") "@@)}}}")))
|
||||
(let* ((full (or (cdr (assq :wrap (nth 2 info))) "results"))
|
||||
(split (split-string full))
|
||||
(type (car split))
|
||||
(opening-line (concat "#+begin_" full))
|
||||
(closing-line (concat "#+end_" type)))
|
||||
(cond
|
||||
;; Escape contents from "export" wrap. Wrap
|
||||
;; inline results within an export snippet with
|
||||
;; appropriate value.
|
||||
((eq t (compare-strings type nil nil "export" nil nil t))
|
||||
(let ((backend (pcase split
|
||||
(`(,_) "none")
|
||||
(`(,_ ,b . ,_) b))))
|
||||
(funcall wrap
|
||||
opening-line closing-line
|
||||
nil nil
|
||||
(format "{{{results(@@%s:"
|
||||
backend) "@@)}}}")))
|
||||
;; Escape contents from "example" wrap. Mark
|
||||
;; inline results as verbatim.
|
||||
((eq t (compare-strings type nil nil "example" nil nil t))
|
||||
(funcall wrap
|
||||
opening-line closing-line
|
||||
nil nil
|
||||
"{{{results(=" "=)}}}"))
|
||||
;; Escape contents from "src" wrap. Mark
|
||||
;; inline results as inline source code.
|
||||
((eq t (compare-strings type nil nil "src" nil nil t))
|
||||
(let ((inline-open
|
||||
(pcase split
|
||||
(`(,_)
|
||||
"{{{results(src_none{")
|
||||
(`(,_ ,language)
|
||||
(format "{{{results(src_%s{" language))
|
||||
(`(,_ ,language . ,rest)
|
||||
(let ((r (mapconcat #'identity rest " ")))
|
||||
(format "{{{results(src_%s[%s]{"
|
||||
language r))))))
|
||||
(funcall wrap
|
||||
opening-line closing-line
|
||||
nil nil
|
||||
inline-open "})}}}")))
|
||||
;; Do not escape contents in non-verbatim
|
||||
;; blocks. Return plain inline results.
|
||||
(t
|
||||
(funcall wrap
|
||||
opening-line closing-line
|
||||
t nil
|
||||
"{{{results(" ")}}}")))))
|
||||
((member "html" result-params)
|
||||
(funcall wrap "#+begin_export html" "#+end_export" nil nil
|
||||
"{{{results(@@html:" "@@)}}}"))
|
||||
|
@ -2433,11 +2499,12 @@ INFO may provide the values of these header arguments (in the
|
|||
(defun org-babel-remove-result (&optional info keep-keyword)
|
||||
"Remove the result of the current source block."
|
||||
(interactive)
|
||||
(let ((location (org-babel-where-is-src-block-result nil info)))
|
||||
(let ((location (org-babel-where-is-src-block-result nil info))
|
||||
(case-fold-search t))
|
||||
(when location
|
||||
(save-excursion
|
||||
(goto-char location)
|
||||
(when (looking-at (concat org-babel-result-regexp ".*$"))
|
||||
(when (looking-at org-babel-result-regexp)
|
||||
(delete-region
|
||||
(if keep-keyword (line-beginning-position 2)
|
||||
(save-excursion
|
||||
|
@ -2488,7 +2555,7 @@ in the buffer."
|
|||
(if (memq (org-element-type element)
|
||||
;; Possible results types.
|
||||
'(drawer example-block export-block fixed-width item
|
||||
plain-list src-block table))
|
||||
plain-list special-block src-block table))
|
||||
(save-excursion
|
||||
(goto-char (min (point-max) ;for narrowed buffers
|
||||
(org-element-property :end element)))
|
||||
|
@ -2502,16 +2569,19 @@ If the `default-directory' is different from the containing
|
|||
file's directory then expand relative links."
|
||||
(when (stringp result)
|
||||
(let ((same-directory?
|
||||
(and buffer-file-name
|
||||
(and (buffer-file-name (buffer-base-buffer))
|
||||
(not (string= (expand-file-name default-directory)
|
||||
(expand-file-name
|
||||
(file-name-directory buffer-file-name)))))))
|
||||
(expand-file-name
|
||||
(file-name-directory
|
||||
(buffer-file-name (buffer-base-buffer)))))))))
|
||||
(format "[[file:%s]%s]"
|
||||
(if (and default-directory buffer-file-name same-directory?)
|
||||
(if (and default-directory
|
||||
(buffer-file-name (buffer-base-buffer)) same-directory?)
|
||||
(if (eq org-link-file-path-type 'adaptive)
|
||||
(file-relative-name
|
||||
(expand-file-name result default-directory)
|
||||
(file-name-directory (buffer-file-name)))
|
||||
(file-name-directory
|
||||
(buffer-file-name (buffer-base-buffer))))
|
||||
(expand-file-name result default-directory))
|
||||
result)
|
||||
(if description (concat "[" description "]") "")))))
|
||||
|
@ -2707,117 +2777,110 @@ would set the value of argument \"a\" equal to \"9\". Note that
|
|||
these arguments are not evaluated in the current source-code
|
||||
block but are passed literally to the \"example-block\"."
|
||||
(let* ((parent-buffer (or parent-buffer (current-buffer)))
|
||||
(info (or info (org-babel-get-src-block-info 'light)))
|
||||
(info (or info (org-babel-get-src-block-info 'light)))
|
||||
(lang (nth 0 info))
|
||||
(body (nth 1 info))
|
||||
(ob-nww-start org-babel-noweb-wrap-start)
|
||||
(ob-nww-end org-babel-noweb-wrap-end)
|
||||
(new-body "")
|
||||
(nb-add (lambda (text) (setq new-body (concat new-body text))))
|
||||
index source-name evaluate prefix)
|
||||
(with-temp-buffer
|
||||
(setq-local org-babel-noweb-wrap-start ob-nww-start)
|
||||
(setq-local org-babel-noweb-wrap-end ob-nww-end)
|
||||
(insert body) (goto-char (point-min))
|
||||
(setq index (point))
|
||||
(while (and (re-search-forward (org-babel-noweb-wrap) nil t))
|
||||
(save-match-data (setf source-name (match-string 1)))
|
||||
(save-match-data (setq evaluate (string-match "(.*)" source-name)))
|
||||
(save-match-data
|
||||
(setq prefix
|
||||
(buffer-substring (match-beginning 0)
|
||||
(save-excursion
|
||||
(beginning-of-line 1) (point)))))
|
||||
;; add interval to new-body (removing noweb reference)
|
||||
(goto-char (match-beginning 0))
|
||||
(funcall nb-add (buffer-substring index (point)))
|
||||
(goto-char (match-end 0))
|
||||
(setq index (point))
|
||||
(funcall
|
||||
nb-add
|
||||
(with-current-buffer parent-buffer
|
||||
(save-restriction
|
||||
(widen)
|
||||
(mapconcat ;; Interpose PREFIX between every line.
|
||||
#'identity
|
||||
(split-string
|
||||
(if evaluate
|
||||
(let ((raw (org-babel-ref-resolve source-name)))
|
||||
(if (stringp raw) raw (format "%S" raw)))
|
||||
(or
|
||||
;; Retrieve from the Library of Babel.
|
||||
(nth 2 (assoc-string source-name org-babel-library-of-babel))
|
||||
;; Return the contents of headlines literally.
|
||||
(save-excursion
|
||||
(when (org-babel-ref-goto-headline-id source-name)
|
||||
(org-babel-ref-headline-body)))
|
||||
;; Find the expansion of reference in this buffer.
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let* ((name-regexp
|
||||
(org-babel-named-src-block-regexp-for-name
|
||||
source-name))
|
||||
(comment
|
||||
(string= "noweb"
|
||||
(cdr (assq :comments (nth 2 info)))))
|
||||
(c-wrap
|
||||
(lambda (s)
|
||||
;; Comment, according to LANG mode,
|
||||
;; string S. Return new string.
|
||||
(with-temp-buffer
|
||||
(funcall (org-src-get-lang-mode lang))
|
||||
(comment-region (point)
|
||||
(progn (insert s) (point)))
|
||||
(org-trim (buffer-string)))))
|
||||
(expand-body
|
||||
(lambda (i)
|
||||
;; Expand body of code blocked
|
||||
;; represented by block info I.
|
||||
(let ((b (if (org-babel-noweb-p (nth 2 i) :eval)
|
||||
(org-babel-expand-noweb-references i)
|
||||
(nth 1 i))))
|
||||
(if (not comment) b
|
||||
(let ((cs (org-babel-tangle-comment-links i)))
|
||||
(concat (funcall c-wrap (car cs)) "\n"
|
||||
b "\n"
|
||||
(funcall c-wrap (cadr cs)))))))))
|
||||
(if (and (re-search-forward name-regexp nil t)
|
||||
(not (org-in-commented-heading-p)))
|
||||
;; Found a source block named SOURCE-NAME.
|
||||
;; Assume it is unique; do not look after
|
||||
;; `:noweb-ref' header argument.
|
||||
(funcall expand-body
|
||||
(org-babel-get-src-block-info 'light))
|
||||
;; Though luck. We go into the long process
|
||||
;; of checking each source block and expand
|
||||
;; those with a matching Noweb reference.
|
||||
(let ((expansion nil))
|
||||
(org-babel-map-src-blocks nil
|
||||
(unless (org-in-commented-heading-p)
|
||||
(let* ((info
|
||||
(org-babel-get-src-block-info 'light))
|
||||
(parameters (nth 2 info)))
|
||||
(when (equal source-name
|
||||
(cdr (assq :noweb-ref parameters)))
|
||||
(push (funcall expand-body info) expansion)
|
||||
(push (or (cdr (assq :noweb-sep parameters))
|
||||
"\n")
|
||||
expansion)))))
|
||||
(when expansion
|
||||
(mapconcat #'identity
|
||||
(nreverse (cdr expansion))
|
||||
""))))))
|
||||
;; Possibly raise an error if named block doesn't exist.
|
||||
(if (or org-babel-noweb-error-all-langs
|
||||
(member lang org-babel-noweb-error-langs))
|
||||
(error "%s could not be resolved (see \
|
||||
`org-babel-noweb-error-langs')"
|
||||
(org-babel-noweb-wrap source-name))
|
||||
"")))
|
||||
"[\n\r]")
|
||||
(concat "\n" prefix))))))
|
||||
(funcall nb-add (buffer-substring index (point-max))))
|
||||
new-body))
|
||||
(comment (string= "noweb" (cdr (assq :comments (nth 2 info)))))
|
||||
(noweb-re (format "\\(.*?\\)\\(%s\\)"
|
||||
(with-current-buffer parent-buffer
|
||||
(org-babel-noweb-wrap))))
|
||||
(cache nil)
|
||||
(c-wrap
|
||||
(lambda (s)
|
||||
;; Comment string S, according to LANG mode. Return new
|
||||
;; string.
|
||||
(unless org-babel-tangle-uncomment-comments
|
||||
(with-temp-buffer
|
||||
(funcall (org-src-get-lang-mode lang))
|
||||
(comment-region (point)
|
||||
(progn (insert s) (point)))
|
||||
(org-trim (buffer-string))))))
|
||||
(expand-body
|
||||
(lambda (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)
|
||||
(nth 1 i))))
|
||||
(if (not comment) b
|
||||
(let ((cs (org-babel-tangle-comment-links i)))
|
||||
(concat (funcall c-wrap (car cs)) "\n"
|
||||
b "\n"
|
||||
(funcall c-wrap (cadr cs))))))))
|
||||
(expand-references
|
||||
(lambda (ref cache)
|
||||
(pcase (gethash ref cache)
|
||||
(`(,last . ,previous)
|
||||
;; Ignore separator for last block.
|
||||
(let ((strings (list (funcall expand-body last))))
|
||||
(dolist (i previous)
|
||||
(let ((parameters (nth 2 i)))
|
||||
;; Since we're operating in reverse order, first
|
||||
;; push separator, then body.
|
||||
(push (or (cdr (assq :noweb-sep parameters)) "\n")
|
||||
strings)
|
||||
(push (funcall expand-body i) strings)))
|
||||
(mapconcat #'identity strings "")))
|
||||
;; Raise an error about missing reference, or return the
|
||||
;; empty string.
|
||||
((guard (or org-babel-noweb-error-all-langs
|
||||
(member lang org-babel-noweb-error-langs)))
|
||||
(error "Cannot resolve %s (see `org-babel-noweb-error-langs')"
|
||||
(org-babel-noweb-wrap ref)))
|
||||
(_ "")))))
|
||||
(replace-regexp-in-string
|
||||
noweb-re
|
||||
(lambda (m)
|
||||
(with-current-buffer parent-buffer
|
||||
(save-match-data
|
||||
(let* ((prefix (match-string 1 m))
|
||||
(id (match-string 3 m))
|
||||
(evaluate (string-match-p "(.*)" id))
|
||||
(expansion
|
||||
(cond
|
||||
(evaluate
|
||||
;; Evaluation can potentially modify the buffer
|
||||
;; and invalidate the cache: reset it.
|
||||
(setq cache nil)
|
||||
(let ((raw (org-babel-ref-resolve id)))
|
||||
(if (stringp raw) raw (format "%S" raw))))
|
||||
;; Retrieve from the Library of Babel.
|
||||
((nth 2 (assoc-string id org-babel-library-of-babel)))
|
||||
;; Return the contents of headlines literally.
|
||||
((org-babel-ref-goto-headline-id id)
|
||||
(org-babel-ref-headline-body))
|
||||
;; Look for a source block named SOURCE-NAME. If
|
||||
;; found, assume it is unique; do not look after
|
||||
;; `:noweb-ref' header argument.
|
||||
((org-with-point-at 1
|
||||
(let ((r (org-babel-named-src-block-regexp-for-name id)))
|
||||
(and (re-search-forward r nil t)
|
||||
(not (org-in-commented-heading-p))
|
||||
(funcall expand-body
|
||||
(org-babel-get-src-block-info t))))))
|
||||
;; All Noweb references were cached in a previous
|
||||
;; run. Extract the information from the cache.
|
||||
((hash-table-p cache)
|
||||
(funcall expand-references id cache))
|
||||
;; Though luck. We go into the long process of
|
||||
;; checking each source block and expand those
|
||||
;; with a matching Noweb reference. Since we're
|
||||
;; going to visit all source blocks in the
|
||||
;; document, cache information about them as well.
|
||||
(t
|
||||
(setq cache (make-hash-table :test #'equal))
|
||||
(org-with-wide-buffer
|
||||
(org-babel-map-src-blocks nil
|
||||
(if (org-in-commented-heading-p)
|
||||
(org-forward-heading-same-level nil t)
|
||||
(let* ((info (org-babel-get-src-block-info t))
|
||||
(ref (cdr (assq :noweb-ref (nth 2 info)))))
|
||||
(push info (gethash ref cache))))))
|
||||
(funcall expand-references id cache)))))
|
||||
;; Interpose PREFIX between every line.
|
||||
(mapconcat #'identity
|
||||
(split-string expansion "[\n\r]")
|
||||
(concat "\n" prefix))))))
|
||||
body t t 2)))
|
||||
|
||||
(defun org-babel--script-escape-inner (str)
|
||||
(let (in-single in-double backslash out)
|
||||
|
@ -2931,30 +2994,41 @@ situations in which is it not appropriate."
|
|||
(defun org-babel--string-to-number (string)
|
||||
"If STRING represents a number return its value.
|
||||
Otherwise return nil."
|
||||
(and (string-match-p "\\`-?\\([0-9]\\|\\([1-9]\\|[0-9]*\\.\\)[0-9]*\\)\\'" string)
|
||||
(string-to-number string)))
|
||||
(unless (or (string-match-p "\\s-" (org-trim string))
|
||||
(not (string-match-p "^[0-9-e.+ ]+$" string)))
|
||||
(let ((interned-string (ignore-errors (read string))))
|
||||
(when (numberp interned-string)
|
||||
interned-string))))
|
||||
|
||||
(defun org-babel-import-elisp-from-file (file-name &optional separator)
|
||||
"Read the results located at FILE-NAME into an elisp table.
|
||||
If the table is trivial, then return it as a scalar."
|
||||
(save-window-excursion
|
||||
(let ((result
|
||||
(with-temp-buffer
|
||||
(condition-case err
|
||||
(progn
|
||||
(org-table-import file-name separator)
|
||||
(delete-file file-name)
|
||||
(delq nil
|
||||
(mapcar (lambda (row)
|
||||
(and (not (eq row 'hline))
|
||||
(mapcar #'org-babel-string-read row)))
|
||||
(org-table-to-lisp))))
|
||||
(error (message "Error reading results: %s" err) nil)))))
|
||||
(pcase result
|
||||
(`((,scalar)) scalar)
|
||||
(`((,_ ,_ . ,_)) result)
|
||||
(`(,scalar) scalar)
|
||||
(_ result)))))
|
||||
(let ((result
|
||||
(with-temp-buffer
|
||||
(condition-case err
|
||||
(progn
|
||||
(insert-file-contents file-name)
|
||||
(delete-file file-name)
|
||||
(let ((pmax (point-max)))
|
||||
;; If the file was empty, don't bother trying to
|
||||
;; convert the table.
|
||||
(when (> pmax 1)
|
||||
(org-table-convert-region (point-min) pmax separator)
|
||||
(delq nil
|
||||
(mapcar (lambda (row)
|
||||
(and (not (eq row 'hline))
|
||||
(mapcar #'org-babel-string-read row)))
|
||||
(org-table-to-lisp))))))
|
||||
(error
|
||||
(display-warning 'org-babel
|
||||
(format "Error reading results: %S" err)
|
||||
:error)
|
||||
nil)))))
|
||||
(pcase result
|
||||
(`((,scalar)) scalar)
|
||||
(`((,_ ,_ . ,_)) result)
|
||||
(`(,scalar) scalar)
|
||||
(_ result))))
|
||||
|
||||
(defun org-babel-string-read (cell)
|
||||
"Strip nested \"s from around strings."
|
||||
|
@ -3053,9 +3127,8 @@ of `org-babel-temporary-directory'."
|
|||
(if (eq t (car (file-attributes file)))
|
||||
(delete-directory file)
|
||||
(delete-file file)))
|
||||
;; We do not want to delete "." and "..".
|
||||
(directory-files org-babel-temporary-directory 'full
|
||||
(rx (or (not ".") "..."))))
|
||||
directory-files-no-dot-files-regexp))
|
||||
(delete-directory org-babel-temporary-directory))
|
||||
(error
|
||||
(message "Failed to remove temporary Org-babel directory %s"
|
||||
|
|
|
@ -43,6 +43,4 @@ CSS does not support sessions."
|
|||
|
||||
(provide 'ob-css)
|
||||
|
||||
|
||||
|
||||
;;; ob-css.el ends here
|
||||
|
|
|
@ -119,6 +119,4 @@ This function is called by `org-babel-execute-src-block'."
|
|||
|
||||
(provide 'ob-ditaa)
|
||||
|
||||
|
||||
|
||||
;;; ob-ditaa.el ends here
|
||||
|
|
|
@ -87,6 +87,4 @@ This function is called by `org-babel-execute-src-block'."
|
|||
|
||||
(provide 'ob-dot)
|
||||
|
||||
|
||||
|
||||
;;; ob-dot.el ends here
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
;; Author: Michael Gauland
|
||||
;; Keywords: literate programming, reproducible research
|
||||
;; Homepage: https://orgmode.org
|
||||
;; Version: 1.00
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
|
@ -24,18 +23,18 @@
|
|||
|
||||
;;; Commentary:
|
||||
|
||||
;;; Org-Babel support for using ebnf2ps to generate encapsulated postscript
|
||||
;;; railroad diagrams. It recognizes these arguments:
|
||||
;;;
|
||||
;;; :file is required; it must include the extension '.eps.' All the rules
|
||||
;;; in the block will be drawn in the same file. This is done by
|
||||
;;; inserting a '[<file>' comment at the start of the block (see the
|
||||
;;; documentation for ebnf-eps-buffer for more information).
|
||||
;;;
|
||||
;;; :style specifies a value in ebnf-style-database. This provides the
|
||||
;;; ability to customize the output. The style can also specify the
|
||||
;;; grammar syntax (by setting ebnf-syntax); note that only ebnf,
|
||||
;;; iso-ebnf, and yacc are supported by this file.
|
||||
;; Org-Babel support for using ebnf2ps to generate encapsulated postscript
|
||||
;; railroad diagrams. It recognizes these arguments:
|
||||
;;
|
||||
;; :file is required; it must include the extension '.eps.' All the rules
|
||||
;; in the block will be drawn in the same file. This is done by
|
||||
;; inserting a '[<file>' comment at the start of the block (see the
|
||||
;; documentation for ebnf-eps-buffer for more information).
|
||||
;;
|
||||
;; :style specifies a value in ebnf-style-database. This provides the
|
||||
;; ability to customize the output. The style can also specify the
|
||||
;; grammar syntax (by setting ebnf-syntax); note that only ebnf,
|
||||
;; iso-ebnf, and yacc are supported by this file.
|
||||
|
||||
;;; Requirements:
|
||||
|
||||
|
@ -78,4 +77,5 @@ This function is called by `org-babel-execute-src-block'."
|
|||
result)))
|
||||
|
||||
(provide 'ob-ebnf)
|
||||
|
||||
;;; ob-ebnf.el ends here
|
||||
|
|
|
@ -61,31 +61,30 @@ by `org-edit-src-code'.")
|
|||
|
||||
(defun org-babel-execute:emacs-lisp (body params)
|
||||
"Execute a block of emacs-lisp code with Babel."
|
||||
(save-window-excursion
|
||||
(let* ((lexical (cdr (assq :lexical params)))
|
||||
(result-params (cdr (assq :result-params params)))
|
||||
(body (format (if (member "output" result-params)
|
||||
"(with-output-to-string %s\n)"
|
||||
"(progn %s\n)")
|
||||
(org-babel-expand-body:emacs-lisp body params)))
|
||||
(result (eval (read (if (or (member "code" result-params)
|
||||
(member "pp" result-params))
|
||||
(concat "(pp " body ")")
|
||||
body))
|
||||
(org-babel-emacs-lisp-lexical lexical))))
|
||||
(org-babel-result-cond result-params
|
||||
(let ((print-level nil)
|
||||
(print-length nil))
|
||||
(if (or (member "scalar" result-params)
|
||||
(member "verbatim" result-params))
|
||||
(format "%S" result)
|
||||
(format "%s" result)))
|
||||
(org-babel-reassemble-table
|
||||
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))))))))
|
||||
(let* ((lexical (cdr (assq :lexical params)))
|
||||
(result-params (cdr (assq :result-params params)))
|
||||
(body (format (if (member "output" result-params)
|
||||
"(with-output-to-string %s\n)"
|
||||
"(progn %s\n)")
|
||||
(org-babel-expand-body:emacs-lisp body params)))
|
||||
(result (eval (read (if (or (member "code" result-params)
|
||||
(member "pp" result-params))
|
||||
(concat "(pp " body ")")
|
||||
body))
|
||||
(org-babel-emacs-lisp-lexical lexical))))
|
||||
(org-babel-result-cond result-params
|
||||
(let ((print-level nil)
|
||||
(print-length nil))
|
||||
(if (or (member "scalar" result-params)
|
||||
(member "verbatim" result-params))
|
||||
(format "%S" result)
|
||||
(format "%s" result)))
|
||||
(org-babel-reassemble-table
|
||||
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-emacs-lisp-lexical (lexical)
|
||||
"Interpret :lexical source block argument.
|
||||
|
@ -108,6 +107,4 @@ corresponding :lexical source block argument."
|
|||
|
||||
(provide 'ob-emacs-lisp)
|
||||
|
||||
|
||||
|
||||
;;; ob-emacs-lisp.el ends here
|
||||
|
|
|
@ -144,6 +144,4 @@ This buffer is named by `org-babel-error-buffer-name'."
|
|||
|
||||
(provide 'ob-eval)
|
||||
|
||||
|
||||
|
||||
;;; ob-eval.el ends here
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
(declare-function org-escape-code-in-string "org-src" (s))
|
||||
(declare-function org-export-copy-buffer "ox" ())
|
||||
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
|
||||
(declare-function org-in-archived-heading-p "org" (&optional no-inheritance))
|
||||
|
||||
(defvar org-src-preserve-indentation)
|
||||
|
||||
|
@ -157,7 +158,8 @@ this template."
|
|||
;; encountered.
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward regexp nil t)
|
||||
(unless (save-match-data (org-in-commented-heading-p))
|
||||
(unless (save-match-data (or (org-in-commented-heading-p)
|
||||
(org-in-archived-heading-p)))
|
||||
(let* ((object? (match-end 1))
|
||||
(element (save-match-data
|
||||
(if object? (org-element-context)
|
||||
|
@ -403,9 +405,7 @@ inhibit insertion of results into the buffer."
|
|||
(`lob
|
||||
(save-excursion
|
||||
(goto-char (nth 5 info))
|
||||
(let (org-confirm-babel-evaluate)
|
||||
(org-babel-execute-src-block nil info)))))))))
|
||||
|
||||
(org-babel-execute-src-block nil info))))))))
|
||||
|
||||
(provide 'ob-exp)
|
||||
|
||||
|
|
|
@ -76,7 +76,8 @@ This function is called by `org-babel-execute-src-block'."
|
|||
;; Report errors.
|
||||
(org-babel-eval-error-notify 1
|
||||
(buffer-substring
|
||||
(+ (match-beginning 0) 1) (point-max))) nil))))
|
||||
(+ (match-beginning 0) 1) (point-max)))
|
||||
nil))))
|
||||
(split-string (org-trim
|
||||
(org-babel-expand-body:generic body params))
|
||||
"\n"
|
||||
|
|
|
@ -101,12 +101,13 @@ its header arguments."
|
|||
(concat
|
||||
;; variables
|
||||
(mapconcat 'org-babel-fortran-var-to-fortran vars "\n")
|
||||
body) params)
|
||||
body)
|
||||
params)
|
||||
body) "\n") "\n")))
|
||||
|
||||
(defun org-babel-fortran-ensure-main-wrap (body params)
|
||||
"Wrap body in a \"program ... end program\" block if none exists."
|
||||
(if (string-match "^[ \t]*program[ \t]*.*" (capitalize body))
|
||||
(if (string-match "^[ \t]*program\\>" (capitalize body))
|
||||
(let ((vars (org-babel--get-vars params)))
|
||||
(when vars (error "Cannot use :vars if `program' statement is present"))
|
||||
body)
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
;; - gnuplot :: http://www.gnuplot.info/
|
||||
;;
|
||||
;; - gnuplot-mode :: http://cars9.uchicago.edu/~ravel/software/gnuplot-mode.html
|
||||
;; - gnuplot-mode :: you can search the web for the latest active one.
|
||||
|
||||
;;; Code:
|
||||
(require 'ob)
|
||||
|
@ -278,6 +278,4 @@ Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE."
|
|||
|
||||
(provide 'ob-gnuplot)
|
||||
|
||||
|
||||
|
||||
;;; ob-gnuplot.el ends here
|
||||
|
|
|
@ -65,7 +65,6 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
|
||||
|
||||
(defvar org-babel-groovy-wrapper-method
|
||||
|
||||
"class Runner extends Script {
|
||||
def out = new PrintWriter(new ByteArrayOutputStream())
|
||||
def run() { %s }
|
||||
|
@ -74,7 +73,6 @@ This function is called by `org-babel-execute-src-block'."
|
|||
println(new Runner().run())
|
||||
")
|
||||
|
||||
|
||||
(defun org-babel-groovy-evaluate
|
||||
(session body &optional result-type result-params)
|
||||
"Evaluate BODY in external Groovy process.
|
||||
|
@ -111,6 +109,4 @@ supported in Groovy."
|
|||
|
||||
(provide 'ob-groovy)
|
||||
|
||||
|
||||
|
||||
;;; ob-groovy.el ends here
|
||||
|
|
|
@ -23,20 +23,19 @@
|
|||
|
||||
;;; Commentary:
|
||||
|
||||
;; Org-Babel support for evaluating haskell source code. This one will
|
||||
;; be sort of tricky because haskell programs must be compiled before
|
||||
;; Org Babel support for evaluating Haskell source code.
|
||||
;; Haskell programs must be compiled before
|
||||
;; they can be run, but haskell code can also be run through an
|
||||
;; interactive interpreter.
|
||||
;;
|
||||
;; For now lets only allow evaluation using the haskell interpreter.
|
||||
;; By default we evaluate using the Haskell interpreter.
|
||||
;; To use the compiler, specify :compile yes in the header.
|
||||
|
||||
;;; Requirements:
|
||||
|
||||
;; - haskell-mode :: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
|
||||
;;
|
||||
;; - inf-haskell :: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
|
||||
;;
|
||||
;; - (optionally) lhs2tex :: http://people.cs.uu.nl/andres/lhs2tex/
|
||||
;; - haskell-mode: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
|
||||
;; - inf-haskell: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
|
||||
;; - (optionally) lhs2tex: http://people.cs.uu.nl/andres/lhs2tex/
|
||||
|
||||
;;; Code:
|
||||
(require 'ob)
|
||||
|
@ -47,6 +46,7 @@
|
|||
(declare-function run-haskell "ext:inf-haskell" (&optional arg))
|
||||
(declare-function inferior-haskell-load-file
|
||||
"ext:inf-haskell" (&optional reload))
|
||||
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
|
||||
|
||||
(defvar org-babel-tangle-lang-exts)
|
||||
(add-to-list 'org-babel-tangle-lang-exts '("haskell" . "hs"))
|
||||
|
@ -60,8 +60,63 @@
|
|||
|
||||
(defvar haskell-prompt-regexp)
|
||||
|
||||
(defun org-babel-execute:haskell (body params)
|
||||
"Execute a block of Haskell code."
|
||||
(defcustom org-babel-haskell-compiler "ghc"
|
||||
"Command used to compile a Haskell source code file into an executable.
|
||||
May be either a command in the path, like \"ghc\" or an absolute
|
||||
path name, like \"/usr/local/bin/ghc\". The command can include
|
||||
a parameter, such as \"ghc -v\"."
|
||||
:group 'org-babel
|
||||
:package-version '(Org "9.4")
|
||||
:type 'string)
|
||||
|
||||
(defconst org-babel-header-args:haskell '(compile . :any)
|
||||
"Haskell-specific header arguments.")
|
||||
|
||||
(defun org-babel-haskell-execute (body params)
|
||||
"This function should only be called by `org-babel-execute:haskell'"
|
||||
(let* ((tmp-src-file (org-babel-temp-file "Haskell-src-" ".hs"))
|
||||
(tmp-bin-file
|
||||
(org-babel-process-file-name
|
||||
(org-babel-temp-file "Haskell-bin-" org-babel-exeext)))
|
||||
(cmdline (cdr (assq :cmdline params)))
|
||||
(cmdline (if cmdline (concat " " cmdline) ""))
|
||||
(flags (cdr (assq :flags params)))
|
||||
(flags (mapconcat #'identity
|
||||
(if (listp flags)
|
||||
flags
|
||||
(list flags))
|
||||
" "))
|
||||
(libs (org-babel-read
|
||||
(or (cdr (assq :libs params))
|
||||
(org-entry-get nil "libs" t))
|
||||
nil))
|
||||
(libs (mapconcat #'identity
|
||||
(if (listp libs) libs (list libs))
|
||||
" ")))
|
||||
(with-temp-file tmp-src-file (insert body))
|
||||
(org-babel-eval
|
||||
(format "%s -o %s %s %s %s"
|
||||
org-babel-haskell-compiler
|
||||
tmp-bin-file
|
||||
flags
|
||||
(org-babel-process-file-name tmp-src-file)
|
||||
libs)
|
||||
"")
|
||||
(let ((results (org-babel-eval (concat tmp-bin-file cmdline) "")))
|
||||
(when results
|
||||
(setq results (org-trim (org-remove-indentation results)))
|
||||
(org-babel-reassemble-table
|
||||
(org-babel-result-cond (cdr (assq :result-params params))
|
||||
(org-babel-read results t)
|
||||
(let ((tmp-file (org-babel-temp-file "Haskell-")))
|
||||
(with-temp-file tmp-file (insert results))
|
||||
(org-babel-import-elisp-from-file tmp-file)))
|
||||
(org-babel-pick-name
|
||||
(cdr (assq :colname-names params)) (cdr (assq :colnames params)))
|
||||
(org-babel-pick-name
|
||||
(cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))))
|
||||
|
||||
(defun org-babel-interpret-haskell (body params)
|
||||
(require 'inf-haskell)
|
||||
(add-hook 'inferior-haskell-hook
|
||||
(lambda ()
|
||||
|
@ -87,7 +142,7 @@
|
|||
(org-babel-reassemble-table
|
||||
(let ((result
|
||||
(pcase result-type
|
||||
(`output (mapconcat #'identity (reverse (cdr results)) "\n"))
|
||||
(`output (mapconcat #'identity (reverse results) "\n"))
|
||||
(`value (car results)))))
|
||||
(org-babel-result-cond (cdr (assq :result-params params))
|
||||
result (org-babel-script-escape result)))
|
||||
|
@ -96,6 +151,13 @@
|
|||
(org-babel-pick-name (cdr (assq :rowname-names params))
|
||||
(cdr (assq :rowname-names params))))))
|
||||
|
||||
(defun org-babel-execute:haskell (body params)
|
||||
"Execute a block of Haskell code."
|
||||
(let ((compile (string= "yes" (cdr (assq :compile params)))))
|
||||
(if (not compile)
|
||||
(org-babel-interpret-haskell body params)
|
||||
(org-babel-haskell-execute body params))))
|
||||
|
||||
(defun org-babel-haskell-initiate-session (&optional _session _params)
|
||||
"Initiate a haskell session.
|
||||
If there is not a current inferior-process-buffer in SESSION
|
||||
|
@ -215,6 +277,4 @@ constructs (header arguments, no-web syntax etc...) are ignored."
|
|||
|
||||
(provide 'ob-haskell)
|
||||
|
||||
|
||||
|
||||
;;; ob-haskell.el ends here
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
;; probably ~/.hledger.journal (it may not notice your $LEDGER_FILE env var).
|
||||
;; So make ~/.hledger.journal a symbolic link to the real file if necessary.
|
||||
|
||||
;; TODO Unit tests are more than welcome, too.
|
||||
|
||||
;;; Code:
|
||||
(require 'ob)
|
||||
|
||||
|
@ -64,7 +66,4 @@ This function is called by `org-babel-execute-src-block'."
|
|||
|
||||
(provide 'ob-hledger)
|
||||
|
||||
|
||||
|
||||
;;; ob-hledger.el ends here
|
||||
;; TODO Unit tests are more than welcome, too.
|
||||
|
|
|
@ -90,7 +90,6 @@ in BODY as elisp."
|
|||
raw
|
||||
(org-babel-script-escape raw)))))))
|
||||
|
||||
|
||||
(defun org-babel-prep-session:io (_session _params)
|
||||
"Prepare SESSION according to the header arguments specified in PARAMS."
|
||||
(error "Sessions are not (yet) supported for Io"))
|
||||
|
@ -103,6 +102,4 @@ supported in Io."
|
|||
|
||||
(provide 'ob-io)
|
||||
|
||||
|
||||
|
||||
;;; ob-io.el ends here
|
||||
|
|
|
@ -58,6 +58,7 @@ parameters may be used, like javac -verbose"
|
|||
(src-file (concat classname ".java"))
|
||||
(cmpflag (or (cdr (assq :cmpflag params)) ""))
|
||||
(cmdline (or (cdr (assq :cmdline params)) ""))
|
||||
(cmdargs (or (cdr (assq :cmdargs params)) ""))
|
||||
(full-body (org-babel-expand-body:generic body params)))
|
||||
(with-temp-file src-file (insert full-body))
|
||||
(org-babel-eval
|
||||
|
@ -66,10 +67,10 @@ parameters may be used, like javac -verbose"
|
|||
(unless (or (not packagename) (file-exists-p packagename))
|
||||
(make-directory packagename 'parents))
|
||||
(let ((results (org-babel-eval (concat org-babel-java-command
|
||||
" " cmdline " " classname) "")))
|
||||
" " cmdline " " classname " " cmdargs) "")))
|
||||
(org-babel-reassemble-table
|
||||
(org-babel-result-cond (cdr (assq :result-params params))
|
||||
(org-babel-read results)
|
||||
(org-babel-read results t)
|
||||
(let ((tmp-file (org-babel-temp-file "c-")))
|
||||
(with-temp-file tmp-file (insert results))
|
||||
(org-babel-import-elisp-from-file tmp-file)))
|
||||
|
@ -80,6 +81,4 @@ parameters may be used, like javac -verbose"
|
|||
|
||||
(provide 'ob-java)
|
||||
|
||||
|
||||
|
||||
;;; ob-java.el ends here
|
||||
|
|
|
@ -30,11 +30,11 @@
|
|||
|
||||
;;; Requirements:
|
||||
|
||||
;; - a non-browser javascript engine such as node.js http://nodejs.org/
|
||||
;; or mozrepl http://wiki.github.com/bard/mozrepl/
|
||||
;; - a non-browser javascript engine such as node.js https://nodejs.org/
|
||||
;; or mozrepl https://wiki.github.com/bard/mozrepl/
|
||||
;;
|
||||
;; - for session based evaluation mozrepl and moz.el are required see
|
||||
;; http://wiki.github.com/bard/mozrepl/emacs-integration for
|
||||
;; https://wiki.github.com/bard/mozrepl/emacs-integration for
|
||||
;; configuration instructions
|
||||
|
||||
;;; Code:
|
||||
|
@ -65,7 +65,7 @@
|
|||
:safe #'stringp)
|
||||
|
||||
(defvar org-babel-js-function-wrapper
|
||||
"require('sys').print(require('sys').inspect(function(){\n%s\n}()));"
|
||||
"require('process').stdout.write(require('util').inspect(function(){%s}()));"
|
||||
"Javascript code to print value of body.")
|
||||
|
||||
(defun org-babel-execute:js (body params)
|
||||
|
@ -201,6 +201,4 @@ then create. Return the initialized session."
|
|||
|
||||
(provide 'ob-js)
|
||||
|
||||
|
||||
|
||||
;;; ob-js.el ends here
|
||||
|
|
|
@ -84,7 +84,8 @@
|
|||
(regexp-quote (format "%S" (car pair)))
|
||||
(if (stringp (cdr pair))
|
||||
(cdr pair) (format "%S" (cdr pair)))
|
||||
body))) (org-babel--get-vars params))
|
||||
body)))
|
||||
(org-babel--get-vars params))
|
||||
(org-trim body))
|
||||
|
||||
(defun org-babel-execute:latex (body params)
|
||||
|
@ -108,8 +109,11 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(append (cdr (assq :packages params)) org-latex-packages-alist)))
|
||||
(cond
|
||||
((and (string-suffix-p ".png" out-file) (not imagemagick))
|
||||
(org-create-formula-image
|
||||
body out-file org-format-latex-options in-buffer))
|
||||
(let ((org-format-latex-header
|
||||
(concat org-format-latex-header "\n"
|
||||
(mapconcat #'identity headers "\n"))))
|
||||
(org-create-formula-image
|
||||
body out-file org-format-latex-options in-buffer)))
|
||||
((string-suffix-p ".tikz" out-file)
|
||||
(when (file-exists-p out-file) (delete-file out-file))
|
||||
(with-temp-file out-file
|
||||
|
@ -221,6 +225,6 @@ This function is called by `org-babel-execute-src-block'."
|
|||
"Return an error because LaTeX doesn't support sessions."
|
||||
(error "LaTeX does not support sessions"))
|
||||
|
||||
|
||||
(provide 'ob-latex)
|
||||
|
||||
;;; ob-latex.el ends here
|
||||
|
|
|
@ -65,6 +65,4 @@ called by `org-babel-execute-src-block'."
|
|||
|
||||
(provide 'ob-ledger)
|
||||
|
||||
|
||||
|
||||
;;; ob-ledger.el ends here
|
||||
|
|
|
@ -67,12 +67,15 @@ the midi file is not automatically played. Default value is t")
|
|||
(defvar org-babel-lilypond-ly-command ""
|
||||
"Command to execute lilypond on your system.
|
||||
Do not set it directly. Customize `org-babel-lilypond-commands' instead.")
|
||||
|
||||
(defvar org-babel-lilypond-pdf-command ""
|
||||
"Command to show a PDF file on your system.
|
||||
Do not set it directly. Customize `org-babel-lilypond-commands' instead.")
|
||||
|
||||
(defvar org-babel-lilypond-midi-command ""
|
||||
"Command to play a MIDI file on your system.
|
||||
Do not set it directly. Customize `org-babel-lilypond-commands' instead.")
|
||||
|
||||
(defcustom org-babel-lilypond-commands
|
||||
(cond
|
||||
((eq system-type 'darwin)
|
||||
|
@ -94,7 +97,8 @@ you can leave the string empty on this case."
|
|||
:version "24.4"
|
||||
:package-version '(Org . "8.2.7")
|
||||
:set
|
||||
(lambda (_symbol value)
|
||||
(lambda (symbol value)
|
||||
(set symbol value)
|
||||
(setq
|
||||
org-babel-lilypond-ly-command (nth 0 value)
|
||||
org-babel-lilypond-pdf-command (nth 1 value)
|
||||
|
@ -201,7 +205,7 @@ If error in compilation, attempt to mark the error in lilypond org file."
|
|||
(delete-file org-babel-lilypond-temp-file))
|
||||
(rename-file org-babel-lilypond-tangled-file
|
||||
org-babel-lilypond-temp-file))
|
||||
(switch-to-buffer-other-window "*lilypond*")
|
||||
(org-switch-to-buffer-other-window "*lilypond*")
|
||||
(erase-buffer)
|
||||
(org-babel-lilypond-compile-lilyfile org-babel-lilypond-temp-file)
|
||||
(goto-char (point-min))
|
||||
|
@ -258,7 +262,7 @@ FILE-NAME is full path to lilypond file."
|
|||
"Mark the erroneous lines in the lilypond org buffer.
|
||||
FILE-NAME is full path to lilypond file.
|
||||
LINE is the erroneous line."
|
||||
(switch-to-buffer-other-window
|
||||
(org-switch-to-buffer-other-window
|
||||
(concat (file-name-nondirectory
|
||||
(org-babel-lilypond-switch-extension file-name ".org"))))
|
||||
(let ((temp (point)))
|
||||
|
@ -387,7 +391,8 @@ If TEST is non-nil, the shell command is returned and is not run."
|
|||
(defun org-babel-lilypond-switch-extension (file-name ext)
|
||||
"Utility command to swap current FILE-NAME extension with EXT."
|
||||
(concat (file-name-sans-extension
|
||||
file-name) ext))
|
||||
file-name)
|
||||
ext))
|
||||
|
||||
(defun org-babel-lilypond-get-header-args (mode)
|
||||
"Default arguments to use when evaluating a lilypond source block.
|
||||
|
|
|
@ -122,6 +122,4 @@ a property list containing the parameters of the block."
|
|||
|
||||
(provide 'ob-lisp)
|
||||
|
||||
|
||||
|
||||
;;; ob-lisp.el ends here
|
||||
|
|
|
@ -107,7 +107,8 @@ VARS contains resolved variable references."
|
|||
(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))
|
||||
(org-babel-comint-wait-for-output session))
|
||||
var-lines))
|
||||
session))
|
||||
|
||||
(defun org-babel-load-session:lua (session body params)
|
||||
|
@ -397,6 +398,4 @@ fd:close()"
|
|||
|
||||
(provide 'ob-lua)
|
||||
|
||||
|
||||
|
||||
;;; ob-lua.el ends here
|
||||
|
|
|
@ -43,6 +43,4 @@ does not support sessions."
|
|||
|
||||
(provide 'ob-makefile)
|
||||
|
||||
|
||||
|
||||
;;; ob-makefile.el ends here
|
||||
|
|
|
@ -42,6 +42,4 @@
|
|||
|
||||
(provide 'ob-matlab)
|
||||
|
||||
|
||||
|
||||
;;; ob-matlab.el ends here
|
||||
|
|
|
@ -27,9 +27,7 @@
|
|||
;; Org-Babel support for evaluating maxima entries.
|
||||
;;
|
||||
;; This differs from most standard languages in that
|
||||
;;
|
||||
;; 1) there is no such thing as a "session" in maxima
|
||||
;;
|
||||
;; 2) we are adding the "cmdline" header argument
|
||||
|
||||
;;; Code:
|
||||
|
@ -125,9 +123,6 @@ of the same value."
|
|||
(concat "[" (mapconcat #'org-babel-maxima-elisp-to-maxima val ", ") "]")
|
||||
(format "%s" val)))
|
||||
|
||||
|
||||
(provide 'ob-maxima)
|
||||
|
||||
|
||||
|
||||
;;; ob-maxima.el ends here
|
||||
|
|
|
@ -68,8 +68,7 @@ mscgen supported formats."
|
|||
(let* ((out-file (or (cdr (assq :file params)) "output.png" ))
|
||||
(filetype (or (cdr (assq :filetype params)) "png" )))
|
||||
(unless (cdr (assq :file params))
|
||||
(error "
|
||||
ERROR: no output file specified. Add \":file name.png\" to the src header"))
|
||||
(error "ERROR: no output file specified. Add \":file name.png\" to the src header"))
|
||||
(org-babel-eval (concat "mscgen -T " filetype " -o " out-file) body)
|
||||
nil)) ;; signal that output has already been written to file
|
||||
|
||||
|
@ -79,6 +78,4 @@ ERROR: no output file specified. Add \":file name.png\" to the src header"))
|
|||
|
||||
(provide 'ob-mscgen)
|
||||
|
||||
|
||||
|
||||
;;; ob-msc.el ends here
|
||||
|
|
|
@ -166,6 +166,4 @@ Emacs-lisp table, otherwise return the results as a string."
|
|||
|
||||
(provide 'ob-ocaml)
|
||||
|
||||
|
||||
|
||||
;;; ob-ocaml.el ends here
|
||||
|
|
|
@ -136,7 +136,8 @@ specifying a variable of the same value."
|
|||
(org-babel-comint-in-buffer session
|
||||
(mapc (lambda (var)
|
||||
(end-of-line 1) (insert var) (comint-send-input nil t)
|
||||
(org-babel-comint-wait-for-output session)) var-lines))
|
||||
(org-babel-comint-wait-for-output session))
|
||||
var-lines))
|
||||
session))
|
||||
|
||||
(defun org-babel-matlab-initiate-session (&optional session params)
|
||||
|
@ -230,7 +231,8 @@ value of the last statement in BODY, as elisp."
|
|||
org-babel-octave-eoe-indicator
|
||||
org-babel-octave-eoe-output)
|
||||
t full-body)
|
||||
(insert full-body) (comint-send-input nil t)))) results)
|
||||
(insert full-body) (comint-send-input nil t))))
|
||||
results)
|
||||
(pcase result-type
|
||||
(`value
|
||||
(org-babel-octave-import-elisp-from-file tmp-file))
|
||||
|
@ -259,6 +261,4 @@ This removes initial blank and comment lines and then calls
|
|||
|
||||
(provide 'ob-octave)
|
||||
|
||||
|
||||
|
||||
;;; ob-octave.el ends here
|
||||
|
|
|
@ -67,6 +67,4 @@ This function is called by `org-babel-execute-src-block'."
|
|||
|
||||
(provide 'ob-org)
|
||||
|
||||
|
||||
|
||||
;;; ob-org.el ends here
|
||||
|
|
|
@ -152,6 +152,4 @@ return the value of the last statement in BODY, as elisp."
|
|||
|
||||
(provide 'ob-perl)
|
||||
|
||||
|
||||
|
||||
;;; ob-perl.el ends here
|
||||
|
|
|
@ -111,11 +111,11 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(cond
|
||||
((or (member "code" result-params)
|
||||
(member "pp" result-params))
|
||||
(format "(pretty (out \"/dev/null\" %s))" full-body))
|
||||
(format "(pretty (out \"%s\" %s))" null-device full-body))
|
||||
((and (member "value" result-params) (not session))
|
||||
(format "(print (out \"/dev/null\" %s))" full-body))
|
||||
(format "(print (out \"%s\" %s))" null-device full-body))
|
||||
((member "value" result-params)
|
||||
(format "(out \"/dev/null\" %s)" full-body))
|
||||
(format "(out \"%s\" %s)" null-device full-body))
|
||||
(t full-body)))
|
||||
(result
|
||||
(if (not (string= session-name "none"))
|
||||
|
@ -182,6 +182,4 @@ then create. Return the initialized session."
|
|||
|
||||
(provide 'ob-picolisp)
|
||||
|
||||
|
||||
|
||||
;;; ob-picolisp.el ends here
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
;; Org-Babel support for evaluating plantuml script.
|
||||
;;
|
||||
;; Inspired by Ian Yang's org-export-blocks-format-plantuml
|
||||
;; http://www.emacswiki.org/emacs/org-export-blocks-format-plantuml.el
|
||||
;; https://www.emacswiki.org/emacs/org-export-blocks-format-plantuml.el
|
||||
|
||||
;;; Requirements:
|
||||
|
||||
;; plantuml | http://plantuml.sourceforge.net/
|
||||
;; plantuml.jar | `org-plantuml-jar-path' should point to the jar file
|
||||
;; plantuml.jar | `org-plantuml-jar-path' should point to the jar file (when exec mode is `jar')
|
||||
|
||||
;;; Code:
|
||||
(require 'ob)
|
||||
|
@ -46,6 +46,31 @@
|
|||
:version "24.1"
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-plantuml-exec-mode 'jar
|
||||
"Method to use for PlantUML diagram generation.
|
||||
`jar' means to use java together with the JAR.
|
||||
The JAR can be configured via `org-plantuml-jar-path'.
|
||||
|
||||
`plantuml' means to use the PlantUML executable.
|
||||
The executable can be configured via `org-plantuml-executable-path'.
|
||||
You can also configure extra arguments via `org-plantuml-executable-args'."
|
||||
:group 'org-babel
|
||||
:package-version '(Org . "9.4")
|
||||
:type 'symbol
|
||||
:options '(jar plantuml))
|
||||
|
||||
(defcustom org-plantuml-executable-path "plantuml"
|
||||
"File name of the PlantUML executable."
|
||||
:group 'org-babel
|
||||
:package-version '(Org . "9.4")
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-plantuml-executable-args (list "-headless")
|
||||
"The arguments passed to plantuml executable when executing PlantUML."
|
||||
:group 'org-babel
|
||||
:package-version '(Org . "9.4")
|
||||
:type '(repeat string))
|
||||
|
||||
(defun org-babel-variable-assignments:plantuml (params)
|
||||
"Return a list of PlantUML statements assigning the block's variables.
|
||||
PARAMS is a property list of source block parameters, which may
|
||||
|
@ -69,10 +94,11 @@ function to convert variables to PlantUML assignments.
|
|||
|
||||
If BODY does not contain @startXXX ... @endXXX clauses, @startuml
|
||||
... @enduml will be added."
|
||||
(let ((assignments (org-babel-variable-assignments:plantuml params)))
|
||||
(if (string-prefix-p "@start" body t) assignments
|
||||
(format "@startuml\n%s\n@enduml"
|
||||
(org-babel-expand-body:generic body params assignments)))))
|
||||
(let ((full-body
|
||||
(org-babel-expand-body:generic
|
||||
body params (org-babel-variable-assignments:plantuml params))))
|
||||
(if (string-prefix-p "@start" body t) full-body
|
||||
(format "@startuml\n%s\n@enduml" full-body))))
|
||||
|
||||
(defun org-babel-execute:plantuml (body params)
|
||||
"Execute a block of plantuml code with org-babel.
|
||||
|
@ -82,40 +108,41 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(cmdline (cdr (assq :cmdline params)))
|
||||
(in-file (org-babel-temp-file "plantuml-"))
|
||||
(java (or (cdr (assq :java params)) ""))
|
||||
(executable (cond ((eq org-plantuml-exec-mode 'plantuml) org-plantuml-executable-path)
|
||||
(t "java")))
|
||||
(executable-args (cond ((eq org-plantuml-exec-mode 'plantuml) org-plantuml-executable-args)
|
||||
((string= "" org-plantuml-jar-path)
|
||||
(error "`org-plantuml-jar-path' is not set"))
|
||||
((not (file-exists-p org-plantuml-jar-path))
|
||||
(error "Could not find plantuml.jar at %s" org-plantuml-jar-path))
|
||||
(t (list java
|
||||
"-jar"
|
||||
(shell-quote-argument (expand-file-name org-plantuml-jar-path))))))
|
||||
(full-body (org-babel-plantuml-make-body body params))
|
||||
(cmd (if (string= "" org-plantuml-jar-path)
|
||||
(error "`org-plantuml-jar-path' is not set")
|
||||
(concat "java " java " -jar "
|
||||
(shell-quote-argument
|
||||
(expand-file-name org-plantuml-jar-path))
|
||||
(if (string= (file-name-extension out-file) "png")
|
||||
" -tpng" "")
|
||||
(if (string= (file-name-extension out-file) "svg")
|
||||
" -tsvg" "")
|
||||
(if (string= (file-name-extension out-file) "eps")
|
||||
" -teps" "")
|
||||
(if (string= (file-name-extension out-file) "pdf")
|
||||
" -tpdf" "")
|
||||
(if (string= (file-name-extension out-file) "tex")
|
||||
" -tlatex" "")
|
||||
(if (string= (file-name-extension out-file) "vdx")
|
||||
" -tvdx" "")
|
||||
(if (string= (file-name-extension out-file) "xmi")
|
||||
" -txmi" "")
|
||||
(if (string= (file-name-extension out-file) "scxml")
|
||||
" -tscxml" "")
|
||||
(if (string= (file-name-extension out-file) "html")
|
||||
" -thtml" "")
|
||||
(if (string= (file-name-extension out-file) "txt")
|
||||
" -ttxt" "")
|
||||
(if (string= (file-name-extension out-file) "utxt")
|
||||
" -utxt" "")
|
||||
" -p " cmdline " < "
|
||||
(org-babel-process-file-name in-file)
|
||||
" > "
|
||||
(org-babel-process-file-name out-file)))))
|
||||
(unless (file-exists-p org-plantuml-jar-path)
|
||||
(error "Could not find plantuml.jar at %s" org-plantuml-jar-path))
|
||||
(cmd (mapconcat #'identity
|
||||
(append
|
||||
(list executable)
|
||||
executable-args
|
||||
(pcase (file-name-extension out-file)
|
||||
("png" '("-tpng"))
|
||||
("svg" '("-tsvg"))
|
||||
("eps" '("-teps"))
|
||||
("pdf" '("-tpdf"))
|
||||
("tex" '("-tlatex"))
|
||||
("vdx" '("-tvdx"))
|
||||
("xmi" '("-txmi"))
|
||||
("scxml" '("-tscxml"))
|
||||
("html" '("-thtml"))
|
||||
("txt" '("-ttxt"))
|
||||
("utxt" '("-utxt")))
|
||||
(list
|
||||
"-p"
|
||||
cmdline
|
||||
"<"
|
||||
(org-babel-process-file-name in-file)
|
||||
">"
|
||||
(org-babel-process-file-name out-file)))
|
||||
" ")))
|
||||
(with-temp-file in-file (insert full-body))
|
||||
(message "%s" cmd) (org-babel-eval cmd "")
|
||||
nil)) ;; signal that output has already been written to file
|
||||
|
@ -126,6 +153,4 @@ This function is called by `org-babel-execute-src-block'."
|
|||
|
||||
(provide 'ob-plantuml)
|
||||
|
||||
|
||||
|
||||
;;; ob-plantuml.el ends here
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
;; Authors: Eric Schulte
|
||||
;; Dan Davison
|
||||
;; Maintainer: Jack Kamm <jackkamm@gmail.com>
|
||||
;; Keywords: literate programming, reproducible research
|
||||
;; Homepage: https://orgmode.org
|
||||
|
||||
|
@ -29,10 +30,11 @@
|
|||
;;; Code:
|
||||
(require 'ob)
|
||||
(require 'org-macs)
|
||||
(require 'python)
|
||||
|
||||
(declare-function py-shell "ext:python-mode" (&optional argprompt))
|
||||
(declare-function py-shell "ext:python-mode" (&rest args))
|
||||
(declare-function py-toggle-shells "ext:python-mode" (arg))
|
||||
(declare-function run-python "ext:python" (&optional cmd dedicated show))
|
||||
(declare-function py-shell-send-string "ext:python-mode" (strg &optional process))
|
||||
|
||||
(defvar org-babel-tangle-lang-exts)
|
||||
(add-to-list 'org-babel-tangle-lang-exts '("python" . "py"))
|
||||
|
@ -104,7 +106,8 @@ VARS contains resolved variable references."
|
|||
(org-babel-comint-in-buffer session
|
||||
(mapc (lambda (var)
|
||||
(end-of-line 1) (insert var) (comint-send-input)
|
||||
(org-babel-comint-wait-for-output session)) var-lines))
|
||||
(org-babel-comint-wait-for-output session))
|
||||
var-lines))
|
||||
session))
|
||||
|
||||
(defun org-babel-load-session:python (session body params)
|
||||
|
@ -177,42 +180,40 @@ Emacs-lisp table, otherwise return the results as a string."
|
|||
"Initiate a python session.
|
||||
If there is not a current inferior-process-buffer in SESSION
|
||||
then create. Return the initialized session."
|
||||
(require org-babel-python-mode)
|
||||
(save-window-excursion
|
||||
(let* ((session (if session (intern session) :default))
|
||||
(python-buffer (org-babel-python-session-buffer session))
|
||||
(py-buffer (org-babel-python-session-buffer session))
|
||||
(cmd (if (member system-type '(cygwin windows-nt ms-dos))
|
||||
(concat org-babel-python-command " -i")
|
||||
org-babel-python-command)))
|
||||
(cond
|
||||
((and (eq 'python org-babel-python-mode)
|
||||
(fboundp 'run-python)) ; python.el
|
||||
(if (not (version< "24.1" emacs-version))
|
||||
(run-python cmd)
|
||||
(unless python-buffer
|
||||
(setq python-buffer (org-babel-python-with-earmuffs session)))
|
||||
(let ((python-shell-buffer-name
|
||||
(org-babel-python-without-earmuffs python-buffer)))
|
||||
(run-python cmd))))
|
||||
((eq 'python org-babel-python-mode) ; python.el
|
||||
(unless py-buffer
|
||||
(setq py-buffer (org-babel-python-with-earmuffs session)))
|
||||
(let ((python-shell-buffer-name
|
||||
(org-babel-python-without-earmuffs py-buffer)))
|
||||
(run-python cmd)
|
||||
(sleep-for 0 10)))
|
||||
((and (eq 'python-mode org-babel-python-mode)
|
||||
(fboundp 'py-shell)) ; python-mode.el
|
||||
(require 'python-mode)
|
||||
;; Make sure that py-which-bufname is initialized, as otherwise
|
||||
;; it will be overwritten the first time a Python buffer is
|
||||
;; created.
|
||||
(py-toggle-shells py-default-interpreter)
|
||||
;; `py-shell' creates a buffer whose name is the value of
|
||||
;; `py-which-bufname' with '*'s at the beginning and end
|
||||
(let* ((bufname (if (and python-buffer (buffer-live-p python-buffer))
|
||||
(let* ((bufname (if (and py-buffer (buffer-live-p py-buffer))
|
||||
(replace-regexp-in-string ;; zap surrounding *
|
||||
"^\\*\\([^*]+\\)\\*$" "\\1" python-buffer)
|
||||
"^\\*\\([^*]+\\)\\*$" "\\1" py-buffer)
|
||||
(concat "Python-" (symbol-name session))))
|
||||
(py-which-bufname bufname))
|
||||
(py-shell)
|
||||
(setq python-buffer (org-babel-python-with-earmuffs bufname))))
|
||||
(setq py-buffer (org-babel-python-with-earmuffs bufname))
|
||||
(py-shell nil nil t org-babel-python-command py-buffer nil nil t nil)))
|
||||
(t
|
||||
(error "No function available for running an inferior Python")))
|
||||
(setq org-babel-python-buffers
|
||||
(cons (cons session python-buffer)
|
||||
(cons (cons session py-buffer)
|
||||
(assq-delete-all session org-babel-python-buffers)))
|
||||
session)))
|
||||
|
||||
|
@ -222,8 +223,9 @@ then create. Return the initialized session."
|
|||
(org-babel-python-session-buffer
|
||||
(org-babel-python-initiate-session-by-key session))))
|
||||
|
||||
(defvar org-babel-python-eoe-indicator "'org_babel_python_eoe'"
|
||||
(defvar org-babel-python-eoe-indicator "org_babel_python_eoe"
|
||||
"A string to indicate that evaluation has completed.")
|
||||
|
||||
(defconst org-babel-python-wrapper-method
|
||||
"
|
||||
def main():
|
||||
|
@ -238,14 +240,39 @@ def main():
|
|||
|
||||
open('%s', 'w').write( pprint.pformat(main()) )")
|
||||
|
||||
(defconst org-babel-python--exec-tmpfile
|
||||
(concat
|
||||
"__org_babel_python_fname = '%s'; "
|
||||
"__org_babel_python_fh = open(__org_babel_python_fname); "
|
||||
"exec(compile("
|
||||
"__org_babel_python_fh.read(), __org_babel_python_fname, 'exec'"
|
||||
")); "
|
||||
"__org_babel_python_fh.close()"))
|
||||
(defconst org-babel-python--exec-tmpfile "\
|
||||
with open('%s') as __org_babel_python_tmpfile:
|
||||
exec(compile(__org_babel_python_tmpfile.read(), __org_babel_python_tmpfile.name, 'exec'))"
|
||||
"Template for Python session command with output results.
|
||||
|
||||
Has a single %s escape, the tempfile containing the source code
|
||||
to evaluate.")
|
||||
|
||||
(defun org-babel-python-format-session-value
|
||||
(src-file result-file result-params)
|
||||
"Return Python code to evaluate SRC-FILE and write result to RESULT-FILE."
|
||||
(format "\
|
||||
import ast
|
||||
with open('%s') as __org_babel_python_tmpfile:
|
||||
__org_babel_python_ast = ast.parse(__org_babel_python_tmpfile.read())
|
||||
__org_babel_python_final = __org_babel_python_ast.body[-1]
|
||||
if isinstance(__org_babel_python_final, ast.Expr):
|
||||
__org_babel_python_ast.body = __org_babel_python_ast.body[:-1]
|
||||
exec(compile(__org_babel_python_ast, '<string>', 'exec'))
|
||||
__org_babel_python_final = eval(compile(ast.Expression(
|
||||
__org_babel_python_final.value), '<string>', 'eval'))
|
||||
with open('%s', 'w') as __org_babel_python_tmpfile:
|
||||
if %s:
|
||||
import pprint
|
||||
__org_babel_python_tmpfile.write(pprint.pformat(__org_babel_python_final))
|
||||
else:
|
||||
__org_babel_python_tmpfile.write(str(__org_babel_python_final))
|
||||
else:
|
||||
exec(compile(__org_babel_python_ast, '<string>', 'exec'))
|
||||
__org_babel_python_final = None"
|
||||
(org-babel-process-file-name src-file 'noquote)
|
||||
(org-babel-process-file-name result-file 'noquote)
|
||||
(if (member "pp" result-params) "True" "False")))
|
||||
|
||||
(defun org-babel-python-evaluate
|
||||
(session body &optional result-type result-params preamble)
|
||||
|
@ -256,6 +283,19 @@ open('%s', 'w').write( pprint.pformat(main()) )")
|
|||
(org-babel-python-evaluate-external-process
|
||||
body result-type result-params preamble)))
|
||||
|
||||
(defun org-babel-python--shift-right (body &optional count)
|
||||
(with-temp-buffer
|
||||
(python-mode)
|
||||
(insert body)
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(unless (python-syntax-context 'string)
|
||||
(python-indent-shift-right (line-beginning-position)
|
||||
(line-end-position)
|
||||
count))
|
||||
(forward-line 1))
|
||||
(buffer-string)))
|
||||
|
||||
(defun org-babel-python-evaluate-external-process
|
||||
(body &optional result-type result-params preamble)
|
||||
"Evaluate BODY in external python process.
|
||||
|
@ -276,89 +316,70 @@ last statement in BODY, as elisp."
|
|||
(if (member "pp" result-params)
|
||||
org-babel-python-pp-wrapper-method
|
||||
org-babel-python-wrapper-method)
|
||||
(mapconcat
|
||||
(lambda (line) (format "\t%s" line))
|
||||
(split-string (org-remove-indentation (org-trim body))
|
||||
"[\r\n]")
|
||||
"\n")
|
||||
(org-babel-python--shift-right body)
|
||||
(org-babel-process-file-name tmp-file 'noquote))))
|
||||
(org-babel-eval-read-file tmp-file))))))
|
||||
(org-babel-result-cond result-params
|
||||
raw
|
||||
(org-babel-python-table-or-string (org-trim raw)))))
|
||||
|
||||
(defun org-babel-python--send-string (session body)
|
||||
"Pass BODY to the Python process in SESSION.
|
||||
Return output."
|
||||
(with-current-buffer session
|
||||
(let* ((string-buffer "")
|
||||
(comint-output-filter-functions
|
||||
(cons (lambda (text) (setq string-buffer
|
||||
(concat string-buffer text)))
|
||||
comint-output-filter-functions))
|
||||
(body (format "\
|
||||
try:
|
||||
%s
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
print('%s')"
|
||||
(org-babel-python--shift-right body 4)
|
||||
org-babel-python-eoe-indicator)))
|
||||
(if (not (eq 'python-mode org-babel-python-mode))
|
||||
(let ((python-shell-buffer-name
|
||||
(org-babel-python-without-earmuffs session)))
|
||||
(python-shell-send-string body))
|
||||
(require 'python-mode)
|
||||
(py-shell-send-string body (get-buffer-process session)))
|
||||
;; same as `python-shell-comint-end-of-output-p' in emacs-25.1+
|
||||
(while (not (string-match
|
||||
org-babel-python-eoe-indicator
|
||||
string-buffer))
|
||||
(accept-process-output (get-buffer-process (current-buffer))))
|
||||
(org-babel-chomp (substring string-buffer 0 (match-beginning 0))))))
|
||||
|
||||
(defun org-babel-python-evaluate-session
|
||||
(session body &optional result-type result-params)
|
||||
"Pass BODY to the Python 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 elisp."
|
||||
(let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5)))
|
||||
(dump-last-value
|
||||
(lambda
|
||||
(tmp-file pp)
|
||||
(mapc
|
||||
(lambda (statement) (insert statement) (funcall send-wait))
|
||||
(if pp
|
||||
(list
|
||||
"import pprint"
|
||||
(format "open('%s', 'w').write(pprint.pformat(_))"
|
||||
(org-babel-process-file-name tmp-file 'noquote)))
|
||||
(list (format "open('%s', 'w').write(str(_))"
|
||||
(org-babel-process-file-name tmp-file
|
||||
'noquote)))))))
|
||||
(last-indent 0)
|
||||
(input-body (lambda (body)
|
||||
(dolist (line (split-string body "[\r\n]"))
|
||||
;; Insert a blank line to end an indent
|
||||
;; block.
|
||||
(let ((curr-indent (string-match "\\S-" line)))
|
||||
(if curr-indent
|
||||
(progn
|
||||
(when (< curr-indent last-indent)
|
||||
(insert "")
|
||||
(funcall send-wait))
|
||||
(setq last-indent curr-indent))
|
||||
(setq last-indent 0)))
|
||||
(insert line)
|
||||
(funcall send-wait))
|
||||
(funcall send-wait)))
|
||||
(let* ((tmp-src-file (org-babel-temp-file "python-"))
|
||||
(results
|
||||
(pcase result-type
|
||||
(`output
|
||||
(let ((body (if (string-match-p ".\n+." body) ; Multiline
|
||||
(let ((tmp-src-file (org-babel-temp-file
|
||||
"python-")))
|
||||
(with-temp-file tmp-src-file (insert body))
|
||||
(format org-babel-python--exec-tmpfile
|
||||
tmp-src-file))
|
||||
body)))
|
||||
(mapconcat
|
||||
#'org-trim
|
||||
(butlast
|
||||
(org-babel-comint-with-output
|
||||
(session org-babel-python-eoe-indicator t body)
|
||||
(funcall input-body body)
|
||||
(funcall send-wait) (funcall send-wait)
|
||||
(insert org-babel-python-eoe-indicator)
|
||||
(funcall send-wait))
|
||||
2) "\n")))
|
||||
(`value
|
||||
(let ((tmp-file (org-babel-temp-file "python-")))
|
||||
(org-babel-comint-with-output
|
||||
(session org-babel-python-eoe-indicator nil body)
|
||||
(let ((comint-process-echoes nil))
|
||||
(funcall input-body body)
|
||||
(funcall dump-last-value tmp-file
|
||||
(member "pp" result-params))
|
||||
(funcall send-wait) (funcall send-wait)
|
||||
(insert org-babel-python-eoe-indicator)
|
||||
(funcall send-wait)))
|
||||
(org-babel-eval-read-file tmp-file))))))
|
||||
(unless (string= (substring org-babel-python-eoe-indicator 1 -1) results)
|
||||
(org-babel-result-cond result-params
|
||||
results
|
||||
(org-babel-python-table-or-string results)))))
|
||||
(progn
|
||||
(with-temp-file tmp-src-file (insert body))
|
||||
(pcase result-type
|
||||
(`output
|
||||
(let ((body (format org-babel-python--exec-tmpfile
|
||||
(org-babel-process-file-name
|
||||
tmp-src-file 'noquote))))
|
||||
(org-babel-python--send-string session body)))
|
||||
(`value
|
||||
(let* ((tmp-results-file (org-babel-temp-file "python-"))
|
||||
(body (org-babel-python-format-session-value
|
||||
tmp-src-file tmp-results-file result-params)))
|
||||
(org-babel-python--send-string session body)
|
||||
(sleep-for 0 10)
|
||||
(org-babel-eval-read-file tmp-results-file)))))))
|
||||
(org-babel-result-cond result-params
|
||||
results
|
||||
(org-babel-python-table-or-string results))))
|
||||
|
||||
(defun org-babel-python-read-string (string)
|
||||
"Strip \\='s from around Python string."
|
||||
|
@ -369,6 +390,4 @@ last statement in BODY, as elisp."
|
|||
|
||||
(provide 'ob-python)
|
||||
|
||||
|
||||
|
||||
;;; ob-python.el ends here
|
||||
|
|
|
@ -143,7 +143,8 @@ Emacs Lisp representation of the value of the variable."
|
|||
(org-babel-ref-split-args new-referent))))
|
||||
(when (> (length new-header-args) 0)
|
||||
(setq args (append (org-babel-parse-header-arguments
|
||||
new-header-args) args)))
|
||||
new-header-args)
|
||||
args)))
|
||||
(setq ref new-refere)))
|
||||
(when (string-match "^\\(.+\\):\\(.+\\)$" ref)
|
||||
(setq split-file (match-string 1 ref))
|
||||
|
@ -240,7 +241,6 @@ to \"0:-1\"."
|
|||
"Split ARG-STRING into top-level arguments of balanced parenthesis."
|
||||
(mapcar #'org-trim (org-babel-balanced-split arg-string 44)))
|
||||
|
||||
|
||||
(provide 'ob-ref)
|
||||
|
||||
;;; ob-ref.el ends here
|
||||
|
|
|
@ -30,16 +30,17 @@
|
|||
;; - ruby and irb executables :: http://www.ruby-lang.org/
|
||||
;;
|
||||
;; - ruby-mode :: Can be installed through ELPA, or from
|
||||
;; http://github.com/eschulte/rinari/raw/master/util/ruby-mode.el
|
||||
;; https://github.com/eschulte/rinari/raw/master/util/ruby-mode.el
|
||||
;;
|
||||
;; - inf-ruby mode :: Can be installed through ELPA, or from
|
||||
;; http://github.com/eschulte/rinari/raw/master/util/inf-ruby.el
|
||||
;; https://github.com/eschulte/rinari/raw/master/util/inf-ruby.el
|
||||
|
||||
;;; Code:
|
||||
(require 'ob)
|
||||
(require 'org-macs)
|
||||
|
||||
(declare-function run-ruby "ext:inf-ruby" (&optional command name))
|
||||
(declare-function run-ruby-or-pop-to-buffer "ext:inf-ruby" (command &optional name buffer))
|
||||
(declare-function inf-ruby-buffer "ext:inf-ruby" ())
|
||||
(declare-function xmp "ext:rcodetools" (&optional option))
|
||||
|
||||
(defvar inf-ruby-default-implementation)
|
||||
|
@ -51,7 +52,8 @@
|
|||
(defvar org-babel-default-header-args:ruby '())
|
||||
|
||||
(defvar org-babel-ruby-command "ruby"
|
||||
"Name of command to use for executing ruby code.")
|
||||
"Name of command to use for executing ruby code.
|
||||
It's possible to override it by using a header argument `:ruby'")
|
||||
|
||||
(defcustom org-babel-ruby-hline-to "nil"
|
||||
"Replace hlines in incoming tables with this when translating to ruby."
|
||||
|
@ -71,9 +73,12 @@
|
|||
"Execute a block of Ruby code with Babel.
|
||||
This function is called by `org-babel-execute-src-block'."
|
||||
(let* ((session (org-babel-ruby-initiate-session
|
||||
(cdr (assq :session params))))
|
||||
(cdr (assq :session params)) params))
|
||||
(result-params (cdr (assq :result-params params)))
|
||||
(result-type (cdr (assq :result-type params)))
|
||||
(org-babel-ruby-command
|
||||
(or (cdr (assq :ruby params))
|
||||
org-babel-ruby-command))
|
||||
(full-body (org-babel-expand-body:generic
|
||||
body params (org-babel-variable-assignments:ruby params)))
|
||||
(result (if (member "xmp" result-params)
|
||||
|
@ -103,7 +108,8 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(mapc (lambda (var)
|
||||
(insert var) (comint-send-input nil t)
|
||||
(org-babel-comint-wait-for-output session)
|
||||
(sit-for .1) (goto-char (point-max))) var-lines))
|
||||
(sit-for .1) (goto-char (point-max)))
|
||||
var-lines))
|
||||
session))
|
||||
|
||||
(defun org-babel-load-session:ruby (session body params)
|
||||
|
@ -147,17 +153,21 @@ Emacs-lisp table, otherwise return the results as a string."
|
|||
res)
|
||||
res)))
|
||||
|
||||
(defun org-babel-ruby-initiate-session (&optional session _params)
|
||||
(defun org-babel-ruby-initiate-session (&optional session params)
|
||||
"Initiate a ruby session.
|
||||
If there is not a current inferior-process-buffer in SESSION
|
||||
then create one. Return the initialized session."
|
||||
(unless (string= session "none")
|
||||
(require 'inf-ruby)
|
||||
(let* ((cmd (cdr (assoc inf-ruby-default-implementation
|
||||
inf-ruby-implementations)))
|
||||
(let* ((cmd (cdr (or (assq :ruby params)
|
||||
(assoc inf-ruby-default-implementation
|
||||
inf-ruby-implementations))))
|
||||
(buffer (get-buffer (format "*%s*" session)))
|
||||
(session-buffer (or buffer (save-window-excursion
|
||||
(run-ruby cmd session)
|
||||
(run-ruby-or-pop-to-buffer
|
||||
cmd (or session "ruby")
|
||||
(unless session
|
||||
(inf-ruby-buffer)))
|
||||
(current-buffer)))))
|
||||
(if (org-babel-comint-buffer-livep session-buffer)
|
||||
(progn (sit-for .25) session-buffer)
|
||||
|
@ -263,6 +273,4 @@ return the value of the last statement in BODY, as elisp."
|
|||
|
||||
(provide 'ob-ruby)
|
||||
|
||||
|
||||
|
||||
;;; ob-ruby.el ends here
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
;;; Requirements:
|
||||
|
||||
;; - sass-mode :: http://github.com/nex3/haml/blob/master/extra/sass-mode.el
|
||||
;; - sass-mode :: https://github.com/nex3/haml/blob/master/extra/sass-mode.el
|
||||
|
||||
;;; Code:
|
||||
(require 'ob)
|
||||
|
@ -65,6 +65,4 @@ This function is called by `org-babel-execute-src-block'."
|
|||
|
||||
(provide 'ob-sass)
|
||||
|
||||
|
||||
|
||||
;;; ob-sass.el ends here
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
(require 'geiser-impl nil t)
|
||||
(defvar geiser-repl--repl) ; Defined in geiser-repl.el
|
||||
(defvar geiser-impl--implementation) ; Defined in geiser-impl.el
|
||||
(defvar geiser-scheme-implementation) ; Defined in geiser-impl.el
|
||||
(defvar geiser-default-implementation) ; Defined in geiser-impl.el
|
||||
(defvar geiser-active-implementations) ; Defined in geiser-impl.el
|
||||
(defvar geiser-debug-show-debug-p) ; Defined in geiser-debug.el
|
||||
|
@ -71,7 +72,8 @@
|
|||
(defun org-babel-expand-body:scheme (body params)
|
||||
"Expand BODY according to PARAMS, return the expanded body."
|
||||
(let ((vars (org-babel--get-vars params))
|
||||
(prepends (cdr (assq :prologue params))))
|
||||
(prepends (cdr (assq :prologue params)))
|
||||
(postpends (cdr (assq :epilogue params))))
|
||||
(concat (and prepends (concat prepends "\n"))
|
||||
(if (null vars) body
|
||||
(format "(let (%s)\n%s\n)"
|
||||
|
@ -80,7 +82,8 @@
|
|||
(format "%S" (print `(,(car var) ',(cdr var)))))
|
||||
vars
|
||||
"\n ")
|
||||
body)))))
|
||||
body))
|
||||
(and postpends (concat "\n" postpends)))))
|
||||
|
||||
|
||||
(defvar org-babel-scheme-repl-map (make-hash-table :test #'equal)
|
||||
|
@ -175,7 +178,8 @@ is true; otherwise returns the last value."
|
|||
(geiser-debug-show-debug-p nil))
|
||||
(let ((ret (geiser-eval-region (point-min) (point-max))))
|
||||
(setq result (if output
|
||||
(geiser-eval--retort-output ret)
|
||||
(or (geiser-eval--retort-output ret)
|
||||
"Geiser Interpreter produced no output")
|
||||
(geiser-eval--retort-result-str ret "")))))
|
||||
(when (not repl)
|
||||
(save-current-buffer (set-buffer repl-buffer)
|
||||
|
@ -208,6 +212,7 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(let* ((result-type (cdr (assq :result-type params)))
|
||||
(impl (or (when (cdr (assq :scheme params))
|
||||
(intern (cdr (assq :scheme params))))
|
||||
geiser-scheme-implementation
|
||||
geiser-default-implementation
|
||||
(car geiser-active-implementations)))
|
||||
(session (org-babel-scheme-make-session-name
|
||||
|
|
|
@ -40,7 +40,8 @@
|
|||
In case you want to use a different screen than one selected by your $PATH")
|
||||
|
||||
(defvar org-babel-default-header-args:screen
|
||||
'((:results . "silent") (:session . "default") (:cmd . "sh") (:terminal . "xterm"))
|
||||
`((:results . "silent") (:session . "default") (:cmd . "sh")
|
||||
(:terminal . "xterm") (:screenrc . ,null-device))
|
||||
"Default arguments to use when running screen source blocks.")
|
||||
|
||||
(defun org-babel-execute:screen (body params)
|
||||
|
@ -59,11 +60,11 @@ In case you want to use a different screen than one selected by your $PATH")
|
|||
(let* ((session (cdr (assq :session params)))
|
||||
(cmd (cdr (assq :cmd params)))
|
||||
(terminal (cdr (assq :terminal params)))
|
||||
(screenrc (cdr (assq :screenrc params)))
|
||||
(process-name (concat "org-babel: terminal (" session ")")))
|
||||
(apply 'start-process process-name "*Messages*"
|
||||
terminal `("-T" ,(concat "org-babel: " session) "-e" ,org-babel-screen-location
|
||||
"-c" "/dev/null" "-mS" ,(concat "org-babel-session-" session)
|
||||
,cmd))
|
||||
"-c" ,screenrc "-mS" ,session ,cmd))
|
||||
;; XXX: Is there a better way than the following?
|
||||
(while (not (org-babel-screen-session-socketname session))
|
||||
;; wait until screen session is available before returning
|
||||
|
@ -97,9 +98,8 @@ In case you want to use a different screen than one selected by your $PATH")
|
|||
nil
|
||||
(mapcar
|
||||
(lambda (x)
|
||||
(when (string-match
|
||||
(concat "org-babel-session-" session) x)
|
||||
x))
|
||||
(and (string-match-p (regexp-quote session) x)
|
||||
x))
|
||||
sockets)))))
|
||||
(when match-socket (car (split-string match-socket)))))
|
||||
|
||||
|
@ -108,6 +108,7 @@ In case you want to use a different screen than one selected by your $PATH")
|
|||
(let ((tmpfile (org-babel-temp-file "screen-")))
|
||||
(with-temp-file tmpfile
|
||||
(insert body)
|
||||
(insert "\n")
|
||||
|
||||
;; org-babel has superfluous spaces
|
||||
(goto-char (point-min))
|
||||
|
@ -126,7 +127,7 @@ The terminal should shortly flicker."
|
|||
;; XXX: need to find a better way to do the following
|
||||
(while (not (file-readable-p tmpfile))
|
||||
;; do something, otherwise this will be optimized away
|
||||
(format "org-babel-screen: File not readable yet."))
|
||||
(message "org-babel-screen: File not readable yet."))
|
||||
(setq tmp-string (with-temp-buffer
|
||||
(insert-file-contents-literally tmpfile)
|
||||
(buffer-substring (point-min) (point-max))))
|
||||
|
@ -138,6 +139,4 @@ The terminal should shortly flicker."
|
|||
|
||||
(provide 'ob-screen)
|
||||
|
||||
|
||||
|
||||
;;; ob-screen.el ends here
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
;; Author: Bjarte Johansen
|
||||
;; Keywords: literate programming, reproducible research
|
||||
;; Version: 0.1.1
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
|
@ -68,7 +67,8 @@ function is called by `org-babel-execute-src-block'."
|
|||
(in-file (cdr (assq :in-file params)))
|
||||
(code-file (let ((file (org-babel-temp-file "sed-")))
|
||||
(with-temp-file file
|
||||
(insert body)) file))
|
||||
(insert body))
|
||||
file))
|
||||
(stdin (let ((stdin (cdr (assq :stdin params))))
|
||||
(when stdin
|
||||
(let ((tmp (org-babel-temp-file "sed-stdin-"))
|
||||
|
@ -102,4 +102,5 @@ function is called by `org-babel-execute-src-block'."
|
|||
(cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
|
||||
|
||||
(provide 'ob-sed)
|
||||
|
||||
;;; ob-sed.el ends here
|
||||
|
|
|
@ -71,6 +71,19 @@ outside the Customize interface."
|
|||
(set-default symbol value)
|
||||
(org-babel-shell-initialize)))
|
||||
|
||||
(defcustom org-babel-shell-results-defaults-to-output t
|
||||
"Let shell execution defaults to \":results output\".
|
||||
|
||||
When set to t, use \":results output\" when no :results setting
|
||||
is set. This is especially useful for inline source blocks.
|
||||
|
||||
When set to nil, stick to the convention of using :results value
|
||||
as the default setting when no :results is set, the \"value\" of
|
||||
a shell execution being its exit code."
|
||||
:group 'org-babel
|
||||
:type 'boolean
|
||||
:package-version '(Org . "9.4"))
|
||||
|
||||
(defun org-babel-execute:shell (body params)
|
||||
"Execute a block of Shell commands with Babel.
|
||||
This function is called by `org-babel-execute-src-block'."
|
||||
|
@ -79,9 +92,17 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(stdin (let ((stdin (cdr (assq :stdin params))))
|
||||
(when stdin (org-babel-sh-var-to-string
|
||||
(org-babel-ref-resolve stdin)))))
|
||||
(results-params (cdr (assq :result-params params)))
|
||||
(value-is-exit-status
|
||||
(or (and
|
||||
(equal '("replace") results-params)
|
||||
(not org-babel-shell-results-defaults-to-output))
|
||||
(member "value" results-params)))
|
||||
(cmdline (cdr (assq :cmdline params)))
|
||||
(full-body (org-babel-expand-body:generic
|
||||
body params (org-babel-variable-assignments:shell params))))
|
||||
(full-body (concat
|
||||
(org-babel-expand-body:generic
|
||||
body params (org-babel-variable-assignments:shell params))
|
||||
(when value-is-exit-status "\necho $?"))))
|
||||
(org-babel-reassemble-table
|
||||
(org-babel-sh-evaluate session full-body params stdin cmdline)
|
||||
(org-babel-pick-name
|
||||
|
@ -96,7 +117,8 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(org-babel-comint-in-buffer session
|
||||
(mapc (lambda (var)
|
||||
(insert var) (comint-send-input nil t)
|
||||
(org-babel-comint-wait-for-output session)) var-lines))
|
||||
(org-babel-comint-wait-for-output session))
|
||||
var-lines))
|
||||
session))
|
||||
|
||||
(defun org-babel-load-session:shell (session body params)
|
||||
|
@ -129,15 +151,15 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(varname values &optional sep hline)
|
||||
"Return a list of statements declaring the values as bash associative array."
|
||||
(format "unset %s\ndeclare -A %s\n%s"
|
||||
varname varname
|
||||
(mapconcat
|
||||
(lambda (items)
|
||||
(format "%s[%s]=%s"
|
||||
varname
|
||||
(org-babel-sh-var-to-sh (car items) sep hline)
|
||||
(org-babel-sh-var-to-sh (cdr items) sep hline)))
|
||||
values
|
||||
"\n")))
|
||||
varname varname
|
||||
(mapconcat
|
||||
(lambda (items)
|
||||
(format "%s[%s]=%s"
|
||||
varname
|
||||
(org-babel-sh-var-to-sh (car items) sep hline)
|
||||
(org-babel-sh-var-to-sh (cdr items) sep hline)))
|
||||
values
|
||||
"\n")))
|
||||
|
||||
(defun org-babel--variable-assignments:bash (varname values &optional sep hline)
|
||||
"Represent the parameters as useful Bash shell variables."
|
||||
|
@ -208,6 +230,12 @@ If RESULT-TYPE equals `output' then return a list of the outputs
|
|||
of the statements in BODY, if RESULT-TYPE equals `value' then
|
||||
return the value of the last statement in BODY."
|
||||
(let* ((shebang (cdr (assq :shebang params)))
|
||||
(results-params (cdr (assq :result-params params)))
|
||||
(value-is-exit-status
|
||||
(or (and
|
||||
(equal '("replace") results-params)
|
||||
(not org-babel-shell-results-defaults-to-output))
|
||||
(member "value" results-params)))
|
||||
(results
|
||||
(cond
|
||||
((or stdin cmdline) ; external shell script w/STDIN
|
||||
|
@ -259,8 +287,9 @@ return the value of the last statement in BODY."
|
|||
(insert body))
|
||||
(set-file-modes script-file #o755)
|
||||
(org-babel-eval script-file "")))
|
||||
(t
|
||||
(org-babel-eval shell-file-name (org-trim body))))))
|
||||
(t (org-babel-eval shell-file-name (org-trim body))))))
|
||||
(when value-is-exit-status
|
||||
(setq results (car (reverse (split-string results "\n" t)))))
|
||||
(when results
|
||||
(let ((result-params (cdr (assq :result-params params))))
|
||||
(org-babel-result-cond result-params
|
||||
|
@ -277,6 +306,4 @@ return the value of the last statement in BODY."
|
|||
|
||||
(provide 'ob-shell)
|
||||
|
||||
|
||||
|
||||
;;; ob-shell.el ends here
|
||||
|
|
|
@ -75,4 +75,5 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(error results))))))
|
||||
|
||||
(provide 'ob-shen)
|
||||
|
||||
;;; ob-shen.el ends here
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
;; - dbi
|
||||
;; - mssql
|
||||
;; - sqsh
|
||||
;; - postgresql
|
||||
;; - postgresql (postgres)
|
||||
;; - oracle
|
||||
;; - vertica
|
||||
;;
|
||||
|
@ -73,6 +73,7 @@
|
|||
(declare-function orgtbl-to-csv "org-table" (table params))
|
||||
(declare-function org-table-to-lisp "org-table" (&optional txt))
|
||||
(declare-function cygwin-convert-file-name-to-windows "cygw32.c" (file &optional absolute-p))
|
||||
(declare-function sql-set-product "sql" (product))
|
||||
|
||||
(defvar sql-connection-alist)
|
||||
(defvar org-babel-default-header-args:sql '())
|
||||
|
@ -92,6 +93,13 @@
|
|||
(org-babel-sql-expand-vars
|
||||
body (org-babel--get-vars params)))
|
||||
|
||||
(defun org-babel-edit-prep:sql (info)
|
||||
"Set `sql-product' in Org edit buffer.
|
||||
Set `sql-product' in Org edit buffer according to the
|
||||
corresponding :engine source block header argument."
|
||||
(let ((product (cdr (assq :engine (nth 2 info)))))
|
||||
(sql-set-product product)))
|
||||
|
||||
(defun org-babel-sql-dbstring-mysql (host port user password database)
|
||||
"Make MySQL cmd line args for database connection. Pass nil to omit that arg."
|
||||
(combine-and-quote-strings
|
||||
|
@ -211,64 +219,64 @@ This function is called by `org-babel-execute-src-block'."
|
|||
(out-file (or (cdr (assq :out-file params))
|
||||
(org-babel-temp-file "sql-out-")))
|
||||
(header-delim "")
|
||||
(command (pcase (intern engine)
|
||||
(`dbi (format "dbish --batch %s < %s | sed '%s' > %s"
|
||||
(or cmdline "")
|
||||
(org-babel-process-file-name in-file)
|
||||
"/^+/d;s/^|//;s/(NULL)/ /g;$d"
|
||||
(org-babel-process-file-name out-file)))
|
||||
(`monetdb (format "mclient -f tab %s < %s > %s"
|
||||
(or cmdline "")
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)))
|
||||
(`mssql (format "sqlcmd %s -s \"\t\" %s -i %s -o %s"
|
||||
(or cmdline "")
|
||||
(org-babel-sql-dbstring-mssql
|
||||
dbhost dbuser dbpassword database)
|
||||
(org-babel-sql-convert-standard-filename
|
||||
(org-babel-process-file-name in-file))
|
||||
(org-babel-sql-convert-standard-filename
|
||||
(org-babel-process-file-name out-file))))
|
||||
(`mysql (format "mysql %s %s %s < %s > %s"
|
||||
(org-babel-sql-dbstring-mysql
|
||||
dbhost dbport dbuser dbpassword database)
|
||||
(if colnames-p "" "-N")
|
||||
(or cmdline "")
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)))
|
||||
(`postgresql (format
|
||||
"%spsql --set=\"ON_ERROR_STOP=1\" %s -A -P \
|
||||
footer=off -F \"\t\" %s -f %s -o %s %s"
|
||||
(if dbpassword
|
||||
(format "PGPASSWORD=%s " dbpassword)
|
||||
"")
|
||||
(if colnames-p "" "-t")
|
||||
(org-babel-sql-dbstring-postgresql
|
||||
dbhost dbport dbuser database)
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)
|
||||
(or cmdline "")))
|
||||
(`sqsh (format "sqsh %s %s -i %s -o %s -m csv"
|
||||
(command (cl-case (intern engine)
|
||||
(dbi (format "dbish --batch %s < %s | sed '%s' > %s"
|
||||
(or cmdline "")
|
||||
(org-babel-process-file-name in-file)
|
||||
"/^+/d;s/^|//;s/(NULL)/ /g;$d"
|
||||
(org-babel-process-file-name out-file)))
|
||||
(monetdb (format "mclient -f tab %s < %s > %s"
|
||||
(or cmdline "")
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)))
|
||||
(mssql (format "sqlcmd %s -s \"\t\" %s -i %s -o %s"
|
||||
(or cmdline "")
|
||||
(org-babel-sql-dbstring-sqsh
|
||||
(org-babel-sql-dbstring-mssql
|
||||
dbhost dbuser dbpassword database)
|
||||
(org-babel-sql-convert-standard-filename
|
||||
(org-babel-process-file-name in-file))
|
||||
(org-babel-sql-convert-standard-filename
|
||||
(org-babel-process-file-name out-file))))
|
||||
(`vertica (format "vsql %s -f %s -o %s %s"
|
||||
(org-babel-sql-dbstring-vertica
|
||||
dbhost dbport dbuser dbpassword database)
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)
|
||||
(or cmdline "")))
|
||||
(`oracle (format
|
||||
"sqlplus -s %s < %s > %s"
|
||||
(org-babel-sql-dbstring-oracle
|
||||
dbhost dbport dbuser dbpassword database)
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)))
|
||||
(_ (error "No support for the %s SQL engine" engine)))))
|
||||
(mysql (format "mysql %s %s %s < %s > %s"
|
||||
(org-babel-sql-dbstring-mysql
|
||||
dbhost dbport dbuser dbpassword database)
|
||||
(if colnames-p "" "-N")
|
||||
(or cmdline "")
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)))
|
||||
((postgresql postgres) (format
|
||||
"%spsql --set=\"ON_ERROR_STOP=1\" %s -A -P \
|
||||
footer=off -F \"\t\" %s -f %s -o %s %s"
|
||||
(if dbpassword
|
||||
(format "PGPASSWORD=%s " dbpassword)
|
||||
"")
|
||||
(if colnames-p "" "-t")
|
||||
(org-babel-sql-dbstring-postgresql
|
||||
dbhost dbport dbuser database)
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)
|
||||
(or cmdline "")))
|
||||
(sqsh (format "sqsh %s %s -i %s -o %s -m csv"
|
||||
(or cmdline "")
|
||||
(org-babel-sql-dbstring-sqsh
|
||||
dbhost dbuser dbpassword database)
|
||||
(org-babel-sql-convert-standard-filename
|
||||
(org-babel-process-file-name in-file))
|
||||
(org-babel-sql-convert-standard-filename
|
||||
(org-babel-process-file-name out-file))))
|
||||
(vertica (format "vsql %s -f %s -o %s %s"
|
||||
(org-babel-sql-dbstring-vertica
|
||||
dbhost dbport dbuser dbpassword database)
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)
|
||||
(or cmdline "")))
|
||||
(oracle (format
|
||||
"sqlplus -s %s < %s > %s"
|
||||
(org-babel-sql-dbstring-oracle
|
||||
dbhost dbport dbuser dbpassword database)
|
||||
(org-babel-process-file-name in-file)
|
||||
(org-babel-process-file-name out-file)))
|
||||
(t (user-error "No support for the %s SQL engine" engine)))))
|
||||
(with-temp-file in-file
|
||||
(insert
|
||||
(pcase (intern engine)
|
||||
|
@ -301,7 +309,7 @@ SET COLSEP '|'
|
|||
(progn (insert-file-contents-literally out-file) (buffer-string)))
|
||||
(with-temp-buffer
|
||||
(cond
|
||||
((memq (intern engine) '(dbi mysql postgresql sqsh vertica))
|
||||
((memq (intern engine) '(dbi mysql postgresql postgres sqsh vertica))
|
||||
;; Add header row delimiter after column-names header in first line
|
||||
(cond
|
||||
(colnames-p
|
||||
|
@ -365,6 +373,4 @@ SET COLSEP '|'
|
|||
|
||||
(provide 'ob-sql)
|
||||
|
||||
|
||||
|
||||
;;; ob-sql.el ends here
|
||||
|
|
|
@ -133,11 +133,12 @@ This function is called by `org-babel-execute-src-block'."
|
|||
"If RESULT looks like a trivial table, then unwrap it."
|
||||
(if (and (equal 1 (length result))
|
||||
(equal 1 (length (car result))))
|
||||
(org-babel-read (caar result))
|
||||
(org-babel-read (caar result) t)
|
||||
(mapcar (lambda (row)
|
||||
(if (eq 'hline row)
|
||||
'hline
|
||||
(mapcar #'org-babel-string-read row))) result)))
|
||||
(mapcar #'org-babel-string-read row)))
|
||||
result)))
|
||||
|
||||
(defun org-babel-sqlite-offset-colnames (table headers-p)
|
||||
"If HEADERS-P is non-nil then offset the first row as column names."
|
||||
|
@ -152,6 +153,4 @@ Prepare SESSION according to the header arguments specified in PARAMS."
|
|||
|
||||
(provide 'ob-sqlite)
|
||||
|
||||
|
||||
|
||||
;;; ob-sqlite.el ends here
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
;; For more information and usage examples, visit
|
||||
;; https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-stan.html
|
||||
;;
|
||||
;; [1] http://mc-stan.org/
|
||||
;; [1] https://mc-stan.org/
|
||||
|
||||
;;; Code:
|
||||
(require 'ob)
|
||||
|
@ -82,4 +82,5 @@ Otherwise, write the Stan code directly to the named file."
|
|||
(user-error "Stan does not support sessions"))
|
||||
|
||||
(provide 'ob-stan)
|
||||
|
||||
;;; ob-stan.el ends here
|
||||
|
|
|
@ -62,7 +62,8 @@ If STRING ends in a newline character, then remove the newline
|
|||
character and replace it with ellipses."
|
||||
(if (and (stringp string) (string-match "[\n\r]\\(.\\)?" string))
|
||||
(concat (substring string 0 (match-beginning 0))
|
||||
(when (match-string 1 string) "...")) string))
|
||||
(when (match-string 1 string) "..."))
|
||||
string))
|
||||
|
||||
(defmacro org-sbe (source-block &rest variables)
|
||||
"Return the results of calling SOURCE-BLOCK with VARIABLES.
|
||||
|
@ -147,6 +148,4 @@ as shown in the example below.
|
|||
|
||||
(provide 'ob-table)
|
||||
|
||||
|
||||
|
||||
;;; ob-table.el ends here
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
(declare-function org-element-type "org-element" (element))
|
||||
(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" ())
|
||||
|
||||
(defcustom org-babel-tangle-lang-exts
|
||||
|
@ -166,13 +167,14 @@ evaluating BODY."
|
|||
(def-edebug-spec org-babel-with-temp-filebuffer (form body))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-babel-tangle-file (file &optional target-file lang)
|
||||
(defun org-babel-tangle-file (file &optional target-file lang-re)
|
||||
"Extract the bodies of source code blocks in FILE.
|
||||
Source code blocks are extracted with `org-babel-tangle'.
|
||||
Optional argument TARGET-FILE can be used to specify a default
|
||||
export file for all source blocks. Optional argument LANG can be
|
||||
used to limit the exported source code blocks by language.
|
||||
Return a list whose CAR is the tangled file name."
|
||||
export file for all source blocks. Optional argument LANG-RE can
|
||||
be used to limit the exported source code blocks by languages
|
||||
matching a regular expression. Return a list whose CAR is the
|
||||
tangled file name."
|
||||
(interactive "fFile to tangle: \nP")
|
||||
(let ((visited-p (find-buffer-visiting (expand-file-name file)))
|
||||
to-be-removed)
|
||||
|
@ -180,7 +182,7 @@ Return a list whose CAR is the tangled file name."
|
|||
(save-window-excursion
|
||||
(find-file file)
|
||||
(setq to-be-removed (current-buffer))
|
||||
(mapcar #'expand-file-name (org-babel-tangle nil target-file lang)))
|
||||
(mapcar #'expand-file-name (org-babel-tangle nil target-file lang-re)))
|
||||
(unless visited-p
|
||||
(kill-buffer to-be-removed)))))
|
||||
|
||||
|
@ -192,7 +194,7 @@ Return a list whose CAR is the tangled file name."
|
|||
(mapc (lambda (el) (copy-file el pub-dir t)) (org-babel-tangle-file filename)))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-babel-tangle (&optional arg target-file lang)
|
||||
(defun org-babel-tangle (&optional arg target-file lang-re)
|
||||
"Write code blocks to source-specific files.
|
||||
Extract the bodies of all source code blocks from the current
|
||||
file into their own source-specific files.
|
||||
|
@ -200,8 +202,9 @@ With one universal prefix argument, only tangle the block at point.
|
|||
When two universal prefix arguments, only tangle blocks for the
|
||||
tangle file of the block at point.
|
||||
Optional argument TARGET-FILE can be used to specify a default
|
||||
export file for all source blocks. Optional argument LANG can be
|
||||
used to limit the exported source code blocks by language."
|
||||
export file for all source blocks. Optional argument LANG-RE can
|
||||
be used to limit the exported source code blocks by languages
|
||||
matching a regular expression."
|
||||
(interactive "P")
|
||||
(run-hooks 'org-babel-pre-tangle-hook)
|
||||
;; Possibly Restrict the buffer to the current code block
|
||||
|
@ -286,7 +289,7 @@ used to limit the exported source code blocks by language."
|
|||
specs)))
|
||||
(if (equal arg '(4))
|
||||
(org-babel-tangle-single-block 1 t)
|
||||
(org-babel-tangle-collect-blocks lang tangle-file)))
|
||||
(org-babel-tangle-collect-blocks lang-re tangle-file)))
|
||||
(message "Tangled %d code block%s from %s" block-counter
|
||||
(if (= block-counter 1) "" "s")
|
||||
(file-name-nondirectory
|
||||
|
@ -364,13 +367,14 @@ that the appropriate major-mode is set. SPEC has the form:
|
|||
(org-fill-template
|
||||
org-babel-tangle-comment-format-end link-data)))))
|
||||
|
||||
(defun org-babel-tangle-collect-blocks (&optional language tangle-file)
|
||||
(defun org-babel-tangle-collect-blocks (&optional lang-re tangle-file)
|
||||
"Collect source blocks in the current Org file.
|
||||
Return an association list of source-code block specifications of
|
||||
the form used by `org-babel-spec-to-string' grouped by language.
|
||||
Optional argument LANGUAGE can be used to limit the collected
|
||||
source code blocks by language. Optional argument TANGLE-FILE
|
||||
can be used to limit the collected code blocks by target file."
|
||||
Optional argument LANG-RE can be used to limit the collected
|
||||
source code blocks by languages matching a regular expression.
|
||||
Optional argument TANGLE-FILE can be used to limit the collected
|
||||
code blocks by target file."
|
||||
(let ((counter 0) last-heading-pos blocks)
|
||||
(org-babel-map-src-blocks (buffer-file-name)
|
||||
(let ((current-heading-pos
|
||||
|
@ -379,13 +383,14 @@ can be used to limit the collected code blocks by target file."
|
|||
(if (eq last-heading-pos current-heading-pos) (cl-incf counter)
|
||||
(setq counter 1)
|
||||
(setq last-heading-pos current-heading-pos)))
|
||||
(unless (org-in-commented-heading-p)
|
||||
(unless (or (org-in-commented-heading-p)
|
||||
(org-in-archived-heading-p))
|
||||
(let* ((info (org-babel-get-src-block-info 'light))
|
||||
(src-lang (nth 0 info))
|
||||
(src-tfile (cdr (assq :tangle (nth 2 info)))))
|
||||
(unless (or (string= src-tfile "no")
|
||||
(and tangle-file (not (equal tangle-file src-tfile)))
|
||||
(and language (not (string= language src-lang))))
|
||||
(and lang-re (not (string-match-p lang-re src-lang))))
|
||||
;; Add the spec for this block to blocks under its
|
||||
;; language.
|
||||
(let ((by-lang (assoc src-lang blocks))
|
||||
|
@ -471,9 +476,9 @@ non-nil, return the full association list to be used by
|
|||
file)
|
||||
(if (and org-babel-tangle-use-relative-file-links
|
||||
(string-match org-link-types-re link)
|
||||
(string= (match-string 0 link) "file"))
|
||||
(string= (match-string 1 link) "file"))
|
||||
(concat "file:"
|
||||
(file-relative-name (match-string 1 link)
|
||||
(file-relative-name (substring link (match-end 0))
|
||||
(file-name-directory
|
||||
(cdr (assq :tangle params)))))
|
||||
link)
|
||||
|
@ -513,14 +518,16 @@ which enable the original code blocks to be found."
|
|||
(goto-char (point-min))
|
||||
(let ((counter 0) new-body end)
|
||||
(while (re-search-forward org-link-bracket-re nil t)
|
||||
(when (re-search-forward
|
||||
(concat " " (regexp-quote (match-string 2)) " ends here"))
|
||||
(setq end (match-end 0))
|
||||
(forward-line -1)
|
||||
(save-excursion
|
||||
(when (setq new-body (org-babel-tangle-jump-to-org))
|
||||
(org-babel-update-block-body new-body)))
|
||||
(setq counter (+ 1 counter)))
|
||||
(if (and (match-string 2)
|
||||
(re-search-forward
|
||||
(concat " " (regexp-quote (match-string 2)) " ends here") nil t))
|
||||
(progn (setq end (match-end 0))
|
||||
(forward-line -1)
|
||||
(save-excursion
|
||||
(when (setq new-body (org-babel-tangle-jump-to-org))
|
||||
(org-babel-update-block-body new-body)))
|
||||
(setq counter (+ 1 counter)))
|
||||
(setq end (point)))
|
||||
(goto-char end))
|
||||
(prog1 counter (message "Detangled %d code blocks" counter)))))
|
||||
|
||||
|
@ -541,7 +548,8 @@ which enable the original code blocks to be found."
|
|||
(save-match-data
|
||||
(re-search-forward
|
||||
(concat " " (regexp-quote block-name)
|
||||
" ends here") nil t)
|
||||
" ends here")
|
||||
nil t)
|
||||
(setq end (line-beginning-position))))))))
|
||||
(unless (and start (< start mid) (< mid end))
|
||||
(error "Not in tangled code"))
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
;;; Commentary:
|
||||
|
||||
;; ob-vala.el provides Babel support for the Vala language
|
||||
;; (see http://live.gnome.org/Vala for details)
|
||||
;; (see https://live.gnome.org/Vala for details)
|
||||
|
||||
;;; Requirements:
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
(require 'org-macs)
|
||||
(require 'ol)
|
||||
|
||||
;; Declare functions and variables
|
||||
;;; Declare functions and variables
|
||||
|
||||
(declare-function bbdb "ext:bbdb-com" (string elidep))
|
||||
(declare-function bbdb-company "ext:bbdb-com" (string elidep))
|
||||
|
@ -126,9 +126,9 @@
|
|||
|
||||
(declare-function diary-ordinal-suffix "diary-lib" (n))
|
||||
|
||||
(with-no-warnings (defvar date)) ;unprefixed, from calendar.el
|
||||
(with-no-warnings (defvar date)) ; unprefixed, from calendar.el
|
||||
|
||||
;; Customization
|
||||
;;; Customization
|
||||
|
||||
(defgroup org-bbdb-anniversaries nil
|
||||
"Customizations for including anniversaries from BBDB into Agenda."
|
||||
|
@ -162,13 +162,13 @@ used."
|
|||
'(("birthday" .
|
||||
(lambda (name years suffix)
|
||||
(concat "Birthday: [[bbdb:" name "][" name " ("
|
||||
(format "%s" years) ; handles numbers as well as strings
|
||||
suffix ")]]")))
|
||||
(format "%s" years) ; handles numbers as well as strings
|
||||
suffix ")]]")))
|
||||
("wedding" .
|
||||
(lambda (name years suffix)
|
||||
(concat "[[bbdb:" name "][" name "'s "
|
||||
(format "%s" years)
|
||||
suffix " wedding anniversary]]"))))
|
||||
(format "%s" years)
|
||||
suffix " wedding anniversary]]"))))
|
||||
"How different types of anniversaries should be formatted.
|
||||
An alist of elements (STRING . FORMAT) where STRING is the name of an
|
||||
anniversary class and format is either:
|
||||
|
@ -221,7 +221,8 @@ date year)."
|
|||
:complete #'org-bbdb-complete-link
|
||||
:store #'org-bbdb-store-link)
|
||||
|
||||
;; Implementation
|
||||
;;; Implementation
|
||||
|
||||
(defun org-bbdb-store-link ()
|
||||
"Store a link to a BBDB database entry."
|
||||
(when (eq major-mode 'bbdb-mode)
|
||||
|
@ -236,7 +237,7 @@ date year)."
|
|||
:link link :description name)
|
||||
link)))
|
||||
|
||||
(defun org-bbdb-export (path desc format)
|
||||
(defun org-bbdb-export (path desc format _)
|
||||
"Create the export version of a BBDB link specified by PATH or DESC.
|
||||
If exporting to either HTML or LaTeX FORMAT the link will be
|
||||
italicized, in all other cases it is left unchanged."
|
||||
|
@ -249,7 +250,7 @@ italicized, in all other cases it is left unchanged."
|
|||
(format "<text:span text:style-name=\"Emphasis\">%s</text:span>" desc))
|
||||
(t desc)))
|
||||
|
||||
(defun org-bbdb-open (name)
|
||||
(defun org-bbdb-open (name _)
|
||||
"Follow a BBDB link to NAME."
|
||||
(require 'bbdb-com)
|
||||
(let ((inhibit-redisplay (not debug-on-error)))
|
||||
|
@ -362,7 +363,9 @@ This is used by Org to re-create the anniversary hash table."
|
|||
|
||||
;;;###autoload
|
||||
(defun org-bbdb-anniversaries ()
|
||||
"Extract anniversaries from BBDB for display in the agenda."
|
||||
"Extract anniversaries from BBDB for display in the agenda.
|
||||
When called programmatically, this function expects the `date'
|
||||
variable to be globally bound."
|
||||
(require 'bbdb)
|
||||
(require 'diary-lib)
|
||||
(unless (hash-table-p org-bbdb-anniv-hash)
|
||||
|
@ -380,7 +383,7 @@ This is used by Org to re-create the anniversary hash table."
|
|||
(text ())
|
||||
rec recs)
|
||||
|
||||
;; we don't want to miss people born on Feb. 29th
|
||||
;; We don't want to miss people born on Feb. 29th
|
||||
(when (and (= m 3) (= d 1)
|
||||
(not (null (gethash (list 2 29) org-bbdb-anniv-hash)))
|
||||
(not (calendar-leap-year-p y)))
|
||||
|
@ -415,8 +418,9 @@ This is used by Org to re-create the anniversary hash table."
|
|||
))
|
||||
text))
|
||||
|
||||
;;; Return list of anniversaries for today and the next n-1 (default: n=7) days.
|
||||
;;; This is meant to be used in an org file instead of org-bbdb-anniversaries:
|
||||
;;; Return the list of anniversaries for today and the next n-1
|
||||
;;; (default: n=7) days. This is meant to be used in an org file
|
||||
;;; instead of org-bbdb-anniversaries:
|
||||
;;;
|
||||
;;; %%(org-bbdb-anniversaries-future)
|
||||
;;;
|
||||
|
@ -442,15 +446,14 @@ for the same event depending on if it occurs in the next few days
|
|||
or far away in the future."
|
||||
(let ((delta (- (calendar-absolute-from-gregorian anniv-date)
|
||||
(calendar-absolute-from-gregorian agenda-date))))
|
||||
|
||||
(cond
|
||||
((= delta 0) " -- today\\&")
|
||||
((= delta 1) " -- tomorrow\\&")
|
||||
((< delta org-bbdb-general-anniversary-description-after) (format " -- in %d days\\&" delta))
|
||||
((< delta org-bbdb-general-anniversary-description-after)
|
||||
(format " -- in %d days\\&" delta))
|
||||
((pcase-let ((`(,month ,day ,year) anniv-date))
|
||||
(format " -- %d-%02d-%02d\\&" year month day))))))
|
||||
|
||||
|
||||
(defun org-bbdb-anniversaries-future (&optional n)
|
||||
"Return list of anniversaries for today and the next n-1 days (default n=7)."
|
||||
(let ((n (or n 7)))
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
;; The link creation part has been part of Org for a long time.
|
||||
;;
|
||||
;; Creating better capture template information was inspired by a request
|
||||
;; of Austin Frank: http://article.gmane.org/gmane.emacs.orgmode/4112
|
||||
;; of Austin Frank: https://orgmode.org/list/m0myu03vbx.fsf@gmail.com
|
||||
;; and then implemented by Bastien Guerry.
|
||||
;;
|
||||
;; Eric Schulte eventually added the functions for translating between
|
||||
|
@ -134,7 +134,6 @@
|
|||
(declare-function org-insert-heading "org" (&optional arg invisible-ok top))
|
||||
(declare-function org-map-entries "org" (func &optional match scope &rest skip))
|
||||
(declare-function org-narrow-to-subtree "org" ())
|
||||
(declare-function org-open-file "org" (path &optional in-emacs line search))
|
||||
(declare-function org-set-property "org" (property value))
|
||||
(declare-function org-toggle-tag "org" (tag &optional onoff))
|
||||
|
||||
|
@ -483,12 +482,11 @@ With optional argument OPTIONAL, also prompt for optional fields."
|
|||
:follow #'org-bibtex-open
|
||||
:store #'org-bibtex-store-link)
|
||||
|
||||
(defun org-bibtex-open (path)
|
||||
"Visit the bibliography entry on PATH."
|
||||
(let* ((search (when (string-match "::\\(.+\\)\\'" path)
|
||||
(match-string 1 path)))
|
||||
(path (substring path 0 (match-beginning 0))))
|
||||
(org-open-file path t nil search)))
|
||||
(defun org-bibtex-open (path arg)
|
||||
"Visit the bibliography entry on PATH.
|
||||
ARG, when non-nil, is a universal prefix argument. See
|
||||
`org-open-file' for details."
|
||||
(org-link-open-as-file path arg))
|
||||
|
||||
(defun org-bibtex-store-link ()
|
||||
"Store a link to a BibTeX entry."
|
||||
|
@ -556,7 +554,8 @@ With optional argument OPTIONAL, also prompt for optional fields."
|
|||
;; We construct a regexp that searches for "@entrytype{" followed by the key
|
||||
(goto-char (point-min))
|
||||
(and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*"
|
||||
(regexp-quote s) "[ \t\n]*,") nil t)
|
||||
(regexp-quote s) "[ \t\n]*,")
|
||||
nil t)
|
||||
(goto-char (match-beginning 0)))
|
||||
(if (and (match-beginning 0) (equal current-prefix-arg '(16)))
|
||||
;; Use double prefix to indicate that any web link should be browsed
|
||||
|
@ -596,7 +595,8 @@ Headlines are exported using `org-bibtex-headline'."
|
|||
(with-temp-file filename
|
||||
(insert (mapconcat #'identity bibtex-entries "\n")))
|
||||
(message "Successfully exported %d BibTeX entries to %s"
|
||||
(length bibtex-entries) filename) nil))))
|
||||
(length bibtex-entries) filename)
|
||||
nil))))
|
||||
(when error-point
|
||||
(goto-char error-point)
|
||||
(message "Bibtex error at %S" (nth 4 (org-heading-components))))))
|
||||
|
@ -661,7 +661,8 @@ This uses `bibtex-parse-entry'."
|
|||
(when (and (> (length str) 1)
|
||||
(= (aref str 0) (car pair))
|
||||
(= (aref str (1- (length str))) (cdr pair)))
|
||||
(setf str (substring str 1 (1- (length str)))))) str)))
|
||||
(setf str (substring str 1 (1- (length str))))))
|
||||
str)))
|
||||
(push (mapcar
|
||||
(lambda (pair)
|
||||
(cons (let ((field (funcall keyword (car pair))))
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
((eq format 'ascii) (format "%s (%s)" desc path))
|
||||
(t path)))))
|
||||
|
||||
(defun org-docview-open (link)
|
||||
(defun org-docview-open (link _)
|
||||
(string-match "\\(.*?\\)\\(?:::\\([0-9]+\\)\\)?$" link)
|
||||
(let ((path (match-string 1 link))
|
||||
(page (and (match-beginning 2)
|
||||
|
@ -98,7 +98,6 @@ and append it."
|
|||
"::"
|
||||
(read-from-minibuffer "Page:" "1")))
|
||||
|
||||
|
||||
(provide 'ol-docview)
|
||||
|
||||
;;; ol-docview.el ends here
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
:follow #'org-eshell-open
|
||||
:store #'org-eshell-store-link)
|
||||
|
||||
(defun org-eshell-open (link)
|
||||
(defun org-eshell-open (link _)
|
||||
"Switch to an eshell buffer and execute a command line.
|
||||
The link can be just a command line (executed in the default
|
||||
eshell buffer) or a command line prefixed by a buffer name
|
||||
|
|
|
@ -46,17 +46,22 @@
|
|||
;;; Code:
|
||||
(require 'ol)
|
||||
(require 'cl-lib)
|
||||
(require 'eww)
|
||||
|
||||
;; For Emacsen < 25.
|
||||
(defvar eww-current-title)
|
||||
(defvar eww-current-url)
|
||||
(defvar eww-data)
|
||||
(defvar eww-mode-map)
|
||||
|
||||
(declare-function eww-current-url "eww")
|
||||
|
||||
|
||||
;; Store Org link in Eww mode buffer
|
||||
(org-link-set-parameters "eww" :follow #'eww :store #'org-eww-store-link)
|
||||
(org-link-set-parameters "eww"
|
||||
:follow #'org-eww-open
|
||||
:store #'org-eww-store-link)
|
||||
|
||||
(defun org-eww-open (url _)
|
||||
"Open URL with Eww in the current buffer."
|
||||
(eww url))
|
||||
|
||||
(defun org-eww-store-link ()
|
||||
"Store a link to the url of an EWW buffer."
|
||||
(when (eq major-mode 'eww-mode)
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
(require 'gnus-sum)
|
||||
(require 'gnus-util)
|
||||
(require 'nnheader)
|
||||
(require 'nnir)
|
||||
(or (require 'nnselect nil t) ; Emacs >= 28
|
||||
(require 'nnir nil t)) ; Emacs < 28
|
||||
(require 'ol)
|
||||
|
||||
|
||||
|
@ -61,7 +62,7 @@
|
|||
;;; Customization variables
|
||||
|
||||
(defcustom org-gnus-prefer-web-links nil
|
||||
"If non-nil, `org-store-link' creates web links to Google groups or Gmane.
|
||||
"If non-nil, `org-store-link' creates web links to Google groups.
|
||||
\\<org-mode-map>When nil, Gnus will be used for such links.
|
||||
Using a prefix argument to the command `\\[org-store-link]' (`org-store-link')
|
||||
negates this setting for the duration of the command."
|
||||
|
@ -87,8 +88,8 @@ negates this setting for the duration of the command."
|
|||
(defun org-gnus-group-link (group)
|
||||
"Create a link to the Gnus group GROUP.
|
||||
If GROUP is a newsgroup and `org-gnus-prefer-web-links' is
|
||||
non-nil, create a link to groups.google.com or gmane.org.
|
||||
Otherwise create a link to the group inside Gnus.
|
||||
non-nil, create a link to groups.google.com. Otherwise create a
|
||||
link to the group inside Gnus.
|
||||
|
||||
If `org-store-link' was called with a prefix arg the meaning of
|
||||
`org-gnus-prefer-web-links' is reversed."
|
||||
|
@ -96,10 +97,7 @@ If `org-store-link' was called with a prefix arg the meaning of
|
|||
(if (and (string-prefix-p "nntp" group) ;; Only for nntp groups
|
||||
(org-xor current-prefix-arg
|
||||
org-gnus-prefer-web-links))
|
||||
(concat (if (string-match "gmane" unprefixed-group)
|
||||
"http://news.gmane.org/"
|
||||
"http://groups.google.com/group/")
|
||||
unprefixed-group)
|
||||
(concat "https://groups.google.com/group/" unprefixed-group)
|
||||
(concat "gnus:" group))))
|
||||
|
||||
(defun org-gnus-article-link (group newsgroups message-id x-no-archive)
|
||||
|
@ -110,7 +108,7 @@ parameters are the Gnus GROUP, the NEWSGROUPS the article was
|
|||
posted to and the X-NO-ARCHIVE header value of that article.
|
||||
|
||||
If GROUP is a newsgroup and `org-gnus-prefer-web-links' is
|
||||
non-nil, create a link to groups.google.com or gmane.org.
|
||||
non-nil, create a link to groups.google.com.
|
||||
Otherwise create a link to the article inside Gnus.
|
||||
|
||||
If `org-store-link' was called with a prefix arg the meaning of
|
||||
|
@ -118,9 +116,7 @@ If `org-store-link' was called with a prefix arg the meaning of
|
|||
(if (and (org-xor current-prefix-arg org-gnus-prefer-web-links)
|
||||
newsgroups ;make web links only for nntp groups
|
||||
(not x-no-archive)) ;and if X-No-Archive isn't set
|
||||
(format (if (string-match-p "gmane\\." newsgroups)
|
||||
"http://mid.gmane.org/%s"
|
||||
"http://groups.google.com/groups/search?as_umsgid=%s")
|
||||
(format "https://groups.google.com/groups/search?as_umsgid=%s"
|
||||
(url-encode-url message-id))
|
||||
(concat "gnus:" group "#" message-id)))
|
||||
|
||||
|
@ -140,9 +136,15 @@ If `org-store-link' was called with a prefix arg the meaning of
|
|||
(`(nnvirtual . ,_)
|
||||
(save-excursion
|
||||
(car (nnvirtual-map-article (gnus-summary-article-number)))))
|
||||
(`(nnir . ,_)
|
||||
(`(,(or `nnselect `nnir) . ,_) ; nnir is for Emacs < 28.
|
||||
(save-excursion
|
||||
(nnir-article-group (gnus-summary-article-number))))
|
||||
(cond
|
||||
((fboundp 'nnselect-article-group)
|
||||
(nnselect-article-group (gnus-summary-article-number)))
|
||||
((fboundp 'nnir-article-group)
|
||||
(nnir-article-group (gnus-summary-article-number)))
|
||||
(t
|
||||
(error "No article-group variant bound")))))
|
||||
(_ gnus-newsgroup-name)))
|
||||
(header (if (eq major-mode 'gnus-article-mode)
|
||||
;; When in an article, first move to summary
|
||||
|
@ -215,7 +217,7 @@ If `org-store-link' was called with a prefix arg the meaning of
|
|||
(format "nntp+%s:%s" (or (cdr server) (car server)) group)
|
||||
article)))
|
||||
|
||||
(defun org-gnus-open (path)
|
||||
(defun org-gnus-open (path _)
|
||||
"Follow the Gnus message or folder link specified by PATH."
|
||||
(unless (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)
|
||||
(error "Error in Gnus link %S" path))
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
:link link :desc desc)
|
||||
link)))
|
||||
|
||||
(defun org-info-open (path)
|
||||
(defun org-info-open (path _)
|
||||
"Follow an Info file and node link specified by PATH."
|
||||
(org-info-follow-link path))
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
:store #'org-irc-store-link
|
||||
:export #'org-irc-export)
|
||||
|
||||
(defun org-irc-visit (link)
|
||||
(defun org-irc-visit (link _)
|
||||
"Parse LINK and dispatch to the correct function based on the client found."
|
||||
(let ((link (org-irc-parse-link link)))
|
||||
(cond
|
||||
|
|
|
@ -96,7 +96,7 @@ supported by MH-E."
|
|||
(org-link-add-props :link link :description desc)
|
||||
link))))
|
||||
|
||||
(defun org-mhe-open (path)
|
||||
(defun org-mhe-open (path _)
|
||||
"Follow an MH-E message link specified by PATH."
|
||||
(let (folder article)
|
||||
(if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
(defvar rmail-file-name) ; From rmail.el
|
||||
|
||||
;; Install the link type
|
||||
(org-link-set-parameters "rmail" :follow #'org-rmail-open :store #'org-rmail-store-link)
|
||||
(org-link-set-parameters "rmail"
|
||||
:follow #'org-rmail-open
|
||||
:store #'org-rmail-store-link)
|
||||
|
||||
;; Implementation
|
||||
(defun org-rmail-store-link ()
|
||||
|
@ -75,7 +77,7 @@
|
|||
(rmail-show-message rmail-current-message)
|
||||
link)))))
|
||||
|
||||
(defun org-rmail-open (path)
|
||||
(defun org-rmail-open (path _)
|
||||
"Follow an Rmail message link to the specified PATH."
|
||||
(let (folder article)
|
||||
(if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
|
||||
|
|
495
lisp/org/ol.el
495
lisp/org/ol.el
|
@ -45,6 +45,7 @@
|
|||
(declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
|
||||
(declare-function org-at-heading-p "org" (&optional _))
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-before-first-heading-p "org" ())
|
||||
(declare-function org-do-occur "org" (regexp &optional cleanup))
|
||||
(declare-function org-element-at-point "org-element" ())
|
||||
(declare-function org-element-cache-refresh "org-element" (pos))
|
||||
|
@ -57,7 +58,6 @@
|
|||
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
|
||||
(declare-function org-find-property "org" (property &optional value))
|
||||
(declare-function org-get-heading "org" (&optional no-tags no-todo no-priority no-comment))
|
||||
(declare-function org-heading-components "org" ())
|
||||
(declare-function org-id-find-id-file "org-id" (id))
|
||||
(declare-function org-id-store-link "org-id" ())
|
||||
(declare-function org-insert-heading "org" (&optional arg invisible-ok top))
|
||||
|
@ -85,42 +85,94 @@
|
|||
:group 'org)
|
||||
|
||||
(defcustom org-link-parameters nil
|
||||
"An alist of properties that defines all the links in Org mode.
|
||||
"Alist of properties that defines all the links in Org mode.
|
||||
|
||||
The key in each association is a string of the link type.
|
||||
Subsequent optional elements make up a plist of link properties.
|
||||
Subsequent optional elements make up a property list for that
|
||||
type.
|
||||
|
||||
:follow - A function that takes the link path as an argument.
|
||||
All properties are optional. However, the most important ones
|
||||
are, in this order, `:follow', `:export', and `:store', described
|
||||
below.
|
||||
|
||||
:export - A function that takes the link path, description and
|
||||
export-backend as arguments.
|
||||
`:follow'
|
||||
|
||||
:store - A function responsible for storing the link. See the
|
||||
function `org-store-link-functions'.
|
||||
Function used to follow the link, when the `org-open-at-point'
|
||||
command runs on it. It is called with two arguments: the path,
|
||||
as a string, and a universal prefix argument.
|
||||
|
||||
:complete - A function that inserts a link with completion. The
|
||||
function takes one optional prefix argument.
|
||||
Here, you may use `org-link-open-as-file' helper function for
|
||||
types similar to \"file\".
|
||||
|
||||
:face - A face for the link, or a function that returns a face.
|
||||
The function takes one argument which is the link path. The
|
||||
default face is `org-link'.
|
||||
`:export'
|
||||
|
||||
:mouse-face - The mouse-face. The default is `highlight'.
|
||||
Function that accepts four arguments:
|
||||
- the path, as a string,
|
||||
- the description as a string, or nil,
|
||||
- the export back-end,
|
||||
- the export communication channel, as a plist.
|
||||
|
||||
:display - `full' will not fold the link in descriptive
|
||||
display. Default is `org-link'.
|
||||
When nil, export for that type of link is delegated to the
|
||||
back-end.
|
||||
|
||||
:help-echo - A string or function that takes (window object position)
|
||||
as arguments and returns a string.
|
||||
`:store'
|
||||
|
||||
:keymap - A keymap that is active on the link. The default is
|
||||
`org-mouse-map'.
|
||||
Function responsible for storing the link. See the function
|
||||
`org-store-link-functions' for a description of the expected
|
||||
arguments.
|
||||
|
||||
:htmlize-link - A function for the htmlize-link. Defaults
|
||||
to (list :uri \"type:path\")
|
||||
Additional properties provide more specific control over the
|
||||
link.
|
||||
|
||||
:activate-func - A function to run at the end of font-lock
|
||||
activation. The function must accept (link-start link-end path bracketp)
|
||||
as arguments."
|
||||
`:activate-func'
|
||||
|
||||
Function to run at the end of Font Lock activation. It must
|
||||
accept four arguments:
|
||||
- the buffer position at the start of the link,
|
||||
- the buffer position at its end,
|
||||
- the path, as a string,
|
||||
- a boolean, non-nil when the link has brackets.
|
||||
|
||||
`:complete'
|
||||
|
||||
Function that inserts a link with completion. The function
|
||||
takes one optional prefix argument.
|
||||
|
||||
`:display'
|
||||
|
||||
Value for `invisible' text property on the hidden parts of the
|
||||
link. The most useful value is `full', which will not fold the
|
||||
link in descriptive display. Default is `org-link'.
|
||||
|
||||
`:face'
|
||||
|
||||
Face for the link, or a function returning a face. The
|
||||
function takes one argument, which is the path.
|
||||
|
||||
The default face is `org-link'.
|
||||
|
||||
`:help-echo'
|
||||
|
||||
String or function used as a value for the `help-echo' text
|
||||
property. The function is called with one argument, the help
|
||||
string to display, and should return a string.
|
||||
|
||||
`:htmlize-link'
|
||||
|
||||
Function or plist for the `htmlize-link' text property. The
|
||||
function takes no argument.
|
||||
|
||||
Default is (:uri \"type:path\")
|
||||
|
||||
`:keymap'
|
||||
|
||||
Active keymap when point is on the link. Default is
|
||||
`org-mouse-map'.
|
||||
|
||||
`:mouse-face'
|
||||
|
||||
Face used when hovering over the link. Default is
|
||||
`highlight'."
|
||||
:group 'org-link
|
||||
:package-version '(Org . "9.1")
|
||||
:type '(alist :tag "Link display parameters"
|
||||
|
@ -408,7 +460,7 @@ This is for example useful to limit the length of the subject.
|
|||
|
||||
Examples: \"%f on: %.30s\", \"Email from %f\", \"Email %c\""
|
||||
:group 'org-link-store
|
||||
:package-version '(Org . 9.3)
|
||||
:package-version '(Org . "9.3")
|
||||
:type 'string
|
||||
:safe #'stringp)
|
||||
|
||||
|
@ -674,6 +726,44 @@ White spaces are not significant."
|
|||
(goto-char origin)
|
||||
(user-error "No match for radio target: %s" target))))
|
||||
|
||||
(defun org-link--context-from-region ()
|
||||
"Return context string from active region, or nil."
|
||||
(when (org-region-active-p)
|
||||
(let ((context (buffer-substring (region-beginning) (region-end))))
|
||||
(when (and (wholenump org-link-context-for-files)
|
||||
(> org-link-context-for-files 0))
|
||||
(let ((lines (org-split-string context "\n")))
|
||||
(setq context
|
||||
(mapconcat #'identity
|
||||
(cl-subseq lines 0 org-link-context-for-files)
|
||||
"\n"))))
|
||||
context)))
|
||||
|
||||
(defun org-link--normalize-string (string &optional context)
|
||||
"Remove ignored contents from STRING string and return it.
|
||||
This function removes contiguous white spaces and statistics
|
||||
cookies. When optional argument CONTEXT is non-nil, it assumes
|
||||
STRING is a context string, and also removes special search
|
||||
syntax around the string."
|
||||
(let ((string
|
||||
(org-trim
|
||||
(replace-regexp-in-string
|
||||
(rx (one-or-more (any " \t")))
|
||||
" "
|
||||
(replace-regexp-in-string
|
||||
;; Statistics cookie regexp.
|
||||
(rx (seq "[" (0+ digit) (or "%" (seq "/" (0+ digit))) "]"))
|
||||
" "
|
||||
string)))))
|
||||
(when context
|
||||
(while (cond ((and (string-prefix-p "(" string)
|
||||
(string-suffix-p ")" string))
|
||||
(setq string (org-trim (substring string 1 -1))))
|
||||
((string-match "\\`[#*]+[ \t]*" string)
|
||||
(setq string (substring string (match-end 0))))
|
||||
(t nil))))
|
||||
string))
|
||||
|
||||
|
||||
;;; Public API
|
||||
|
||||
|
@ -692,6 +782,8 @@ TYPE is a string and KEY is a plist keyword. See
|
|||
"Set link TYPE properties to PARAMETERS.
|
||||
PARAMETERS should be keyword value pairs. See
|
||||
`org-link-parameters' for supported keys."
|
||||
(when (member type '("coderef" "custom-id" "fuzzy" "radio"))
|
||||
(error "Cannot override reserved link type: %S" type))
|
||||
(let ((data (assoc type org-link-parameters)))
|
||||
(if data (setcdr data (org-combine-plists (cdr data) parameters))
|
||||
(push (cons type parameters) org-link-parameters)
|
||||
|
@ -716,12 +808,10 @@ This should be called after the variable `org-link-parameters' has changed."
|
|||
(rx (seq "[["
|
||||
;; URI part: match group 1.
|
||||
(group
|
||||
;; Allow an even number of backslashes right
|
||||
;; before the closing bracket.
|
||||
(or (one-or-more "\\\\")
|
||||
(and (*? anything)
|
||||
(not (any "\\"))
|
||||
(zero-or-more "\\\\"))))
|
||||
(one-or-more
|
||||
(or (not (any "[]\\"))
|
||||
(and "\\" (zero-or-more "\\\\") (any "[]"))
|
||||
(and (one-or-more "\\") (not (any "[]"))))))
|
||||
"]"
|
||||
;; Description (optional): match group 2.
|
||||
(opt "[" (group (+? anything)) "]")
|
||||
|
@ -838,37 +928,26 @@ E.g. \"%C3%B6\" becomes the german o-Umlaut."
|
|||
|
||||
(defun org-link-escape (link)
|
||||
"Backslash-escape sensitive characters in string LINK."
|
||||
;; Escape closing square brackets followed by another square bracket
|
||||
;; or at the end of the link. Also escape final backslashes so that
|
||||
;; we do not escape inadvertently URI's closing bracket.
|
||||
(with-temp-buffer
|
||||
(insert link)
|
||||
(insert (make-string (- (skip-chars-backward "\\\\"))
|
||||
?\\))
|
||||
(while (search-backward "\]" nil t)
|
||||
(when (looking-at-p "\\]\\(?:[][]\\|\\'\\)")
|
||||
(insert (make-string (1+ (- (skip-chars-backward "\\\\")))
|
||||
?\\))))
|
||||
(buffer-string)))
|
||||
(replace-regexp-in-string
|
||||
(rx (seq (group (zero-or-more "\\")) (group (or string-end (any "[]")))))
|
||||
(lambda (m)
|
||||
(concat (match-string 1 m)
|
||||
(match-string 1 m)
|
||||
(and (/= (match-beginning 2) (match-end 2)) "\\")))
|
||||
link nil t 1))
|
||||
|
||||
(defun org-link-unescape (link)
|
||||
"Remove escaping backslash characters from string LINK."
|
||||
(with-temp-buffer
|
||||
(save-excursion (insert link))
|
||||
(while (re-search-forward "\\(\\\\+\\)\\]\\(?:[][]\\|\\'\\)" nil t)
|
||||
(replace-match (make-string (/ (- (match-end 1) (match-beginning 1)) 2)
|
||||
?\\)
|
||||
nil t nil 1))
|
||||
(goto-char (point-max))
|
||||
(delete-char (/ (- (skip-chars-backward "\\\\")) 2))
|
||||
(buffer-string)))
|
||||
(replace-regexp-in-string
|
||||
(rx (group (one-or-more "\\")) (or string-end (any "[]")))
|
||||
(lambda (_)
|
||||
(concat (make-string (/ (- (match-end 1) (match-beginning 1)) 2) ?\\)))
|
||||
link nil t 1))
|
||||
|
||||
(defun org-link-make-string (link &optional description)
|
||||
"Make a bracket link, consisting of LINK and DESCRIPTION.
|
||||
LINK is escaped with backslashes for inclusion in buffer."
|
||||
(unless (org-string-nw-p link) (error "Empty link"))
|
||||
(let* ((uri (org-link-escape link))
|
||||
(zero-width-space (string ?\x200B))
|
||||
(let* ((zero-width-space (string ?\x200B))
|
||||
(description
|
||||
(and (org-string-nw-p description)
|
||||
;; Description cannot contain two consecutive square
|
||||
|
@ -881,9 +960,10 @@ LINK is escaped with backslashes for inclusion in buffer."
|
|||
(replace-regexp-in-string "]\\'"
|
||||
(concat "\\&" zero-width-space)
|
||||
(org-trim description))))))
|
||||
(format "[[%s]%s]"
|
||||
uri
|
||||
(if description (format "[%s]" description) ""))))
|
||||
(if (not (org-string-nw-p link)) description
|
||||
(format "[[%s]%s]"
|
||||
(org-link-escape link)
|
||||
(if description (format "[%s]" description) "")))))
|
||||
|
||||
(defun org-store-link-functions ()
|
||||
"List of functions that are called to create and store a link.
|
||||
|
@ -930,7 +1010,8 @@ Abbreviations are defined in `org-link-abbrev-alist'."
|
|||
((string-match "%(\\([^)]+\\))" rpl)
|
||||
(replace-match
|
||||
(save-match-data
|
||||
(funcall (intern-soft (match-string 1 rpl)) tag)) t t rpl))
|
||||
(funcall (intern-soft (match-string 1 rpl)) tag))
|
||||
t t rpl))
|
||||
((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
|
||||
((string-match "%h" rpl)
|
||||
(replace-match (url-hexify-string (or tag "")) t t rpl))
|
||||
|
@ -938,63 +1019,60 @@ Abbreviations are defined in `org-link-abbrev-alist'."
|
|||
|
||||
(defun org-link-open (link &optional arg)
|
||||
"Open a link object LINK.
|
||||
Optional argument is passed to `org-open-file' when S is
|
||||
a \"file\" link."
|
||||
|
||||
ARG is an optional prefix argument. Some link types may handle
|
||||
it. For example, it determines what application to run when
|
||||
opening a \"file\" link.
|
||||
|
||||
Functions responsible for opening the link are either hard-coded
|
||||
for internal and \"file\" links, or stored as a parameter in
|
||||
`org-link-parameters', which see."
|
||||
(let ((type (org-element-property :type link))
|
||||
(path (org-element-property :path link)))
|
||||
(cond
|
||||
((equal type "file")
|
||||
(if (string-match "[*?{]" (file-name-nondirectory path))
|
||||
(dired path)
|
||||
;; Look into `org-link-parameters' in order to find
|
||||
;; a DEDICATED-FUNCTION to open file. The function will be
|
||||
;; applied on raw link instead of parsed link due to the
|
||||
;; limitation in `org-add-link-type' ("open" function called
|
||||
;; with a single argument). If no such function is found,
|
||||
;; fallback to `org-open-file'.
|
||||
(let* ((option (org-element-property :search-option link))
|
||||
(app (org-element-property :application link))
|
||||
(dedicated-function
|
||||
(org-link-get-parameter (if app (concat type "+" app) type)
|
||||
:follow)))
|
||||
(if dedicated-function
|
||||
(funcall dedicated-function
|
||||
(concat path
|
||||
(and option (concat "::" option))))
|
||||
(apply #'org-open-file
|
||||
path
|
||||
(cond (arg)
|
||||
((equal app "emacs") 'emacs)
|
||||
((equal app "sys") 'system))
|
||||
(cond ((not option) nil)
|
||||
((string-match-p "\\`[0-9]+\\'" option)
|
||||
(list (string-to-number option)))
|
||||
(t (list nil option))))))))
|
||||
((functionp (org-link-get-parameter type :follow))
|
||||
(funcall (org-link-get-parameter type :follow) path))
|
||||
((member type '("coderef" "custom-id" "fuzzy" "radio"))
|
||||
(unless (run-hook-with-args-until-success 'org-open-link-functions path)
|
||||
(if (not arg) (org-mark-ring-push)
|
||||
(switch-to-buffer-other-window (org-link--buffer-for-internals)))
|
||||
(let ((destination
|
||||
(org-with-wide-buffer
|
||||
(if (equal type "radio")
|
||||
(org-link--search-radio-target
|
||||
(org-element-property :path link))
|
||||
(org-link-search
|
||||
(pcase type
|
||||
("custom-id" (concat "#" path))
|
||||
("coderef" (format "(%s)" path))
|
||||
(_ path))
|
||||
;; Prevent fuzzy links from matching themselves.
|
||||
(and (equal type "fuzzy")
|
||||
(+ 2 (org-element-property :begin link)))))
|
||||
(point))))
|
||||
(unless (and (<= (point-min) destination)
|
||||
(>= (point-max) destination))
|
||||
(widen))
|
||||
(goto-char destination))))
|
||||
(t (browse-url-at-point)))))
|
||||
(pcase type
|
||||
;; Opening a "file" link requires special treatment since we
|
||||
;; first need to integrate search option, if any.
|
||||
("file"
|
||||
(let* ((option (org-element-property :search-option link))
|
||||
(path (if option (concat path "::" option) path)))
|
||||
(org-link-open-as-file path
|
||||
(pcase (org-element-property :application link)
|
||||
((guard arg) arg)
|
||||
("emacs" 'emacs)
|
||||
("sys" 'system)))))
|
||||
;; Internal links.
|
||||
((or "coderef" "custom-id" "fuzzy" "radio")
|
||||
(unless (run-hook-with-args-until-success 'org-open-link-functions path)
|
||||
(if (not arg) (org-mark-ring-push)
|
||||
(switch-to-buffer-other-window (org-link--buffer-for-internals)))
|
||||
(let ((destination
|
||||
(org-with-wide-buffer
|
||||
(if (equal type "radio")
|
||||
(org-link--search-radio-target path)
|
||||
(org-link-search
|
||||
(pcase type
|
||||
("custom-id" (concat "#" path))
|
||||
("coderef" (format "(%s)" path))
|
||||
(_ path))
|
||||
;; Prevent fuzzy links from matching themselves.
|
||||
(and (equal type "fuzzy")
|
||||
(+ 2 (org-element-property :begin link)))))
|
||||
(point))))
|
||||
(unless (and (<= (point-min) destination)
|
||||
(>= (point-max) destination))
|
||||
(widen))
|
||||
(goto-char destination))))
|
||||
(_
|
||||
;; Look for a dedicated "follow" function in custom links.
|
||||
(let ((f (org-link-get-parameter type :follow)))
|
||||
(when (functionp f)
|
||||
;; Function defined in `:follow' parameter may use a single
|
||||
;; argument, as it was mandatory before Org 9.4. This is
|
||||
;; deprecated, but support it for now.
|
||||
(condition-case nil
|
||||
(funcall (org-link-get-parameter type :follow) path arg)
|
||||
(wrong-number-of-arguments
|
||||
(funcall (org-link-get-parameter type :follow) path)))))))))
|
||||
|
||||
(defun org-link-open-from-string (s &optional arg)
|
||||
"Open a link in the string S, as if it was in Org mode.
|
||||
|
@ -1095,10 +1173,9 @@ of matched result, which is either `dedicated' or `fuzzy'."
|
|||
(catch :name-match
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward name nil t)
|
||||
(let ((element (org-element-at-point)))
|
||||
(when (equal words
|
||||
(split-string
|
||||
(org-element-property :name element)))
|
||||
(let* ((element (org-element-at-point))
|
||||
(name (org-element-property :name element)))
|
||||
(when (and name (equal words (split-string name)))
|
||||
(setq type 'dedicated)
|
||||
(beginning-of-line)
|
||||
(throw :name-match t))))
|
||||
|
@ -1111,18 +1188,14 @@ of matched result, which is either `dedicated' or `fuzzy'."
|
|||
(format "%s.*\\(?:%s[ \t]\\)?.*%s"
|
||||
org-outline-regexp-bol
|
||||
org-comment-string
|
||||
(mapconcat #'regexp-quote words ".+")))
|
||||
(cookie-re "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]")
|
||||
(comment-re (format "\\`%s[ \t]+" org-comment-string)))
|
||||
(mapconcat #'regexp-quote words ".+"))))
|
||||
(goto-char (point-min))
|
||||
(catch :found
|
||||
(while (re-search-forward title-re nil t)
|
||||
(when (equal words
|
||||
(split-string
|
||||
(replace-regexp-in-string
|
||||
cookie-re ""
|
||||
(replace-regexp-in-string
|
||||
comment-re "" (org-get-heading t t t)))))
|
||||
(org-link--normalize-string
|
||||
(org-get-heading t t t t))))
|
||||
(throw :found t)))
|
||||
nil)))
|
||||
(beginning-of-line)
|
||||
|
@ -1173,24 +1246,40 @@ of matched result, which is either `dedicated' or `fuzzy'."
|
|||
type))
|
||||
|
||||
(defun org-link-heading-search-string (&optional string)
|
||||
"Make search string for the current headline or STRING."
|
||||
(let ((s (or string
|
||||
(and (derived-mode-p 'org-mode)
|
||||
(save-excursion
|
||||
(org-back-to-heading t)
|
||||
(org-element-property :raw-value
|
||||
(org-element-at-point))))))
|
||||
(lines org-link-context-for-files))
|
||||
(unless string (setq s (concat "*" s))) ;Add * for headlines
|
||||
(setq s (replace-regexp-in-string "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" s))
|
||||
(when (and string (integerp lines) (> lines 0))
|
||||
(let ((slines (org-split-string s "\n")))
|
||||
(when (< lines (length slines))
|
||||
(setq s (mapconcat
|
||||
#'identity
|
||||
(reverse (nthcdr (- (length slines) lines)
|
||||
(reverse slines))) "\n")))))
|
||||
(mapconcat #'identity (split-string s) " ")))
|
||||
"Make search string for the current headline or STRING.
|
||||
|
||||
Search string starts with an asterisk. COMMENT keyword and
|
||||
statistics cookies are removed, and contiguous spaces are packed
|
||||
into a single one.
|
||||
|
||||
When optional argument STRING is non-nil, assume it a headline,
|
||||
without any asterisk, TODO or COMMENT keyword, and without any
|
||||
priority cookie or tag."
|
||||
(concat "*"
|
||||
(org-link--normalize-string
|
||||
(or string (org-get-heading t t t t)))))
|
||||
|
||||
(defun org-link-open-as-file (path arg)
|
||||
"Pretend PATH is a file name and open it.
|
||||
|
||||
According to \"file\"-link syntax, PATH may include additional
|
||||
search options, separated from the file name with \"::\".
|
||||
|
||||
This function is meant to be used as a possible tool for
|
||||
`:follow' property in `org-link-parameters'."
|
||||
(let* ((option (and (string-match "::\\(.*\\)\\'" path)
|
||||
(match-string 1 path)))
|
||||
(file-name (if (not option) path
|
||||
(substring path 0 (match-beginning 0)))))
|
||||
(if (string-match "[*?{]" (file-name-nondirectory file-name))
|
||||
(dired file-name)
|
||||
(apply #'org-open-file
|
||||
file-name
|
||||
arg
|
||||
(cond ((not option) nil)
|
||||
((string-match-p "\\`[0-9]+\\'" option)
|
||||
(list (string-to-number option)))
|
||||
(t (list nil option)))))))
|
||||
|
||||
(defun org-link-display-format (s)
|
||||
"Replace links in string S with their description.
|
||||
|
@ -1211,15 +1300,15 @@ If there is no description, use the link target."
|
|||
;;; Built-in link types
|
||||
|
||||
;;;; "doi" link type
|
||||
(defun org-link--open-doi (path)
|
||||
(defun org-link--open-doi (path arg)
|
||||
"Open a \"doi\" type link.
|
||||
PATH is a the path to search for, as a string."
|
||||
(browse-url (url-encode-url (concat org-link-doi-server-url path))))
|
||||
(browse-url (url-encode-url (concat org-link-doi-server-url path)) arg))
|
||||
|
||||
(org-link-set-parameters "doi" :follow #'org-link--open-doi)
|
||||
|
||||
;;;; "elisp" link type
|
||||
(defun org-link--open-elisp (path)
|
||||
(defun org-link--open-elisp (path _)
|
||||
"Open a \"elisp\" type link.
|
||||
PATH is the sexp to evaluate, as a string."
|
||||
(if (or (and (org-string-nw-p org-link-elisp-skip-confirm-regexp)
|
||||
|
@ -1240,7 +1329,7 @@ PATH is the sexp to evaluate, as a string."
|
|||
(org-link-set-parameters "file" :complete #'org-link-complete-file)
|
||||
|
||||
;;;; "help" link type
|
||||
(defun org-link--open-help (path)
|
||||
(defun org-link--open-help (path _)
|
||||
"Open a \"help\" type link.
|
||||
PATH is a symbol name, as a string."
|
||||
(pcase (intern path)
|
||||
|
@ -1254,10 +1343,11 @@ PATH is a symbol name, as a string."
|
|||
(dolist (scheme '("ftp" "http" "https" "mailto" "news"))
|
||||
(org-link-set-parameters scheme
|
||||
:follow
|
||||
(lambda (url) (browse-url (concat scheme ":" url)))))
|
||||
(lambda (url arg)
|
||||
(browse-url (concat scheme ":" url) arg))))
|
||||
|
||||
;;;; "shell" link type
|
||||
(defun org-link--open-shell (path)
|
||||
(defun org-link--open-shell (path _)
|
||||
"Open a \"shell\" type link.
|
||||
PATH is the command to execute, as a string."
|
||||
(if (or (and (org-string-nw-p org-link-shell-skip-confirm-regexp)
|
||||
|
@ -1375,7 +1465,7 @@ non-nil."
|
|||
(move-beginning-of-line 2)
|
||||
(set-mark (point)))))
|
||||
(setq org-store-link-plist nil)
|
||||
(let (link cpltxt desc description search txt custom-id agenda-link)
|
||||
(let (link cpltxt desc description search custom-id agenda-link)
|
||||
(cond
|
||||
;; Store a link using an external link type, if any function is
|
||||
;; available. If more than one can generate a link from current
|
||||
|
@ -1465,10 +1555,16 @@ non-nil."
|
|||
(org-link-store-props :type "calendar" :date cd)))
|
||||
|
||||
((eq major-mode 'help-mode)
|
||||
(setq link (concat "help:" (save-excursion
|
||||
(goto-char (point-min))
|
||||
(looking-at "^[^ ]+")
|
||||
(match-string 0))))
|
||||
(let ((symbol (replace-regexp-in-string
|
||||
;; Help mode escapes backquotes and backslashes
|
||||
;; before displaying them. E.g., "`" appears
|
||||
;; as "\'" for reasons. Work around this.
|
||||
(rx "\\" (group (or "`" "\\"))) "\\1"
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(looking-at "^[^ ]+")
|
||||
(match-string 0)))))
|
||||
(setq link (concat "help:" symbol)))
|
||||
(org-link-store-props :type "help"))
|
||||
|
||||
((eq major-mode 'w3-mode)
|
||||
|
@ -1534,30 +1630,35 @@ non-nil."
|
|||
(abbreviate-file-name
|
||||
(buffer-file-name (buffer-base-buffer))))))))
|
||||
(t
|
||||
;; Just link to current headline
|
||||
;; Just link to current headline.
|
||||
(setq cpltxt (concat "file:"
|
||||
(abbreviate-file-name
|
||||
(buffer-file-name (buffer-base-buffer)))))
|
||||
;; Add a context search string
|
||||
;; Add a context search string.
|
||||
(when (org-xor org-link-context-for-files (equal arg '(4)))
|
||||
(let* ((element (org-element-at-point))
|
||||
(name (org-element-property :name element)))
|
||||
(setq txt (cond
|
||||
((org-at-heading-p) nil)
|
||||
(name)
|
||||
((org-region-active-p)
|
||||
(buffer-substring (region-beginning) (region-end)))))
|
||||
(when (or (null txt) (string-match "\\S-" txt))
|
||||
(setq cpltxt
|
||||
(concat cpltxt "::"
|
||||
(condition-case nil
|
||||
(org-link-heading-search-string txt)
|
||||
(error "")))
|
||||
desc (or name
|
||||
(nth 4 (ignore-errors (org-heading-components)))
|
||||
"NONE")))))
|
||||
(when (string-match "::\\'" cpltxt)
|
||||
(setq cpltxt (substring cpltxt 0 -2)))
|
||||
(name (org-element-property :name element))
|
||||
(context
|
||||
(cond
|
||||
((let ((region (org-link--context-from-region)))
|
||||
(and region (org-link--normalize-string region t))))
|
||||
(name)
|
||||
((org-before-first-heading-p)
|
||||
(org-link--normalize-string (org-current-line-string) t))
|
||||
(t (org-link-heading-search-string)))))
|
||||
(when (org-string-nw-p context)
|
||||
(setq cpltxt (format "%s::%s" cpltxt context))
|
||||
(setq desc
|
||||
(or name
|
||||
;; Although description is not a search
|
||||
;; string, use `org-link--normalize-string'
|
||||
;; to prettify it (contiguous white spaces)
|
||||
;; and remove volatile contents (statistics
|
||||
;; cookies).
|
||||
(and (not (org-before-first-heading-p))
|
||||
(org-link--normalize-string
|
||||
(org-get-heading t t t t)))
|
||||
"NONE")))))
|
||||
(setq link cpltxt)))))
|
||||
|
||||
((buffer-file-name (buffer-base-buffer))
|
||||
|
@ -1565,16 +1666,16 @@ non-nil."
|
|||
(setq cpltxt (concat "file:"
|
||||
(abbreviate-file-name
|
||||
(buffer-file-name (buffer-base-buffer)))))
|
||||
;; Add a context string.
|
||||
;; Add a context search string.
|
||||
(when (org-xor org-link-context-for-files (equal arg '(4)))
|
||||
(setq txt (if (org-region-active-p)
|
||||
(buffer-substring (region-beginning) (region-end))
|
||||
(buffer-substring (point-at-bol) (point-at-eol))))
|
||||
;; Only use search option if there is some text.
|
||||
(when (string-match "\\S-" txt)
|
||||
(setq cpltxt
|
||||
(concat cpltxt "::" (org-link-heading-search-string txt))
|
||||
desc "NONE")))
|
||||
(let ((context (org-link--normalize-string
|
||||
(or (org-link--context-from-region)
|
||||
(org-current-line-string))
|
||||
t)))
|
||||
;; Only use search option if there is some text.
|
||||
(when (org-string-nw-p context)
|
||||
(setq cpltxt (format "%s::%s" cpltxt context))
|
||||
(setq desc "NONE"))))
|
||||
(setq link cpltxt))
|
||||
|
||||
(interactive?
|
||||
|
@ -1589,15 +1690,19 @@ non-nil."
|
|||
(cond ((not desc))
|
||||
((equal desc "NONE") (setq desc nil))
|
||||
(t (setq desc (org-link-display-format desc))))
|
||||
;; Return the link
|
||||
;; Store and return the link
|
||||
(if (not (and interactive? link))
|
||||
(or agenda-link (and link (org-link-make-string link desc)))
|
||||
(push (list link desc) org-stored-links)
|
||||
(message "Stored: %s" (or desc link))
|
||||
(when custom-id
|
||||
(setq link (concat "file:" (abbreviate-file-name
|
||||
(buffer-file-name)) "::#" custom-id))
|
||||
(push (list link desc) org-stored-links))
|
||||
(if (member (list link desc) org-stored-links)
|
||||
(message "This link already exists")
|
||||
(push (list link desc) org-stored-links)
|
||||
(message "Stored: %s" (or desc link))
|
||||
(when custom-id
|
||||
(setq link (concat "file:"
|
||||
(abbreviate-file-name
|
||||
(buffer-file-name (buffer-base-buffer)))
|
||||
"::#" custom-id))
|
||||
(push (list link desc) org-stored-links)))
|
||||
(car org-stored-links)))))
|
||||
|
||||
;;;###autoload
|
||||
|
@ -1737,13 +1842,14 @@ Use TAB to complete link prefixes, then RET for type-specific completion support
|
|||
;; Check if we are linking to the current file with a search
|
||||
;; option If yes, simplify the link by using only the search
|
||||
;; option.
|
||||
(when (and buffer-file-name
|
||||
(when (and (buffer-file-name (buffer-base-buffer))
|
||||
(let ((case-fold-search nil))
|
||||
(string-match "\\`file:\\(.+?\\)::" link)))
|
||||
(let ((path (match-string-no-properties 1 link))
|
||||
(search (substring-no-properties link (match-end 0))))
|
||||
(save-match-data
|
||||
(when (equal (file-truename buffer-file-name) (file-truename path))
|
||||
(when (equal (file-truename (buffer-file-name (buffer-base-buffer)))
|
||||
(file-truename path))
|
||||
;; We are linking to this same file, with a search option
|
||||
(setq link search)))))
|
||||
|
||||
|
@ -1903,7 +2009,10 @@ Also refresh fontification if needed."
|
|||
|
||||
(org-link-make-regexps)
|
||||
|
||||
|
||||
(provide 'ol)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; ol.el ends here
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,7 +24,7 @@
|
|||
;;
|
||||
;;; Commentary:
|
||||
|
||||
;; This file contains the face definitions for Org.
|
||||
;; This file contains the archive functionality for Org.
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
@ -91,6 +91,25 @@ When a string, a %s formatter will be replaced by the file name."
|
|||
(const :tag "When archiving a subtree to the same file" infile)
|
||||
(const :tag "Always" t)))
|
||||
|
||||
(defcustom org-archive-subtree-save-file-p 'from-org
|
||||
"Conditionally save the archive file after archiving a subtree.
|
||||
This variable can be any of the following symbols:
|
||||
|
||||
t saves in all cases.
|
||||
`from-org' prevents saving from an agenda-view.
|
||||
`from-agenda' saves only when the archive is initiated from an agenda-view.
|
||||
nil prevents saving in all cases.
|
||||
|
||||
Note that, regardless of this value, the archive buffer is never
|
||||
saved when archiving into a location in the current buffer."
|
||||
:group 'org-archive
|
||||
:package-version '(Org . "9.4")
|
||||
:type '(choice
|
||||
(const :tag "Save archive buffer" t)
|
||||
(const :tag "Save when archiving from agenda" from-agenda)
|
||||
(const :tag "Save when archiving from an Org buffer" from-org)
|
||||
(const :tag "Do not save")))
|
||||
|
||||
(defcustom org-archive-save-context-info '(time file olpath category todo itags)
|
||||
"Parts of context info that should be stored as properties when archiving.
|
||||
When a subtree is moved to an archive file, it loses information given by
|
||||
|
@ -230,12 +249,20 @@ direct children of this heading."
|
|||
((find-buffer-visiting afile))
|
||||
((find-file-noselect afile))
|
||||
(t (error "Cannot access file \"%s\"" afile))))
|
||||
(org-odd-levels-only
|
||||
(if (local-variable-p 'org-odd-levels-only (current-buffer))
|
||||
org-odd-levels-only
|
||||
tr-org-odd-levels-only))
|
||||
level datetree-date datetree-subheading-p)
|
||||
(when (string-match "\\`datetree/" heading)
|
||||
;; Replace with ***, to represent the 3 levels of headings the
|
||||
;; datetree has.
|
||||
(setq heading (replace-regexp-in-string "\\`datetree/" "***" heading))
|
||||
(setq datetree-subheading-p (> (length heading) 3))
|
||||
(when (string-match "\\`datetree/\\(\\**\\)" heading)
|
||||
;; "datetree/" corresponds to 3 levels of headings.
|
||||
(let ((nsub (length (match-string 1 heading))))
|
||||
(setq heading (concat (make-string
|
||||
(+ (if org-odd-levels-only 5 3)
|
||||
(* (org-level-increment) nsub))
|
||||
?*)
|
||||
(substring heading (match-end 0))))
|
||||
(setq datetree-subheading-p (> nsub 0)))
|
||||
(setq datetree-date (org-date-to-gregorian
|
||||
(or (org-entry-get nil "CLOSED" t) time))))
|
||||
(if (and (> (length heading) 0)
|
||||
|
@ -290,11 +317,7 @@ direct children of this heading."
|
|||
(org-todo-kwd-alist tr-org-todo-kwd-alist)
|
||||
(org-done-keywords tr-org-done-keywords)
|
||||
(org-todo-regexp tr-org-todo-regexp)
|
||||
(org-todo-line-regexp tr-org-todo-line-regexp)
|
||||
(org-odd-levels-only
|
||||
(if (local-variable-p 'org-odd-levels-only (current-buffer))
|
||||
org-odd-levels-only
|
||||
tr-org-odd-levels-only)))
|
||||
(org-todo-line-regexp tr-org-todo-line-regexp))
|
||||
(goto-char (point-min))
|
||||
(org-show-all '(headings blocks))
|
||||
(if (and heading (not (and datetree-date (not datetree-subheading-p))))
|
||||
|
@ -361,6 +384,15 @@ direct children of this heading."
|
|||
(point)
|
||||
(concat "ARCHIVE_" (upcase (symbol-name item)))
|
||||
value))))
|
||||
;; Save the buffer, if it is not the same buffer and
|
||||
;; depending on `org-archive-subtree-save-file-p'.
|
||||
(unless (eq this-buffer buffer)
|
||||
(when (or (eq org-archive-subtree-save-file-p t)
|
||||
(eq org-archive-subtree-save-file-p
|
||||
(if (boundp 'org-archive-from-agenda)
|
||||
'from-agenda
|
||||
'from-org)))
|
||||
(save-buffer)))
|
||||
(widen))))
|
||||
;; Here we are back in the original buffer. Everything seems
|
||||
;; to have worked. So now run hooks, cut the tree and finish
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
;; Author: John Wiegley <johnw@newartisans.com>
|
||||
;; Keywords: org data attachment
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
;;
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
|
@ -41,6 +40,8 @@
|
|||
(require 'org-id)
|
||||
|
||||
(declare-function dired-dwim-target-directory "dired-aux")
|
||||
(declare-function org-element-property "org-element" (property element))
|
||||
(declare-function org-element-type "org-element" (element))
|
||||
|
||||
(defgroup org-attach nil
|
||||
"Options concerning attachments in Org mode."
|
||||
|
@ -129,8 +130,7 @@ Selective means to respect the inheritance setting in
|
|||
:type '(choice
|
||||
(const :tag "Don't use inheritance" nil)
|
||||
(const :tag "Inherit parent node attachments" t)
|
||||
(const :tag "Respect org-use-property-inheritance" selective))
|
||||
:type 'boolean)
|
||||
(const :tag "Respect org-use-property-inheritance" selective)))
|
||||
|
||||
(defcustom org-attach-store-link-p nil
|
||||
"Non-nil means store a link to a file when attaching it."
|
||||
|
@ -139,7 +139,8 @@ Selective means to respect the inheritance setting in
|
|||
:type '(choice
|
||||
(const :tag "Don't store link" nil)
|
||||
(const :tag "Link to origin location" t)
|
||||
(const :tag "Link to the attach-dir location" attached)))
|
||||
(const :tag "Attachment link to the attach-dir location" attached)
|
||||
(const :tag "File link to the attach-dir location" file)))
|
||||
|
||||
(defcustom org-attach-archive-delete nil
|
||||
"Non-nil means attachments are deleted upon archiving a subtree.
|
||||
|
@ -254,16 +255,16 @@ Shows a list of commands and prompts for another key to execute a command."
|
|||
(get-text-property (point) 'org-marker)))
|
||||
(unless marker
|
||||
(error "No item in current line")))
|
||||
(save-excursion
|
||||
(when marker
|
||||
(set-buffer (marker-buffer marker))
|
||||
(goto-char marker))
|
||||
(org-back-to-heading t)
|
||||
(org-with-point-at marker
|
||||
(org-back-to-heading-or-point-min t)
|
||||
(save-excursion
|
||||
(save-window-excursion
|
||||
(unless org-attach-expert
|
||||
(with-output-to-temp-buffer "*Org Attach*"
|
||||
(princ
|
||||
(org-switch-to-buffer-other-window "*Org Attach*")
|
||||
(erase-buffer)
|
||||
(setq cursor-type nil
|
||||
header-line-format "Use C-v, M-v, C-n or C-p to navigate.")
|
||||
(insert
|
||||
(concat "Attachment folder:\n"
|
||||
(or dir
|
||||
"Can't find an existing attachment-folder")
|
||||
|
@ -286,11 +287,14 @@ Shows a list of commands and prompts for another key to execute a command."
|
|||
"Invalid `org-attach-commands' item: %S"
|
||||
entry))))
|
||||
org-attach-commands
|
||||
"\n"))))))
|
||||
"\n")))))
|
||||
(org-fit-window-to-buffer (get-buffer-window "*Org Attach*"))
|
||||
(message "Select command: [%s]"
|
||||
(concat (mapcar #'caar org-attach-commands)))
|
||||
(setq c (read-char-exclusive))
|
||||
(let ((msg (format "Select command: [%s]"
|
||||
(concat (mapcar #'caar org-attach-commands)))))
|
||||
(message msg)
|
||||
(while (and (setq c (read-char-exclusive))
|
||||
(memq c '(14 16 22 134217846)))
|
||||
(org-scroll c t)))
|
||||
(and (get-buffer "*Org Attach*") (kill-buffer "*Org Attach*"))))
|
||||
(let ((command (cl-some (lambda (entry)
|
||||
(and (memq c (nth 0 entry)) (nth 1 entry)))
|
||||
|
@ -457,14 +461,6 @@ DIR-property exists (that is different from the unset one)."
|
|||
"Turn the autotag off."
|
||||
(org-attach-tag 'off))
|
||||
|
||||
(defun org-attach-store-link (file)
|
||||
"Add a link to `org-stored-link' when attaching a file.
|
||||
Only do this when `org-attach-store-link-p' is non-nil."
|
||||
(setq org-stored-links
|
||||
(cons (list (org-attach-expand-link file)
|
||||
(file-name-nondirectory file))
|
||||
org-stored-links)))
|
||||
|
||||
(defun org-attach-url (url)
|
||||
(interactive "MURL of the file to attach: \n")
|
||||
(let ((org-attach-method 'url))
|
||||
|
@ -491,7 +487,7 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
|
|||
`org-attach-method'."
|
||||
(interactive
|
||||
(list
|
||||
(read-file-name "File to keep as an attachment:"
|
||||
(read-file-name "File to keep as an attachment: "
|
||||
(or (progn
|
||||
(require 'dired-aux)
|
||||
(dired-dwim-target-directory))
|
||||
|
@ -501,22 +497,30 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
|
|||
(setq method (or method org-attach-method))
|
||||
(let ((basename (file-name-nondirectory file)))
|
||||
(let* ((attach-dir (org-attach-dir 'get-create))
|
||||
(fname (expand-file-name basename attach-dir)))
|
||||
(attach-file (expand-file-name basename attach-dir)))
|
||||
(cond
|
||||
((eq method 'mv) (rename-file file fname))
|
||||
((eq method 'cp) (copy-file file fname))
|
||||
((eq method 'ln) (add-name-to-file file fname))
|
||||
((eq method 'lns) (make-symbolic-link file fname))
|
||||
((eq method 'url) (url-copy-file file fname)))
|
||||
((eq method 'mv) (rename-file file attach-file))
|
||||
((eq method 'cp) (copy-file file attach-file))
|
||||
((eq method 'ln) (add-name-to-file file attach-file))
|
||||
((eq method 'lns) (make-symbolic-link file attach-file))
|
||||
((eq method 'url) (url-copy-file file attach-file)))
|
||||
(run-hook-with-args 'org-attach-after-change-hook attach-dir)
|
||||
(org-attach-tag)
|
||||
(cond ((eq org-attach-store-link-p 'attached)
|
||||
(org-attach-store-link fname))
|
||||
(push (list (concat "attachment:" (file-name-nondirectory attach-file))
|
||||
(file-name-nondirectory attach-file))
|
||||
org-stored-links))
|
||||
((eq org-attach-store-link-p t)
|
||||
(org-attach-store-link file)))
|
||||
(push (list (concat "file:" file)
|
||||
(file-name-nondirectory file))
|
||||
org-stored-links))
|
||||
((eq org-attach-store-link-p 'file)
|
||||
(push (list (concat "file:" attach-file)
|
||||
(file-name-nondirectory attach-file))
|
||||
org-stored-links)))
|
||||
(if visit-dir
|
||||
(dired attach-dir)
|
||||
(message "File %S is now an attachment." basename)))))
|
||||
(message "File %S is now an attachment" basename)))))
|
||||
|
||||
(defun org-attach-attach-cp ()
|
||||
"Attach a file by copying it."
|
||||
|
@ -569,13 +573,18 @@ The attachment is created as an Emacs buffer."
|
|||
(defun org-attach-delete-all (&optional force)
|
||||
"Delete all attachments from the current outline node.
|
||||
This actually deletes the entire attachment directory.
|
||||
A safer way is to open the directory in dired and delete from there."
|
||||
A safer way is to open the directory in dired and delete from there.
|
||||
|
||||
With prefix argument FORCE, directory will be recursively deleted
|
||||
with no prompts."
|
||||
(interactive "P")
|
||||
(let ((attach-dir (org-attach-dir)))
|
||||
(when (and attach-dir
|
||||
(or force
|
||||
(yes-or-no-p "Really remove all attachments of this entry? ")))
|
||||
(delete-directory attach-dir (yes-or-no-p "Recursive?") t)
|
||||
(delete-directory attach-dir
|
||||
(or force (yes-or-no-p "Recursive?"))
|
||||
t)
|
||||
(message "Attachment directory removed")
|
||||
(run-hook-with-args 'org-attach-after-change-hook attach-dir)
|
||||
(org-attach-untag))))
|
||||
|
@ -642,37 +651,37 @@ See `org-attach-open'."
|
|||
Basically, this adds the path to the attachment directory."
|
||||
(expand-file-name file (org-attach-dir)))
|
||||
|
||||
(defun org-attach-expand-link (file)
|
||||
"Return a file link pointing to the current entry's attachment file FILE.
|
||||
Basically, this adds the path to the attachment directory, and a \"file:\"
|
||||
prefix."
|
||||
(concat "file:" (org-attach-expand file)))
|
||||
(defun org-attach-expand-links (_)
|
||||
"Expand links in current buffer.
|
||||
It is meant to be added to `org-export-before-parsing-hook'."
|
||||
(save-excursion
|
||||
(while (re-search-forward "attachment:" nil t)
|
||||
(let ((link (org-element-context)))
|
||||
(when (and (eq 'link (org-element-type link))
|
||||
(string-equal "attachment"
|
||||
(org-element-property :type link)))
|
||||
(let* ((description (and (org-element-property :contents-begin link)
|
||||
(buffer-substring-no-properties
|
||||
(org-element-property :contents-begin link)
|
||||
(org-element-property :contents-end link))))
|
||||
(file (org-element-property :path link))
|
||||
(new-link (org-link-make-string
|
||||
(concat "file:" (org-attach-expand file))
|
||||
description)))
|
||||
(goto-char (org-element-property :end link))
|
||||
(skip-chars-backward " \t")
|
||||
(delete-region (org-element-property :begin link) (point))
|
||||
(insert new-link)))))))
|
||||
|
||||
(defun org-attach-follow (file arg)
|
||||
"Open FILE attachment.
|
||||
See `org-open-file' for details about ARG."
|
||||
(org-link-open-as-file (org-attach-expand file) arg))
|
||||
|
||||
(org-link-set-parameters "attachment"
|
||||
:follow #'org-attach-open-link
|
||||
:export #'org-attach-export-link
|
||||
:follow #'org-attach-follow
|
||||
:complete #'org-attach-complete-link)
|
||||
|
||||
(defun org-attach-open-link (link &optional in-emacs)
|
||||
"Attachment link type LINK is expanded with the attached directory and opened.
|
||||
|
||||
With optional prefix argument IN-EMACS, Emacs will visit the file.
|
||||
With a double \\[universal-argument] \\[universal-argument] \
|
||||
prefix arg, Org tries to avoid opening in Emacs
|
||||
and to use an external application to visit the file."
|
||||
(interactive "P")
|
||||
(let (line search)
|
||||
(cond
|
||||
((string-match "::\\([0-9]+\\)\\'" link)
|
||||
(setq line (string-to-number (match-string 1 link))
|
||||
link (substring link 0 (match-beginning 0))))
|
||||
((string-match "::\\(.+\\)\\'" link)
|
||||
(setq search (match-string 1 link)
|
||||
link (substring link 0 (match-beginning 0)))))
|
||||
(if (string-match "[*?{]" (file-name-nondirectory link))
|
||||
(dired (org-attach-expand link))
|
||||
(org-open-file (org-attach-expand link) in-emacs line search))))
|
||||
|
||||
(defun org-attach-complete-link ()
|
||||
"Advise the user with the available files in the attachment directory."
|
||||
(let ((attach-dir (org-attach-dir)))
|
||||
|
@ -691,26 +700,6 @@ and to use an external application to visit the file."
|
|||
(t (concat "attachment:" file))))
|
||||
(error "No attachment directory exist"))))
|
||||
|
||||
(defun org-attach-export-link (link description format)
|
||||
"Translate attachment LINK from Org mode format to exported FORMAT.
|
||||
Also includes the DESCRIPTION of the link in the export."
|
||||
(save-excursion
|
||||
(let (path desc)
|
||||
(cond
|
||||
((string-match "::\\([0-9]+\\)\\'" link)
|
||||
(setq link (substring link 0 (match-beginning 0))))
|
||||
((string-match "::\\(.+\\)\\'" link)
|
||||
(setq link (substring link 0 (match-beginning 0)))))
|
||||
(setq path (file-relative-name (org-attach-expand link))
|
||||
desc (or description link))
|
||||
(pcase format
|
||||
(`html (format "<a target=\"_blank\" href=\"%s\">%s</a>" path desc))
|
||||
(`latex (format "\\href{%s}{%s}" path desc))
|
||||
(`texinfo (format "@uref{%s,%s}" path desc))
|
||||
(`ascii (format "%s (%s)" desc path))
|
||||
(`md (format "[%s](%s)" desc path))
|
||||
(_ path)))))
|
||||
|
||||
(defun org-attach-archive-delete-maybe ()
|
||||
"Maybe delete subtree attachments when archiving.
|
||||
This function is called by `org-archive-hook'. The option
|
||||
|
@ -758,6 +747,7 @@ Idea taken from `gnus-dired-attach'."
|
|||
|
||||
|
||||
(add-hook 'org-archive-hook 'org-attach-archive-delete-maybe)
|
||||
(add-hook 'org-export-before-parsing-hook 'org-attach-expand-links)
|
||||
|
||||
(provide 'org-attach)
|
||||
|
||||
|
|
|
@ -49,11 +49,13 @@
|
|||
|
||||
(require 'cl-lib)
|
||||
(require 'org)
|
||||
(require 'org-refile)
|
||||
|
||||
(declare-function org-at-encrypted-entry-p "org-crypt" ())
|
||||
(declare-function org-at-table-p "org-table" (&optional table-type))
|
||||
(declare-function org-clock-update-mode-line "org-clock" (&optional refresh))
|
||||
(declare-function org-datetree-find-date-create "org-datetree" (date &optional keep-restriction))
|
||||
(declare-function org-datetree-find-month-create (d &optional keep-restriction))
|
||||
(declare-function org-decrypt-entry "org-crypt" ())
|
||||
(declare-function org-element-at-point "org-element" ())
|
||||
(declare-function org-element-lineage "org-element" (datum &optional types with-self))
|
||||
|
@ -68,6 +70,7 @@
|
|||
|
||||
(defvar dired-buffers)
|
||||
(defvar org-end-time-was-given)
|
||||
(defvar org-keyword-properties)
|
||||
(defvar org-remember-default-headline)
|
||||
(defvar org-remember-templates)
|
||||
(defvar org-store-link-plist)
|
||||
|
@ -156,14 +159,20 @@ description A short string describing the template, will be shown during
|
|||
type The type of entry. Valid types are:
|
||||
entry an Org node, with a headline. Will be filed
|
||||
as the child of the target entry or as a
|
||||
top-level entry.
|
||||
top-level entry. Its default template is:
|
||||
\"* %?\n %a\"
|
||||
item a plain list item, will be placed in the
|
||||
first plain list at the target
|
||||
location.
|
||||
first plain list at the target location.
|
||||
Its default template is:
|
||||
\"- %?\"
|
||||
checkitem a checkbox item. This differs from the
|
||||
plain list item only in so far as it uses a
|
||||
different default template.
|
||||
different default template. Its default
|
||||
template is:
|
||||
\"- [ ] %?\"
|
||||
table-line a new line in the first table at target location.
|
||||
Its default template is:
|
||||
\"| %? |\"
|
||||
plain text to be inserted as it is.
|
||||
|
||||
target Specification of where the captured item should be placed.
|
||||
|
@ -211,9 +220,10 @@ target Specification of where the captured item should be placed.
|
|||
Most general way: write your own function which both visits
|
||||
the file and moves point to the right location
|
||||
|
||||
template The template for creating the capture item. If you leave this
|
||||
empty, an appropriate default template will be used. See below
|
||||
for more details. Instead of a string, this may also be one of
|
||||
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).
|
||||
Instead of a string, this may also be one of:
|
||||
|
||||
(file \"/path/to/template-file\")
|
||||
(function function-returning-the-template)
|
||||
|
@ -236,15 +246,15 @@ properties are:
|
|||
|
||||
:jump-to-captured When set, jump to the captured entry when finished.
|
||||
|
||||
:empty-lines Set this to the number of lines the should be inserted
|
||||
:empty-lines Set this to the number of lines that should be inserted
|
||||
before and after the new item. Default 0, only common
|
||||
other value is 1.
|
||||
|
||||
:empty-lines-before Set this to the number of lines the should be inserted
|
||||
:empty-lines-before Set this to the number of lines that should be inserted
|
||||
before the new item. Overrides :empty-lines for the
|
||||
number lines inserted before.
|
||||
|
||||
:empty-lines-after Set this to the number of lines the should be inserted
|
||||
:empty-lines-after Set this to the number of lines that should be inserted
|
||||
after the new item. Overrides :empty-lines for the
|
||||
number of lines inserted after.
|
||||
|
||||
|
@ -260,7 +270,9 @@ properties are:
|
|||
:time-prompt Prompt for a date/time to be used for date/week trees
|
||||
and when filling the template.
|
||||
|
||||
:tree-type When `week', make a week tree instead of the month tree.
|
||||
:tree-type When `week', make a week tree instead of the month-day
|
||||
tree. When `month', make a month tree instead of the
|
||||
month-day tree.
|
||||
|
||||
:unnarrowed Do not narrow the target buffer, simply show the
|
||||
full buffer. Default is to narrow it so that you
|
||||
|
@ -322,7 +334,7 @@ be replaced with content and expanded:
|
|||
%^L Like %^C, but insert as link.
|
||||
%^{prop}p Prompt the user for a value for property `prop'.
|
||||
%^{prompt} Prompt the user for a string and replace this sequence with it.
|
||||
A default value and a completion table ca be specified like this:
|
||||
A default value and a completion table can be specified like this:
|
||||
%^{prompt|default|completion2|completion3|...}.
|
||||
%? After completing the template, position cursor here.
|
||||
%\\1 ... %\\N Insert the text entered at the nth %^{prompt}, where N
|
||||
|
@ -625,7 +637,7 @@ of the day at point (if any) or the current HH:MM time."
|
|||
(setq org-overriding-default-time
|
||||
(org-get-cursor-date (equal goto 1))))
|
||||
(cond
|
||||
((equal goto '(4)) (org-capture-goto-target))
|
||||
((equal goto '(4)) (org-capture-goto-target keys))
|
||||
((equal goto '(16)) (org-capture-goto-last-stored))
|
||||
(t
|
||||
(let* ((orig-buf (current-buffer))
|
||||
|
@ -698,21 +710,19 @@ of the day at point (if any) or the current HH:MM time."
|
|||
|
||||
(defun org-capture-get-template ()
|
||||
"Get the template from a file or a function if necessary."
|
||||
(let ((txt (org-capture-get :template)) file)
|
||||
(cond
|
||||
((and (listp txt) (eq (car txt) 'file))
|
||||
(if (file-exists-p
|
||||
(setq file (expand-file-name (nth 1 txt) org-directory)))
|
||||
(setq txt (org-file-contents file))
|
||||
(setq txt (format "* Template file %s not found" (nth 1 txt)))))
|
||||
((and (listp txt) (eq (car txt) 'function))
|
||||
(if (fboundp (nth 1 txt))
|
||||
(setq txt (funcall (nth 1 txt)))
|
||||
(setq txt (format "* Template function %s not found" (nth 1 txt)))))
|
||||
((not txt) (setq txt ""))
|
||||
((stringp txt))
|
||||
(t (setq txt "* Invalid capture template")))
|
||||
(org-capture-put :template txt)))
|
||||
(org-capture-put
|
||||
:template
|
||||
(pcase (org-capture-get :template)
|
||||
(`nil "")
|
||||
((and (pred stringp) template) template)
|
||||
(`(file ,file)
|
||||
(let ((filename (expand-file-name file org-directory)))
|
||||
(if (file-exists-p filename) (org-file-contents filename)
|
||||
(format "* Template file %S not found" file))))
|
||||
(`(function ,f)
|
||||
(if (functionp f) (funcall f)
|
||||
(format "* Template function %S not found" f)))
|
||||
(_ "* Invalid capture template"))))
|
||||
|
||||
(defun org-capture-finalize (&optional stay-with-capture)
|
||||
"Finalize the capture process.
|
||||
|
@ -727,6 +737,11 @@ captured item after finalizing."
|
|||
|
||||
(run-hooks 'org-capture-prepare-finalize-hook)
|
||||
|
||||
;; Update `org-capture-plist' with the buffer-local value. Since
|
||||
;; captures can be run concurrently, this is to ensure that
|
||||
;; `org-capture-after-finalize-hook' accesses the proper plist.
|
||||
(setq org-capture-plist org-capture-current-plist)
|
||||
|
||||
;; Did we start the clock in this capture buffer?
|
||||
(when (and org-capture-clock-was-started
|
||||
org-clock-marker
|
||||
|
@ -996,11 +1011,13 @@ Store them in the capture property list."
|
|||
(org-capture-put-target-region-and-position)
|
||||
(widen)
|
||||
;; Make a date/week tree entry, with the current date (or
|
||||
;; yesterday, if we are extending dates for a couple of hours)
|
||||
;; yesterday, if we are extending dates for a couple of
|
||||
;; hours)
|
||||
(funcall
|
||||
(if (eq (org-capture-get :tree-type) 'week)
|
||||
#'org-datetree-find-iso-week-create
|
||||
#'org-datetree-find-date-create)
|
||||
(pcase (org-capture-get :tree-type)
|
||||
(`week #'org-datetree-find-iso-week-create)
|
||||
(`month #'org-datetree-find-month-create)
|
||||
(_ #'org-datetree-find-date-create))
|
||||
(calendar-gregorian-from-absolute
|
||||
(cond
|
||||
(org-overriding-default-time
|
||||
|
@ -1021,7 +1038,7 @@ Store them in the capture property list."
|
|||
(apply #'encode-time 0 0
|
||||
org-extend-today-until
|
||||
(cl-cdddr (decode-time prompt-time))))
|
||||
((string-match "\\([^ ]+\\)--?[^ ]+[ ]+\\(.*\\)"
|
||||
((string-match "\\([^ ]+\\)-[^ ]+[ ]+\\(.*\\)"
|
||||
org-read-date-final-answer)
|
||||
;; Replace any time range by its start.
|
||||
(apply #'encode-time
|
||||
|
@ -1058,7 +1075,7 @@ Store them in the capture property list."
|
|||
(org-capture-put-target-region-and-position)
|
||||
(widen)
|
||||
(goto-char org-clock-hd-marker))
|
||||
(error "No running clock that could be used as capture target")))
|
||||
(user-error "No running clock that could be used as capture target")))
|
||||
(target (error "Invalid capture target specification: %S" target)))
|
||||
|
||||
(org-capture-put :buffer (current-buffer)
|
||||
|
@ -1115,8 +1132,8 @@ may have been stored before."
|
|||
(`plain (org-capture-place-plain-text))
|
||||
(`item (org-capture-place-item))
|
||||
(`checkitem (org-capture-place-item)))
|
||||
(org-capture-mode 1)
|
||||
(setq-local org-capture-current-plist org-capture-plist))
|
||||
(setq-local org-capture-current-plist org-capture-plist)
|
||||
(org-capture-mode 1))
|
||||
|
||||
(defun org-capture-place-entry ()
|
||||
"Place the template as a new Org entry."
|
||||
|
@ -1129,7 +1146,14 @@ may have been stored before."
|
|||
(when exact-position (goto-char exact-position))
|
||||
(cond
|
||||
;; Force insertion at point.
|
||||
((org-capture-get :insert-here) nil)
|
||||
(insert-here?
|
||||
;; FIXME: level should probably set directly within (let ...).
|
||||
(setq level (org-get-valid-level
|
||||
(if (or (org-at-heading-p)
|
||||
(ignore-errors
|
||||
(save-excursion (org-back-to-heading t))))
|
||||
(org-outline-level)
|
||||
1))))
|
||||
;; Insert as a child of the current entry.
|
||||
((org-capture-get :target-entry-p)
|
||||
(setq level (org-get-valid-level
|
||||
|
@ -1150,14 +1174,11 @@ may have been stored before."
|
|||
(when insert-here? (narrow-to-region beg beg))
|
||||
(org-paste-subtree level template 'for-yank))
|
||||
(org-capture-position-for-last-stored beg)
|
||||
(let ((end (if (org-at-heading-p) (line-end-position 0) (point))))
|
||||
(org-capture-empty-lines-after)
|
||||
(unless (org-at-heading-p) (outline-next-heading))
|
||||
(org-capture-mark-kill-region origin (point))
|
||||
(org-capture-narrow beg end)
|
||||
(when (or (search-backward "%?" beg t)
|
||||
(search-forward "%?" end t))
|
||||
(replace-match "")))))))
|
||||
(org-capture-empty-lines-after)
|
||||
(unless (org-at-heading-p) (outline-next-heading))
|
||||
(org-capture-mark-kill-region origin (point))
|
||||
(org-capture-narrow beg (if (eobp) (point) (1- (point))))
|
||||
(org-capture--position-cursor beg (point))))))
|
||||
|
||||
(defun org-capture-place-item ()
|
||||
"Place the template as a new plain list item."
|
||||
|
@ -1269,9 +1290,7 @@ may have been stored before."
|
|||
;; not narrow at the beginning of the next line, possibly
|
||||
;; altering its structure (e.g., when it is a headline).
|
||||
(org-capture-narrow beg (1- end))
|
||||
(when (or (search-backward "%?" beg t)
|
||||
(search-forward "%?" end t))
|
||||
(replace-match ""))))))
|
||||
(org-capture--position-cursor beg end)))))
|
||||
|
||||
(defun org-capture-place-table-line ()
|
||||
"Place the template as a table line."
|
||||
|
@ -1353,9 +1372,7 @@ may have been stored before."
|
|||
;; TEXT is guaranteed to end with a newline character. Ignore
|
||||
;; it when narrowing so as to not alter data on the next line.
|
||||
(org-capture-narrow beg (1- end))
|
||||
(when (or (search-backward "%?" beg t)
|
||||
(search-forward "%?" end t))
|
||||
(replace-match ""))))))
|
||||
(org-capture--position-cursor beg (1- end))))))
|
||||
|
||||
(defun org-capture-place-plain-text ()
|
||||
"Place the template plainly.
|
||||
|
@ -1390,9 +1407,7 @@ Of course, if exact position has been required, just put it there."
|
|||
(org-capture-empty-lines-after)
|
||||
(org-capture-mark-kill-region origin (point))
|
||||
(org-capture-narrow beg end)
|
||||
(when (or (search-backward "%?" beg t)
|
||||
(search-forward "%?" end t))
|
||||
(replace-match ""))))))
|
||||
(org-capture--position-cursor beg end)))))
|
||||
|
||||
(defun org-capture-mark-kill-region (beg end)
|
||||
"Mark the region that will have to be killed when aborting capture."
|
||||
|
@ -1438,8 +1453,15 @@ Of course, if exact position has been required, just put it there."
|
|||
(defun org-capture-narrow (beg end)
|
||||
"Narrow, unless configuration says not to narrow."
|
||||
(unless (org-capture-get :unnarrowed)
|
||||
(narrow-to-region beg end)
|
||||
(goto-char beg)))
|
||||
(narrow-to-region beg end)))
|
||||
|
||||
(defun org-capture--position-cursor (beg end)
|
||||
"Move point to first \"%?\" location or at start of template.
|
||||
BEG and END are buffer positions at the beginning and end position
|
||||
of the template."
|
||||
(goto-char beg)
|
||||
(when (search-forward "%?" end t)
|
||||
(replace-match "")))
|
||||
|
||||
(defun org-capture-empty-lines-before (&optional n)
|
||||
"Set the correct number of empty lines before the insertion point.
|
||||
|
@ -1736,11 +1758,11 @@ The template may still contain \"%?\" for cursor positioning."
|
|||
(_ (error "Invalid `org-capture--clipboards' value: %S"
|
||||
org-capture--clipboards)))))
|
||||
("p"
|
||||
;; We remove file properties inherited from
|
||||
;; We remove keyword properties inherited from
|
||||
;; target buffer so `org-read-property-value' has
|
||||
;; a chance to find allowed values in sub-trees
|
||||
;; from the target buffer.
|
||||
(setq-local org-file-properties nil)
|
||||
(setq-local org-keyword-properties nil)
|
||||
(let* ((origin (set-marker (make-marker)
|
||||
(org-capture-get :pos)
|
||||
(org-capture-get :buffer)))
|
||||
|
@ -1925,4 +1947,8 @@ Assume sexps have been marked with
|
|||
|
||||
(provide 'org-capture)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-capture.el ends here
|
||||
|
|
|
@ -35,11 +35,17 @@
|
|||
(declare-function notifications-notify "notifications" (&rest params))
|
||||
(declare-function org-element-property "org-element" (property element))
|
||||
(declare-function org-element-type "org-element" (element))
|
||||
(declare-function org-inlinetask-at-task-p "org-inlinetask" ())
|
||||
(declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
|
||||
(declare-function org-inlinetask-goto-end "org-inlinetask" ())
|
||||
(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
|
||||
(declare-function org-link-display-format "ol" (s))
|
||||
(declare-function org-link-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))
|
||||
|
||||
(defvar org-frame-title-format-backup nil)
|
||||
(defvar org-state)
|
||||
|
@ -273,6 +279,15 @@ also using the face `org-mode-line-clock-overrun'."
|
|||
(const :tag "Just mark the time string" nil)
|
||||
(string :tag "Text to prepend")))
|
||||
|
||||
(defcustom org-show-notification-timeout 3
|
||||
"Number of seconds to wait before closing Org notifications.
|
||||
This is applied to notifications sent with `notifications-notify'
|
||||
and `w32-notification-notify' only, not other mechanisms possibly
|
||||
set through `org-show-notification-handler'."
|
||||
:group 'org-clock
|
||||
:package-version '(Org . "9.4")
|
||||
:type 'integer)
|
||||
|
||||
(defcustom org-show-notification-handler nil
|
||||
"Function or program to send notification with.
|
||||
The function or program will be called with the notification
|
||||
|
@ -457,6 +472,19 @@ Valid values are: `today', `yesterday', `thisweek', `lastweek',
|
|||
(const :tag "Select range interactively" interactive))
|
||||
:safe #'symbolp)
|
||||
|
||||
(defcustom org-clock-auto-clockout-timer nil
|
||||
"Timer for auto clocking out when Emacs is idle.
|
||||
When set to a number, auto clock out the currently clocked in
|
||||
task after this number of seconds of idle time.
|
||||
|
||||
This is only effective when `org-clock-auto-clockout-insinuate'
|
||||
is added to the user configuration."
|
||||
:group 'org-clock
|
||||
:package-version '(Org . "9.4")
|
||||
:type '(choice
|
||||
(integer :tag "Clock out after Emacs is idle for X seconds")
|
||||
(const :tag "Never auto clock out" nil)))
|
||||
|
||||
(defvar org-clock-in-prepare-hook nil
|
||||
"Hook run when preparing the clock.
|
||||
This hook is run before anything happens to the task that
|
||||
|
@ -698,7 +726,8 @@ If not, show simply the clocked time like 01:50."
|
|||
(save-excursion
|
||||
(let ((end (save-excursion (org-end-of-subtree))))
|
||||
(when (re-search-forward (concat org-clock-string
|
||||
".*\\]--\\(\\[[^]]+\\]\\)") end t)
|
||||
".*\\]--\\(\\[[^]]+\\]\\)")
|
||||
end t)
|
||||
(org-time-string-to-time (match-string 1))))))
|
||||
|
||||
(defun org-clock-update-mode-line (&optional refresh)
|
||||
|
@ -725,7 +754,8 @@ menu\nmouse-2 will jump to task"))
|
|||
(setq org-mode-line-string
|
||||
(concat (propertize
|
||||
org-clock-task-overrun-text
|
||||
'face 'org-mode-line-clock-overrun) org-mode-line-string)))
|
||||
'face 'org-mode-line-clock-overrun)
|
||||
org-mode-line-string)))
|
||||
(force-mode-line-update))
|
||||
|
||||
(defun org-clock-get-clocked-time ()
|
||||
|
@ -808,15 +838,26 @@ If PLAY-SOUND is non-nil, it overrides `org-clock-sound'."
|
|||
"Show notification.
|
||||
Use `org-show-notification-handler' if defined,
|
||||
use libnotify if available, or fall back on a message."
|
||||
(ignore-errors (require 'notifications))
|
||||
(cond ((functionp org-show-notification-handler)
|
||||
(funcall org-show-notification-handler notification))
|
||||
((stringp org-show-notification-handler)
|
||||
(start-process "emacs-timer-notification" nil
|
||||
org-show-notification-handler notification))
|
||||
((fboundp 'w32-notification-notify)
|
||||
(let ((id (w32-notification-notify
|
||||
:title "Org mode message"
|
||||
:body notification
|
||||
:urgency 'low)))
|
||||
(run-with-timer
|
||||
org-show-notification-timeout
|
||||
nil
|
||||
(lambda () (w32-notification-close id)))))
|
||||
((fboundp 'notifications-notify)
|
||||
(notifications-notify
|
||||
:title "Org mode message"
|
||||
:body notification
|
||||
:timeout (* org-show-notification-timeout 1000)
|
||||
;; FIXME how to link to the Org icon?
|
||||
;; :app-icon "~/.emacs.d/icons/mail.png"
|
||||
:urgency 'low))
|
||||
|
@ -859,7 +900,8 @@ If CLOCK-SOUND is non-nil, it overrides `org-clock-sound'."
|
|||
(goto-char (point-min))
|
||||
(while (re-search-forward org-clock-re nil t)
|
||||
(push (cons (copy-marker (match-end 1) t)
|
||||
(org-time-string-to-time (match-string 1))) clocks))))
|
||||
(org-time-string-to-time (match-string 1)))
|
||||
clocks))))
|
||||
clocks))
|
||||
|
||||
(defsubst org-is-active-clock (clock)
|
||||
|
@ -983,7 +1025,7 @@ CLOCK is a cons cell of the form (MARKER START-TIME)."
|
|||
(let ((element (org-element-at-point)))
|
||||
(when (eq (org-element-type element) 'drawer)
|
||||
(when (> (org-element-property :end element) (car clock))
|
||||
(org-flag-drawer nil element))
|
||||
(org-hide-drawer-toggle 'off nil element))
|
||||
(throw 'exit nil)))))))))))
|
||||
|
||||
(defun org-clock-resolve (clock &optional prompt-fn last-valid fail-quietly)
|
||||
|
@ -1022,6 +1064,9 @@ k/K Keep X minutes of the idle time (default is all). If this
|
|||
that many minutes after the time that idling began, and then
|
||||
clocked back in at the present time.
|
||||
|
||||
t/T Like `k', but will ask you to specify a time (when you got
|
||||
distracted away), instead of a number of minutes.
|
||||
|
||||
g/G Indicate that you \"got back\" X minutes ago. This is quite
|
||||
different from `k': it clocks you out from the beginning of
|
||||
the idle period and clock you back in X minutes ago.
|
||||
|
@ -1041,19 +1086,24 @@ to be CLOCKED OUT."))))
|
|||
(while (or (null char-pressed)
|
||||
(and (not (memq char-pressed
|
||||
'(?k ?K ?g ?G ?s ?S ?C
|
||||
?j ?J ?i ?q)))
|
||||
?j ?J ?i ?q ?t ?T)))
|
||||
(or (ding) t)))
|
||||
(setq char-pressed
|
||||
(read-char (concat (funcall prompt-fn clock)
|
||||
" [jkKgGSscCiq]? ")
|
||||
" [jkKtTgGSscCiq]? ")
|
||||
nil 45)))
|
||||
(and (not (memq char-pressed '(?i ?q))) char-pressed)))))
|
||||
(default
|
||||
(floor (org-time-convert-to-integer (org-time-since last-valid))
|
||||
60))
|
||||
(keep
|
||||
(and (memq ch '(?k ?K))
|
||||
(read-number "Keep how many minutes? " default)))
|
||||
(or (and (memq ch '(?k ?K))
|
||||
(read-number "Keep how many minutes? " default))
|
||||
(and (memq ch '(?t ?T))
|
||||
(floor
|
||||
(/ (float-time
|
||||
(org-time-subtract (org-read-date t t) last-valid))
|
||||
60)))))
|
||||
(gotback
|
||||
(and (memq ch '(?g ?G))
|
||||
(read-number "Got back how many minutes ago? " default)))
|
||||
|
@ -1068,7 +1118,7 @@ to be CLOCKED OUT."))))
|
|||
(org-clock-resolve-clock clock 'now nil t nil fail-quietly))
|
||||
(org-clock-jump-to-current-clock clock))
|
||||
((or (null ch)
|
||||
(not (memq ch '(?k ?K ?g ?G ?s ?S ?C))))
|
||||
(not (memq ch '(?k ?K ?g ?G ?s ?S ?C ?t ?T))))
|
||||
(message ""))
|
||||
(t
|
||||
(org-clock-resolve-clock
|
||||
|
@ -1092,7 +1142,7 @@ to be CLOCKED OUT."))))
|
|||
(t
|
||||
(error "Unexpected, please report this as a bug")))
|
||||
(and gotback last-valid)
|
||||
(memq ch '(?K ?G ?S))
|
||||
(memq ch '(?K ?G ?S ?T))
|
||||
(and start-over
|
||||
(not (memq ch '(?K ?G ?S ?C))))
|
||||
fail-quietly)))))
|
||||
|
@ -1315,7 +1365,6 @@ the default behavior."
|
|||
(t
|
||||
(insert-before-markers "\n")
|
||||
(backward-char 1)
|
||||
(org-indent-line)
|
||||
(when (and (save-excursion
|
||||
(end-of-line 0)
|
||||
(org-in-item-p)))
|
||||
|
@ -1340,7 +1389,8 @@ the default behavior."
|
|||
start-time
|
||||
(org-current-time org-clock-rounding-minutes t)))
|
||||
(setq ts (org-insert-time-stamp org-clock-start-time
|
||||
'with-hm 'inactive))))
|
||||
'with-hm 'inactive))
|
||||
(org-indent-line)))
|
||||
(move-marker org-clock-marker (point) (buffer-base-buffer))
|
||||
(move-marker org-clock-hd-marker
|
||||
(save-excursion (org-back-to-heading t) (point))
|
||||
|
@ -1375,6 +1425,26 @@ the default behavior."
|
|||
(message "Clock starts at %s - %s" ts org--msg-extra)
|
||||
(run-hooks 'org-clock-in-hook))))))
|
||||
|
||||
(defun org-clock-auto-clockout ()
|
||||
"Clock out the currently clocked in task if Emacs is idle.
|
||||
See `org-clock-auto-clockout-timer' to set the idle time span.
|
||||
|
||||
This is only effective when `org-clock-auto-clockout-insinuate'
|
||||
is present in the user configuration."
|
||||
(when (and (numberp org-clock-auto-clockout-timer)
|
||||
org-clock-current-task)
|
||||
(run-with-idle-timer
|
||||
org-clock-auto-clockout-timer nil #'org-clock-out)))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-clock-toggle-auto-clockout ()
|
||||
(interactive)
|
||||
(if (memq 'org-clock-auto-clockout org-clock-in-hook)
|
||||
(progn (remove-hook 'org-clock-in-hook #'org-clock-auto-clockout)
|
||||
(message "Auto clock-out after idle time turned off"))
|
||||
(add-hook 'org-clock-in-hook #'org-clock-auto-clockout t)
|
||||
(message "Auto clock-out after idle time turned on")))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-clock-in-last (&optional arg)
|
||||
"Clock in the last closed clocked item.
|
||||
|
@ -1512,7 +1582,7 @@ line and position cursor in that line."
|
|||
(insert ":" drawer ":\n:END:\n")
|
||||
(org-indent-region beg (point))
|
||||
(org-flag-region
|
||||
(line-end-position -1) (1- (point)) t 'org-hide-drawer)
|
||||
(line-end-position -1) (1- (point)) t 'outline)
|
||||
(forward-line -1))))
|
||||
;; When a clock drawer needs to be created because of the
|
||||
;; number of clock items or simply if it is missing, collect
|
||||
|
@ -1537,7 +1607,7 @@ line and position cursor in that line."
|
|||
(let ((end (point-marker)))
|
||||
(goto-char beg)
|
||||
(save-excursion (insert ":" drawer ":\n"))
|
||||
(org-flag-region (line-end-position) (1- end) t 'org-hide-drawer)
|
||||
(org-flag-region (line-end-position) (1- end) t 'outline)
|
||||
(org-indent-region (point) end)
|
||||
(forward-line)
|
||||
(unless org-log-states-order-reversed
|
||||
|
@ -1579,7 +1649,7 @@ to, overriding the existing value of `org-clock-out-switch-to-state'."
|
|||
org-clock-out-switch-to-state))
|
||||
(now (org-current-time org-clock-rounding-minutes))
|
||||
ts te s h m remove)
|
||||
(setq org-clock-out-time now)
|
||||
(setq org-clock-out-time (or at-time now))
|
||||
(save-excursion ; Do not replace this with `with-current-buffer'.
|
||||
(with-no-warnings (set-buffer (org-clocking-buffer)))
|
||||
(save-restriction
|
||||
|
@ -1724,7 +1794,7 @@ Optional argument N tells to change by that many units."
|
|||
(delq 'org-mode-line-string global-mode-string))
|
||||
(org-clock-restore-frame-title-format)
|
||||
(force-mode-line-update)
|
||||
(error "No active clock"))
|
||||
(user-error "No active clock"))
|
||||
(save-excursion ; Do not replace this with `with-current-buffer'.
|
||||
(with-no-warnings (set-buffer (org-clocking-buffer)))
|
||||
(goto-char org-clock-marker)
|
||||
|
@ -1753,14 +1823,14 @@ With prefix arg SELECT, offer recently clocked tasks for selection."
|
|||
(m (cond
|
||||
(select
|
||||
(or (org-clock-select-task "Select task to go to: ")
|
||||
(error "No task selected")))
|
||||
(user-error "No task selected")))
|
||||
((org-clocking-p) org-clock-marker)
|
||||
((and org-clock-goto-may-find-recent-task
|
||||
(car org-clock-history)
|
||||
(marker-buffer (car org-clock-history)))
|
||||
(setq recent t)
|
||||
(car org-clock-history))
|
||||
(t (error "No active or recent clock task")))))
|
||||
(t (user-error "No active or recent clock task")))))
|
||||
(pop-to-buffer-same-window (marker-buffer m))
|
||||
(if (or (< m (point-min)) (> m (point-max))) (widen))
|
||||
(goto-char m)
|
||||
|
@ -1890,7 +1960,12 @@ PROPNAME lets you set a custom text property instead of :org-clock-minutes."
|
|||
"Return time, clocked on current item in total."
|
||||
(save-excursion
|
||||
(save-restriction
|
||||
(org-narrow-to-subtree)
|
||||
(if (and (featurep 'org-inlinetask)
|
||||
(or (org-inlinetask-at-task-p)
|
||||
(org-inlinetask-in-task-p)))
|
||||
(narrow-to-region (save-excursion (org-inlinetask-goto-beginning) (point))
|
||||
(save-excursion (org-inlinetask-goto-end) (point)))
|
||||
(org-narrow-to-subtree))
|
||||
(org-clock-sum tstart)
|
||||
org-clock-file-total-minutes)))
|
||||
|
||||
|
@ -2067,7 +2142,10 @@ in the buffer and update it."
|
|||
(start (goto-char start)))
|
||||
(org-update-dblock))
|
||||
|
||||
(org-dynamic-block-define "clocktable" #'org-clock-report)
|
||||
;;;###autoload
|
||||
(eval-after-load 'org
|
||||
'(progn
|
||||
(org-dynamic-block-define "clocktable" #'org-clock-report)))
|
||||
|
||||
(defun org-day-of-week (day month year)
|
||||
"Return the day of the week as an integer."
|
||||
|
@ -2310,7 +2388,7 @@ the currently selected interval size."
|
|||
(save-excursion
|
||||
(goto-char (point-at-bol))
|
||||
(if (not (looking-at "^[ \t]*#\\+BEGIN:[ \t]+clocktable\\>.*?:block[ \t]+\\(\\S-+\\)"))
|
||||
(error "Line needs a :block definition before this command works")
|
||||
(user-error "Line needs a :block definition before this command works")
|
||||
(let* ((b (match-beginning 1)) (e (match-end 1))
|
||||
(s (match-string 1))
|
||||
block shift ins y mw d date wp m)
|
||||
|
@ -2369,7 +2447,7 @@ the currently selected interval size."
|
|||
(encode-time 0 0 0 1 (+ mw n) y))))
|
||||
(y
|
||||
(setq ins (number-to-string (+ y n))))))
|
||||
(t (error "Cannot shift clocktable block")))
|
||||
(t (user-error "Cannot shift clocktable block")))
|
||||
(when ins
|
||||
(goto-char b)
|
||||
(insert ins)
|
||||
|
@ -2384,20 +2462,21 @@ the currently selected interval size."
|
|||
(setq params (org-combine-plists org-clocktable-defaults params))
|
||||
(catch 'exit
|
||||
(let* ((scope (plist-get params :scope))
|
||||
(base-buffer (org-base-buffer (current-buffer)))
|
||||
(files (pcase scope
|
||||
(`agenda
|
||||
(org-agenda-files t))
|
||||
(`agenda-with-archives
|
||||
(org-add-archive-files (org-agenda-files t)))
|
||||
(`file-with-archives
|
||||
(and buffer-file-name
|
||||
(org-add-archive-files (list buffer-file-name))))
|
||||
(let ((base-file (buffer-file-name base-buffer)))
|
||||
(and base-file
|
||||
(org-add-archive-files (list base-file)))))
|
||||
((or `nil `file `subtree `tree
|
||||
(and (pred symbolp)
|
||||
(guard (string-match "\\`tree\\([0-9]+\\)\\'"
|
||||
(symbol-name scope)))))
|
||||
(or (buffer-file-name (buffer-base-buffer))
|
||||
(current-buffer)))
|
||||
base-buffer)
|
||||
((pred functionp) (funcall scope))
|
||||
((pred consp) scope)
|
||||
(_ (user-error "Unknown scope: %S" scope))))
|
||||
|
@ -2421,7 +2500,7 @@ the currently selected interval size."
|
|||
(when step
|
||||
;; Write many tables, in steps
|
||||
(unless (or block (and ts te))
|
||||
(error "Clocktable `:step' can only be used with `:block' or `:tstart,:end'"))
|
||||
(user-error "Clocktable `:step' can only be used with `:block' or `:tstart, :end'"))
|
||||
(org-clocktable-steps params)
|
||||
(throw 'exit nil))
|
||||
|
||||
|
@ -2527,7 +2606,7 @@ from the dynamic block definition."
|
|||
(guard (string-match-p "\\`[0-9]+!\\'" (symbol-name narrow))))
|
||||
(setq narrow-cut-p t)
|
||||
(setq narrow (string-to-number (symbol-name narrow))))
|
||||
(_ (error "Invalid value %s of :narrow property in clock table" narrow)))
|
||||
(_ (user-error "Invalid value %s of :narrow property in clock table" narrow)))
|
||||
|
||||
;; Now we need to output this table stuff.
|
||||
(goto-char ipos)
|
||||
|
@ -2718,6 +2797,7 @@ a number of clock tables."
|
|||
(pcase step
|
||||
(`day "Daily report: ")
|
||||
(`week "Weekly report starting on: ")
|
||||
(`semimonth "Semimonthly report starting on: ")
|
||||
(`month "Monthly report starting on: ")
|
||||
(`year "Annual report starting on: ")
|
||||
(_ (user-error "Unknown `:step' specification: %S" step))))
|
||||
|
@ -2767,6 +2847,9 @@ a number of clock tables."
|
|||
(let ((offset (if (= dow week-start) 7
|
||||
(mod (- week-start dow) 7))))
|
||||
(list 0 0 org-extend-today-until (+ d offset) m y)))
|
||||
(`semimonth (list 0 0 0
|
||||
(if (< d 16) 16 1)
|
||||
(if (< d 16) m (1+ m)) y))
|
||||
(`month (list 0 0 0 month-start (1+ m) y))
|
||||
(`year (list 0 0 org-extend-today-until 1 1 (1+ y)))))))
|
||||
(table-begin (line-beginning-position 0))
|
||||
|
@ -2883,7 +2966,7 @@ PROPERTIES: The list properties specified in the `:properties' parameter
|
|||
(org-trim
|
||||
(org-link-display-format
|
||||
(replace-regexp-in-string
|
||||
"\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" ""
|
||||
"\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]" ""
|
||||
headline)))))))
|
||||
(tgs (and tags (org-get-tags)))
|
||||
(tsp
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
(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))
|
||||
(declare-function face-remap-add-relative "face-remap" (face &rest specs))
|
||||
|
||||
(defvar org-agenda-columns-add-appointments-to-effort-sum)
|
||||
(defvar org-agenda-columns-compute-summary-properties)
|
||||
|
@ -164,7 +166,7 @@ See `org-columns-summary-types' for details.")
|
|||
(org-defkey org-columns-map "o" 'org-overview)
|
||||
(org-defkey org-columns-map "e" 'org-columns-edit-value)
|
||||
(org-defkey org-columns-map "\C-c\C-t" 'org-columns-todo)
|
||||
(org-defkey org-columns-map "\C-c\C-c" 'org-columns-set-tags-or-toggle)
|
||||
(org-defkey org-columns-map "\C-c\C-c" 'org-columns-toggle-or-columns-quit)
|
||||
(org-defkey org-columns-map "\C-c\C-o" 'org-columns-open-link)
|
||||
(org-defkey org-columns-map "v" 'org-columns-show-value)
|
||||
(org-defkey org-columns-map "q" 'org-columns-quit)
|
||||
|
@ -257,6 +259,8 @@ value for ITEM property."
|
|||
(if org-hide-leading-stars ?\s ?*))
|
||||
"* "))))
|
||||
(concat stars (org-link-display-format value))))
|
||||
(`(,(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
|
||||
;; obey to the format string.
|
||||
|
@ -364,11 +368,18 @@ ORIGINAL is the real string, i.e., before it is modified by
|
|||
("TODO" (propertize v 'face (org-get-todo-face original)))
|
||||
(_ v)))))
|
||||
|
||||
(defvar org-columns-header-line-remap nil
|
||||
"Store the relative remapping of column header-line.
|
||||
This is needed to later remove this relative remapping.")
|
||||
|
||||
(defun org-columns--display-here (columns &optional dateline)
|
||||
"Overlay the current line with column display.
|
||||
COLUMNS is an alist (SPEC VALUE DISPLAYED). Optional argument
|
||||
DATELINE is non-nil when the face used should be
|
||||
`org-agenda-column-dateline'."
|
||||
(when (ignore-errors (require 'face-remap))
|
||||
(setq org-columns-header-line-remap
|
||||
(face-remap-add-relative 'header-line '(:inherit default))))
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(let* ((level-face (and (looking-at "\\(\\**\\)\\(\\* \\)")
|
||||
|
@ -378,8 +389,7 @@ DATELINE is non-nil when the face used should be
|
|||
(org-get-at-bol 'face))
|
||||
'default))
|
||||
(color (list :foreground (face-attribute ref-face :foreground)))
|
||||
(font (list :height (face-attribute 'default :height)
|
||||
:family (face-attribute 'default :family)))
|
||||
(font (list :family (face-attribute 'default :family)))
|
||||
(face (list color font 'org-column ref-face))
|
||||
(face1 (list color font 'org-agenda-column-dateline ref-face)))
|
||||
;; Each column is an overlay on top of a character. So there has
|
||||
|
@ -502,6 +512,9 @@ for the duration of the command.")
|
|||
(defun org-columns-remove-overlays ()
|
||||
"Remove all currently active column overlays."
|
||||
(interactive)
|
||||
(when (and (fboundp 'face-remap-remove-relative)
|
||||
org-columns-header-line-remap)
|
||||
(face-remap-remove-relative org-columns-header-line-remap))
|
||||
(when org-columns-overlays
|
||||
(when (local-variable-p 'org-previous-header-line-format)
|
||||
(setq header-line-format org-previous-header-line-format)
|
||||
|
@ -554,13 +567,19 @@ for the duration of the command.")
|
|||
(interactive "P")
|
||||
(org-columns-edit-value "TODO"))
|
||||
|
||||
(defun org-columns-set-tags-or-toggle (&optional _arg)
|
||||
"Toggle checkbox at point, or set tags for current headline."
|
||||
(interactive "P")
|
||||
(if (string-match "\\`\\[[ xX-]\\]\\'"
|
||||
(get-char-property (point) 'org-columns-value))
|
||||
(org-columns-next-allowed-value)
|
||||
(org-columns-edit-value "TAGS")))
|
||||
(defun org-columns-toggle-or-columns-quit ()
|
||||
"Toggle checkbox at point, or quit column view."
|
||||
(interactive)
|
||||
(or (org-columns--toggle)
|
||||
(org-columns-quit)))
|
||||
|
||||
(defun org-columns--toggle ()
|
||||
"Toggle checkbox at point. Return non-nil if toggle happened, else nil.
|
||||
See info documentation about realizing a suitable checkbox."
|
||||
(when (string-match "\\`\\[[ xX-]\\]\\'"
|
||||
(get-char-property (point) 'org-columns-value))
|
||||
(org-columns-next-allowed-value)
|
||||
t))
|
||||
|
||||
(defvar org-overriding-columns-format nil
|
||||
"When set, overrides any other format definition for the agenda.
|
||||
|
@ -1550,7 +1569,10 @@ PARAMS is a property list of parameters:
|
|||
(id)))))
|
||||
(org-update-dblock))
|
||||
|
||||
(org-dynamic-block-define "columnview" #'org-columns-insert-dblock)
|
||||
;;;###autoload
|
||||
(eval-after-load 'org
|
||||
'(progn
|
||||
(org-dynamic-block-define "columnview" #'org-columns-insert-dblock)))
|
||||
|
||||
|
||||
;;; Column view in the agenda
|
||||
|
@ -1564,6 +1586,7 @@ PARAMS is a property list of parameters:
|
|||
(move-marker org-columns-begin-marker (point))
|
||||
(setq org-columns-begin-marker (point-marker)))
|
||||
(let* ((org-columns--time (float-time))
|
||||
(org-done-keywords org-done-keywords-for-agenda)
|
||||
(fmt
|
||||
(cond
|
||||
((bound-and-true-p org-overriding-columns-format))
|
||||
|
@ -1613,6 +1636,7 @@ PARAMS is a property list of parameters:
|
|||
(dolist (entry cache)
|
||||
(goto-char (car entry))
|
||||
(org-columns--display-here (cdr entry)))
|
||||
(setq-local org-agenda-columns-active t)
|
||||
(when org-agenda-columns-show-summaries
|
||||
(org-agenda-colview-summarize cache)))))))
|
||||
|
||||
|
@ -1677,8 +1701,7 @@ This will add overlays to the date lines, to show the summary for each day."
|
|||
'face 'bold final))
|
||||
(list spec final final)))))
|
||||
fmt)
|
||||
'dateline)
|
||||
(setq-local org-agenda-columns-active t))))
|
||||
'dateline))))
|
||||
(if (bobp) (throw :complete t) (forward-line -1)))))))
|
||||
|
||||
(defun org-agenda-colview-compute (fmt)
|
||||
|
@ -1704,4 +1727,8 @@ This will add overlays to the date lines, to show the summary for each day."
|
|||
|
||||
(provide 'org-colview)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-colview.el ends here
|
||||
|
|
|
@ -46,11 +46,13 @@
|
|||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
|
||||
(declare-function org-get-heading "org" (&optional no-tags no-todo no-priority no-comment))
|
||||
(declare-function org-get-tags "org" (&optional pos local))
|
||||
(declare-function org-hide-block-toggle "org" (&optional force no-error element))
|
||||
(declare-function org-link-display-format "ol" (s))
|
||||
(declare-function org-link-set-parameters "ol" (type &rest rest))
|
||||
(declare-function org-log-into-drawer "org" ())
|
||||
(declare-function org-make-tag-string "org" (tags))
|
||||
(declare-function org-reduced-level "org" (l))
|
||||
(declare-function org-return "org" (&optional indent arg interactive))
|
||||
(declare-function org-show-context "org" (&optional key))
|
||||
(declare-function org-table-end "org-table" (&optional table-type))
|
||||
(declare-function outline-next-heading "outline" ())
|
||||
|
@ -101,6 +103,20 @@ is nil)."
|
|||
(defun org-time-convert-to-list (time)
|
||||
(seconds-to-time (float-time time))))
|
||||
|
||||
;; `newline-and-indent' did not take a numeric argument before 27.1.
|
||||
(if (version< emacs-version "27")
|
||||
(defsubst org-newline-and-indent (&optional _arg)
|
||||
(newline-and-indent))
|
||||
(defalias 'org-newline-and-indent #'newline-and-indent))
|
||||
|
||||
(defun org--set-faces-extend (faces extend-p)
|
||||
"Set the :extend attribute of FACES to EXTEND-P.
|
||||
|
||||
This is a no-op for Emacs versions lower than 27, since face
|
||||
extension beyond end of line was not controllable."
|
||||
(when (fboundp 'set-face-extend)
|
||||
(mapc (lambda (f) (set-face-extend f extend-p)) faces)))
|
||||
|
||||
|
||||
;;; Emacs < 26.1 compatibility
|
||||
|
||||
|
@ -314,6 +330,8 @@ Counting starts at 1."
|
|||
|
||||
(define-obsolete-variable-alias 'org-attach-directory
|
||||
'org-attach-id-dir "Org 9.3")
|
||||
(make-obsolete 'org-attach-store-link "No longer used" "Org 9.4")
|
||||
(make-obsolete 'org-attach-expand-link "No longer used" "Org 9.4")
|
||||
|
||||
(defun org-in-fixed-width-region-p ()
|
||||
"Non-nil if point in a fixed-width region."
|
||||
|
@ -556,6 +574,11 @@ use of this function is for the stuck project list."
|
|||
(define-obsolete-function-alias 'org-make-link-regexps
|
||||
'org-link-make-regexps "Org 9.3")
|
||||
|
||||
(define-obsolete-function-alias 'org-property-global-value
|
||||
'org-property-global-or-keyword-value "Org 9.3")
|
||||
|
||||
(make-obsolete-variable 'org-file-properties 'org-keyword-properties "Org 9.3")
|
||||
|
||||
(define-obsolete-variable-alias 'org-angle-link-re
|
||||
'org-link-angle-re "Org 9.3")
|
||||
|
||||
|
@ -616,6 +639,72 @@ use of this function is for the stuck project list."
|
|||
(declare (obsolete "use `org-align-tags' instead." "Org 9.2"))
|
||||
(org-align-tags t))
|
||||
|
||||
(define-obsolete-function-alias
|
||||
'org-at-property-block-p 'org-at-property-drawer-p "Org 9.4")
|
||||
|
||||
(defun org-flag-drawer (flag &optional element beg end)
|
||||
"When FLAG is non-nil, hide the drawer we are at.
|
||||
Otherwise make it visible.
|
||||
|
||||
When optional argument ELEMENT is a parsed drawer, as returned by
|
||||
`org-element-at-point', hide or show that drawer instead.
|
||||
|
||||
When buffer positions BEG and END are provided, hide or show that
|
||||
region as a drawer without further ado."
|
||||
(declare (obsolete "use `org-hide-drawer-toggle' instead." "Org 9.4"))
|
||||
(if (and beg end) (org-flag-region beg end flag 'outline)
|
||||
(let ((drawer
|
||||
(or element
|
||||
(and (save-excursion
|
||||
(beginning-of-line)
|
||||
(looking-at-p "^[ \t]*:\\(\\(?:\\w\\|[-_]\\)+\\):[ \t]*$"))
|
||||
(org-element-at-point)))))
|
||||
(when (memq (org-element-type drawer) '(drawer property-drawer))
|
||||
(let ((post (org-element-property :post-affiliated drawer)))
|
||||
(org-flag-region
|
||||
(save-excursion (goto-char post) (line-end-position))
|
||||
(save-excursion (goto-char (org-element-property :end drawer))
|
||||
(skip-chars-backward " \t\n")
|
||||
(line-end-position))
|
||||
flag 'outline)
|
||||
;; When the drawer is hidden away, make sure point lies in
|
||||
;; a visible part of the buffer.
|
||||
(when (invisible-p (max (1- (point)) (point-min)))
|
||||
(goto-char post)))))))
|
||||
|
||||
(defun org-hide-block-toggle-maybe ()
|
||||
"Toggle visibility of block at point.
|
||||
Unlike to `org-hide-block-toggle', this function does not throw
|
||||
an error. Return a non-nil value when toggling is successful."
|
||||
(declare (obsolete "use `org-hide-block-toggle' instead." "Org 9.4"))
|
||||
(interactive)
|
||||
(org-hide-block-toggle nil t))
|
||||
|
||||
(defun org-hide-block-toggle-all ()
|
||||
"Toggle the visibility of all blocks in the current buffer."
|
||||
(declare (obsolete "please notify Org mailing list if you use this function."
|
||||
"Org 9.4"))
|
||||
(let ((start (point-min))
|
||||
(end (point-max)))
|
||||
(save-excursion
|
||||
(goto-char start)
|
||||
(while (and (< (point) end)
|
||||
(re-search-forward "^[ \t]*#\\+begin_?\
|
||||
\\([^ \n]+\\)\\(\\([^\n]+\\)\\)?\n\\([^\000]+?\\)#\\+end_?\\1[ \t]*$" end t))
|
||||
(save-excursion
|
||||
(save-match-data
|
||||
(goto-char (match-beginning 0))
|
||||
(org-hide-block-toggle)))))))
|
||||
|
||||
(defun org-return-indent ()
|
||||
"Goto next table row or insert a newline and indent.
|
||||
Calls `org-table-next-row' or `newline-and-indent', depending on
|
||||
context. See the individual commands for more information."
|
||||
(declare (obsolete "use `org-return' with INDENT set to t instead."
|
||||
"Org 9.4"))
|
||||
(interactive)
|
||||
(org-return t))
|
||||
|
||||
(defmacro org-with-silent-modifications (&rest body)
|
||||
(declare (obsolete "use `with-silent-modifications' instead." "Org 9.2")
|
||||
(debug (body)))
|
||||
|
@ -624,6 +713,23 @@ use of this function is for the stuck project list."
|
|||
(define-obsolete-function-alias 'org-babel-strip-quotes
|
||||
'org-strip-quotes "Org 9.2")
|
||||
|
||||
(define-obsolete-variable-alias 'org-sort-agenda-notime-is-late
|
||||
'org-agenda-sort-notime-is-late "9.4")
|
||||
|
||||
(define-obsolete-variable-alias 'org-sort-agenda-noeffort-is-high
|
||||
'org-agenda-sort-noeffort-is-high "9.4")
|
||||
|
||||
(defconst org-maybe-keyword-time-regexp
|
||||
(concat "\\(\\<\\(\\(?:CLO\\(?:CK\\|SED\\)\\|DEADLINE\\|SCHEDULED\\):\\)\\)?"
|
||||
" *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^]\r\n>]*[]>]"
|
||||
"\\|"
|
||||
"<%%([^\r\n>]*>\\)")
|
||||
"Matches a timestamp, possibly preceded by a keyword.")
|
||||
(make-obsolete-variable
|
||||
'org-maybe-keyword-time-regexp
|
||||
"use `org-planning-line-re', followed by `org-ts-regexp-both' instead."
|
||||
"Org 9.4")
|
||||
|
||||
;;;; Obsolete link types
|
||||
|
||||
(eval-after-load 'ol
|
||||
|
@ -808,7 +914,7 @@ This also applied for speedbar access."
|
|||
(setq last-level level)))))
|
||||
(aref subs 1))))
|
||||
|
||||
(eval-after-load "imenu"
|
||||
(eval-after-load 'imenu
|
||||
'(progn
|
||||
(add-hook 'imenu-after-jump-hook
|
||||
(lambda ()
|
||||
|
@ -870,7 +976,7 @@ To get rid of the restriction, use `\\[org-agenda-remove-restriction-lock]'."
|
|||
|
||||
(defvar speedbar-file-key-map)
|
||||
(declare-function speedbar-add-supported-extension "speedbar" (extension))
|
||||
(eval-after-load "speedbar"
|
||||
(eval-after-load 'speedbar
|
||||
'(progn
|
||||
(speedbar-add-supported-extension ".org")
|
||||
(define-key speedbar-file-key-map "<" 'org-speedbar-set-agenda-restriction)
|
||||
|
@ -980,7 +1086,7 @@ ELEMENT is the element at point."
|
|||
(flyspell-delete-region-overlays beg end)))
|
||||
|
||||
(defvar flyspell-delayed-commands)
|
||||
(eval-after-load "flyspell"
|
||||
(eval-after-load 'flyspell
|
||||
'(add-to-list 'flyspell-delayed-commands 'org-self-insert-command))
|
||||
|
||||
;;;; Bookmark
|
||||
|
@ -994,7 +1100,7 @@ ELEMENT is the element at point."
|
|||
(org-show-context 'bookmark-jump)))
|
||||
|
||||
;; Make `bookmark-jump' shows the jump location if it was hidden.
|
||||
(eval-after-load "bookmark"
|
||||
(eval-after-load 'bookmark
|
||||
'(if (boundp 'bookmark-after-jump-hook)
|
||||
;; We can use the hook
|
||||
(add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide)
|
||||
|
@ -1043,17 +1149,18 @@ key."
|
|||
((guard (not (lookup-key calendar-mode-map "c")))
|
||||
(local-set-key "c" #'org-calendar-goto-agenda))
|
||||
(_ nil))
|
||||
(unless (eq org-agenda-diary-file 'diary-file)
|
||||
(unless (and (boundp 'org-agenda-diary-file)
|
||||
(eq org-agenda-diary-file 'diary-file))
|
||||
(local-set-key org-calendar-insert-diary-entry-key
|
||||
#'org-agenda-diary-entry)))
|
||||
|
||||
(eval-after-load "calendar"
|
||||
(eval-after-load 'calendar
|
||||
'(add-hook 'calendar-mode-hook #'org--setup-calendar-bindings))
|
||||
|
||||
;;;; Saveplace
|
||||
|
||||
;; Make sure saveplace shows the location if it was hidden
|
||||
(eval-after-load "saveplace"
|
||||
(eval-after-load 'saveplace
|
||||
'(defadvice save-place-find-file-hook (after org-make-visible activate)
|
||||
"Make the position visible."
|
||||
(org-bookmark-jump-unhide)))
|
||||
|
@ -1061,7 +1168,7 @@ key."
|
|||
;;;; Ecb
|
||||
|
||||
;; Make sure ecb shows the location if it was hidden
|
||||
(eval-after-load "ecb"
|
||||
(eval-after-load 'ecb
|
||||
'(defadvice ecb-method-clicked (after esf/org-show-context activate)
|
||||
"Make hierarchy visible when jumping into location from ECB tree buffer."
|
||||
(when (derived-mode-p 'org-mode)
|
||||
|
@ -1075,17 +1182,17 @@ key."
|
|||
(org-invisible-p))
|
||||
(org-show-context 'mark-goto)))
|
||||
|
||||
(eval-after-load "simple"
|
||||
(eval-after-load 'simple
|
||||
'(defadvice pop-to-mark-command (after org-make-visible activate)
|
||||
"Make the point visible with `org-show-context'."
|
||||
(org-mark-jump-unhide)))
|
||||
|
||||
(eval-after-load "simple"
|
||||
(eval-after-load 'simple
|
||||
'(defadvice exchange-point-and-mark (after org-make-visible activate)
|
||||
"Make the point visible with `org-show-context'."
|
||||
(org-mark-jump-unhide)))
|
||||
|
||||
(eval-after-load "simple"
|
||||
(eval-after-load 'simple
|
||||
'(defadvice pop-global-mark (after org-make-visible activate)
|
||||
"Make the point visible with `org-show-context'."
|
||||
(org-mark-jump-unhide)))
|
||||
|
@ -1094,9 +1201,13 @@ key."
|
|||
|
||||
;; Make "session.el" ignore our circular variable.
|
||||
(defvar session-globals-exclude)
|
||||
(eval-after-load "session"
|
||||
(eval-after-load 'session
|
||||
'(add-to-list 'session-globals-exclude 'org-mark-ring))
|
||||
|
||||
(provide 'org-compat)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-compat.el ends here
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
;;; org-crypt.el --- Public Key Encryption for Org Entries -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (C) 2007-2020 Free Software Foundation, Inc.
|
||||
|
||||
;; Emacs Lisp Archive Entry
|
||||
;; Filename: org-crypt.el
|
||||
;; Keywords: org-mode
|
||||
;; Author: John Wiegley <johnw@gnu.org>
|
||||
;; Maintainer: Peter Jones <pjones@pmade.com>
|
||||
;; Description: Adds public key encryption to Org buffers
|
||||
;; URL: http://www.newartisans.com/software/emacs.html
|
||||
;; Compatibility: Emacs22
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
;;
|
||||
|
@ -47,9 +41,7 @@
|
|||
;;
|
||||
;; 3. To later decrypt an entry, use `org-decrypt-entries' or
|
||||
;; `org-decrypt-entry'. It might be useful to bind this to a key,
|
||||
;; like C-c C-/. I hope that in the future, C-c C-r can be might
|
||||
;; overloaded to also decrypt an entry if it's encrypted, since
|
||||
;; that fits nicely with the meaning of "reveal".
|
||||
;; like C-c C-/.
|
||||
;;
|
||||
;; 4. To automatically encrypt all necessary entries when saving a
|
||||
;; file, call `org-crypt-use-before-save-magic' after loading
|
||||
|
@ -60,10 +52,11 @@
|
|||
;; - Carsten Dominik
|
||||
;; - Vitaly Ostanin
|
||||
|
||||
(require 'org)
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'org-macs)
|
||||
(require 'org-compat)
|
||||
|
||||
(declare-function epg-decrypt-string "epg" (context cipher))
|
||||
(declare-function epg-list-keys "epg" (context &optional name mode))
|
||||
(declare-function epg-make-context "epg"
|
||||
|
@ -74,6 +67,17 @@
|
|||
(context plain recipients &optional sign always-trust))
|
||||
(defvar epg-context)
|
||||
|
||||
(declare-function org-back-over-empty-lines "org" ())
|
||||
(declare-function org-back-to-heading "org" (&optional invisible-ok))
|
||||
(declare-function org-before-first-heading-p "org" ())
|
||||
(declare-function org-end-of-meta-data "org" (&optional full))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
|
||||
(declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
|
||||
(declare-function org-flag-subtree "org" (flag))
|
||||
(declare-function org-make-tags-matcher "org" (match))
|
||||
(declare-function org-previous-visible-heading "org" (arg))
|
||||
(declare-function org-scan-tags "org" (action matcher todo-only &optional start-level))
|
||||
(declare-function org-set-property "org" (property value))
|
||||
|
||||
(defgroup org-crypt nil
|
||||
"Org Crypt."
|
||||
|
@ -90,9 +94,18 @@ See the \"Match syntax\" section of the org manual for more details."
|
|||
(defcustom org-crypt-key ""
|
||||
"The default key to use when encrypting the contents of a heading.
|
||||
|
||||
This setting can also be overridden in the CRYPTKEY property."
|
||||
:type 'string
|
||||
:group 'org-crypt)
|
||||
If this variable is nil, always use symmetric encryption, unconditionally.
|
||||
|
||||
Otherwise, The string is matched against all keys in the key ring.
|
||||
In particular, the empty string matches no key. If no key is found,
|
||||
look for the `epa-file-encrypt-to' local variable. Ultimately fall back
|
||||
to symmetric encryption.
|
||||
|
||||
This setting can be overridden in the CRYPTKEY property."
|
||||
:group 'org-crypt
|
||||
:type '(choice
|
||||
(string :tag "Public key(s) matching")
|
||||
(const :tag "Symmetric encryption" nil)))
|
||||
|
||||
(defcustom org-crypt-disable-auto-save 'ask
|
||||
"What org-decrypt should do if `auto-save-mode' is enabled.
|
||||
|
@ -118,6 +131,36 @@ nil : Leave auto-save-mode enabled.
|
|||
(const :tag "Ask" ask)
|
||||
(const :tag "Encrypt" encrypt)))
|
||||
|
||||
(defun org-crypt--encrypted-text (beg end)
|
||||
"Return encrypted text in between BEG and END."
|
||||
;; Ignore indentation.
|
||||
(replace-regexp-in-string
|
||||
"^[ \t]*" ""
|
||||
(buffer-substring-no-properties beg end)))
|
||||
|
||||
(defun org-at-encrypted-entry-p ()
|
||||
"Is the current entry encrypted?
|
||||
When the entry is encrypted, return a pair (BEG . END) where BEG
|
||||
and END are buffer positions delimiting the encrypted area."
|
||||
(org-with-wide-buffer
|
||||
(unless (org-before-first-heading-p)
|
||||
(org-back-to-heading t)
|
||||
(org-end-of-meta-data 'standard)
|
||||
(let ((case-fold-search nil)
|
||||
(banner-start (rx (seq bol
|
||||
(zero-or-more (any "\t "))
|
||||
"-----BEGIN PGP MESSAGE-----"
|
||||
eol))))
|
||||
(when (looking-at banner-start)
|
||||
(let ((start (point))
|
||||
(banner-end (rx (seq bol
|
||||
(or (group (zero-or-more (any "\t "))
|
||||
"-----END PGP MESSAGE-----"
|
||||
eol)
|
||||
(seq (one-or-more "*") " "))))))
|
||||
(when (and (re-search-forward banner-end nil t) (match-string 1))
|
||||
(cons start (line-beginning-position 2)))))))))
|
||||
|
||||
(defun org-crypt-check-auto-save ()
|
||||
"Check whether auto-save-mode is enabled for the current buffer.
|
||||
|
||||
|
@ -149,93 +192,99 @@ See `org-crypt-disable-auto-save'."
|
|||
(t nil))))
|
||||
|
||||
(defun org-crypt-key-for-heading ()
|
||||
"Return the encryption key for the current heading."
|
||||
(save-excursion
|
||||
(org-back-to-heading t)
|
||||
(or (org-entry-get nil "CRYPTKEY" 'selective)
|
||||
org-crypt-key
|
||||
(and (boundp 'epa-file-encrypt-to) epa-file-encrypt-to)
|
||||
(message "No crypt key set, using symmetric encryption."))))
|
||||
|
||||
(defun org-encrypt-string (str crypt-key)
|
||||
"Return STR encrypted with CRYPT-KEY."
|
||||
;; Text and key have to be identical, otherwise we re-crypt.
|
||||
(if (and (string= crypt-key (get-text-property 0 'org-crypt-key str))
|
||||
(string= (sha1 str) (get-text-property 0 'org-crypt-checksum str)))
|
||||
(get-text-property 0 'org-crypt-text str)
|
||||
(setq-local epg-context (epg-make-context nil t t))
|
||||
(epg-encrypt-string epg-context str (epg-list-keys epg-context crypt-key))))
|
||||
"Return the encryption key(s) for the current heading.
|
||||
Assume `epg-context' is set."
|
||||
(and org-crypt-key
|
||||
(or (epg-list-keys epg-context
|
||||
(or (org-entry-get nil "CRYPTKEY" 'selective)
|
||||
org-crypt-key))
|
||||
(bound-and-true-p epa-file-encrypt-to)
|
||||
(progn
|
||||
(message "No crypt key set, using symmetric encryption.")
|
||||
nil))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-encrypt-entry ()
|
||||
"Encrypt the content of the current headline."
|
||||
(interactive)
|
||||
(require 'epg)
|
||||
(org-with-wide-buffer
|
||||
(org-back-to-heading t)
|
||||
(setq-local epg-context (epg-make-context nil t t))
|
||||
(let ((start-heading (point)))
|
||||
(org-end-of-meta-data)
|
||||
(unless (looking-at-p "-----BEGIN PGP MESSAGE-----")
|
||||
(let ((folded (org-invisible-p))
|
||||
(crypt-key (org-crypt-key-for-heading))
|
||||
(beg (point)))
|
||||
(unless (org-at-encrypted-entry-p)
|
||||
(require 'epg)
|
||||
(setq-local epg-context (epg-make-context nil t t))
|
||||
(org-with-wide-buffer
|
||||
(org-back-to-heading t)
|
||||
(let ((start-heading (point))
|
||||
(crypt-key (org-crypt-key-for-heading))
|
||||
(folded? (org-invisible-p (line-beginning-position))))
|
||||
(org-end-of-meta-data 'standard)
|
||||
(let ((beg (point))
|
||||
(folded-heading
|
||||
(and folded?
|
||||
(save-excursion
|
||||
(org-previous-visible-heading 1)
|
||||
(point)))))
|
||||
(goto-char start-heading)
|
||||
(org-end-of-subtree t t)
|
||||
(org-back-over-empty-lines)
|
||||
(let ((contents (delete-and-extract-region beg (point))))
|
||||
(let* ((contents (delete-and-extract-region beg (point)))
|
||||
(key (get-text-property 0 'org-crypt-key contents))
|
||||
(checksum (get-text-property 0 'org-crypt-checksum contents)))
|
||||
(condition-case err
|
||||
(insert (org-encrypt-string contents crypt-key))
|
||||
(insert
|
||||
;; Text and key have to be identical, otherwise we
|
||||
;; re-crypt.
|
||||
(if (and (equal crypt-key key)
|
||||
(string= checksum (sha1 contents)))
|
||||
(get-text-property 0 'org-crypt-text contents)
|
||||
(epg-encrypt-string epg-context contents crypt-key)))
|
||||
;; If encryption failed, make sure to insert back entry
|
||||
;; contents in the buffer.
|
||||
(error (insert contents) (error (nth 1 err)))))
|
||||
(when folded
|
||||
(goto-char start-heading)
|
||||
(error
|
||||
(insert contents)
|
||||
(error (error-message-string err)))))
|
||||
(when folded-heading
|
||||
(goto-char folded-heading)
|
||||
(org-flag-subtree t))
|
||||
nil)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-decrypt-entry ()
|
||||
"Decrypt the content of the current headline."
|
||||
(interactive)
|
||||
(require 'epg)
|
||||
(unless (org-before-first-heading-p)
|
||||
(org-with-wide-buffer
|
||||
(org-back-to-heading t)
|
||||
(let ((heading-point (point))
|
||||
(heading-was-invisible-p
|
||||
(save-excursion
|
||||
(outline-end-of-heading)
|
||||
(org-invisible-p))))
|
||||
(org-end-of-meta-data)
|
||||
(when (looking-at "-----BEGIN PGP MESSAGE-----")
|
||||
(org-crypt-check-auto-save)
|
||||
(setq-local epg-context (epg-make-context nil t t))
|
||||
(let* ((end (save-excursion
|
||||
(search-forward "-----END PGP MESSAGE-----")
|
||||
(forward-line)
|
||||
(point)))
|
||||
(encrypted-text (buffer-substring-no-properties (point) end))
|
||||
(decrypted-text
|
||||
(decode-coding-string
|
||||
(epg-decrypt-string
|
||||
epg-context
|
||||
encrypted-text)
|
||||
'utf-8)))
|
||||
;; Delete region starting just before point, because the
|
||||
;; outline property starts at the \n of the heading.
|
||||
(delete-region (1- (point)) end)
|
||||
;; Store a checksum of the decrypted and the encrypted
|
||||
;; text value. This allows reusing the same encrypted text
|
||||
;; if the text does not change, and therefore avoid a
|
||||
;; re-encryption process.
|
||||
(insert "\n" (propertize decrypted-text
|
||||
'org-crypt-checksum (sha1 decrypted-text)
|
||||
'org-crypt-key (org-crypt-key-for-heading)
|
||||
'org-crypt-text encrypted-text))
|
||||
(when heading-was-invisible-p
|
||||
(goto-char heading-point)
|
||||
(org-flag-subtree t))
|
||||
nil))))))
|
||||
(pcase (org-at-encrypted-entry-p)
|
||||
(`(,beg . ,end)
|
||||
(require 'epg)
|
||||
(setq-local epg-context (epg-make-context nil t t))
|
||||
(org-with-point-at beg
|
||||
(org-crypt-check-auto-save)
|
||||
(let* ((folded-heading
|
||||
(and (org-invisible-p)
|
||||
(save-excursion
|
||||
(org-previous-visible-heading 1)
|
||||
(point))))
|
||||
(encrypted-text (org-crypt--encrypted-text beg end))
|
||||
(decrypted-text
|
||||
(decode-coding-string
|
||||
(epg-decrypt-string epg-context encrypted-text)
|
||||
'utf-8)))
|
||||
;; Delete region starting just before point, because the
|
||||
;; outline property starts at the \n of the heading.
|
||||
(delete-region (1- (point)) end)
|
||||
;; Store a checksum of the decrypted and the encrypted text
|
||||
;; value. This allows reusing the same encrypted text if the
|
||||
;; text does not change, and therefore avoid a re-encryption
|
||||
;; process.
|
||||
(insert "\n"
|
||||
(propertize decrypted-text
|
||||
'org-crypt-checksum (sha1 decrypted-text)
|
||||
'org-crypt-key (org-crypt-key-for-heading)
|
||||
'org-crypt-text encrypted-text))
|
||||
(when folded-heading
|
||||
(goto-char folded-heading)
|
||||
(org-flag-subtree t))
|
||||
nil)))
|
||||
(_ nil)))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-encrypt-entries ()
|
||||
"Encrypt all top-level entries in the current buffer."
|
||||
(interactive)
|
||||
|
@ -245,6 +294,7 @@ See `org-crypt-disable-auto-save'."
|
|||
(cdr (org-make-tags-matcher org-crypt-tag-matcher))
|
||||
org--matcher-tags-todo-only)))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-decrypt-entries ()
|
||||
"Decrypt all entries in the current buffer."
|
||||
(interactive)
|
||||
|
@ -254,14 +304,7 @@ See `org-crypt-disable-auto-save'."
|
|||
(cdr (org-make-tags-matcher org-crypt-tag-matcher))
|
||||
org--matcher-tags-todo-only)))
|
||||
|
||||
(defun org-at-encrypted-entry-p ()
|
||||
"Is the current entry encrypted?"
|
||||
(unless (org-before-first-heading-p)
|
||||
(save-excursion
|
||||
(org-back-to-heading t)
|
||||
(search-forward "-----BEGIN PGP MESSAGE-----"
|
||||
(save-excursion (outline-next-heading)) t))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-crypt-use-before-save-magic ()
|
||||
"Add a hook to automatically encrypt entries before a file is saved to disk."
|
||||
(add-hook
|
||||
|
|
|
@ -51,11 +51,29 @@ Added time stamp is active unless value is `inactive'."
|
|||
|
||||
;;;###autoload
|
||||
(defun org-datetree-find-date-create (d &optional keep-restriction)
|
||||
"Find or create an entry for date D.
|
||||
"Find or create a day entry for date D.
|
||||
If KEEP-RESTRICTION is non-nil, do not widen the buffer.
|
||||
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))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-datetree-find-month-create (d &optional keep-restriction)
|
||||
"Find or create a month entry for date D.
|
||||
Compared to `org-datetree-find-date-create' this function creates
|
||||
entries grouped by month instead of days.
|
||||
If KEEP-RESTRICTION is non-nil, do not widen the buffer.
|
||||
When it is nil, the buffer will be widened to make sure an existing date
|
||||
tree can be found. If it is the symbol `subtree-at-point', then the tree
|
||||
will be built under the headline at point."
|
||||
(org-datetree--find-create-group d 'month keep-restriction))
|
||||
|
||||
(defun org-datetree--find-create-group
|
||||
(d time-grouping &optional keep-restriction)
|
||||
"Find or create an entry for date D.
|
||||
If time-period is day, group entries by day. If time-period is
|
||||
month, then group entries by month."
|
||||
(setq-local org-datetree-base-level 1)
|
||||
(save-restriction
|
||||
(if (eq keep-restriction 'subtree-at-point)
|
||||
|
@ -84,9 +102,10 @@ will be built under the headline at point."
|
|||
(org-datetree--find-create
|
||||
"^\\*+[ \t]+%d-\\([01][0-9]\\) \\w+$"
|
||||
year month)
|
||||
(org-datetree--find-create
|
||||
"^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$"
|
||||
year month day))))
|
||||
(when (eq time-grouping 'day)
|
||||
(org-datetree--find-create
|
||||
"^\\*+[ \t]+%d-%02d-\\([0123][0-9]\\) \\w+$"
|
||||
year month day)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-datetree-find-iso-week-create (d &optional keep-restriction)
|
||||
|
@ -166,6 +185,8 @@ inserted into the buffer."
|
|||
|
||||
(defun org-datetree-insert-line (year &optional month day text)
|
||||
(delete-region (save-excursion (skip-chars-backward " \t\n") (point)) (point))
|
||||
(when (assq 'heading org-blank-before-new-entry)
|
||||
(insert "\n"))
|
||||
(insert "\n" (make-string org-datetree-base-level ?*) " \n")
|
||||
(backward-char)
|
||||
(when month (org-do-demote))
|
||||
|
|
|
@ -28,14 +28,16 @@
|
|||
;; - 3:12
|
||||
;; - 1:23:45
|
||||
;; - 1y 3d 3h 4min
|
||||
;; - 1d3h5min
|
||||
;; - 3d 13:35
|
||||
;; - 2.35h
|
||||
;;
|
||||
;; More accurately, it consists of numbers and units, as defined in
|
||||
;; variable `org-duration-units', separated with white spaces, and
|
||||
;; a "H:MM" or "H:MM:SS" part. White spaces are tolerated between the
|
||||
;; number and its relative unit. Variable `org-duration-format'
|
||||
;; controls durations default representation.
|
||||
;; variable `org-duration-units', possibly separated with white
|
||||
;; spaces, and an optional "H:MM" or "H:MM:SS" part, which always
|
||||
;; comes last. White spaces are tolerated between the number and its
|
||||
;; relative unit. Variable `org-duration-format' controls durations
|
||||
;; default representation.
|
||||
;;
|
||||
;; The library provides functions allowing to convert a duration to,
|
||||
;; and from, a number of minutes: `org-duration-to-minutes' and
|
||||
|
@ -122,8 +124,7 @@ are specified here.
|
|||
Units with a zero value are skipped, unless REQUIRED? is non-nil.
|
||||
In that case, the unit is always used.
|
||||
|
||||
Eventually, the list can contain one of the following special
|
||||
entries:
|
||||
The list can also contain one of the following special entries:
|
||||
|
||||
(special . h:mm)
|
||||
(special . h:mm:ss)
|
||||
|
@ -139,6 +140,10 @@ entries:
|
|||
first one required or with a non-zero integer part. If there
|
||||
is no such unit, the smallest one is used.
|
||||
|
||||
Eventually, if the list contains the symbol `compact', the
|
||||
duration is expressed in a compact form, without any white space
|
||||
between units.
|
||||
|
||||
For example,
|
||||
|
||||
((\"d\" . nil) (\"h\" . t) (\"min\" . t))
|
||||
|
@ -172,7 +177,6 @@ a 2-digits fractional part, of \"d\" unit. A duration shorter
|
|||
than a day uses \"h\" unit instead."
|
||||
:group 'org-time
|
||||
:group 'org-clock
|
||||
:version "26.1"
|
||||
:package-version '(Org . "9.1")
|
||||
:type '(choice
|
||||
(const :tag "Use H:MM" h:mm)
|
||||
|
@ -191,7 +195,8 @@ than a day uses \"h\" unit instead."
|
|||
(const h:mm))
|
||||
(cons :tag "Use both units and H:MM:SS"
|
||||
(const special)
|
||||
(const h:mm:ss))))))
|
||||
(const h:mm:ss))
|
||||
(const :tag "Use compact form" compact)))))
|
||||
|
||||
|
||||
;;; Internal variables and functions
|
||||
|
@ -249,13 +254,10 @@ When optional argument CANONICAL is non-nil, refer to
|
|||
org-duration-units))
|
||||
t)))
|
||||
(setq org-duration--full-re
|
||||
(format "\\`[ \t]*%s\\(?:[ \t]+%s\\)*[ \t]*\\'"
|
||||
org-duration--unit-re
|
||||
org-duration--unit-re))
|
||||
(format "\\`\\(?:[ \t]*%s\\)+[ \t]*\\'" org-duration--unit-re))
|
||||
(setq org-duration--mixed-re
|
||||
(format "\\`[ \t]*\\(?1:%s\\(?:[ \t]+%s\\)*\\)[ \t]+\
|
||||
(format "\\`\\(?1:\\([ \t]*%s\\)+\\)[ \t]*\
|
||||
\\(?2:[0-9]+\\(?::[0-9][0-9]\\)\\{1,2\\}\\)[ \t]*\\'"
|
||||
org-duration--unit-re
|
||||
org-duration--unit-re)))
|
||||
|
||||
;;;###autoload
|
||||
|
@ -353,10 +355,11 @@ Raise an error if expected format is unknown."
|
|||
;; Represent minutes above hour using provided units and H:MM
|
||||
;; or H:MM:SS below.
|
||||
(let* ((units-part (* min-modifier (/ (floor minutes) min-modifier)))
|
||||
(minutes-part (- minutes units-part)))
|
||||
(minutes-part (- minutes units-part))
|
||||
(compact (memq 'compact duration-format)))
|
||||
(concat
|
||||
(org-duration-from-minutes units-part truncated-format canonical)
|
||||
" "
|
||||
(and (not compact) " ")
|
||||
(org-duration-from-minutes minutes-part mode))))))
|
||||
;; Units format.
|
||||
(duration-format
|
||||
|
@ -368,12 +371,16 @@ Raise an error if expected format is unknown."
|
|||
(format "%%.%df" digits))))
|
||||
(selected-units
|
||||
(sort (cl-remove-if
|
||||
;; Ignore special format cells.
|
||||
(lambda (pair) (pcase pair (`(special . ,_) t) (_ nil)))
|
||||
;; Ignore special format cells and compact option.
|
||||
(lambda (pair)
|
||||
(pcase pair
|
||||
((or `compact `(special . ,_)) t)
|
||||
(_ nil)))
|
||||
duration-format)
|
||||
(lambda (a b)
|
||||
(> (org-duration--modifier (car a) canonical)
|
||||
(org-duration--modifier (car b) canonical))))))
|
||||
(org-duration--modifier (car b) canonical)))))
|
||||
(separator (if (memq 'compact duration-format) "" " ")))
|
||||
(cond
|
||||
;; Fractional duration: use first unit that is either required
|
||||
;; or smaller than MINUTES.
|
||||
|
@ -402,8 +409,8 @@ Raise an error if expected format is unknown."
|
|||
(cond ((<= modifier minutes)
|
||||
(let ((value (floor minutes modifier)))
|
||||
(cl-decf minutes (* value modifier))
|
||||
(format " %d%s" value unit)))
|
||||
(required? (concat " 0" unit))
|
||||
(format "%s%d%s" separator value unit)))
|
||||
(required? (concat separator "0" unit))
|
||||
(t ""))))
|
||||
selected-units
|
||||
""))))
|
||||
|
@ -441,4 +448,9 @@ with \"H:MM:SS\" format, return `h:mm:ss'. Otherwise, return
|
|||
(org-duration-set-regexps)
|
||||
|
||||
(provide 'org-duration)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-duration.el ends here
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
(declare-function org-at-heading-p "org" (&optional _))
|
||||
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
|
||||
(declare-function org-escape-code-in-string "org-src" (s))
|
||||
(declare-function org-find-visible "org" ())
|
||||
(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))
|
||||
|
@ -330,7 +329,9 @@ match group 2.
|
|||
Don't modify it, set `org-element-affiliated-keywords' instead.")
|
||||
|
||||
(defconst org-element-object-restrictions
|
||||
(let* ((standard-set (remq 'table-cell org-element-all-objects))
|
||||
(let* ((minimal-set '(bold code entity italic latex-fragment strike-through
|
||||
subscript superscript underline verbatim))
|
||||
(standard-set (remq 'table-cell org-element-all-objects))
|
||||
(standard-set-no-line-break (remq 'line-break standard-set)))
|
||||
`((bold ,@standard-set)
|
||||
(footnote-reference ,@standard-set)
|
||||
|
@ -341,23 +342,20 @@ Don't modify it, set `org-element-affiliated-keywords' instead.")
|
|||
(keyword ,@(remq 'footnote-reference standard-set))
|
||||
;; Ignore all links in a link description. Also ignore
|
||||
;; radio-targets and line breaks.
|
||||
(link bold code entity export-snippet inline-babel-call inline-src-block
|
||||
italic latex-fragment macro statistics-cookie strike-through
|
||||
subscript superscript underline verbatim)
|
||||
(link export-snippet inline-babel-call inline-src-block macro
|
||||
statistics-cookie ,@minimal-set)
|
||||
(paragraph ,@standard-set)
|
||||
;; Remove any variable object from radio target as it would
|
||||
;; prevent it from being properly recognized.
|
||||
(radio-target bold code entity italic latex-fragment strike-through
|
||||
subscript superscript underline superscript)
|
||||
(radio-target ,@minimal-set)
|
||||
(strike-through ,@standard-set)
|
||||
(subscript ,@standard-set)
|
||||
(superscript ,@standard-set)
|
||||
;; Ignore inline babel call and inline source block as formulas
|
||||
;; are possible. Also ignore line breaks and statistics
|
||||
;; cookies.
|
||||
(table-cell bold code entity export-snippet footnote-reference italic
|
||||
latex-fragment link macro radio-target strike-through
|
||||
subscript superscript target timestamp underline verbatim)
|
||||
(table-cell export-snippet footnote-reference link macro radio-target
|
||||
target timestamp ,@minimal-set)
|
||||
(table-row table-cell)
|
||||
(underline ,@standard-set)
|
||||
(verse-block ,@standard-set)))
|
||||
|
@ -367,10 +365,6 @@ key is an element or object type containing objects and value is
|
|||
a list of types that can be contained within an element or object
|
||||
of such type.
|
||||
|
||||
For example, in a `radio-target' object, one can only find
|
||||
entities, latex-fragments, subscript, superscript and text
|
||||
markup.
|
||||
|
||||
This alist also applies to secondary string. For example, an
|
||||
`headline' type element doesn't directly contain objects, but
|
||||
still has an entry since one of its properties (`:title') does.")
|
||||
|
@ -1806,13 +1800,10 @@ Return a list whose CAR is `clock' and CDR is a plist containing
|
|||
|
||||
;;;; Comment
|
||||
|
||||
(defun org-element-comment-parser (limit affiliated)
|
||||
(defun org-element-comment-parser (limit)
|
||||
"Parse a comment.
|
||||
|
||||
LIMIT bounds the search. AFFILIATED is a list of which CAR is
|
||||
the buffer position at the beginning of the first affiliated
|
||||
keyword and CDR is a plist of affiliated keywords along with
|
||||
their value.
|
||||
LIMIT bounds the search.
|
||||
|
||||
Return a list whose CAR is `comment' and CDR is a plist
|
||||
containing `:begin', `:end', `:value', `:post-blank',
|
||||
|
@ -1820,8 +1811,7 @@ containing `:begin', `:end', `:value', `:post-blank',
|
|||
|
||||
Assume point is at comment beginning."
|
||||
(save-excursion
|
||||
(let* ((begin (car affiliated))
|
||||
(post-affiliated (point))
|
||||
(let* ((begin (point))
|
||||
(value (prog2 (looking-at "[ \t]*# ?")
|
||||
(buffer-substring-no-properties
|
||||
(match-end 0) (line-end-position))
|
||||
|
@ -1843,13 +1833,11 @@ Assume point is at comment beginning."
|
|||
(skip-chars-forward " \r\t\n" limit)
|
||||
(if (eobp) (point) (line-beginning-position)))))
|
||||
(list 'comment
|
||||
(nconc
|
||||
(list :begin begin
|
||||
:end end
|
||||
:value value
|
||||
:post-blank (count-lines com-end end)
|
||||
:post-affiliated post-affiliated)
|
||||
(cdr affiliated))))))
|
||||
(list :begin begin
|
||||
:end end
|
||||
:value value
|
||||
:post-blank (count-lines com-end end)
|
||||
:post-affiliated begin)))))
|
||||
|
||||
(defun org-element-comment-interpreter (comment _)
|
||||
"Interpret COMMENT element as Org syntax.
|
||||
|
@ -2186,9 +2174,9 @@ the buffer position at the beginning of the first affiliated
|
|||
keyword and CDR is a plist of affiliated keywords along with
|
||||
their value.
|
||||
|
||||
Return a list whose CAR is `keyword' and CDR is a plist
|
||||
containing `:key', `:value', `:begin', `:end', `:post-blank' and
|
||||
`:post-affiliated' keywords."
|
||||
Return a list whose CAR is a normalized `keyword' (uppercase) and
|
||||
CDR is a plist containing `:key', `:value', `:begin', `:end',
|
||||
`:post-blank' and `:post-affiliated' keywords."
|
||||
(save-excursion
|
||||
;; An orphaned affiliated keyword is considered as a regular
|
||||
;; keyword. In this case AFFILIATED is nil, so we take care of
|
||||
|
@ -3217,10 +3205,11 @@ Assume point is at the beginning of the link."
|
|||
(setq post-blank
|
||||
(progn (goto-char link-end) (skip-chars-forward " \t")))
|
||||
(setq end (point)))
|
||||
;; Special "file" type link processing. Extract opening
|
||||
;; Special "file"-type link processing. Extract opening
|
||||
;; application and search option, if any. Also normalize URI.
|
||||
(when (string-match "\\`file\\(?:\\+\\(.+\\)\\)?\\'" type)
|
||||
(setq application (match-string 1 type) type "file")
|
||||
(setq application (match-string 1 type))
|
||||
(setq type "file")
|
||||
(when (string-match "::\\(.*\\)\\'" path)
|
||||
(setq search-option (match-string 1 path))
|
||||
(setq path (replace-match "" nil nil path)))
|
||||
|
@ -3823,12 +3812,6 @@ Assume point is at the first equal sign marker."
|
|||
;; `org-element--current-element' is the core function of this section.
|
||||
;; It returns the Lisp representation of the element starting at
|
||||
;; point.
|
||||
;;
|
||||
;; `org-element--current-element' makes use of special modes. They
|
||||
;; are activated for fixed element chaining (e.g., `plain-list' >
|
||||
;; `item') or fixed conditional element chaining (e.g., `headline' >
|
||||
;; `section'). Special modes are: `first-section', `item',
|
||||
;; `node-property', `section' and `table-row'.
|
||||
|
||||
(defun org-element--current-element (limit &optional granularity mode structure)
|
||||
"Parse the element starting at point.
|
||||
|
@ -3848,8 +3831,9 @@ nil), secondary values will not be parsed, since they only
|
|||
contain objects.
|
||||
|
||||
Optional argument MODE, when non-nil, can be either
|
||||
`first-section', `section', `planning', `item', `node-property'
|
||||
and `table-row'.
|
||||
`first-section', `item', `node-property', `planning',
|
||||
`property-drawer', `section', `table-row', or `top-comment'.
|
||||
|
||||
|
||||
If STRUCTURE isn't provided but MODE is set to `item', it will be
|
||||
computed.
|
||||
|
@ -3879,15 +3863,22 @@ element it has to parse."
|
|||
(org-element-section-parser
|
||||
(or (save-excursion (org-with-limited-levels (outline-next-heading)))
|
||||
limit)))
|
||||
;; Comments.
|
||||
((looking-at "^[ \t]*#\\(?: \\|$\\)")
|
||||
(org-element-comment-parser limit))
|
||||
;; Planning.
|
||||
((and (eq mode 'planning)
|
||||
(eq ?* (char-after (line-beginning-position 0)))
|
||||
(looking-at org-planning-line-re))
|
||||
(org-element-planning-parser limit))
|
||||
;; Property drawer.
|
||||
((and (memq mode '(planning property-drawer))
|
||||
(eq ?* (char-after (line-beginning-position
|
||||
(if (eq mode 'planning) 0 -1))))
|
||||
((and (pcase mode
|
||||
(`planning (eq ?* (char-after (line-beginning-position 0))))
|
||||
((or `property-drawer `top-comment)
|
||||
(save-excursion
|
||||
(beginning-of-line 0)
|
||||
(not (looking-at "[[:blank:]]*$"))))
|
||||
(_ nil))
|
||||
(looking-at org-property-drawer-re))
|
||||
(org-element-property-drawer-parser limit))
|
||||
;; When not at bol, point is at the beginning of an item or
|
||||
|
@ -3896,7 +3887,7 @@ element it has to parse."
|
|||
;; Clock.
|
||||
((looking-at org-clock-line-re) (org-element-clock-parser limit))
|
||||
;; Inlinetask.
|
||||
((org-at-heading-p)
|
||||
((looking-at "^\\*+ ")
|
||||
(org-element-inlinetask-parser limit raw-secondary-p))
|
||||
;; From there, elements can have affiliated keywords.
|
||||
(t (let ((affiliated (org-element--collect-affiliated-keywords
|
||||
|
@ -3910,7 +3901,7 @@ element it has to parse."
|
|||
;; LaTeX Environment.
|
||||
((looking-at org-element--latex-begin-environment)
|
||||
(org-element-latex-environment-parser limit affiliated))
|
||||
;; Drawer and Property Drawer.
|
||||
;; Drawer.
|
||||
((looking-at org-drawer-regexp)
|
||||
(org-element-drawer-parser limit affiliated))
|
||||
;; Fixed Width
|
||||
|
@ -3918,13 +3909,10 @@ element it has to parse."
|
|||
(org-element-fixed-width-parser limit affiliated))
|
||||
;; Inline Comments, Blocks, Babel Calls, Dynamic Blocks and
|
||||
;; Keywords.
|
||||
((looking-at "[ \t]*#")
|
||||
((looking-at "[ \t]*#\\+")
|
||||
(goto-char (match-end 0))
|
||||
(cond
|
||||
((looking-at "\\(?: \\|$\\)")
|
||||
(beginning-of-line)
|
||||
(org-element-comment-parser limit affiliated))
|
||||
((looking-at "\\+BEGIN_\\(\\S-+\\)")
|
||||
((looking-at "BEGIN_\\(\\S-+\\)")
|
||||
(beginning-of-line)
|
||||
(funcall (pcase (upcase (match-string 1))
|
||||
("CENTER" #'org-element-center-block-parser)
|
||||
|
@ -3937,13 +3925,13 @@ element it has to parse."
|
|||
(_ #'org-element-special-block-parser))
|
||||
limit
|
||||
affiliated))
|
||||
((looking-at "\\+CALL:")
|
||||
((looking-at "CALL:")
|
||||
(beginning-of-line)
|
||||
(org-element-babel-call-parser limit affiliated))
|
||||
((looking-at "\\+BEGIN:? ")
|
||||
((looking-at "BEGIN:? ")
|
||||
(beginning-of-line)
|
||||
(org-element-dynamic-block-parser limit affiliated))
|
||||
((looking-at "\\+\\S-+:")
|
||||
((looking-at "\\S-+:")
|
||||
(beginning-of-line)
|
||||
(org-element-keyword-parser limit affiliated))
|
||||
(t
|
||||
|
@ -4024,7 +4012,8 @@ When PARSE is non-nil, values from keywords belonging to
|
|||
(skip-chars-backward " \t")
|
||||
(point))))
|
||||
(if parsed?
|
||||
(org-element--parse-objects beg end nil restrict)
|
||||
(save-match-data
|
||||
(org-element--parse-objects beg end nil restrict))
|
||||
(org-trim (buffer-substring-no-properties beg end)))))
|
||||
;; If KWD is a dual keyword, find its secondary value.
|
||||
;; Maybe parse it.
|
||||
|
@ -4144,7 +4133,9 @@ If STRING is the empty string or nil, return nil."
|
|||
(dolist (v local-variables)
|
||||
(ignore-errors
|
||||
(if (symbolp v) (makunbound v)
|
||||
(set (make-local-variable (car v)) (cdr v)))))
|
||||
;; Don't set file name to avoid mishandling hooks (bug#44524)
|
||||
(unless (memq (car v) '(buffer-file-name buffer-file-truename))
|
||||
(set (make-local-variable (car v)) (cdr v))))))
|
||||
;; Transferring local variables may put the temporary buffer
|
||||
;; into a read-only state. Make sure we can insert STRING.
|
||||
(let ((inhibit-read-only t)) (insert string))
|
||||
|
@ -4320,34 +4311,41 @@ looking into captions:
|
|||
;; `org-element--object-lex' to find the next object in the current
|
||||
;; container.
|
||||
|
||||
(defsubst org-element--next-mode (type parentp)
|
||||
"Return next special mode according to TYPE, or nil.
|
||||
TYPE is a symbol representing the type of an element or object
|
||||
containing next element if PARENTP is non-nil, or before it
|
||||
otherwise. Modes can be either `first-section', `item',
|
||||
`node-property', `planning', `property-drawer', `section',
|
||||
`table-row' or nil."
|
||||
(if parentp
|
||||
(defsubst org-element--next-mode (mode type parent?)
|
||||
"Return next mode according to current one.
|
||||
|
||||
MODE is a symbol representing the expectation about the next
|
||||
element or object. Meaningful values are `first-section',
|
||||
`item', `node-property', `planning', `property-drawer',
|
||||
`section', `table-row', `top-comment', and nil.
|
||||
|
||||
TYPE is the type of the current element or object.
|
||||
|
||||
If PARENT? is non-nil, assume the next element or object will be
|
||||
located inside the current one. "
|
||||
(if parent?
|
||||
(pcase type
|
||||
(`headline 'section)
|
||||
((and (guard (eq mode 'first-section)) `section) 'top-comment)
|
||||
(`inlinetask 'planning)
|
||||
(`plain-list 'item)
|
||||
(`property-drawer 'node-property)
|
||||
(`section 'planning)
|
||||
(`table 'table-row))
|
||||
(pcase type
|
||||
(pcase mode
|
||||
(`item 'item)
|
||||
(`node-property 'node-property)
|
||||
(`planning 'property-drawer)
|
||||
(`table-row 'table-row))))
|
||||
((and `planning (guard (eq type 'planning))) 'property-drawer)
|
||||
(`table-row 'table-row)
|
||||
((and `top-comment (guard (eq type 'comment))) 'property-drawer))))
|
||||
|
||||
(defun org-element--parse-elements
|
||||
(beg end mode structure granularity visible-only acc)
|
||||
"Parse elements between BEG and END positions.
|
||||
|
||||
MODE prioritizes some elements over the others. It can be set to
|
||||
`first-section', `section', `planning', `item', `node-property'
|
||||
or `table-row'.
|
||||
`first-section', `item', `node-property', `planning',
|
||||
`property-drawer', `section', `table-row', `top-comment', or nil.
|
||||
|
||||
When value is `item', STRUCTURE will be used as the current list
|
||||
structure.
|
||||
|
@ -4361,54 +4359,52 @@ elements.
|
|||
Elements are accumulated into ACC."
|
||||
(save-excursion
|
||||
(goto-char beg)
|
||||
;; Visible only: skip invisible parts at the beginning of the
|
||||
;; element.
|
||||
(when (and visible-only (org-invisible-p2))
|
||||
(goto-char (min (1+ (org-find-visible)) end)))
|
||||
;; When parsing only headlines, skip any text before first one.
|
||||
(when (and (eq granularity 'headline) (not (org-at-heading-p)))
|
||||
(org-with-limited-levels (outline-next-heading)))
|
||||
(let (elements)
|
||||
(while (< (point) end)
|
||||
;; Find current element's type and parse it accordingly to
|
||||
;; its category.
|
||||
(let* ((element (org-element--current-element
|
||||
end granularity mode structure))
|
||||
(type (org-element-type element))
|
||||
(cbeg (org-element-property :contents-begin element)))
|
||||
(goto-char (org-element-property :end element))
|
||||
;; Visible only: skip invisible parts between siblings.
|
||||
(when (and visible-only (org-invisible-p2))
|
||||
(goto-char (min (1+ (org-find-visible)) end)))
|
||||
;; Fill ELEMENT contents by side-effect.
|
||||
(cond
|
||||
;; If element has no contents, don't modify it.
|
||||
((not cbeg))
|
||||
;; Greater element: parse it between `contents-begin' and
|
||||
;; `contents-end'. Make sure GRANULARITY allows the
|
||||
;; recursion, or ELEMENT is a headline, in which case going
|
||||
;; inside is mandatory, in order to get sub-level headings.
|
||||
((and (memq type org-element-greater-elements)
|
||||
(or (memq granularity '(element object nil))
|
||||
(and (eq granularity 'greater-element)
|
||||
(eq type 'section))
|
||||
(eq type 'headline)))
|
||||
(org-element--parse-elements
|
||||
cbeg (org-element-property :contents-end element)
|
||||
;; Possibly switch to a special mode.
|
||||
(org-element--next-mode type t)
|
||||
(and (memq type '(item plain-list))
|
||||
(org-element-property :structure element))
|
||||
granularity visible-only element))
|
||||
;; ELEMENT has contents. Parse objects inside, if
|
||||
;; GRANULARITY allows it.
|
||||
((memq granularity '(object nil))
|
||||
(org-element--parse-objects
|
||||
cbeg (org-element-property :contents-end element) element
|
||||
(org-element-restriction type))))
|
||||
(push (org-element-put-property element :parent acc) elements)
|
||||
;; Update mode.
|
||||
(setq mode (org-element--next-mode type nil))))
|
||||
;; Visible only: skip invisible parts due to folding.
|
||||
(if (and visible-only (org-invisible-p nil t))
|
||||
(progn
|
||||
(goto-char (org-find-visible))
|
||||
(when (and (eolp) (not (eobp))) (forward-char)))
|
||||
;; Find current element's type and parse it accordingly to
|
||||
;; its category.
|
||||
(let* ((element (org-element--current-element
|
||||
end granularity mode structure))
|
||||
(type (org-element-type element))
|
||||
(cbeg (org-element-property :contents-begin element)))
|
||||
(goto-char (org-element-property :end element))
|
||||
;; Fill ELEMENT contents by side-effect.
|
||||
(cond
|
||||
;; If element has no contents, don't modify it.
|
||||
((not cbeg))
|
||||
;; Greater element: parse it between `contents-begin' and
|
||||
;; `contents-end'. Ensure GRANULARITY allows recursion,
|
||||
;; or ELEMENT is a headline, in which case going inside
|
||||
;; is mandatory, in order to get sub-level headings.
|
||||
((and (memq type org-element-greater-elements)
|
||||
(or (memq granularity '(element object nil))
|
||||
(and (eq granularity 'greater-element)
|
||||
(eq type 'section))
|
||||
(eq type 'headline)))
|
||||
(org-element--parse-elements
|
||||
cbeg (org-element-property :contents-end element)
|
||||
;; Possibly switch to a special mode.
|
||||
(org-element--next-mode mode type t)
|
||||
(and (memq type '(item plain-list))
|
||||
(org-element-property :structure element))
|
||||
granularity visible-only element))
|
||||
;; ELEMENT has contents. Parse objects inside, if
|
||||
;; GRANULARITY allows it.
|
||||
((memq granularity '(object nil))
|
||||
(org-element--parse-objects
|
||||
cbeg (org-element-property :contents-end element) element
|
||||
(org-element-restriction type))))
|
||||
(push (org-element-put-property element :parent acc) elements)
|
||||
;; Update mode.
|
||||
(setq mode (org-element--next-mode mode type nil)))))
|
||||
;; Return result.
|
||||
(apply #'org-element-set-contents acc (nreverse elements)))))
|
||||
|
||||
|
@ -4498,15 +4494,21 @@ to an appropriate container (e.g., a paragraph)."
|
|||
(and (memq 'latex-fragment restriction)
|
||||
(org-element-latex-fragment-parser)))))
|
||||
(?\[
|
||||
(if (eq (aref result 1) ?\[)
|
||||
(and (memq 'link restriction)
|
||||
(org-element-link-parser))
|
||||
(or (and (memq 'footnote-reference restriction)
|
||||
(org-element-footnote-reference-parser))
|
||||
(and (memq 'timestamp restriction)
|
||||
(org-element-timestamp-parser))
|
||||
(and (memq 'statistics-cookie restriction)
|
||||
(org-element-statistics-cookie-parser)))))
|
||||
(pcase (aref result 1)
|
||||
((and ?\[
|
||||
(guard (memq 'link restriction)))
|
||||
(org-element-link-parser))
|
||||
((and ?f
|
||||
(guard (memq 'footnote-reference restriction)))
|
||||
(org-element-footnote-reference-parser))
|
||||
((and (or ?% ?/)
|
||||
(guard (memq 'statistics-cookie restriction)))
|
||||
(org-element-statistics-cookie-parser))
|
||||
(_
|
||||
(or (and (memq 'timestamp restriction)
|
||||
(org-element-timestamp-parser))
|
||||
(and (memq 'statistics-cookie restriction)
|
||||
(org-element-statistics-cookie-parser))))))
|
||||
;; This is probably a plain link.
|
||||
(_ (and (memq 'link restriction)
|
||||
(org-element-link-parser)))))))
|
||||
|
@ -4821,10 +4823,12 @@ indentation removed from its contents."
|
|||
;;
|
||||
;; A single public function is provided: `org-element-cache-reset'.
|
||||
;;
|
||||
;; Cache is enabled by default, but can be disabled globally with
|
||||
;; Cache is disabled by default for now because it sometimes triggers
|
||||
;; freezes, but it can be enabled globally with
|
||||
;; `org-element-use-cache'. `org-element-cache-sync-idle-time',
|
||||
;; org-element-cache-sync-duration' and `org-element-cache-sync-break'
|
||||
;; can be tweaked to control caching behavior.
|
||||
;; `org-element-cache-sync-duration' and
|
||||
;; `org-element-cache-sync-break' can be tweaked to control caching
|
||||
;; behavior.
|
||||
;;
|
||||
;; Internally, parsed elements are stored in an AVL tree,
|
||||
;; `org-element--cache'. This tree is updated lazily: whenever
|
||||
|
@ -4892,7 +4896,7 @@ with `org-element--cache-compare'. This cache is used in
|
|||
|
||||
A request is a vector with the following pattern:
|
||||
|
||||
\[NEXT BEG END OFFSET PARENT PHASE]
|
||||
[NEXT BEG END OFFSET PARENT PHASE]
|
||||
|
||||
Processing a synchronization request consists of three phases:
|
||||
|
||||
|
@ -5450,9 +5454,11 @@ the process stopped before finding the expected result."
|
|||
;; element following headline above, or first element in
|
||||
;; buffer.
|
||||
((not cached)
|
||||
(when (org-with-limited-levels (outline-previous-heading))
|
||||
(setq mode 'planning)
|
||||
(forward-line))
|
||||
(if (org-with-limited-levels (outline-previous-heading))
|
||||
(progn
|
||||
(setq mode 'planning)
|
||||
(forward-line))
|
||||
(setq mode 'top-comment))
|
||||
(skip-chars-forward " \r\t\n")
|
||||
(beginning-of-line))
|
||||
;; Cache returned exact match: return it.
|
||||
|
@ -5521,7 +5527,7 @@ the process stopped before finding the expected result."
|
|||
;; after it.
|
||||
((and (<= elem-end pos) (/= (point-max) elem-end))
|
||||
(goto-char elem-end)
|
||||
(setq mode (org-element--next-mode type nil)))
|
||||
(setq mode (org-element--next-mode mode type nil)))
|
||||
;; A non-greater element contains point: return it.
|
||||
((not (memq type org-element-greater-elements))
|
||||
(throw 'exit element))
|
||||
|
@ -5549,7 +5555,7 @@ the process stopped before finding the expected result."
|
|||
(and (= cend pos) (= (point-max) pos)))))
|
||||
(goto-char (or next cbeg))
|
||||
(setq next nil
|
||||
mode (org-element--next-mode type t)
|
||||
mode (org-element--next-mode mode type t)
|
||||
parent element
|
||||
end cend))))
|
||||
;; Otherwise, return ELEMENT as it is the smallest
|
||||
|
@ -5813,7 +5819,7 @@ element.
|
|||
|
||||
Possible types are defined in `org-element-all-elements'.
|
||||
Properties depend on element or object type, but always include
|
||||
`:begin', `:end', `:parent' and `:post-blank' properties.
|
||||
`:begin', `:end', and `:post-blank' properties.
|
||||
|
||||
As a special case, if point is at the very beginning of the first
|
||||
item in a list or sub-list, returned element will be that list
|
||||
|
|
|
@ -226,7 +226,7 @@ packages to be loaded, add these packages to `org-latex-packages-alist'."
|
|||
("beth" "\\beth" t "ℶ" "beth" "beth" "ב")
|
||||
("dalet" "\\daleth" t "ℸ" "dalet" "dalet" "ד")
|
||||
|
||||
"** Dead languages"
|
||||
"** Icelandic"
|
||||
("ETH" "\\DH{}" nil "Ð" "D" "Ð" "Ð")
|
||||
("eth" "\\dh{}" nil "ð" "dh" "ð" "ð")
|
||||
("THORN" "\\TH{}" nil "Þ" "TH" "Þ" "Þ")
|
||||
|
@ -386,7 +386,7 @@ packages to be loaded, add these packages to `org-latex-packages-alist'."
|
|||
("exists" "\\exists" t "∃" "[there exists]" "[there exists]" "∃")
|
||||
("nexist" "\\nexists" t "∃" "[there does not exists]" "[there does not exists]" "∄")
|
||||
("nexists" "\\nexists" t "∃" "[there does not exists]" "[there does not exists]" "∄")
|
||||
("empty" "\\empty" t "∅" "[empty set]" "[empty set]" "∅")
|
||||
("empty" "\\emptyset" t "∅" "[empty set]" "[empty set]" "∅")
|
||||
("emptyset" "\\emptyset" t "∅" "[empty set]" "[empty set]" "∅")
|
||||
("isin" "\\in" t "∈" "[element of]" "[element of]" "∈")
|
||||
("in" "\\in" t "∈" "[element of]" "[element of]" "∈")
|
||||
|
|
|
@ -243,6 +243,15 @@ is of course immediately visible, but for example a passed deadline is
|
|||
of the frame, for example."
|
||||
:group 'org-faces)
|
||||
|
||||
(defface org-headline-todo ;Copied from `font-lock-string-face'
|
||||
'((((class color) (min-colors 16) (background light)) (:foreground "Red4"))
|
||||
(((class color) (min-colors 16) (background dark)) (:foreground "Pink2"))
|
||||
(((class color) (min-colors 8) (background light)) (:bold t)))
|
||||
"Face used to indicate that a headline is marked as TODO.
|
||||
This face is only used if `org-fontify-todo-headline' is set. If applies
|
||||
to the part of the headline after the TODO keyword."
|
||||
:group 'org-faces)
|
||||
|
||||
(defface org-headline-done ;Copied from `font-lock-string-face'
|
||||
'((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
|
||||
(((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
|
||||
|
@ -355,6 +364,12 @@ changes."
|
|||
"Face used for tables."
|
||||
:group 'org-faces)
|
||||
|
||||
(defface org-table-header '((t :inherit org-table
|
||||
:background "LightGray"
|
||||
:foreground "Black"))
|
||||
"Face for table header."
|
||||
:group 'org-faces)
|
||||
|
||||
(defface org-formula
|
||||
'((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
|
||||
(((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
|
||||
|
@ -393,9 +408,17 @@ follows a #+DATE:, #+AUTHOR: or #+EMAIL: keyword."
|
|||
"Face for #+TITLE:, #+AUTHOR:, #+EMAIL: and #+DATE: keywords."
|
||||
:group 'org-faces)
|
||||
|
||||
(defface org-block '((t :inherit shadow))
|
||||
"Face text in #+begin ... #+end blocks.
|
||||
For source-blocks `org-src-block-faces' takes precedence."
|
||||
(defface org-block `((t :inherit shadow
|
||||
,@(and (>= emacs-major-version 27) '(:extend t))))
|
||||
"Face used for text inside various blocks.
|
||||
|
||||
It is always used for source blocks. You can refine what face
|
||||
should be used depending on the source block language by setting,
|
||||
`org-src-block-faces', which takes precedence.
|
||||
|
||||
When `org-fontify-quote-and-verse-blocks' is not nil, text inside
|
||||
verse and quote blocks are fontified using the `org-verse' and
|
||||
`org-quote' faces, which inherit from `org-block'."
|
||||
:group 'org-faces
|
||||
:version "26.1")
|
||||
|
||||
|
|
|
@ -22,27 +22,8 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(require 'org-macs)
|
||||
(require 'org-compat)
|
||||
|
||||
(declare-function org-at-heading-p "org" (&optional ignored))
|
||||
(declare-function org-beginning-of-line "org" (&optional n))
|
||||
(declare-function org-defkey "org" (keymap key def))
|
||||
(declare-function org-mark-ring-push "org" (&optional pos buffer))
|
||||
(declare-function org-overview "org" ())
|
||||
(declare-function org-refile-check-position "org" (refile-pointer))
|
||||
(declare-function org-refile-get-location "org" (&optional prompt default-buffer new-nodes))
|
||||
(declare-function org-show-context "org" (&optional key))
|
||||
(declare-function org-show-set-visibility "org" (detail))
|
||||
|
||||
(defvar org-complex-heading-regexp)
|
||||
(defvar org-startup-align-all-tables)
|
||||
(defvar org-startup-folded)
|
||||
(defvar org-startup-truncated)
|
||||
(defvar org-special-ctrl-a/e)
|
||||
(defvar org-refile-target-verify-function)
|
||||
(defvar org-refile-use-outline-path)
|
||||
(defvar org-refile-targets)
|
||||
(require 'org)
|
||||
(require 'org-refile)
|
||||
|
||||
(defvar org-goto-exit-command nil)
|
||||
(defvar org-goto-map nil)
|
||||
|
@ -234,20 +215,15 @@ position or nil."
|
|||
(and (get-buffer "*org-goto*") (kill-buffer "*org-goto*"))
|
||||
(pop-to-buffer-same-window
|
||||
(condition-case nil
|
||||
(make-indirect-buffer (current-buffer) "*org-goto*")
|
||||
(error (make-indirect-buffer (current-buffer) "*org-goto*"))))
|
||||
(make-indirect-buffer (current-buffer) "*org-goto*" t)
|
||||
(error (make-indirect-buffer (current-buffer) "*org-goto*" t))))
|
||||
(let (temp-buffer-show-function temp-buffer-show-hook)
|
||||
(with-output-to-temp-buffer "*Org Help*"
|
||||
(princ (format help (if org-goto-auto-isearch
|
||||
" Just type for auto-isearch."
|
||||
" n/p/f/b/u to navigate, q to quit.")))))
|
||||
(org-fit-window-to-buffer (get-buffer-window "*Org Help*"))
|
||||
(setq buffer-read-only nil)
|
||||
(let ((org-startup-truncated t)
|
||||
(org-startup-folded nil)
|
||||
(org-startup-align-all-tables nil))
|
||||
(org-mode)
|
||||
(org-overview))
|
||||
(org-overview)
|
||||
(setq buffer-read-only t)
|
||||
(if (and (boundp 'org-goto-start-pos)
|
||||
(integer-or-marker-p org-goto-start-pos))
|
||||
|
@ -309,4 +285,8 @@ With a prefix argument, use the alternative interface: e.g., if
|
|||
|
||||
(provide 'org-goto)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-goto.el ends here
|
||||
|
|
|
@ -90,7 +90,7 @@ It will be green even if it was done after the deadline."
|
|||
:type 'boolean)
|
||||
|
||||
(defcustom org-habit-scheduled-past-days nil
|
||||
"Value to use instead of `org-scheduled-past-days', for habits only.
|
||||
"Value to use instead of `org-scheduled-past-days', for habits only.
|
||||
|
||||
If nil, `org-scheduled-past-days' is used.
|
||||
|
||||
|
@ -343,7 +343,10 @@ current time."
|
|||
(if (and in-the-past-p
|
||||
(not last-done-date)
|
||||
(not (< scheduled now)))
|
||||
'(org-habit-clear-face . org-habit-clear-future-face)
|
||||
(if (and all-done-dates (= (car all-done-dates) start))
|
||||
;; This is the very first done of this habit.
|
||||
'(org-habit-ready-face . org-habit-ready-future-face)
|
||||
'(org-habit-clear-face . org-habit-clear-future-face))
|
||||
(org-habit-get-faces
|
||||
habit start
|
||||
(and in-the-past-p
|
||||
|
@ -409,7 +412,7 @@ current time."
|
|||
'help-echo
|
||||
(concat (format-time-string
|
||||
(org-time-stamp-format)
|
||||
(time-add starting (days-to-time (- start (time-to-days starting)))))
|
||||
(time-add starting (days-to-time (- start (time-to-days starting)))))
|
||||
(if donep " DONE" ""))
|
||||
graph))
|
||||
(setq start (1+ start)
|
||||
|
@ -436,7 +439,7 @@ current time."
|
|||
habit
|
||||
(time-subtract moment (days-to-time org-habit-preceding-days))
|
||||
moment
|
||||
(time-add moment (days-to-time org-habit-following-days))))))
|
||||
(time-add moment (days-to-time org-habit-following-days))))))
|
||||
(forward-line)))))
|
||||
|
||||
(defun org-habit-toggle-habits ()
|
||||
|
|
|
@ -71,11 +71,11 @@
|
|||
;;; Code:
|
||||
|
||||
(require 'org)
|
||||
(require 'org-refile)
|
||||
(require 'ol)
|
||||
|
||||
(declare-function message-make-fqdn "message" ())
|
||||
(declare-function org-goto-location "org-goto" (&optional _buf help))
|
||||
(declare-function org-link-set-parameters "ol" (type &rest rest))
|
||||
|
||||
;;; Customization
|
||||
|
||||
|
@ -259,6 +259,11 @@ Create an ID if necessary."
|
|||
(interactive)
|
||||
(org-kill-new (org-id-get nil 'create)))
|
||||
|
||||
(defvar org-id-overriding-file-name nil
|
||||
"Tell `org-id-get' to use this as the file name when creating an ID.
|
||||
This is useful when working with contents in a temporary buffer
|
||||
that will be copied back to the original.")
|
||||
|
||||
;;;###autoload
|
||||
(defun org-id-get (&optional pom create prefix)
|
||||
"Get the ID property of the entry at point-or-marker POM.
|
||||
|
@ -275,7 +280,9 @@ In any case, the ID of the entry is returned."
|
|||
(create
|
||||
(setq id (org-id-new prefix))
|
||||
(org-entry-put pom "ID" id)
|
||||
(org-id-add-location id (buffer-file-name (buffer-base-buffer)))
|
||||
(org-id-add-location id
|
||||
(or org-id-overriding-file-name
|
||||
(buffer-file-name (buffer-base-buffer))))
|
||||
id)))))
|
||||
|
||||
;;;###autoload
|
||||
|
@ -478,55 +485,64 @@ This will scan all agenda files, all associated archives, and all
|
|||
files currently mentioned in `org-id-locations'.
|
||||
When FILES is given, scan also these files."
|
||||
(interactive)
|
||||
(if (not org-id-track-globally)
|
||||
(error "Please turn on `org-id-track-globally' if you want to track IDs")
|
||||
(let* ((files (delete-dups
|
||||
(mapcar #'file-truename
|
||||
(append
|
||||
;; Agenda files and all associated archives
|
||||
(org-agenda-files t org-id-search-archives)
|
||||
;; Explicit extra files
|
||||
(unless (symbolp org-id-extra-files)
|
||||
org-id-extra-files)
|
||||
;; All files known to have IDs
|
||||
org-id-files
|
||||
;; function input
|
||||
files))))
|
||||
(nfiles (length files))
|
||||
ids seen-ids (ndup 0) (i 0) file-id-alist)
|
||||
(with-temp-buffer
|
||||
(delay-mode-hooks
|
||||
(org-mode)
|
||||
(dolist (file files)
|
||||
(unless silent
|
||||
(setq i (1+ i))
|
||||
(message "Finding ID locations (%d/%d files): %s"
|
||||
i nfiles file))
|
||||
(when (file-exists-p file)
|
||||
(insert-file-contents file nil nil nil 'replace)
|
||||
(setq ids (org-map-entries
|
||||
(lambda ()
|
||||
(org-entry-get (point) "ID"))
|
||||
"ID<>\"\""))
|
||||
(dolist (id ids)
|
||||
(if (member id seen-ids)
|
||||
(progn
|
||||
(message "Duplicate ID \"%s\"" id)
|
||||
(setq ndup (1+ ndup)))
|
||||
(push id seen-ids)))
|
||||
(unless org-id-track-globally
|
||||
(error "Please turn on `org-id-track-globally' if you want to track IDs"))
|
||||
(setq org-id-locations nil)
|
||||
(let* ((files
|
||||
(delete-dups
|
||||
(mapcar #'file-truename
|
||||
(cl-remove-if-not
|
||||
;; Default `org-id-extra-files' value contains
|
||||
;; `agenda-archives' symbol.
|
||||
#'stringp
|
||||
(append
|
||||
;; Agenda files and all associated archives.
|
||||
(org-agenda-files t org-id-search-archives)
|
||||
;; Explicit extra files.
|
||||
(if (symbolp org-id-extra-files)
|
||||
(symbol-value org-id-extra-files)
|
||||
org-id-extra-files)
|
||||
;; All files known to have IDs.
|
||||
org-id-files
|
||||
;; Additional files from function call.
|
||||
files)))))
|
||||
(nfiles (length files))
|
||||
(id-regexp
|
||||
(rx (seq bol (0+ (any "\t ")) ":ID:" (1+ " ") (not (any " ")))))
|
||||
(seen-ids nil)
|
||||
(ndup 0)
|
||||
(i 0))
|
||||
(dolist (file files)
|
||||
(when (file-exists-p file)
|
||||
(unless silent
|
||||
(cl-incf i)
|
||||
(message "Finding ID locations (%d/%d files): %s" i nfiles file))
|
||||
(with-current-buffer (find-file-noselect file t)
|
||||
(let ((ids nil)
|
||||
(case-fold-search t))
|
||||
(org-with-point-at 1
|
||||
(while (re-search-forward id-regexp nil t)
|
||||
(when (org-at-property-p)
|
||||
(push (org-entry-get (point) "ID") ids)))
|
||||
(when ids
|
||||
(setq file-id-alist (cons (cons (abbreviate-file-name file) ids)
|
||||
file-id-alist)))))))
|
||||
(setq org-id-locations file-id-alist)
|
||||
(setq org-id-files (mapcar 'car org-id-locations))
|
||||
(org-id-locations-save)
|
||||
;; now convert to a hash
|
||||
(setq org-id-locations (org-id-alist-to-hash org-id-locations))
|
||||
(when (> ndup 0)
|
||||
(warn "WARNING: %d duplicate IDs found, check *Messages* buffer" ndup))
|
||||
(message "%d files scanned, %d files contains IDs and in total %d IDs found."
|
||||
nfiles (length org-id-files) (hash-table-count org-id-locations))
|
||||
org-id-locations)))
|
||||
(push (cons (abbreviate-file-name file) ids)
|
||||
org-id-locations)
|
||||
(dolist (id ids)
|
||||
(cond
|
||||
((not (member id seen-ids)) (push id seen-ids))
|
||||
(silent nil)
|
||||
(t
|
||||
(message "Duplicate ID %S" id)
|
||||
(cl-incf ndup))))))))))
|
||||
(setq org-id-files (mapcar #'car org-id-locations))
|
||||
(org-id-locations-save)
|
||||
;; Now convert to a hash table.
|
||||
(setq org-id-locations (org-id-alist-to-hash org-id-locations))
|
||||
(when (and (not silent) (> ndup 0))
|
||||
(warn "WARNING: %d duplicate IDs found, check *Messages* buffer" ndup))
|
||||
(message "%d files scanned, %d files contains IDs, and %d IDs found."
|
||||
nfiles (length org-id-files) (hash-table-count org-id-locations))
|
||||
org-id-locations))
|
||||
|
||||
(defun org-id-locations-save ()
|
||||
"Save `org-id-locations' in `org-id-locations-file'."
|
||||
|
@ -572,8 +588,10 @@ When FILES is given, scan also these files."
|
|||
(defun org-id-add-location (id file)
|
||||
"Add the ID with location FILE to the database of ID locations."
|
||||
;; Only if global tracking is on, and when the buffer has a file
|
||||
(unless file
|
||||
(error "bug: org-id-get expects a file-visiting buffer"))
|
||||
(let ((afile (abbreviate-file-name file)))
|
||||
(when (and org-id-track-globally id file)
|
||||
(when (and org-id-track-globally id)
|
||||
(unless org-id-locations (org-id-locations-load))
|
||||
(puthash id afile org-id-locations)
|
||||
(unless (member afile org-id-files)
|
||||
|
@ -631,7 +649,7 @@ When FILES is given, scan also these files."
|
|||
(or (and org-id-locations
|
||||
(hash-table-p org-id-locations)
|
||||
(gethash id org-id-locations))
|
||||
;; ball back on current buffer
|
||||
;; Fall back on current buffer
|
||||
(buffer-file-name (or (buffer-base-buffer (current-buffer))
|
||||
(current-buffer)))))
|
||||
|
||||
|
@ -665,8 +683,11 @@ optional argument MARKERP, return the position as a new marker."
|
|||
(let* ((link (concat "id:" (org-id-get-create)))
|
||||
(case-fold-search nil)
|
||||
(desc (save-excursion
|
||||
(org-back-to-heading t)
|
||||
(or (and (looking-at org-complex-heading-regexp)
|
||||
(org-back-to-heading-or-point-min t)
|
||||
(or (and (org-before-first-heading-p)
|
||||
(file-name-nondirectory
|
||||
(buffer-file-name (buffer-base-buffer))))
|
||||
(and (looking-at org-complex-heading-regexp)
|
||||
(if (match-end 4)
|
||||
(match-string 4)
|
||||
(match-string 0)))
|
||||
|
@ -674,7 +695,7 @@ optional argument MARKERP, return the position as a new marker."
|
|||
(org-link-store-props :link link :description desc :type "id")
|
||||
link)))
|
||||
|
||||
(defun org-id-open (id)
|
||||
(defun org-id-open (id _)
|
||||
"Go to the entry with id ID."
|
||||
(org-mark-ring-push)
|
||||
(let ((m (org-id-find id 'marker))
|
||||
|
|
|
@ -71,8 +71,6 @@ Delay used when the buffer to initialize isn't current.")
|
|||
(defvar org-indent--initial-marker nil
|
||||
"Position of initialization before interrupt.
|
||||
This is used locally in each buffer being initialized.")
|
||||
(defvar org-hide-leading-stars-before-indent-mode nil
|
||||
"Used locally.")
|
||||
(defvar org-indent-modified-headline-flag nil
|
||||
"Non-nil means the last deletion operated on a headline.
|
||||
It is modified by `org-indent-notify-modified-headline'.")
|
||||
|
@ -178,10 +176,11 @@ during idle time."
|
|||
(setq-local indent-tabs-mode nil)
|
||||
(setq-local org-indent--initial-marker (copy-marker 1))
|
||||
(when org-indent-mode-turns-off-org-adapt-indentation
|
||||
(setq-local org-adapt-indentation nil))
|
||||
;; Don't turn off `org-adapt-indentation' when its value is
|
||||
;; 'headline-data, just indent headline data specially.
|
||||
(or (eq org-adapt-indentation 'headline-data)
|
||||
(setq-local org-adapt-indentation nil)))
|
||||
(when org-indent-mode-turns-on-hiding-stars
|
||||
(setq-local org-hide-leading-stars-before-indent-mode
|
||||
org-hide-leading-stars)
|
||||
(setq-local org-hide-leading-stars t))
|
||||
(org-indent--compute-prefixes)
|
||||
(if (boundp 'filter-buffer-substring-functions)
|
||||
|
@ -207,15 +206,14 @@ during idle time."
|
|||
(setq org-indent-agent-timer
|
||||
(run-with-idle-timer 0.2 t #'org-indent-initialize-agent))))
|
||||
(t
|
||||
;; mode was turned off (or we refused to turn it on)
|
||||
;; Mode was turned off (or we refused to turn it on)
|
||||
(kill-local-variable 'org-adapt-indentation)
|
||||
(setq org-indent-agentized-buffers
|
||||
(delq (current-buffer) org-indent-agentized-buffers))
|
||||
(when (markerp org-indent--initial-marker)
|
||||
(set-marker org-indent--initial-marker nil))
|
||||
(when (boundp 'org-hide-leading-stars-before-indent-mode)
|
||||
(setq-local org-hide-leading-stars
|
||||
org-hide-leading-stars-before-indent-mode))
|
||||
(when (local-variable-p 'org-hide-leading-stars)
|
||||
(kill-local-variable 'org-hide-leading-stars))
|
||||
(if (boundp 'filter-buffer-substring-functions)
|
||||
(remove-hook 'filter-buffer-substring-functions
|
||||
(lambda (fun start end delete)
|
||||
|
@ -365,7 +363,18 @@ stopped."
|
|||
level (org-list-item-body-column (point))))
|
||||
;; Regular line.
|
||||
(t
|
||||
(org-indent-set-line-properties level (current-indentation))))))))))
|
||||
(org-indent-set-line-properties
|
||||
level
|
||||
(current-indentation)
|
||||
;; When adapt indentation is 'headline-data, use
|
||||
;; `org-indent--heading-line-prefixes' for setting
|
||||
;; headline data indentation.
|
||||
(and (eq org-adapt-indentation 'headline-data)
|
||||
(or (org-at-planning-p)
|
||||
(org-at-clock-log-p)
|
||||
(looking-at-p org-property-start-re)
|
||||
(looking-at-p org-property-end-re)
|
||||
(looking-at-p org-property-re))))))))))))
|
||||
|
||||
(defun org-indent-notify-modified-headline (beg end)
|
||||
"Set `org-indent-modified-headline-flag' depending on context.
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
(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-comment-dwim "org" (arg))
|
||||
(declare-function org-copy "org" ())
|
||||
(declare-function org-refile-copy "org" ())
|
||||
(declare-function org-copy-special "org" ())
|
||||
(declare-function org-copy-visible "org" (beg end))
|
||||
(declare-function org-ctrl-c-ctrl-c "org" (&optional arg))
|
||||
|
@ -148,7 +148,7 @@
|
|||
(declare-function org-remove-file "org" (&optional file))
|
||||
(declare-function org-resolve-clocks "org" (&optional only-dangling-p prompt-fn last-valid))
|
||||
(declare-function org-return "org" (&optional indent))
|
||||
(declare-function org-return-indent "org" ())
|
||||
(declare-function org-return-and-maybe-indent "org" ())
|
||||
(declare-function org-reveal "org" (&optional siblings))
|
||||
(declare-function org-schedule "org" (arg &optional time))
|
||||
(declare-function org-self-insert-command "org" (N))
|
||||
|
@ -196,6 +196,7 @@
|
|||
(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-comment "org" ())
|
||||
(declare-function org-toggle-fixed-width "org" ())
|
||||
(declare-function org-toggle-inline-images "org" (&optional include-linked))
|
||||
|
@ -218,7 +219,7 @@
|
|||
;;; Variables
|
||||
|
||||
(defvar org-mode-map (make-sparse-keymap)
|
||||
"Keymap fo Org mode.")
|
||||
"Keymap for Org mode.")
|
||||
|
||||
(defvaralias 'org-CUA-compatible 'org-replace-disputed-keys)
|
||||
|
||||
|
@ -444,7 +445,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
|
|||
;;;; TAB key with modifiers
|
||||
(org-defkey org-mode-map (kbd "C-i") #'org-cycle)
|
||||
(org-defkey org-mode-map (kbd "<tab>") #'org-cycle)
|
||||
(org-defkey org-mode-map (kbd "C-<tab>") #'org-force-cycle-archived)
|
||||
(org-defkey org-mode-map (kbd "C-c C-<tab>") #'org-force-cycle-archived)
|
||||
;; Override text-mode binding to expose `complete-symbol' for
|
||||
;; pcomplete functionality.
|
||||
(org-defkey org-mode-map (kbd "M-<tab>") nil)
|
||||
|
@ -580,7 +581,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
|
|||
(org-defkey org-mode-map (kbd "C-c C-d") #'org-deadline)
|
||||
(org-defkey org-mode-map (kbd "C-c ;") #'org-toggle-comment)
|
||||
(org-defkey org-mode-map (kbd "C-c C-w") #'org-refile)
|
||||
(org-defkey org-mode-map (kbd "C-c M-w") #'org-copy)
|
||||
(org-defkey org-mode-map (kbd "C-c M-w") #'org-refile-copy)
|
||||
(org-defkey org-mode-map (kbd "C-c /") #'org-sparse-tree) ;minor-mode reserved
|
||||
(org-defkey org-mode-map (kbd "C-c \\") #'org-match-sparse-tree) ;minor-mode r.
|
||||
(org-defkey org-mode-map (kbd "C-c RET") #'org-ctrl-c-ret)
|
||||
|
@ -617,7 +618,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
|
|||
(org-defkey org-mode-map (kbd "C-c C-k") #'org-kill-note-or-show-branches)
|
||||
(org-defkey org-mode-map (kbd "C-c #") #'org-update-statistics-cookies)
|
||||
(org-defkey org-mode-map (kbd "RET") #'org-return)
|
||||
(org-defkey org-mode-map (kbd "C-j") #'org-return-indent)
|
||||
(org-defkey org-mode-map (kbd "C-j") #'org-return-and-maybe-indent)
|
||||
(org-defkey org-mode-map (kbd "C-c ?") #'org-table-field-info)
|
||||
(org-defkey org-mode-map (kbd "C-c SPC") #'org-table-blank-field)
|
||||
(org-defkey org-mode-map (kbd "C-c +") #'org-table-sum)
|
||||
|
@ -658,6 +659,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names."
|
|||
(org-defkey org-mode-map (kbd "C-c C-x C-M-v") #'org-redisplay-inline-images)
|
||||
(org-defkey org-mode-map (kbd "C-c C-x \\") #'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)
|
||||
(org-defkey org-mode-map (kbd "C-c C-x p") #'org-set-property)
|
||||
(org-defkey org-mode-map (kbd "C-c C-x P") #'org-set-property-and-value)
|
||||
(org-defkey org-mode-map (kbd "C-c C-x e") #'org-set-effort)
|
||||
|
@ -923,6 +925,10 @@ a-list placed behind the generic `org-babel-key-prefix'.")
|
|||
(interactive)
|
||||
(describe-bindings org-babel-key-prefix))
|
||||
|
||||
|
||||
(provide 'org-keys)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-keys.el ends here
|
||||
|
|
|
@ -108,6 +108,7 @@
|
|||
(require 'cl-lib)
|
||||
(require 'ob)
|
||||
(require 'ol)
|
||||
(require 'org-attach)
|
||||
(require 'org-macro)
|
||||
(require 'ox)
|
||||
|
||||
|
@ -423,8 +424,10 @@ instead"
|
|||
|
||||
(defun org-lint-deprecated-header-syntax (ast)
|
||||
(let* ((deprecated-babel-properties
|
||||
(mapcar (lambda (arg) (symbol-name (car arg)))
|
||||
org-babel-common-header-args-w-values))
|
||||
;; DIR is also used for attachments.
|
||||
(delete "dir"
|
||||
(mapcar (lambda (arg) (downcase (symbol-name (car arg))))
|
||||
org-babel-common-header-args-w-values)))
|
||||
(deprecated-re
|
||||
(format "\\`%s[ \t]" (regexp-opt deprecated-babel-properties t))))
|
||||
(org-element-map ast '(keyword node-property)
|
||||
|
@ -541,15 +544,16 @@ Use :header-args: instead"
|
|||
(org-element-map ast 'drawer
|
||||
(lambda (d)
|
||||
(when (equal (org-element-property :drawer-name d) "PROPERTIES")
|
||||
(let ((section (org-element-lineage d '(section))))
|
||||
(unless (org-element-map section 'property-drawer #'identity nil t)
|
||||
(list (org-element-property :post-affiliated d)
|
||||
(if (save-excursion
|
||||
(goto-char (org-element-property :post-affiliated d))
|
||||
(forward-line -1)
|
||||
(or (org-at-heading-p) (org-at-planning-p)))
|
||||
"Incorrect contents for PROPERTIES drawer"
|
||||
"Incorrect location for PROPERTIES drawer"))))))))
|
||||
(let ((headline? (org-element-lineage d '(headline)))
|
||||
(before
|
||||
(mapcar #'org-element-type
|
||||
(assq d (reverse (org-element-contents
|
||||
(org-element-property :parent d)))))))
|
||||
(list (org-element-property :post-affiliated d)
|
||||
(if (or (and headline? (member before '(nil (planning))))
|
||||
(and (null headline?) (member before '(nil (comment)))))
|
||||
"Incorrect contents for PROPERTIES drawer"
|
||||
"Incorrect location for PROPERTIES drawer")))))))
|
||||
|
||||
(defun org-lint-invalid-effort-property (ast)
|
||||
(org-element-map ast 'node-property
|
||||
|
@ -564,16 +568,23 @@ Use :header-args: instead"
|
|||
(defun org-lint-link-to-local-file (ast)
|
||||
(org-element-map ast 'link
|
||||
(lambda (l)
|
||||
(when (equal "file" (org-element-property :type l))
|
||||
(let ((file (org-element-property :path l)))
|
||||
(and (not (file-remote-p file))
|
||||
(not (file-exists-p file))
|
||||
(list (org-element-property :begin l)
|
||||
(format (if (org-element-lineage l '(link))
|
||||
"Link to non-existent image file \"%s\"\
|
||||
in link description"
|
||||
"Link to non-existent local file \"%s\"")
|
||||
file))))))))
|
||||
(let ((type (org-element-property :type l)))
|
||||
(pcase type
|
||||
((or "attachment" "file")
|
||||
(let* ((path (org-element-property :path l))
|
||||
(file (if (string= type "file")
|
||||
path
|
||||
(org-with-point-at (org-element-property :begin l)
|
||||
(org-attach-expand path)))))
|
||||
(and (not (file-remote-p file))
|
||||
(not (file-exists-p file))
|
||||
(list (org-element-property :begin l)
|
||||
(format (if (org-element-lineage l '(link))
|
||||
"Link to non-existent image file %S \
|
||||
in description"
|
||||
"Link to non-existent local file %S")
|
||||
file)))))
|
||||
(_ nil))))))
|
||||
|
||||
(defun org-lint-non-existent-setupfile-parameter (ast)
|
||||
(org-element-map ast 'keyword
|
||||
|
@ -793,15 +804,25 @@ Use \"export %s\" instead"
|
|||
(let ((name (org-trim (match-string-no-properties 0)))
|
||||
(element (org-element-at-point)))
|
||||
(pcase (org-element-type element)
|
||||
((or `drawer `property-drawer)
|
||||
(goto-char (org-element-property :end element))
|
||||
nil)
|
||||
(`drawer
|
||||
;; Find drawer opening lines within non-empty drawers.
|
||||
(let ((end (org-element-property :contents-end element)))
|
||||
(when end
|
||||
(while (re-search-forward org-drawer-regexp end t)
|
||||
(let ((n (org-trim (match-string-no-properties 0))))
|
||||
(push (list (line-beginning-position)
|
||||
(format "Possible misleading drawer entry %S" n))
|
||||
reports))))
|
||||
(goto-char (org-element-property :end element))))
|
||||
(`property-drawer
|
||||
(goto-char (org-element-property :end element)))
|
||||
((or `comment-block `example-block `export-block `src-block
|
||||
`verse-block)
|
||||
nil)
|
||||
(_
|
||||
;; Find drawer opening lines outside of any drawer.
|
||||
(push (list (line-beginning-position)
|
||||
(format "Possible incomplete drawer \"%s\"" name))
|
||||
(format "Possible incomplete drawer %S" name))
|
||||
reports)))))
|
||||
reports))
|
||||
|
||||
|
@ -1257,6 +1278,10 @@ ARG can also be a list of checker names, as symbols, to run."
|
|||
(org-lint--display-reports (current-buffer) checkers)
|
||||
(message "Org linting process completed"))))
|
||||
|
||||
|
||||
(provide 'org-lint)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-lint.el ends here
|
||||
|
|
|
@ -81,12 +81,12 @@
|
|||
(require 'org-compat)
|
||||
|
||||
(defvar org-M-RET-may-split-line)
|
||||
(defvar org-adapt-indentation)
|
||||
(defvar org-auto-align-tags)
|
||||
(defvar org-blank-before-new-entry)
|
||||
(defvar org-clock-string)
|
||||
(defvar org-closed-string)
|
||||
(defvar org-deadline-string)
|
||||
(defvar org-description-max-indent)
|
||||
(defvar org-done-keywords)
|
||||
(defvar org-drawer-regexp)
|
||||
(defvar org-element-all-objects)
|
||||
|
@ -911,13 +911,13 @@ items, as returned by `org-list-prevs-alist'."
|
|||
STRUCT is the list structure."
|
||||
(let* ((item-end (org-list-get-item-end item struct))
|
||||
(sub-struct (cdr (member (assq item struct) struct)))
|
||||
subtree)
|
||||
(catch 'exit
|
||||
(mapc (lambda (e)
|
||||
(let ((pos (car e)))
|
||||
(if (< pos item-end) (push pos subtree) (throw 'exit nil))))
|
||||
sub-struct))
|
||||
(nreverse subtree)))
|
||||
items)
|
||||
(catch :exit
|
||||
(pcase-dolist (`(,pos . ,_) sub-struct)
|
||||
(if (< pos item-end)
|
||||
(push pos items)
|
||||
(throw :exit nil))))
|
||||
(nreverse items)))
|
||||
|
||||
(defun org-list-get-all-items (item struct prevs)
|
||||
"List all items in the same sub-list as ITEM.
|
||||
|
@ -1234,125 +1234,127 @@ after the bullet. Cursor will be after this text once the
|
|||
function ends.
|
||||
|
||||
This function modifies STRUCT."
|
||||
(let ((case-fold-search t))
|
||||
;; 1. Get information about list: ITEM containing POS, position of
|
||||
;; point with regards to item start (BEFOREP), blank lines
|
||||
;; number separating items (BLANK-NB), if we're allowed to
|
||||
;; (SPLIT-LINE-P).
|
||||
(let* ((item (goto-char (catch :exit
|
||||
(let ((inner-item 0))
|
||||
(pcase-dolist (`(,i . ,_) struct)
|
||||
(cond
|
||||
((= i pos) (throw :exit i))
|
||||
((< i pos) (setq inner-item i))
|
||||
(t (throw :exit inner-item))))
|
||||
inner-item))))
|
||||
(item-end (org-list-get-item-end item struct))
|
||||
(item-end-no-blank (org-list-get-item-end-before-blank item struct))
|
||||
(beforep
|
||||
(progn
|
||||
(looking-at org-list-full-item-re)
|
||||
(<= pos
|
||||
(cond
|
||||
((not (match-beginning 4)) (match-end 0))
|
||||
;; Ignore tag in a non-descriptive list.
|
||||
((save-match-data (string-match "[.)]" (match-string 1)))
|
||||
(match-beginning 4))
|
||||
(t (save-excursion
|
||||
(goto-char (match-end 4))
|
||||
(skip-chars-forward " \t")
|
||||
(point)))))))
|
||||
(split-line-p (org-get-alist-option org-M-RET-may-split-line 'item))
|
||||
(blank-nb (org-list-separating-blank-lines-number
|
||||
pos struct prevs))
|
||||
;; 2. Build the new item to be created. Concatenate same
|
||||
;; bullet as item, checkbox, text AFTER-BULLET if
|
||||
;; provided, and text cut from point to end of item
|
||||
;; (TEXT-CUT) to form item's BODY. TEXT-CUT depends on
|
||||
;; BEFOREP and SPLIT-LINE-P. The difference of size
|
||||
;; between what was cut and what was inserted in buffer
|
||||
;; is stored in SIZE-OFFSET.
|
||||
(ind (org-list-get-ind item struct))
|
||||
(ind-size (if indent-tabs-mode
|
||||
(+ (/ ind tab-width) (mod ind tab-width))
|
||||
ind))
|
||||
(bullet (org-list-bullet-string (org-list-get-bullet item struct)))
|
||||
(box (when checkbox "[ ]"))
|
||||
(text-cut
|
||||
(and (not beforep) split-line-p
|
||||
(progn
|
||||
(goto-char pos)
|
||||
;; If POS is greater than ITEM-END, then point is
|
||||
;; in some white lines after the end of the list.
|
||||
;; Those must be removed, or they will be left,
|
||||
;; stacking up after the list.
|
||||
(when (< item-end pos)
|
||||
(delete-region (1- item-end) (point-at-eol)))
|
||||
(skip-chars-backward " \r\t\n")
|
||||
(setq pos (point))
|
||||
(delete-and-extract-region pos item-end-no-blank))))
|
||||
(body (concat bullet (when box (concat box " ")) after-bullet
|
||||
(and text-cut
|
||||
(if (string-match "\\`[ \t]+" text-cut)
|
||||
(replace-match "" t t text-cut)
|
||||
text-cut))))
|
||||
(item-sep (make-string (1+ blank-nb) ?\n))
|
||||
(item-size (+ ind-size (length body) (length item-sep)))
|
||||
(size-offset (- item-size (length text-cut))))
|
||||
;; 4. Insert effectively item into buffer.
|
||||
(goto-char item)
|
||||
(indent-to-column ind)
|
||||
(insert body item-sep)
|
||||
;; 5. Add new item to STRUCT.
|
||||
(mapc (lambda (e)
|
||||
(let ((p (car e)) (end (nth 6 e)))
|
||||
(cond
|
||||
;; Before inserted item, positions don't change but
|
||||
;; an item ending after insertion has its end shifted
|
||||
;; by SIZE-OFFSET.
|
||||
((< p item)
|
||||
(when (> end item) (setcar (nthcdr 6 e) (+ end size-offset))))
|
||||
;; Trivial cases where current item isn't split in
|
||||
;; two. Just shift every item after new one by
|
||||
;; ITEM-SIZE.
|
||||
((or beforep (not split-line-p))
|
||||
(setcar e (+ p item-size))
|
||||
(setcar (nthcdr 6 e) (+ end item-size)))
|
||||
;; Item is split in two: elements before POS are just
|
||||
;; shifted by ITEM-SIZE. In the case item would end
|
||||
;; after split POS, ending is only shifted by
|
||||
;; SIZE-OFFSET.
|
||||
((< p pos)
|
||||
(setcar e (+ p item-size))
|
||||
(if (< end pos)
|
||||
(setcar (nthcdr 6 e) (+ end item-size))
|
||||
(setcar (nthcdr 6 e) (+ end size-offset))))
|
||||
;; Elements after POS are moved into new item.
|
||||
;; Length of ITEM-SEP has to be removed as ITEM-SEP
|
||||
;; doesn't appear in buffer yet.
|
||||
((< p item-end)
|
||||
(setcar e (+ p size-offset (- item pos (length item-sep))))
|
||||
(if (= end item-end)
|
||||
(setcar (nthcdr 6 e) (+ item item-size))
|
||||
(setcar (nthcdr 6 e)
|
||||
(+ end size-offset
|
||||
(- item pos (length item-sep))))))
|
||||
;; Elements at ITEM-END or after are only shifted by
|
||||
;; SIZE-OFFSET.
|
||||
(t (setcar e (+ p size-offset))
|
||||
(setcar (nthcdr 6 e) (+ end size-offset))))))
|
||||
struct)
|
||||
(push (list item ind bullet nil box nil (+ item item-size)) struct)
|
||||
(setq struct (sort struct (lambda (e1 e2) (< (car e1) (car e2)))))
|
||||
;; 6. If not BEFOREP, new item must appear after ITEM, so
|
||||
;; exchange ITEM with the next item in list. Position cursor
|
||||
;; after bullet, counter, checkbox, and label.
|
||||
(if beforep
|
||||
(goto-char item)
|
||||
(setq struct (org-list-swap-items item (+ item item-size) struct))
|
||||
(goto-char (org-list-get-next-item
|
||||
item struct (org-list-prevs-alist struct))))
|
||||
struct)))
|
||||
(let* ((case-fold-search t)
|
||||
;; Get information about list: ITEM containing POS, position
|
||||
;; of point with regards to item start (BEFOREP), blank lines
|
||||
;; number separating items (BLANK-NB), if we're allowed to
|
||||
;; (SPLIT-LINE-P).
|
||||
(item
|
||||
(catch :exit
|
||||
(let ((i nil))
|
||||
(pcase-dolist (`(,start ,_ ,_ ,_ ,_ ,_ ,end) struct)
|
||||
(cond
|
||||
((> start pos) (throw :exit i))
|
||||
((< end pos) nil) ;skip sub-lists before point
|
||||
(t (setq i start))))
|
||||
;; If no suitable item is found, insert a sibling of the
|
||||
;; last item in buffer.
|
||||
(or i (caar (reverse struct))))))
|
||||
(item-end (org-list-get-item-end item struct))
|
||||
(item-end-no-blank (org-list-get-item-end-before-blank item struct))
|
||||
(beforep
|
||||
(progn
|
||||
(goto-char item)
|
||||
(looking-at org-list-full-item-re)
|
||||
(<= pos
|
||||
(cond
|
||||
((not (match-beginning 4)) (match-end 0))
|
||||
;; Ignore tag in a non-descriptive list.
|
||||
((save-match-data (string-match "[.)]" (match-string 1)))
|
||||
(match-beginning 4))
|
||||
(t (save-excursion
|
||||
(goto-char (match-end 4))
|
||||
(skip-chars-forward " \t")
|
||||
(point)))))))
|
||||
(split-line-p (org-get-alist-option org-M-RET-may-split-line 'item))
|
||||
(blank-nb (org-list-separating-blank-lines-number pos struct prevs))
|
||||
;; Build the new item to be created. Concatenate same bullet
|
||||
;; as item, checkbox, text AFTER-BULLET if provided, and text
|
||||
;; cut from point to end of item (TEXT-CUT) to form item's
|
||||
;; BODY. TEXT-CUT depends on BEFOREP and SPLIT-LINE-P. The
|
||||
;; difference of size between what was cut and what was
|
||||
;; inserted in buffer is stored in SIZE-OFFSET.
|
||||
(ind (org-list-get-ind item struct))
|
||||
(ind-size (if indent-tabs-mode
|
||||
(+ (/ ind tab-width) (mod ind tab-width))
|
||||
ind))
|
||||
(bullet (org-list-bullet-string (org-list-get-bullet item struct)))
|
||||
(box (and checkbox "[ ]"))
|
||||
(text-cut
|
||||
(and (not beforep)
|
||||
split-line-p
|
||||
(progn
|
||||
(goto-char pos)
|
||||
;; If POS is greater than ITEM-END, then point is in
|
||||
;; some white lines after the end of the list. Those
|
||||
;; must be removed, or they will be left, stacking up
|
||||
;; after the list.
|
||||
(when (< item-end pos)
|
||||
(delete-region (1- item-end) (point-at-eol)))
|
||||
(skip-chars-backward " \r\t\n")
|
||||
;; Cut position is after any blank on the line.
|
||||
(save-excursion
|
||||
(skip-chars-forward " \t")
|
||||
(setq pos (point)))
|
||||
(delete-and-extract-region (point) item-end-no-blank))))
|
||||
(body
|
||||
(concat bullet
|
||||
(and box (concat box " "))
|
||||
after-bullet
|
||||
(and text-cut
|
||||
(if (string-match "\\`[ \t]+" text-cut)
|
||||
(replace-match "" t t text-cut)
|
||||
text-cut))))
|
||||
(item-sep (make-string (1+ blank-nb) ?\n))
|
||||
(item-size (+ ind-size (length body) (length item-sep)))
|
||||
(size-offset (- item-size (length text-cut))))
|
||||
;; Insert effectively item into buffer.
|
||||
(goto-char item)
|
||||
(indent-to-column ind)
|
||||
(insert body item-sep)
|
||||
;; Add new item to STRUCT.
|
||||
(dolist (e struct)
|
||||
(let ((p (car e)) (end (nth 6 e)))
|
||||
(cond
|
||||
;; Before inserted item, positions don't change but an item
|
||||
;; ending after insertion has its end shifted by SIZE-OFFSET.
|
||||
((< p item)
|
||||
(when (> end item)
|
||||
(setcar (nthcdr 6 e) (+ end size-offset))))
|
||||
;; Item where insertion happens may be split in two parts.
|
||||
;; In this case, move start by ITEM-SIZE and end by
|
||||
;; SIZE-OFFSET.
|
||||
((and (= p item) (not beforep) split-line-p)
|
||||
(setcar e (+ p item-size))
|
||||
(setcar (nthcdr 6 e) (+ end size-offset)))
|
||||
;; Items starting after modified item fall into two
|
||||
;; categories.
|
||||
;;
|
||||
;; If modified item was split, and current sub-item was
|
||||
;; located after split point, it was moved to the new item:
|
||||
;; the part between body start and split point (POS) was
|
||||
;; removed. So we compute the length of that part and shift
|
||||
;; item's positions accordingly.
|
||||
;;
|
||||
;; Otherwise, the item was simply shifted by SIZE-OFFSET.
|
||||
((and split-line-p (not beforep) (>= p pos) (<= p item-end-no-blank))
|
||||
(let ((offset (- pos item ind (length bullet) (length after-bullet))))
|
||||
(setcar e (- p offset))
|
||||
(setcar (nthcdr 6 e) (- end offset))))
|
||||
(t
|
||||
(setcar e (+ p size-offset))
|
||||
(setcar (nthcdr 6 e) (+ end size-offset))))))
|
||||
(push (list item ind bullet nil box nil (+ item item-size)) struct)
|
||||
(setq struct (sort struct #'car-less-than-car))
|
||||
;; If not BEFOREP, new item must appear after ITEM, so exchange
|
||||
;; ITEM with the next item in list. Position cursor after bullet,
|
||||
;; counter, checkbox, and label.
|
||||
(if beforep
|
||||
(goto-char item)
|
||||
(setq struct (org-list-swap-items item (+ item item-size) struct))
|
||||
(goto-char (org-list-get-next-item
|
||||
item struct (org-list-prevs-alist struct))))
|
||||
struct))
|
||||
|
||||
(defun org-list-delete-item (item struct)
|
||||
"Remove ITEM from the list and return the new structure.
|
||||
|
@ -1793,10 +1795,9 @@ This function modifies STRUCT."
|
|||
;; There are boxes checked after an unchecked one: fix that.
|
||||
(when (member "[X]" after-unchecked)
|
||||
(let ((index (- (length struct) (length after-unchecked))))
|
||||
(mapc (lambda (e)
|
||||
(when (org-list-get-checkbox e struct)
|
||||
(org-list-set-checkbox e struct "[ ]")))
|
||||
(nthcdr index all-items))
|
||||
(dolist (e (nthcdr index all-items))
|
||||
(when (org-list-get-checkbox e struct)
|
||||
(org-list-set-checkbox e struct "[ ]")))
|
||||
;; Verify once again the structure, without ORDERED.
|
||||
(org-list-struct-fix-box struct parents prevs nil)
|
||||
;; Return blocking item.
|
||||
|
@ -1807,24 +1808,22 @@ This function modifies STRUCT."
|
|||
|
||||
This function modifies STRUCT."
|
||||
(let (end-list acc-end)
|
||||
(mapc (lambda (e)
|
||||
(let* ((pos (car e))
|
||||
(ind-pos (org-list-get-ind pos struct))
|
||||
(end-pos (org-list-get-item-end pos struct)))
|
||||
(unless (assq end-pos struct)
|
||||
;; To determine real ind of an ending position that is
|
||||
;; not at an item, we have to find the item it belongs
|
||||
;; to: it is the last item (ITEM-UP), whose ending is
|
||||
;; further than the position we're interested in.
|
||||
(let ((item-up (assoc-default end-pos acc-end '>)))
|
||||
(push (cons
|
||||
;; Else part is for the bottom point.
|
||||
(if item-up (+ (org-list-get-ind item-up struct) 2) 0)
|
||||
end-pos)
|
||||
end-list)))
|
||||
(push (cons ind-pos pos) end-list)
|
||||
(push (cons end-pos pos) acc-end)))
|
||||
struct)
|
||||
(pcase-dolist (`(,pos . ,_) struct)
|
||||
(let ((ind-pos (org-list-get-ind pos struct))
|
||||
(end-pos (org-list-get-item-end pos struct)))
|
||||
(unless (assq end-pos struct)
|
||||
;; To determine real ind of an ending position that is not
|
||||
;; at an item, we have to find the item it belongs to: it is
|
||||
;; the last item (ITEM-UP), whose ending is further than the
|
||||
;; position we're interested in.
|
||||
(let ((item-up (assoc-default end-pos acc-end #'>)))
|
||||
(push (cons
|
||||
;; Else part is for the bottom point.
|
||||
(if item-up (+ (org-list-get-ind item-up struct) 2) 0)
|
||||
end-pos)
|
||||
end-list)))
|
||||
(push (cons ind-pos pos) end-list)
|
||||
(push (cons end-pos pos) acc-end)))
|
||||
(setq end-list (sort end-list (lambda (e1 e2) (< (cdr e1) (cdr e2)))))
|
||||
(org-list-struct-assoc-end struct end-list)))
|
||||
|
||||
|
@ -2021,10 +2020,9 @@ beginning of the item."
|
|||
(item (copy-marker (point-at-bol)))
|
||||
(all (org-list-get-all-items (marker-position item) struct prevs))
|
||||
(value init-value))
|
||||
(mapc (lambda (e)
|
||||
(goto-char e)
|
||||
(setq value (apply function value args)))
|
||||
(nreverse all))
|
||||
(dolist (e (nreverse all))
|
||||
(goto-char e)
|
||||
(setq value (apply function value args)))
|
||||
(goto-char item)
|
||||
(move-marker item nil)
|
||||
value))
|
||||
|
@ -2046,9 +2044,8 @@ Possible values are: `folded', `children' or `subtree'. See
|
|||
;; Then fold every child.
|
||||
(let* ((parents (org-list-parents-alist struct))
|
||||
(children (org-list-get-children item struct parents)))
|
||||
(mapc (lambda (e)
|
||||
(org-list-set-item-visibility e struct 'folded))
|
||||
children)))
|
||||
(dolist (child children)
|
||||
(org-list-set-item-visibility child struct 'folded))))
|
||||
((eq view 'subtree)
|
||||
;; Show everything
|
||||
(let ((item-end (org-list-get-item-end item struct)))
|
||||
|
@ -2303,6 +2300,56 @@ is an integer, 0 means `-', 1 means `+' etc. If WHICH is
|
|||
(org-list-struct-fix-ind struct parents)
|
||||
(org-list-struct-apply-struct struct old-struct)))))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode org-list-checkbox-radio-mode
|
||||
"When turned on, use list checkboxes as radio buttons."
|
||||
nil " CheckBoxRadio" nil
|
||||
(unless (eq major-mode 'org-mode)
|
||||
(user-error "Cannot turn this mode outside org-mode buffers")))
|
||||
|
||||
(defun org-toggle-radio-button (&optional arg)
|
||||
"Toggle off all checkboxes and toggle on the one at point."
|
||||
(interactive "P")
|
||||
(if (not (org-at-item-p))
|
||||
(user-error "Cannot toggle checkbox outside of a list")
|
||||
(let* ((cpos (org-in-item-p))
|
||||
(struct (org-list-struct))
|
||||
(orderedp (org-entry-get nil "ORDERED"))
|
||||
(parents (org-list-parents-alist struct))
|
||||
(old-struct (copy-tree struct))
|
||||
(cbox (org-list-get-checkbox cpos struct))
|
||||
(prevs (org-list-prevs-alist struct))
|
||||
(start (org-list-get-list-begin (point-at-bol) struct prevs))
|
||||
(new (unless (and cbox (equal arg '(4)) (equal start cpos))
|
||||
"[ ]")))
|
||||
(dolist (pos (org-list-get-all-items
|
||||
start struct (org-list-prevs-alist struct)))
|
||||
(org-list-set-checkbox pos struct new))
|
||||
(when new
|
||||
(org-list-set-checkbox
|
||||
cpos struct
|
||||
(cond ((equal arg '(4)) (unless cbox "[ ]"))
|
||||
((equal arg '(16)) (unless cbox "[-]"))
|
||||
(t (if (equal cbox "[X]") "[ ]" "[X]")))))
|
||||
(org-list-struct-fix-box struct parents prevs orderedp)
|
||||
(org-list-struct-apply-struct struct old-struct)
|
||||
(org-update-checkbox-count-maybe))))
|
||||
|
||||
(defun org-at-radio-list-p ()
|
||||
"Is point at a list item with radio buttons?"
|
||||
(when (org-match-line (org-item-re)) ;short-circuit
|
||||
(let* ((e (save-excursion (beginning-of-line) (org-element-at-point))))
|
||||
;; Check we're really on a line with a bullet.
|
||||
(when (memq (org-element-type e) '(item plain-list))
|
||||
;; Look for ATTR_ORG attribute in the current plain list.
|
||||
(let ((plain-list (org-element-lineage e '(plain-list) t)))
|
||||
(org-with-point-at (org-element-property :post-affiliated plain-list)
|
||||
(let ((case-fold-search t)
|
||||
(regexp "^[ \t]*#\\+attr_org:.* :radio \\(\\S-+\\)")
|
||||
(begin (org-element-property :begin plain-list)))
|
||||
(and (re-search-backward regexp begin t)
|
||||
(not (string-equal "nil" (match-string 1)))))))))))
|
||||
|
||||
(defun org-toggle-checkbox (&optional toggle-presence)
|
||||
"Toggle the checkbox in the current line.
|
||||
|
||||
|
@ -2317,92 +2364,94 @@ If point is on a headline, apply this to all checkbox items in
|
|||
the text below the heading, taking as reference the first item in
|
||||
subtree, ignoring planning line and any drawer following it."
|
||||
(interactive "P")
|
||||
(save-excursion
|
||||
(let* (singlep
|
||||
block-item
|
||||
lim-up
|
||||
lim-down
|
||||
(orderedp (org-entry-get nil "ORDERED"))
|
||||
(_bounds
|
||||
;; In a region, start at first item in region.
|
||||
(if (org-at-radio-list-p)
|
||||
(org-toggle-radio-button toggle-presence)
|
||||
(save-excursion
|
||||
(let* (singlep
|
||||
block-item
|
||||
lim-up
|
||||
lim-down
|
||||
(orderedp (org-entry-get nil "ORDERED"))
|
||||
(_bounds
|
||||
;; In a region, start at first item in region.
|
||||
(cond
|
||||
((org-region-active-p)
|
||||
(let ((limit (region-end)))
|
||||
(goto-char (region-beginning))
|
||||
(if (org-list-search-forward (org-item-beginning-re) limit t)
|
||||
(setq lim-up (point-at-bol))
|
||||
(error "No item in region"))
|
||||
(setq lim-down (copy-marker limit))))
|
||||
((org-at-heading-p)
|
||||
;; On a heading, start at first item after drawers and
|
||||
;; time-stamps (scheduled, etc.).
|
||||
(let ((limit (save-excursion (outline-next-heading) (point))))
|
||||
(org-end-of-meta-data t)
|
||||
(if (org-list-search-forward (org-item-beginning-re) limit t)
|
||||
(setq lim-up (point-at-bol))
|
||||
(error "No item in subtree"))
|
||||
(setq lim-down (copy-marker limit))))
|
||||
;; Just one item: set SINGLEP flag.
|
||||
((org-at-item-p)
|
||||
(setq singlep t)
|
||||
(setq lim-up (point-at-bol)
|
||||
lim-down (copy-marker (point-at-eol))))
|
||||
(t (error "Not at an item or heading, and no active region"))))
|
||||
;; Determine the checkbox going to be applied to all items
|
||||
;; within bounds.
|
||||
(ref-checkbox
|
||||
(progn
|
||||
(goto-char lim-up)
|
||||
(let ((cbox (and (org-at-item-checkbox-p) (match-string 1))))
|
||||
(cond
|
||||
((equal toggle-presence '(16)) "[-]")
|
||||
((equal toggle-presence '(4))
|
||||
(unless cbox "[ ]"))
|
||||
((equal "[X]" cbox) "[ ]")
|
||||
(t "[X]"))))))
|
||||
;; When an item is found within bounds, grab the full list at
|
||||
;; point structure, then: (1) set check-box of all its items
|
||||
;; within bounds to REF-CHECKBOX, (2) fix check-boxes of the
|
||||
;; whole list, (3) move point after the list.
|
||||
(goto-char lim-up)
|
||||
(while (and (< (point) lim-down)
|
||||
(org-list-search-forward (org-item-beginning-re)
|
||||
lim-down 'move))
|
||||
(let* ((struct (org-list-struct))
|
||||
(struct-copy (copy-tree struct))
|
||||
(parents (org-list-parents-alist struct))
|
||||
(prevs (org-list-prevs-alist struct))
|
||||
(bottom (copy-marker (org-list-get-bottom-point struct)))
|
||||
(items-to-toggle (cl-remove-if
|
||||
(lambda (e) (or (< e lim-up) (> e lim-down)))
|
||||
(mapcar #'car struct))))
|
||||
(dolist (e items-to-toggle)
|
||||
(org-list-set-checkbox
|
||||
e struct
|
||||
;; If there is no box at item, leave as-is unless
|
||||
;; function was called with C-u prefix.
|
||||
(let ((cur-box (org-list-get-checkbox e struct)))
|
||||
(if (or cur-box (equal toggle-presence '(4)))
|
||||
ref-checkbox
|
||||
cur-box))))
|
||||
(setq block-item (org-list-struct-fix-box
|
||||
struct parents prevs orderedp))
|
||||
;; Report some problems due to ORDERED status of subtree.
|
||||
;; If only one box was being checked, throw an error, else,
|
||||
;; only signal problems.
|
||||
(cond
|
||||
((org-region-active-p)
|
||||
(let ((limit (region-end)))
|
||||
(goto-char (region-beginning))
|
||||
(if (org-list-search-forward (org-item-beginning-re) limit t)
|
||||
(setq lim-up (point-at-bol))
|
||||
(error "No item in region"))
|
||||
(setq lim-down (copy-marker limit))))
|
||||
((org-at-heading-p)
|
||||
;; On a heading, start at first item after drawers and
|
||||
;; time-stamps (scheduled, etc.).
|
||||
(let ((limit (save-excursion (outline-next-heading) (point))))
|
||||
(org-end-of-meta-data t)
|
||||
(if (org-list-search-forward (org-item-beginning-re) limit t)
|
||||
(setq lim-up (point-at-bol))
|
||||
(error "No item in subtree"))
|
||||
(setq lim-down (copy-marker limit))))
|
||||
;; Just one item: set SINGLEP flag.
|
||||
((org-at-item-p)
|
||||
(setq singlep t)
|
||||
(setq lim-up (point-at-bol)
|
||||
lim-down (copy-marker (point-at-eol))))
|
||||
(t (error "Not at an item or heading, and no active region"))))
|
||||
;; Determine the checkbox going to be applied to all items
|
||||
;; within bounds.
|
||||
(ref-checkbox
|
||||
(progn
|
||||
(goto-char lim-up)
|
||||
(let ((cbox (and (org-at-item-checkbox-p) (match-string 1))))
|
||||
(cond
|
||||
((equal toggle-presence '(16)) "[-]")
|
||||
((equal toggle-presence '(4))
|
||||
(unless cbox "[ ]"))
|
||||
((equal "[X]" cbox) "[ ]")
|
||||
(t "[X]"))))))
|
||||
;; When an item is found within bounds, grab the full list at
|
||||
;; point structure, then: (1) set check-box of all its items
|
||||
;; within bounds to REF-CHECKBOX, (2) fix check-boxes of the
|
||||
;; whole list, (3) move point after the list.
|
||||
(goto-char lim-up)
|
||||
(while (and (< (point) lim-down)
|
||||
(org-list-search-forward (org-item-beginning-re)
|
||||
lim-down 'move))
|
||||
(let* ((struct (org-list-struct))
|
||||
(struct-copy (copy-tree struct))
|
||||
(parents (org-list-parents-alist struct))
|
||||
(prevs (org-list-prevs-alist struct))
|
||||
(bottom (copy-marker (org-list-get-bottom-point struct)))
|
||||
(items-to-toggle (cl-remove-if
|
||||
(lambda (e) (or (< e lim-up) (> e lim-down)))
|
||||
(mapcar #'car struct))))
|
||||
(mapc (lambda (e) (org-list-set-checkbox
|
||||
e struct
|
||||
;; If there is no box at item, leave as-is
|
||||
;; unless function was called with C-u prefix.
|
||||
(let ((cur-box (org-list-get-checkbox e struct)))
|
||||
(if (or cur-box (equal toggle-presence '(4)))
|
||||
ref-checkbox
|
||||
cur-box))))
|
||||
items-to-toggle)
|
||||
(setq block-item (org-list-struct-fix-box
|
||||
struct parents prevs orderedp))
|
||||
;; Report some problems due to ORDERED status of subtree.
|
||||
;; If only one box was being checked, throw an error, else,
|
||||
;; only signal problems.
|
||||
(cond
|
||||
((and singlep block-item (> lim-up block-item))
|
||||
(error
|
||||
"Checkbox blocked because of unchecked box at line %d"
|
||||
(org-current-line block-item)))
|
||||
(block-item
|
||||
(message
|
||||
"Checkboxes were removed due to unchecked box at line %d"
|
||||
(org-current-line block-item))))
|
||||
(goto-char bottom)
|
||||
(move-marker bottom nil)
|
||||
(org-list-struct-apply-struct struct struct-copy)))
|
||||
(move-marker lim-down nil)))
|
||||
((and singlep block-item (> lim-up block-item))
|
||||
(error
|
||||
"Checkbox blocked because of unchecked box at line %d"
|
||||
(org-current-line block-item)))
|
||||
(block-item
|
||||
(message
|
||||
"Checkboxes were removed due to unchecked box at line %d"
|
||||
(org-current-line block-item))))
|
||||
(goto-char bottom)
|
||||
(move-marker bottom nil)
|
||||
(org-list-struct-apply-struct struct struct-copy)))
|
||||
(move-marker lim-down nil))))
|
||||
(org-update-checkbox-count-maybe))
|
||||
|
||||
(defun org-reset-checkbox-state-subtree ()
|
||||
|
@ -2632,10 +2681,9 @@ Return t if successful."
|
|||
(org-list-bullet-string "-")))
|
||||
;; Shift every item by OFFSET and fix bullets. Then
|
||||
;; apply changes to buffer.
|
||||
(mapc (lambda (e)
|
||||
(let ((ind (org-list-get-ind (car e) struct)))
|
||||
(org-list-set-ind (car e) struct (+ ind offset))))
|
||||
struct)
|
||||
(pcase-dolist (`(,pos . ,_) struct)
|
||||
(let ((ind (org-list-get-ind pos struct)))
|
||||
(org-list-set-ind pos struct (+ ind offset))))
|
||||
(org-list-struct-fix-bul struct prevs)
|
||||
(org-list-struct-apply-struct struct old-struct))))
|
||||
;; Forbidden move:
|
||||
|
@ -2733,51 +2781,83 @@ If a region is active, all items inside will be moved."
|
|||
(t (error "Not at an item")))))
|
||||
|
||||
(defvar org-tab-ind-state)
|
||||
(defvar org-adapt-indentation)
|
||||
(defun org-cycle-item-indentation ()
|
||||
"Cycle levels of indentation of an empty item.
|
||||
|
||||
The first run indents the item, if applicable. Subsequent runs
|
||||
outdent it at meaningful levels in the list. When done, item is
|
||||
put back at its original position with its original bullet.
|
||||
|
||||
Return t at each successful move."
|
||||
(when (org-at-item-p)
|
||||
(let* ((org-adapt-indentation nil)
|
||||
(struct (org-list-struct))
|
||||
(ind (org-list-get-ind (point-at-bol) struct))
|
||||
(bullet (org-trim (buffer-substring (point-at-bol) (point-at-eol)))))
|
||||
(let* ((struct (org-list-struct))
|
||||
(item (line-beginning-position))
|
||||
(ind (org-list-get-ind item struct)))
|
||||
;; Accept empty items or if cycle has already started.
|
||||
(when (or (eq last-command 'org-cycle-item-indentation)
|
||||
(and (save-excursion
|
||||
(beginning-of-line)
|
||||
(looking-at org-list-full-item-re))
|
||||
(>= (match-end 0) (save-excursion
|
||||
(goto-char (org-list-get-item-end
|
||||
(point-at-bol) struct))
|
||||
(skip-chars-backward " \r\t\n")
|
||||
(point)))))
|
||||
(and (org-match-line org-list-full-item-re)
|
||||
(>= (match-end 0)
|
||||
(save-excursion
|
||||
(goto-char (org-list-get-item-end item struct))
|
||||
(skip-chars-backward " \t\n")
|
||||
(point)))))
|
||||
(setq this-command 'org-cycle-item-indentation)
|
||||
;; When in the middle of the cycle, try to outdent first. If
|
||||
;; it fails, and point is still at initial position, indent.
|
||||
;; Else, re-create it at its original position.
|
||||
(if (eq last-command 'org-cycle-item-indentation)
|
||||
(let ((prevs (org-list-prevs-alist struct))
|
||||
(parents (org-list-parents-alist struct)))
|
||||
(if (eq last-command 'org-cycle-item-indentation)
|
||||
;; When in the middle of the cycle, try to outdent. If
|
||||
;; it fails, move point back to its initial position and
|
||||
;; reset cycle.
|
||||
(pcase-let ((`(,old-ind . ,old-bul) org-tab-ind-state)
|
||||
(allow-outdent
|
||||
(lambda (struct prevs parents)
|
||||
;; Non-nil if current item can be
|
||||
;; outdented.
|
||||
(and (not (org-list-get-next-item item nil prevs))
|
||||
(not (org-list-has-child-p item struct))
|
||||
(org-list-get-parent item struct parents)))))
|
||||
(cond
|
||||
((and (> ind old-ind)
|
||||
(org-list-get-prev-item item nil prevs))
|
||||
(org-list-indent-item-generic 1 t struct))
|
||||
((and (< ind old-ind)
|
||||
(funcall allow-outdent struct prevs parents))
|
||||
(org-list-indent-item-generic -1 t struct))
|
||||
(t
|
||||
(delete-region (line-beginning-position) (line-end-position))
|
||||
(indent-to-column old-ind)
|
||||
(insert old-bul " ")
|
||||
(let* ((struct (org-list-struct))
|
||||
(parents (org-list-parents-alist struct)))
|
||||
(if (and (> ind old-ind)
|
||||
;; We were previously indenting item. It
|
||||
;; is no longer possible. Try to outdent
|
||||
;; from initial position.
|
||||
(funcall allow-outdent
|
||||
struct
|
||||
(org-list-prevs-alist struct)
|
||||
parents))
|
||||
(org-list-indent-item-generic -1 t struct)
|
||||
(org-list-write-struct struct parents)
|
||||
;; Start cycle over.
|
||||
(setq this-command 'identity)
|
||||
t)))))
|
||||
;; If a cycle is starting, remember initial indentation
|
||||
;; and bullet, then try to indent. If it fails, try to
|
||||
;; outdent.
|
||||
(setq org-tab-ind-state
|
||||
(cons ind (org-trim (org-current-line-string))))
|
||||
(cond
|
||||
((ignore-errors (org-list-indent-item-generic -1 t struct)))
|
||||
((and (= ind (car org-tab-ind-state))
|
||||
(ignore-errors (org-list-indent-item-generic 1 t struct))))
|
||||
(t (delete-region (point-at-bol) (point-at-eol))
|
||||
(indent-to-column (car org-tab-ind-state))
|
||||
(insert (cdr org-tab-ind-state) " ")
|
||||
;; Break cycle
|
||||
(setq this-command 'identity)))
|
||||
;; If a cycle is starting, remember indentation and bullet,
|
||||
;; then try to indent. If it fails, try to outdent.
|
||||
(setq org-tab-ind-state (cons ind bullet))
|
||||
(cond
|
||||
((ignore-errors (org-list-indent-item-generic 1 t struct)))
|
||||
((ignore-errors (org-list-indent-item-generic -1 t struct)))
|
||||
(t (user-error "Cannot move item"))))
|
||||
t))))
|
||||
((org-list-get-prev-item item nil prevs)
|
||||
(org-list-indent-item-generic 1 t struct))
|
||||
((and (not (org-list-get-next-item item nil prevs))
|
||||
(org-list-get-parent item struct parents))
|
||||
(org-list-indent-item-generic -1 t struct))
|
||||
(t
|
||||
;; This command failed. So will the following one.
|
||||
;; There's no point in starting the cycle.
|
||||
(setq this-command 'identity)
|
||||
(user-error "Cannot move item")))))))))
|
||||
|
||||
(defun org-sort-list
|
||||
(&optional with-case sorting-type getkey-func compare-func interactive?)
|
||||
|
@ -2794,8 +2874,8 @@ if the current locale allows for it.
|
|||
|
||||
The command prompts for the sorting type unless it has been given
|
||||
to the function through the SORTING-TYPE argument, which needs to
|
||||
be a character, \(?n ?N ?a ?A ?t ?T ?f ?F ?x ?X). Here is the
|
||||
detailed meaning of each character:
|
||||
be a character, among ?n ?N ?a ?A ?t ?T ?f ?F ?x or ?X. Here is
|
||||
the detailed meaning of each character:
|
||||
|
||||
n Numerically, by converting the beginning of the item to a number.
|
||||
a Alphabetically. Only the first line of item is checked.
|
||||
|
@ -2958,7 +3038,7 @@ With a prefix argument ARG, change the region in a single item."
|
|||
(if (org-region-active-p)
|
||||
(setq beg (funcall skip-blanks (region-beginning))
|
||||
end (copy-marker (region-end)))
|
||||
(setq beg (funcall skip-blanks (point-at-bol))
|
||||
(setq beg (point-at-bol)
|
||||
end (copy-marker (point-at-eol))))
|
||||
;; Depending on the starting line, choose an action on the text
|
||||
;; between BEG and END.
|
||||
|
@ -3501,4 +3581,8 @@ overruling parameters for `org-list-to-generic'."
|
|||
|
||||
(provide 'org-list)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-list.el ends here
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
(require 'org-macs)
|
||||
(require 'org-compat)
|
||||
|
||||
(declare-function org-collect-keywords "org" (keywords &optional unique directory))
|
||||
(declare-function org-element-at-point "org-element" ())
|
||||
(declare-function org-element-context "org-element" (&optional element))
|
||||
(declare-function org-element-copy "org-element" (datum))
|
||||
|
@ -88,49 +89,24 @@ directly, use instead:
|
|||
VALUE is the template of the macro. The new value override the
|
||||
previous one, unless VALUE is nil. TEMPLATES is the list of
|
||||
templates. Return the updated list."
|
||||
(when value
|
||||
(let ((old-definition (assoc name templates)))
|
||||
(if old-definition
|
||||
(setcdr old-definition value)
|
||||
(push (cons name value) templates))))
|
||||
(let ((old-definition (assoc name templates)))
|
||||
(cond ((and value old-definition) (setcdr old-definition value))
|
||||
(old-definition)
|
||||
(t (push (cons name (or value "")) templates))))
|
||||
templates)
|
||||
|
||||
(defun org-macro--collect-macros (&optional files templates)
|
||||
(defun org-macro--collect-macros ()
|
||||
"Collect macro definitions in current buffer and setup files.
|
||||
Return an alist containing all macro templates found.
|
||||
|
||||
FILES is a list of setup files names read so far, used to avoid
|
||||
circular dependencies. TEMPLATES is the alist collected so far.
|
||||
The two arguments are used in recursive calls."
|
||||
(let ((case-fold-search t))
|
||||
(org-with-point-at 1
|
||||
(while (re-search-forward "^[ \t]*#\\+\\(MACRO\\|SETUPFILE\\):" nil t)
|
||||
(let ((element (org-element-at-point)))
|
||||
(when (eq (org-element-type element) 'keyword)
|
||||
(let ((val (org-element-property :value element)))
|
||||
(if (equal "MACRO" (org-element-property :key element))
|
||||
;; Install macro in TEMPLATES.
|
||||
(when (string-match "^\\(\\S-+\\)[ \t]*" val)
|
||||
(let ((name (match-string 1 val))
|
||||
(value (substring val (match-end 0))))
|
||||
(setq templates
|
||||
(org-macro--set-template name value templates))))
|
||||
;; Enter setup file.
|
||||
(let* ((uri (org-strip-quotes val))
|
||||
(uri-is-url (org-file-url-p uri))
|
||||
(uri (if uri-is-url
|
||||
uri
|
||||
(expand-file-name uri))))
|
||||
;; Avoid circular dependencies.
|
||||
(unless (member uri files)
|
||||
(with-temp-buffer
|
||||
(unless uri-is-url
|
||||
(setq default-directory (file-name-directory uri)))
|
||||
(org-mode)
|
||||
(insert (org-file-contents uri 'noerror))
|
||||
(setq templates
|
||||
(org-macro--collect-macros
|
||||
(cons uri files) templates)))))))))))
|
||||
Return an alist containing all macro templates found."
|
||||
(let ((templates nil))
|
||||
(pcase (org-collect-keywords '("MACRO"))
|
||||
(`(("MACRO" . ,values))
|
||||
(dolist (value values)
|
||||
(when (string-match "^\\(\\S-+\\)[ \t]*" value)
|
||||
(let ((name (match-string 1 value))
|
||||
(definition (substring value (match-end 0))))
|
||||
(setq templates
|
||||
(org-macro--set-template name definition templates)))))))
|
||||
(let ((macros `(("author" . ,(org-macro--find-keyword-value "AUTHOR"))
|
||||
("email" . ,(org-macro--find-keyword-value "EMAIL"))
|
||||
("title" . ,(org-macro--find-keyword-value "TITLE" t))
|
||||
|
@ -417,6 +393,6 @@ Any other non-empty string resets the counter to 1."
|
|||
(t 1))
|
||||
org-macro--counter-table)))
|
||||
|
||||
|
||||
(provide 'org-macro)
|
||||
|
||||
;;; org-macro.el ends here
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
(require 'cl-lib)
|
||||
(require 'format-spec)
|
||||
|
||||
(declare-function org-show-context "org" (&optional key))
|
||||
(declare-function org-string-collate-lessp "org-compat" (s1 s2 &optional locale ignore-case))
|
||||
|
||||
(defvar org-ts-regexp0)
|
||||
|
@ -122,7 +123,7 @@ means that the buffer should stay alive during the operation,
|
|||
because otherwise all these markers will point to nowhere."
|
||||
(declare (debug (form body)) (indent 1))
|
||||
(org-with-gensyms (data invisible-types markers?)
|
||||
`(let* ((,invisible-types '(org-hide-block org-hide-drawer outline))
|
||||
`(let* ((,invisible-types '(org-hide-block outline))
|
||||
(,markers? ,use-markers)
|
||||
(,data
|
||||
(mapcar (lambda (o)
|
||||
|
@ -416,6 +417,7 @@ is selected, only the bare key is returned."
|
|||
(let ((inhibit-quit t)
|
||||
(buffer (org-switch-to-buffer-other-window "*Org Select*"))
|
||||
(prompt (or prompt "Select: "))
|
||||
case-fold-search
|
||||
current)
|
||||
(unwind-protect
|
||||
(catch 'exit
|
||||
|
@ -644,6 +646,25 @@ The number of levels is controlled by `org-inlinetask-min-level'."
|
|||
limit-level)))
|
||||
(format "\\*\\{1,%d\\} " nstars)))))
|
||||
|
||||
(defun org--line-empty-p (n)
|
||||
"Is the Nth next line empty?
|
||||
Counts the current line as N = 1 and the previous line as N = 0;
|
||||
see `beginning-of-line'."
|
||||
(and (not (bobp))
|
||||
(save-excursion
|
||||
(beginning-of-line n)
|
||||
(looking-at-p "[ \t]*$"))))
|
||||
|
||||
(defun org-previous-line-empty-p ()
|
||||
"Is the previous line a blank line?
|
||||
When NEXT is non-nil, check the next line instead."
|
||||
(org--line-empty-p 0))
|
||||
|
||||
(defun org-next-line-empty-p ()
|
||||
"Is the previous line a blank line?
|
||||
When NEXT is non-nil, check the next line instead."
|
||||
(org--line-empty-p 2))
|
||||
|
||||
|
||||
|
||||
;;; Motion
|
||||
|
@ -695,7 +716,9 @@ SPEC is the invisibility spec, as a symbol."
|
|||
(let ((o (make-overlay from to nil 'front-advance)))
|
||||
(overlay-put o 'evaporate t)
|
||||
(overlay-put o 'invisible spec)
|
||||
(overlay-put o 'isearch-open-invisible #'delete-overlay))))
|
||||
(overlay-put o
|
||||
'isearch-open-invisible
|
||||
(lambda (&rest _) (org-show-context 'isearch))))))
|
||||
|
||||
|
||||
|
||||
|
@ -920,7 +943,8 @@ if necessary."
|
|||
(if (<= (length s) maxlength)
|
||||
s
|
||||
(let* ((n (max (- maxlength 4) 1))
|
||||
(re (concat "\\`\\(.\\{1," (int-to-string n) "\\}[^ ]\\)\\([ ]\\|\\'\\)")))
|
||||
(re (concat "\\`\\(.\\{1," (number-to-string n)
|
||||
"\\}[^ ]\\)\\([ ]\\|\\'\\)")))
|
||||
(if (string-match re s)
|
||||
(concat (match-string 1 s) "...")
|
||||
(concat (substring s 0 (max (- maxlength 3) 0)) "...")))))
|
||||
|
@ -1065,10 +1089,16 @@ the value in cdr."
|
|||
(get-text-property (or (next-single-property-change 0 prop s) 0)
|
||||
prop s)))
|
||||
|
||||
(defun org-invisible-p (&optional pos)
|
||||
(defun org-invisible-p (&optional pos folding-only)
|
||||
"Non-nil if the character after POS is invisible.
|
||||
If POS is nil, use `point' instead."
|
||||
(get-char-property (or pos (point)) 'invisible))
|
||||
If POS is nil, use `point' instead. When optional argument
|
||||
FOLDING-ONLY is non-nil, only consider invisible parts due to
|
||||
folding of a headline, a block or a drawer, i.e., not because of
|
||||
fontification."
|
||||
(let ((value (get-char-property (or pos (point)) 'invisible)))
|
||||
(cond ((not value) nil)
|
||||
(folding-only (memq value '(org-hide-block outline)))
|
||||
(t value))))
|
||||
|
||||
(defun org-truely-invisible-p ()
|
||||
"Check if point is at a character currently not visible.
|
||||
|
@ -1086,6 +1116,18 @@ move it back by one char before doing this check."
|
|||
(backward-char 1))
|
||||
(org-invisible-p)))
|
||||
|
||||
(defun org-find-visible ()
|
||||
"Return closest visible buffer position, or `point-max'"
|
||||
(if (org-invisible-p)
|
||||
(next-single-char-property-change (point) 'invisible)
|
||||
(point)))
|
||||
|
||||
(defun org-find-invisible ()
|
||||
"Return closest invisible buffer position, or `point-max'"
|
||||
(if (org-invisible-p)
|
||||
(point)
|
||||
(next-single-char-property-change (point) 'invisible)))
|
||||
|
||||
|
||||
;;; Time
|
||||
|
||||
|
@ -1182,8 +1224,41 @@ Return 0. if S is not recognized as a valid value."
|
|||
((string-match org-ts-regexp0 s) (org-2ft s))
|
||||
(t 0.)))))
|
||||
|
||||
|
||||
(defun org-scroll (key &optional additional-keys)
|
||||
"Receive KEY and scroll the current window accordingly.
|
||||
When ADDITIONAL-KEYS is not nil, also include SPC and DEL in the
|
||||
allowed keys for scrolling, as expected in the export dispatch
|
||||
window."
|
||||
(let ((scrlup (if additional-keys '(?\s 22) 22))
|
||||
(scrldn (if additional-keys `(?\d 134217846) 134217846)))
|
||||
(eval
|
||||
`(cl-case ,key
|
||||
;; C-n
|
||||
(14 (if (not (pos-visible-in-window-p (point-max)))
|
||||
(ignore-errors (scroll-up 1))
|
||||
(message "End of buffer")
|
||||
(sit-for 1)))
|
||||
;; C-p
|
||||
(16 (if (not (pos-visible-in-window-p (point-min)))
|
||||
(ignore-errors (scroll-down 1))
|
||||
(message "Beginning of buffer")
|
||||
(sit-for 1)))
|
||||
;; SPC or
|
||||
(,scrlup
|
||||
(if (not (pos-visible-in-window-p (point-max)))
|
||||
(scroll-up nil)
|
||||
(message "End of buffer")
|
||||
(sit-for 1)))
|
||||
;; DEL
|
||||
(,scrldn (if (not (pos-visible-in-window-p (point-min)))
|
||||
(scroll-down nil)
|
||||
(message "Beginning of buffer")
|
||||
(sit-for 1)))))))
|
||||
|
||||
(provide 'org-macs)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-macs.el ends here
|
||||
|
|
|
@ -258,6 +258,17 @@ the old and new values for the entry.")
|
|||
(defvar org-mobile-files-alist nil)
|
||||
(defvar org-mobile-checksum-files nil)
|
||||
|
||||
;; Add org mobile commands to the main org menu
|
||||
(easy-menu-add-item
|
||||
org-org-menu
|
||||
nil
|
||||
'("MobileOrg"
|
||||
["Push Files and Views" org-mobile-push t]
|
||||
["Get Captured and Flagged" org-mobile-pull t]
|
||||
["Find FLAGGED Tasks" (org-agenda nil "?") :active t :keys "\\[org-agenda] ?"]
|
||||
"--"
|
||||
["Setup" (customize-group 'org-mobile) t]))
|
||||
|
||||
(defun org-mobile-prepare-file-lists ()
|
||||
(setq org-mobile-files-alist (org-mobile-files-alist))
|
||||
(setq org-mobile-checksum-files nil))
|
||||
|
|
|
@ -386,7 +386,7 @@ DEFAULT is returned if no priority is given in the headline."
|
|||
(save-excursion
|
||||
(if (org-mouse-re-search-line org-mouse-priority-regexp)
|
||||
(match-string 1)
|
||||
(when default (char-to-string org-default-priority)))))
|
||||
(when default (char-to-string org-priority-default)))))
|
||||
|
||||
(defun org-mouse-delete-timestamp ()
|
||||
"Deletes the current timestamp as well as the preceding keyword.
|
||||
|
@ -407,7 +407,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
|
|||
(> (match-end 0) point))))))
|
||||
|
||||
(defun org-mouse-priority-list ()
|
||||
(cl-loop for priority from ?A to org-lowest-priority
|
||||
(cl-loop for priority from ?A to org-priority-lowest
|
||||
collect (char-to-string priority)))
|
||||
|
||||
(defun org-mouse-todo-menu (state)
|
||||
|
@ -495,7 +495,8 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
|
|||
["Check Deadlines"
|
||||
(if (functionp 'org-check-deadlines-and-todos)
|
||||
(org-check-deadlines-and-todos org-deadline-warning-days)
|
||||
(org-check-deadlines org-deadline-warning-days)) t]
|
||||
(org-check-deadlines org-deadline-warning-days))
|
||||
t]
|
||||
["Check TODOs" org-show-todo-tree t]
|
||||
("Check Tags"
|
||||
,@(org-mouse-keyword-menu
|
||||
|
@ -741,7 +742,8 @@ This means, between the beginning of line and the point."
|
|||
(?$ "($) Formula Parameters")
|
||||
(?# "(#) Recalculation: Auto")
|
||||
(?* "(*) Recalculation: Manual")
|
||||
(?' "(') Recalculation: None"))) t))))
|
||||
(?' "(') Recalculation: None")))
|
||||
t))))
|
||||
((assq :table contextlist)
|
||||
(popup-menu
|
||||
'(nil
|
||||
|
|
|
@ -254,6 +254,7 @@ otherwise."
|
|||
org-footnote-section
|
||||
(equal title org-footnote-section))
|
||||
(and org-num-skip-commented
|
||||
title
|
||||
(let ((case-fold-search nil))
|
||||
(string-match org-num--comment-re title))
|
||||
t)
|
||||
|
@ -466,6 +467,10 @@ NUMBERING is a list of numbers."
|
|||
(remove-hook 'after-change-functions #'org-num--verify t)
|
||||
(remove-hook 'change-major-mode-hook #'org-num--clear t))))
|
||||
|
||||
|
||||
(provide 'org-num)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-num.el ends here
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
(require 'pcomplete)
|
||||
|
||||
(declare-function org-at-heading-p "org" (&optional ignored))
|
||||
(declare-function org-babel-combine-header-arg-lists "ob-core" (original &rest others))
|
||||
(declare-function org-babel-get-src-block-info "ob-core" (&optional light datum))
|
||||
(declare-function org-before-first-heading-p "org" ())
|
||||
(declare-function org-buffer-property-keys "org" (&optional specials defaults columns))
|
||||
(declare-function org-element-at-point "org-element" ())
|
||||
|
@ -47,8 +49,9 @@
|
|||
(declare-function org-link-heading-search-string "ol" (&optional string))
|
||||
(declare-function org-tag-alist-to-string "org" (alist &optional skip-key))
|
||||
|
||||
(defvar org-babel-common-header-args-w-values)
|
||||
(defvar org-current-tag-alist)
|
||||
(defvar org-default-priority)
|
||||
(defvar org-priority-default)
|
||||
(defvar org-drawer-regexp)
|
||||
(defvar org-element-affiliated-keywords)
|
||||
(defvar org-entities)
|
||||
|
@ -56,10 +59,10 @@
|
|||
(defvar org-export-exclude-tags)
|
||||
(defvar org-export-select-tags)
|
||||
(defvar org-file-tags)
|
||||
(defvar org-highest-priority)
|
||||
(defvar org-priority-highest)
|
||||
(defvar org-link-abbrev-alist)
|
||||
(defvar org-link-abbrev-alist-local)
|
||||
(defvar org-lowest-priority)
|
||||
(defvar org-priority-lowest)
|
||||
(defvar org-options-keywords)
|
||||
(defvar org-outline-regexp)
|
||||
(defvar org-property-re)
|
||||
|
@ -252,9 +255,9 @@ 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-highest-priority
|
||||
org-lowest-priority
|
||||
org-default-priority))))
|
||||
org-priority-highest
|
||||
org-priority-lowest
|
||||
org-priority-default))))
|
||||
|
||||
(defun pcomplete/org-mode/file-option/select_tags ()
|
||||
"Complete arguments for the #+SELECT_TAGS file option."
|
||||
|
@ -352,8 +355,9 @@ This needs more work, to handle headings with lots of spaces in them."
|
|||
(goto-char (point-min))
|
||||
(let (tbl)
|
||||
(while (re-search-forward org-outline-regexp nil t)
|
||||
(push (org-link-heading-search-string (org-get-heading t t t t))
|
||||
tbl))
|
||||
;; Remove the leading asterisk from
|
||||
;; `org-link-heading-search-string' result.
|
||||
(push (substring (org-link-heading-search-string) 1) tbl))
|
||||
(pcomplete-uniquify-list tbl)))
|
||||
;; When completing a bracketed link, i.e., "[[*", argument
|
||||
;; starts at the star, so remove this character.
|
||||
|
@ -417,11 +421,17 @@ switches."
|
|||
(symbol-plist
|
||||
'org-babel-load-languages)
|
||||
'custom-type)))))))
|
||||
(while (pcomplete-here
|
||||
'("-n" "-r" "-l"
|
||||
":cache" ":colnames" ":comments" ":dir" ":eval" ":exports"
|
||||
":file" ":hlines" ":no-expand" ":noweb" ":results" ":rownames"
|
||||
":session" ":shebang" ":tangle" ":tangle-mode" ":var"))))
|
||||
(let* ((info (org-babel-get-src-block-info 'light))
|
||||
(lang (car info))
|
||||
(lang-headers (intern (concat "org-babel-header-args:" lang)))
|
||||
(headers (org-babel-combine-header-arg-lists
|
||||
org-babel-common-header-args-w-values
|
||||
(and (boundp lang-headers) (eval lang-headers t)))))
|
||||
(while (pcomplete-here
|
||||
(append (mapcar
|
||||
(lambda (arg) (format ":%s" (symbol-name (car arg))))
|
||||
headers)
|
||||
'("-n" "-r" "-l"))))))
|
||||
|
||||
(defun pcomplete/org-mode/block-option/clocktable ()
|
||||
"Complete keywords in a clocktable line."
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
;; Copyright (C) 2008-2020 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; Author: Eric Schulte <schulte dot eric at gmail dot com>
|
||||
;; Maintainer: TEC <tecosaur@gmail.com>
|
||||
;; Keywords: tables, plotting
|
||||
;; Homepage: https://orgmode.org
|
||||
;;
|
||||
|
@ -144,7 +145,8 @@ and dependent variables."
|
|||
row-vals)
|
||||
(when (>= ind 0) ;; collect values of ind col
|
||||
(setf row-vals (mapcar (lambda (row) (setf counter (+ 1 counter))
|
||||
(cons counter (nth ind row))) table)))
|
||||
(cons counter (nth ind row)))
|
||||
table)))
|
||||
(when (or deps (>= ind 0)) ;; remove non-plotting columns
|
||||
(setf deps (delq ind deps))
|
||||
(setf table (mapcar (lambda (row)
|
||||
|
@ -288,14 +290,12 @@ line directly before or after the table."
|
|||
(setf params (plist-put params (car pair) (cdr pair)))))
|
||||
;; collect table and table information
|
||||
(let* ((data-file (make-temp-file "org-plot"))
|
||||
(table (org-table-to-lisp))
|
||||
(num-cols (length (if (eq (nth 0 table) 'hline) (nth 1 table)
|
||||
(nth 0 table)))))
|
||||
(table (org-table-collapse-header (org-table-to-lisp)))
|
||||
(num-cols (length (car table))))
|
||||
(run-with-idle-timer 0.1 nil #'delete-file data-file)
|
||||
(while (eq 'hline (car table)) (setf table (cdr table)))
|
||||
(when (eq (cadr table) 'hline)
|
||||
(setf params
|
||||
(plist-put params :labels (nth 0 table))) ; headers to labels
|
||||
(plist-put params :labels (car table))) ; headers to labels
|
||||
(setf table (delq 'hline (cdr table)))) ; clean non-data from table
|
||||
;; Collect options.
|
||||
(save-excursion (while (and (equal 0 (forward-line -1))
|
||||
|
@ -308,26 +308,20 @@ line directly before or after the table."
|
|||
(`grid (let ((y-labels (org-plot/gnuplot-to-grid-data
|
||||
table data-file params)))
|
||||
(when y-labels (plist-put params :ylabels y-labels)))))
|
||||
;; Check for timestamp ind column.
|
||||
(let ((ind (1- (plist-get params :ind))))
|
||||
(when (and (>= ind 0) (eq '2d (plist-get params :plot-type)))
|
||||
(if (= (length
|
||||
(delq 0 (mapcar
|
||||
(lambda (el)
|
||||
(if (string-match org-ts-regexp3 el) 0 1))
|
||||
(mapcar (lambda (row) (nth ind row)) table))))
|
||||
0)
|
||||
(plist-put params :timeind t)
|
||||
;; Check for text ind column.
|
||||
(if (or (string= (plist-get params :with) "hist")
|
||||
(> (length
|
||||
(delq 0 (mapcar
|
||||
(lambda (el)
|
||||
(if (string-match org-table-number-regexp el)
|
||||
0 1))
|
||||
(mapcar (lambda (row) (nth ind row)) table))))
|
||||
0))
|
||||
(plist-put params :textind t)))))
|
||||
;; Check type of ind column (timestamp? text?)
|
||||
(when (eq `2d (plist-get params :plot-type))
|
||||
(let* ((ind (1- (plist-get params :ind)))
|
||||
(ind-column (mapcar (lambda (row) (nth ind row)) table)))
|
||||
(cond ((< ind 0) nil) ; ind is implicit
|
||||
((cl-every (lambda (el)
|
||||
(string-match org-ts-regexp3 el))
|
||||
ind-column)
|
||||
(plist-put params :timeind t)) ; ind holds timestamps
|
||||
((or (string= (plist-get params :with) "hist")
|
||||
(cl-notevery (lambda (el)
|
||||
(string-match org-table-number-regexp el))
|
||||
ind-column))
|
||||
(plist-put params :textind t))))) ; ind holds text
|
||||
;; Write script.
|
||||
(with-temp-buffer
|
||||
(if (plist-get params :script) ; user script
|
||||
|
|
|
@ -191,7 +191,7 @@ Example:
|
|||
:working-suffix \".org\"
|
||||
:base-url \"https://orgmode.org/worg/\"
|
||||
:working-directory \"/home/user/org/Worg/\")
|
||||
(\"http://localhost/org-notes/\"
|
||||
(\"localhost org-notes/\"
|
||||
:online-suffix \".html\"
|
||||
:working-suffix \".org\"
|
||||
:base-url \"http://localhost/org/\"
|
||||
|
@ -202,12 +202,17 @@ Example:
|
|||
:working-directory \"~/site/content/post/\"
|
||||
:online-suffix \".html\"
|
||||
:working-suffix \".md\"
|
||||
:rewrites ((\"\\(https://site.com/[0-9]+/[0-9]+/[0-9]+/\\)\" . \".md\")))))
|
||||
:rewrites ((\"\\(https://site.com/[0-9]+/[0-9]+/[0-9]+/\\)\" . \".md\")))
|
||||
(\"GNU emacs OpenGrok\"
|
||||
:base-url \"https://opengrok.housegordon.com/source/xref/emacs/\"
|
||||
:working-directory \"~/dev/gnu-emacs/\")))
|
||||
|
||||
|
||||
The last line tells `org-protocol-open-source' to open
|
||||
/home/user/org/index.php, if the URL cannot be mapped to an existing
|
||||
file, and ends with either \"org\" or \"org/\".
|
||||
The :rewrites line of \"localhost org-notes\" entry tells
|
||||
`org-protocol-open-source' to open /home/user/org/index.php,
|
||||
if the URL cannot be mapped to an existing file, and ends with
|
||||
either \"org\" or \"org/\". The \"GNU emacs OpenGrok\" entry
|
||||
does not include any suffix properties, allowing local source
|
||||
file to be opened as found by OpenGrok.
|
||||
|
||||
Consider using the interactive functions `org-protocol-create' and
|
||||
`org-protocol-create-for-org' to help you filling this variable with valid contents."
|
||||
|
@ -278,7 +283,7 @@ This should be a single regexp string."
|
|||
:group 'org-protocol
|
||||
:version "24.4"
|
||||
:package-version '(Org . "8.0")
|
||||
:type 'string)
|
||||
:type 'regexp)
|
||||
|
||||
;;; Helper functions:
|
||||
|
||||
|
@ -545,11 +550,12 @@ The location for a browser's bookmark should look like this:
|
|||
;; ending than strip-suffix here:
|
||||
(f1 (substring f 0 (string-match "\\([\\?#].*\\)?$" f)))
|
||||
(start-pos (+ (string-match wsearch f1) (length base-url)))
|
||||
(end-pos (string-match
|
||||
(regexp-quote strip-suffix) f1))
|
||||
(end-pos (if strip-suffix
|
||||
(string-match (regexp-quote strip-suffix) f1)
|
||||
(length f1)))
|
||||
;; We have to compare redirects without suffix below:
|
||||
(f2 (concat wdir (substring f1 start-pos end-pos)))
|
||||
(the-file (concat f2 add-suffix)))
|
||||
(the-file (if add-suffix (concat f2 add-suffix) f2)))
|
||||
|
||||
;; Note: the-file may still contain `%C3' et al here because browsers
|
||||
;; tend to encode `ä' in URLs to `%25C3' - `%25' being `%'.
|
||||
|
@ -617,13 +623,13 @@ CLIENT is ignored."
|
|||
(let ((proto
|
||||
(concat the-protocol
|
||||
(regexp-quote (plist-get (cdr prolist) :protocol))
|
||||
"\\(:/+\\|\\?\\)")))
|
||||
"\\(:/+\\|/*\\?\\)")))
|
||||
(when (string-match proto fname)
|
||||
(let* ((func (plist-get (cdr prolist) :function))
|
||||
(greedy (plist-get (cdr prolist) :greedy))
|
||||
(split (split-string fname proto))
|
||||
(result (if greedy restoffiles (cadr split)))
|
||||
(new-style (string= (match-string 1 fname) "?")))
|
||||
(new-style (string-match "/*?" (match-string 1 fname))))
|
||||
(when (plist-get (cdr prolist) :kill-client)
|
||||
(message "Greedy org-protocol handler. Killing client.")
|
||||
(server-edit))
|
||||
|
|
742
lisp/org/org-refile.el
Normal file
742
lisp/org/org-refile.el
Normal file
|
@ -0,0 +1,742 @@
|
|||
;;; org-refile.el --- Refile Org Subtrees -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2010-2020 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Carsten Dominik <carsten at orgmode dot org>
|
||||
;; Keywords: outlines, hypermedia, calendar, wp
|
||||
;;
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Org Refile allows you to refile subtrees to various locations.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'org)
|
||||
|
||||
(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
|
||||
|
||||
(defgroup org-refile nil
|
||||
"Options concerning refiling entries in Org mode."
|
||||
:tag "Org Refile"
|
||||
:group 'org)
|
||||
|
||||
(defcustom org-log-refile nil
|
||||
"Information to record when a task is refiled.
|
||||
|
||||
Possible values are:
|
||||
|
||||
nil Don't add anything
|
||||
time Add a time stamp to the task
|
||||
note Prompt for a note and add it with template `org-log-note-headings'
|
||||
|
||||
This option can also be set with on a per-file-basis with
|
||||
|
||||
#+STARTUP: nologrefile
|
||||
#+STARTUP: logrefile
|
||||
#+STARTUP: lognoterefile
|
||||
|
||||
You can have local logging settings for a subtree by setting the LOGGING
|
||||
property to one or more of these keywords.
|
||||
|
||||
When bulk-refiling, e.g., from the agenda, the value `note' is
|
||||
forbidden and will temporarily be changed to `time'."
|
||||
:group 'org-refile
|
||||
:group 'org-progress
|
||||
:version "24.1"
|
||||
:type '(choice
|
||||
(const :tag "No logging" nil)
|
||||
(const :tag "Record timestamp" time)
|
||||
(const :tag "Record timestamp with note." note)))
|
||||
|
||||
(defcustom org-refile-targets nil
|
||||
"Targets for refiling entries with `\\[org-refile]'.
|
||||
This is a list of cons cells. Each cell contains:
|
||||
- a specification of the files to be considered, either a list of files,
|
||||
or a symbol whose function or variable value will be used to retrieve
|
||||
a file name or a list of file names. If you use `org-agenda-files' for
|
||||
that, all agenda files will be scanned for targets. Nil means consider
|
||||
headings in the current buffer.
|
||||
- A specification of how to find candidate refile targets. This may be
|
||||
any of:
|
||||
- a cons cell (:tag . \"TAG\") to identify refile targets by a tag.
|
||||
This tag has to be present in all target headlines, inheritance will
|
||||
not be considered.
|
||||
- a cons cell (:todo . \"KEYWORD\") to identify refile targets by
|
||||
todo keyword.
|
||||
- a cons cell (:regexp . \"REGEXP\") with a regular expression matching
|
||||
headlines that are refiling targets.
|
||||
- a cons cell (:level . N). Any headline of level N is considered a target.
|
||||
Note that, when `org-odd-levels-only' is set, level corresponds to
|
||||
order in hierarchy, not to the number of stars.
|
||||
- a cons cell (:maxlevel . N). Any headline with level <= N is a target.
|
||||
Note that, when `org-odd-levels-only' is set, level corresponds to
|
||||
order in hierarchy, not to the number of stars.
|
||||
|
||||
Each element of this list generates a set of possible targets.
|
||||
The union of these sets is presented (with completion) to
|
||||
the user by `org-refile'.
|
||||
|
||||
You can set the variable `org-refile-target-verify-function' to a function
|
||||
to verify each headline found by the simple criteria above.
|
||||
|
||||
When this variable is nil, all top-level headlines in the current buffer
|
||||
are used, equivalent to the value `((nil . (:level . 1))'."
|
||||
:group 'org-refile
|
||||
:type '(repeat
|
||||
(cons
|
||||
(choice :value org-agenda-files
|
||||
(const :tag "All agenda files" org-agenda-files)
|
||||
(const :tag "Current buffer" nil)
|
||||
(function) (variable) (file))
|
||||
(choice :tag "Identify target headline by"
|
||||
(cons :tag "Specific tag" (const :value :tag) (string))
|
||||
(cons :tag "TODO keyword" (const :value :todo) (string))
|
||||
(cons :tag "Regular expression" (const :value :regexp) (regexp))
|
||||
(cons :tag "Level number" (const :value :level) (integer))
|
||||
(cons :tag "Max Level number" (const :value :maxlevel) (integer))))))
|
||||
|
||||
(defcustom org-refile-target-verify-function nil
|
||||
"Function to verify if the headline at point should be a refile target.
|
||||
The function will be called without arguments, with point at the
|
||||
beginning of the headline. It should return t and leave point
|
||||
where it is if the headline is a valid target for refiling.
|
||||
|
||||
If the target should not be selected, the function must return nil.
|
||||
In addition to this, it may move point to a place from where the search
|
||||
should be continued. For example, the function may decide that the entire
|
||||
subtree of the current entry should be excluded and move point to the end
|
||||
of the subtree."
|
||||
:group 'org-refile
|
||||
:type '(choice
|
||||
(const nil)
|
||||
(function)))
|
||||
|
||||
(defcustom org-refile-use-cache nil
|
||||
"Non-nil means cache refile targets to speed up the process.
|
||||
\\<org-mode-map>\
|
||||
The cache for a particular file will be updated automatically when
|
||||
the buffer has been killed, or when any of the marker used for flagging
|
||||
refile targets no longer points at a live buffer.
|
||||
If you have added new entries to a buffer that might themselves be targets,
|
||||
you need to clear the cache manually by pressing `C-0 \\[org-refile]' or,
|
||||
if you find that easier, \
|
||||
`\\[universal-argument] \\[universal-argument] \\[universal-argument] \
|
||||
\\[org-refile]'."
|
||||
:group 'org-refile
|
||||
:version "24.1"
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom org-refile-use-outline-path nil
|
||||
"Non-nil means provide refile targets as paths.
|
||||
So a level 3 headline will be available as level1/level2/level3.
|
||||
|
||||
When the value is `file', also include the file name (without directory)
|
||||
into the path. In this case, you can also stop the completion after
|
||||
the file name, to get entries inserted as top level in the file.
|
||||
|
||||
When `full-file-path', include the full file path.
|
||||
|
||||
When `buffer-name', use the buffer name."
|
||||
:group 'org-refile
|
||||
:type '(choice
|
||||
(const :tag "Not" nil)
|
||||
(const :tag "Yes" t)
|
||||
(const :tag "Start with file name" file)
|
||||
(const :tag "Start with full file path" full-file-path)
|
||||
(const :tag "Start with buffer name" buffer-name)))
|
||||
|
||||
(defcustom org-outline-path-complete-in-steps t
|
||||
"Non-nil means complete the outline path in hierarchical steps.
|
||||
When Org uses the refile interface to select an outline path (see
|
||||
`org-refile-use-outline-path'), the completion of the path can be
|
||||
done in a single go, or it can be done in steps down the headline
|
||||
hierarchy. Going in steps is probably the best if you do not use
|
||||
a special completion package like `ido' or `icicles'. However,
|
||||
when using these packages, going in one step can be very fast,
|
||||
while still showing the whole path to the entry."
|
||||
:group 'org-refile
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom org-refile-allow-creating-parent-nodes nil
|
||||
"Non-nil means allow the creation of new nodes as refile targets.
|
||||
New nodes are then created by adding \"/new node name\" to the completion
|
||||
of an existing node. When the value of this variable is `confirm',
|
||||
new node creation must be confirmed by the user (recommended).
|
||||
When nil, the completion must match an existing entry.
|
||||
|
||||
Note that, if the new heading is not seen by the criteria
|
||||
listed in `org-refile-targets', multiple instances of the same
|
||||
heading would be created by trying again to file under the new
|
||||
heading."
|
||||
:group 'org-refile
|
||||
:type '(choice
|
||||
(const :tag "Never" nil)
|
||||
(const :tag "Always" t)
|
||||
(const :tag "Prompt for confirmation" confirm)))
|
||||
|
||||
(defcustom org-refile-active-region-within-subtree nil
|
||||
"Non-nil means also refile active region within a subtree.
|
||||
|
||||
By default `org-refile' doesn't allow refiling regions if they
|
||||
don't contain a set of subtrees, but it might be convenient to
|
||||
do so sometimes: in that case, the first line of the region is
|
||||
converted to a headline before refiling."
|
||||
:group 'org-refile
|
||||
:version "24.1"
|
||||
:type 'boolean)
|
||||
|
||||
(defvar org-refile-target-table nil
|
||||
"The list of refile targets, created by `org-refile'.")
|
||||
|
||||
(defvar org-refile-cache nil
|
||||
"Cache for refile targets.")
|
||||
|
||||
(defvar org-refile-markers nil
|
||||
"All the markers used for caching refile locations.")
|
||||
|
||||
;; Add org refile commands to the main org menu
|
||||
(mapc (lambda (i) (easy-menu-add-item
|
||||
org-org-menu
|
||||
'("Edit Structure") i))
|
||||
'(["Refile Subtree" org-refile (org-in-subtree-not-table-p)]
|
||||
["Refile and copy Subtree" org-copy (org-in-subtree-not-table-p)]))
|
||||
|
||||
(defun org-refile-marker (pos)
|
||||
"Get a new refile marker, but only if caching is in use."
|
||||
(if (not org-refile-use-cache)
|
||||
pos
|
||||
(let ((m (make-marker)))
|
||||
(move-marker m pos)
|
||||
(push m org-refile-markers)
|
||||
m)))
|
||||
|
||||
(defun org-refile-cache-clear ()
|
||||
"Clear the refile cache and disable all the markers."
|
||||
(dolist (m org-refile-markers) (move-marker m nil))
|
||||
(setq org-refile-markers nil)
|
||||
(setq org-refile-cache nil)
|
||||
(message "Refile cache has been cleared"))
|
||||
|
||||
(defun org-refile-cache-check-set (set)
|
||||
"Check if all the markers in the cache still have live buffers."
|
||||
(let (marker)
|
||||
(catch 'exit
|
||||
(while (and set (setq marker (nth 3 (pop set))))
|
||||
;; If `org-refile-use-outline-path' is 'file, marker may be nil
|
||||
(when (and marker (null (marker-buffer marker)))
|
||||
(message "Please regenerate the refile cache with `C-0 C-c C-w'")
|
||||
(sit-for 3)
|
||||
(throw 'exit nil)))
|
||||
t)))
|
||||
|
||||
(defun org-refile-cache-put (set &rest identifiers)
|
||||
"Push the refile targets SET into the cache, under IDENTIFIERS."
|
||||
(let* ((key (sha1 (prin1-to-string identifiers)))
|
||||
(entry (assoc key org-refile-cache)))
|
||||
(if entry
|
||||
(setcdr entry set)
|
||||
(push (cons key set) org-refile-cache))))
|
||||
|
||||
(defun org-refile-cache-get (&rest identifiers)
|
||||
"Retrieve the cached value for refile targets given by IDENTIFIERS."
|
||||
(cond
|
||||
((not org-refile-cache) nil)
|
||||
((not org-refile-use-cache) (org-refile-cache-clear) nil)
|
||||
(t
|
||||
(let ((set (cdr (assoc (sha1 (prin1-to-string identifiers))
|
||||
org-refile-cache))))
|
||||
(and set (org-refile-cache-check-set set) set)))))
|
||||
|
||||
(defun org-refile-get-targets (&optional default-buffer)
|
||||
"Produce a table with refile targets."
|
||||
(let ((case-fold-search nil)
|
||||
;; otherwise org confuses "TODO" as a kw and "Todo" as a word
|
||||
(entries (or org-refile-targets '((nil . (:level . 1)))))
|
||||
targets tgs files desc descre)
|
||||
(message "Getting targets...")
|
||||
(with-current-buffer (or default-buffer (current-buffer))
|
||||
(dolist (entry entries)
|
||||
(setq files (car entry) desc (cdr entry))
|
||||
(cond
|
||||
((null files) (setq files (list (current-buffer))))
|
||||
((eq files 'org-agenda-files)
|
||||
(setq files (org-agenda-files 'unrestricted)))
|
||||
((and (symbolp files) (fboundp files))
|
||||
(setq files (funcall files)))
|
||||
((and (symbolp files) (boundp files))
|
||||
(setq files (symbol-value files))))
|
||||
(when (stringp files) (setq files (list files)))
|
||||
(cond
|
||||
((eq (car desc) :tag)
|
||||
(setq descre (concat "^\\*+[ \t]+.*?:" (regexp-quote (cdr desc)) ":")))
|
||||
((eq (car desc) :todo)
|
||||
(setq descre (concat "^\\*+[ \t]+" (regexp-quote (cdr desc)) "[ \t]")))
|
||||
((eq (car desc) :regexp)
|
||||
(setq descre (cdr desc)))
|
||||
((eq (car desc) :level)
|
||||
(setq descre (concat "^\\*\\{" (number-to-string
|
||||
(if org-odd-levels-only
|
||||
(1- (* 2 (cdr desc)))
|
||||
(cdr desc)))
|
||||
"\\}[ \t]")))
|
||||
((eq (car desc) :maxlevel)
|
||||
(setq descre (concat "^\\*\\{1," (number-to-string
|
||||
(if org-odd-levels-only
|
||||
(1- (* 2 (cdr desc)))
|
||||
(cdr desc)))
|
||||
"\\}[ \t]")))
|
||||
(t (error "Bad refiling target description %s" desc)))
|
||||
(dolist (f files)
|
||||
(with-current-buffer (if (bufferp f) f (org-get-agenda-file-buffer f))
|
||||
(or
|
||||
(setq tgs (org-refile-cache-get (buffer-file-name) descre))
|
||||
(progn
|
||||
(when (bufferp f)
|
||||
(setq f (buffer-file-name (buffer-base-buffer f))))
|
||||
(setq f (and f (expand-file-name f)))
|
||||
(when (eq org-refile-use-outline-path 'file)
|
||||
(push (list (file-name-nondirectory f) f nil nil) tgs))
|
||||
(when (eq org-refile-use-outline-path 'buffer-name)
|
||||
(push (list (buffer-name (buffer-base-buffer)) f nil nil) tgs))
|
||||
(when (eq org-refile-use-outline-path 'full-file-path)
|
||||
(push (list (file-truename (buffer-file-name (buffer-base-buffer))) f nil nil) tgs))
|
||||
(org-with-wide-buffer
|
||||
(goto-char (point-min))
|
||||
(setq org-outline-path-cache nil)
|
||||
(while (re-search-forward descre nil t)
|
||||
(beginning-of-line)
|
||||
(let ((case-fold-search nil))
|
||||
(looking-at org-complex-heading-regexp))
|
||||
(let ((begin (point))
|
||||
(heading (match-string-no-properties 4)))
|
||||
(unless (or (and
|
||||
org-refile-target-verify-function
|
||||
(not
|
||||
(funcall org-refile-target-verify-function)))
|
||||
(not heading))
|
||||
(let ((re (format org-complex-heading-regexp-format
|
||||
(regexp-quote heading)))
|
||||
(target
|
||||
(if (not org-refile-use-outline-path) heading
|
||||
(mapconcat
|
||||
#'identity
|
||||
(append
|
||||
(pcase org-refile-use-outline-path
|
||||
(`file (list (file-name-nondirectory
|
||||
(buffer-file-name
|
||||
(buffer-base-buffer)))))
|
||||
(`full-file-path
|
||||
(list (buffer-file-name
|
||||
(buffer-base-buffer))))
|
||||
(`buffer-name
|
||||
(list (buffer-name
|
||||
(buffer-base-buffer))))
|
||||
(_ nil))
|
||||
(mapcar (lambda (s) (replace-regexp-in-string
|
||||
"/" "\\/" s nil t))
|
||||
(org-get-outline-path t t)))
|
||||
"/"))))
|
||||
(push (list target f re (org-refile-marker (point)))
|
||||
tgs)))
|
||||
(when (= (point) begin)
|
||||
;; Verification function has not moved point.
|
||||
(end-of-line)))))))
|
||||
(when org-refile-use-cache
|
||||
(org-refile-cache-put tgs (buffer-file-name) descre))
|
||||
(setq targets (append tgs targets))))))
|
||||
(message "Getting targets...done")
|
||||
(delete-dups (nreverse targets))))
|
||||
|
||||
(defvar org-refile-history nil
|
||||
"History for refiling operations.")
|
||||
|
||||
(defvar org-after-refile-insert-hook nil
|
||||
"Hook run after `org-refile' has inserted its stuff at the new location.
|
||||
Note that this is still *before* the stuff will be removed from
|
||||
the *old* location.")
|
||||
|
||||
(defvar org-refile-keep nil
|
||||
"Non-nil means `org-refile' will copy instead of refile.")
|
||||
|
||||
(define-obsolete-function-alias 'org-copy 'org-refile-copy)
|
||||
|
||||
;;;###autoload
|
||||
(defun org-refile-copy ()
|
||||
"Like `org-refile', but preserve the refiled subtree."
|
||||
(interactive)
|
||||
(let ((org-refile-keep t))
|
||||
(org-refile nil nil nil "Copy")))
|
||||
|
||||
(defvar org-capture-last-stored-marker)
|
||||
|
||||
;;;###autoload
|
||||
(defun org-refile (&optional arg default-buffer rfloc msg)
|
||||
"Move the entry or entries at point to another heading.
|
||||
|
||||
The list of target headings is compiled using the information in
|
||||
`org-refile-targets', which see.
|
||||
|
||||
At the target location, the entry is filed as a subitem of the
|
||||
target heading. Depending on `org-reverse-note-order', the new
|
||||
subitem will either be the first or the last subitem.
|
||||
|
||||
If there is an active region, all entries in that region will be
|
||||
refiled. However, the region must fulfill the requirement that
|
||||
the first heading sets the top-level of the moved text.
|
||||
|
||||
With a `\\[universal-argument]' ARG, the command will only visit the target \
|
||||
location
|
||||
and not actually move anything.
|
||||
|
||||
With a prefix `\\[universal-argument] \\[universal-argument]', go to the \
|
||||
location where the last
|
||||
refiling operation has put the subtree.
|
||||
|
||||
With a numeric prefix argument of `2', refile to the running clock.
|
||||
|
||||
With a numeric prefix argument of `3', emulate `org-refile-keep'
|
||||
being set to t and copy to the target location, don't move it.
|
||||
Beware that keeping refiled entries may result in duplicated ID
|
||||
properties.
|
||||
|
||||
RFLOC can be a refile location obtained in a different way. It
|
||||
should be a list with the following 4 elements:
|
||||
|
||||
1. Name - an identifier for the refile location, typically the
|
||||
headline text
|
||||
2. File - the file the refile location is in
|
||||
3. nil - used for generating refile location candidates, not
|
||||
needed when passing RFLOC
|
||||
4. Position - the position in the specified file of the
|
||||
headline to refile under
|
||||
|
||||
MSG is a string to replace \"Refile\" in the default prompt with
|
||||
another verb. E.g. `org-copy' sets this parameter to \"Copy\".
|
||||
|
||||
See also `org-refile-use-outline-path'.
|
||||
|
||||
If you are using target caching (see `org-refile-use-cache'), you
|
||||
have to clear the target cache in order to find new targets.
|
||||
This can be done with a `0' prefix (`C-0 C-c C-w') or a triple
|
||||
prefix argument (`C-u C-u C-u C-c C-w')."
|
||||
(interactive "P")
|
||||
(if (member arg '(0 (64)))
|
||||
(org-refile-cache-clear)
|
||||
(let* ((actionmsg (cond (msg msg)
|
||||
((equal arg 3) "Refile (and keep)")
|
||||
(t "Refile")))
|
||||
(regionp (org-region-active-p))
|
||||
(region-start (and regionp (region-beginning)))
|
||||
(region-end (and regionp (region-end)))
|
||||
(org-refile-keep (if (equal arg 3) t org-refile-keep))
|
||||
pos it nbuf file level reversed)
|
||||
(setq last-command nil)
|
||||
(when regionp
|
||||
(goto-char region-start)
|
||||
(beginning-of-line)
|
||||
(setq region-start (point))
|
||||
(unless (or (org-kill-is-subtree-p
|
||||
(buffer-substring region-start region-end))
|
||||
(prog1 org-refile-active-region-within-subtree
|
||||
(let ((s (point-at-eol)))
|
||||
(org-toggle-heading)
|
||||
(setq region-end (+ (- (point-at-eol) s) region-end)))))
|
||||
(user-error "The region is not a (sequence of) subtree(s)")))
|
||||
(if (equal arg '(16))
|
||||
(org-refile-goto-last-stored)
|
||||
(when (or
|
||||
(and (equal arg 2)
|
||||
org-clock-hd-marker (marker-buffer org-clock-hd-marker)
|
||||
(prog1
|
||||
(setq it (list (or org-clock-heading "running clock")
|
||||
(buffer-file-name
|
||||
(marker-buffer org-clock-hd-marker))
|
||||
""
|
||||
(marker-position org-clock-hd-marker)))
|
||||
(setq arg nil)))
|
||||
(setq it
|
||||
(or rfloc
|
||||
(let (heading-text)
|
||||
(save-excursion
|
||||
(unless (and arg (listp arg))
|
||||
(org-back-to-heading t)
|
||||
(setq heading-text
|
||||
(replace-regexp-in-string
|
||||
org-link-bracket-re
|
||||
"\\2"
|
||||
(or (nth 4 (org-heading-components))
|
||||
""))))
|
||||
(org-refile-get-location
|
||||
(cond ((and arg (listp arg)) "Goto")
|
||||
(regionp (concat actionmsg " region to"))
|
||||
(t (concat actionmsg " subtree \""
|
||||
heading-text "\" to")))
|
||||
default-buffer
|
||||
(and (not (equal '(4) arg))
|
||||
org-refile-allow-creating-parent-nodes)))))))
|
||||
(setq file (nth 1 it)
|
||||
pos (nth 3 it))
|
||||
(when (and (not arg)
|
||||
pos
|
||||
(equal (buffer-file-name) file)
|
||||
(if regionp
|
||||
(and (>= pos region-start)
|
||||
(<= pos region-end))
|
||||
(and (>= pos (point))
|
||||
(< pos (save-excursion
|
||||
(org-end-of-subtree t t))))))
|
||||
(error "Cannot refile to position inside the tree or region"))
|
||||
(setq nbuf (or (find-buffer-visiting file)
|
||||
(find-file-noselect file)))
|
||||
(if (and arg (not (equal arg 3)))
|
||||
(progn
|
||||
(pop-to-buffer-same-window nbuf)
|
||||
(goto-char (cond (pos)
|
||||
((org-notes-order-reversed-p) (point-min))
|
||||
(t (point-max))))
|
||||
(org-show-context 'org-goto))
|
||||
(if regionp
|
||||
(progn
|
||||
(org-kill-new (buffer-substring region-start region-end))
|
||||
(org-save-markers-in-region region-start region-end))
|
||||
(org-copy-subtree 1 nil t))
|
||||
(with-current-buffer (setq nbuf (or (find-buffer-visiting file)
|
||||
(find-file-noselect file)))
|
||||
(setq reversed (org-notes-order-reversed-p))
|
||||
(org-with-wide-buffer
|
||||
(if pos
|
||||
(progn
|
||||
(goto-char pos)
|
||||
(setq level (org-get-valid-level (funcall outline-level) 1))
|
||||
(goto-char
|
||||
(if reversed
|
||||
(or (outline-next-heading) (point-max))
|
||||
(or (save-excursion (org-get-next-sibling))
|
||||
(org-end-of-subtree t t)
|
||||
(point-max)))))
|
||||
(setq level 1)
|
||||
(if (not reversed)
|
||||
(goto-char (point-max))
|
||||
(goto-char (point-min))
|
||||
(or (outline-next-heading) (goto-char (point-max)))))
|
||||
(unless (bolp) (newline))
|
||||
(org-paste-subtree level nil nil t)
|
||||
;; Record information, according to `org-log-refile'.
|
||||
;; Do not prompt for a note when refiling multiple
|
||||
;; headlines, however. Simply add a time stamp.
|
||||
(cond
|
||||
((not org-log-refile))
|
||||
(regionp
|
||||
(org-map-region
|
||||
(lambda () (org-add-log-setup 'refile nil nil 'time))
|
||||
(point)
|
||||
(+ (point) (- region-end region-start))))
|
||||
(t
|
||||
(org-add-log-setup 'refile nil nil org-log-refile)))
|
||||
(and org-auto-align-tags
|
||||
(let ((org-loop-over-headlines-in-active-region nil))
|
||||
(org-align-tags)))
|
||||
(let ((bookmark-name (plist-get org-bookmark-names-plist
|
||||
:last-refile)))
|
||||
(when bookmark-name
|
||||
(with-demoted-errors
|
||||
(bookmark-set bookmark-name))))
|
||||
;; If we are refiling for capture, make sure that the
|
||||
;; last-capture pointers point here
|
||||
(when (bound-and-true-p org-capture-is-refiling)
|
||||
(let ((bookmark-name (plist-get org-bookmark-names-plist
|
||||
:last-capture-marker)))
|
||||
(when bookmark-name
|
||||
(with-demoted-errors
|
||||
(bookmark-set bookmark-name))))
|
||||
(move-marker org-capture-last-stored-marker (point)))
|
||||
(when (fboundp 'deactivate-mark) (deactivate-mark))
|
||||
(run-hooks 'org-after-refile-insert-hook)))
|
||||
(unless org-refile-keep
|
||||
(if regionp
|
||||
(delete-region (point) (+ (point) (- region-end region-start)))
|
||||
(org-preserve-local-variables
|
||||
(delete-region
|
||||
(and (org-back-to-heading t) (point))
|
||||
(min (1+ (buffer-size)) (org-end-of-subtree t t) (point))))))
|
||||
(when (featurep 'org-inlinetask)
|
||||
(org-inlinetask-remove-END-maybe))
|
||||
(setq org-markers-to-move nil)
|
||||
(message "%s to \"%s\" in file %s: done" actionmsg
|
||||
(car it) file)))))))
|
||||
|
||||
(defun org-refile-goto-last-stored ()
|
||||
"Go to the location where the last refile was stored."
|
||||
(interactive)
|
||||
(bookmark-jump (plist-get org-bookmark-names-plist :last-refile))
|
||||
(message "This is the location of the last refile"))
|
||||
|
||||
(defun org-refile--get-location (refloc tbl)
|
||||
"When user refile to REFLOC, find the associated target in TBL.
|
||||
Also check `org-refile-target-table'."
|
||||
(car (delq
|
||||
nil
|
||||
(mapcar
|
||||
(lambda (r) (or (assoc r tbl)
|
||||
(assoc r org-refile-target-table)))
|
||||
(list (replace-regexp-in-string "/$" "" refloc)
|
||||
(replace-regexp-in-string "\\([^/]\\)$" "\\1/" refloc))))))
|
||||
|
||||
(defun org-refile-get-location (&optional prompt default-buffer new-nodes)
|
||||
"Prompt the user for a refile location, using PROMPT.
|
||||
PROMPT should not be suffixed with a colon and a space, because
|
||||
this function appends the default value from
|
||||
`org-refile-history' automatically, if that is not empty."
|
||||
(let ((org-refile-targets org-refile-targets)
|
||||
(org-refile-use-outline-path org-refile-use-outline-path))
|
||||
(setq org-refile-target-table (org-refile-get-targets default-buffer)))
|
||||
(unless org-refile-target-table
|
||||
(user-error "No refile targets"))
|
||||
(let* ((cbuf (current-buffer))
|
||||
(cfn (buffer-file-name (buffer-base-buffer cbuf)))
|
||||
(cfunc (if (and org-refile-use-outline-path
|
||||
org-outline-path-complete-in-steps)
|
||||
#'org-olpath-completing-read
|
||||
#'completing-read))
|
||||
(extra (if org-refile-use-outline-path "/" ""))
|
||||
(cbnex (concat (buffer-name) extra))
|
||||
(filename (and cfn (expand-file-name cfn)))
|
||||
(tbl (mapcar
|
||||
(lambda (x)
|
||||
(if (and (not (member org-refile-use-outline-path
|
||||
'(file full-file-path)))
|
||||
(not (equal filename (nth 1 x))))
|
||||
(cons (concat (car x) extra " ("
|
||||
(file-name-nondirectory (nth 1 x)) ")")
|
||||
(cdr x))
|
||||
(cons (concat (car x) extra) (cdr x))))
|
||||
org-refile-target-table))
|
||||
(completion-ignore-case t)
|
||||
cdef
|
||||
(prompt (concat prompt
|
||||
(or (and (car org-refile-history)
|
||||
(concat " (default " (car org-refile-history) ")"))
|
||||
(and (assoc cbnex tbl) (setq cdef cbnex)
|
||||
(concat " (default " cbnex ")"))) ": "))
|
||||
pa answ parent-target child parent old-hist)
|
||||
(setq old-hist org-refile-history)
|
||||
(setq answ (funcall cfunc prompt tbl nil (not new-nodes)
|
||||
nil 'org-refile-history
|
||||
(or cdef (concat (car org-refile-history) extra))))
|
||||
(if (setq pa (org-refile--get-location answ tbl))
|
||||
(let* ((last-refile-loc (car org-refile-history))
|
||||
(last-refile-loc-path (concat last-refile-loc extra)))
|
||||
(org-refile-check-position pa)
|
||||
(when (or (not org-refile-history)
|
||||
(not (eq old-hist org-refile-history))
|
||||
(not (equal (car pa) last-refile-loc-path)))
|
||||
(setq org-refile-history
|
||||
(cons (car pa) (if (assoc last-refile-loc tbl)
|
||||
org-refile-history
|
||||
(cdr org-refile-history))))
|
||||
(when (or (equal last-refile-loc-path (nth 1 org-refile-history))
|
||||
(equal last-refile-loc (nth 1 org-refile-history)))
|
||||
(pop org-refile-history)))
|
||||
pa)
|
||||
(if (string-match "\\`\\(.*\\)/\\([^/]+\\)\\'" answ)
|
||||
(progn
|
||||
(setq parent (match-string 1 answ)
|
||||
child (match-string 2 answ))
|
||||
(setq parent-target (org-refile--get-location parent tbl))
|
||||
(when (and parent-target
|
||||
(or (eq new-nodes t)
|
||||
(and (eq new-nodes 'confirm)
|
||||
(y-or-n-p (format "Create new node \"%s\"? "
|
||||
child)))))
|
||||
(org-refile-new-child parent-target child)))
|
||||
(user-error "Invalid target location")))))
|
||||
|
||||
(defun org-refile-check-position (refile-pointer)
|
||||
"Check if the refile pointer matches the headline to which it points."
|
||||
(let* ((file (nth 1 refile-pointer))
|
||||
(re (nth 2 refile-pointer))
|
||||
(pos (nth 3 refile-pointer))
|
||||
buffer)
|
||||
(if (and (not (markerp pos)) (not file))
|
||||
(user-error "Please indicate a target file in the refile path")
|
||||
(when (org-string-nw-p re)
|
||||
(setq buffer (if (markerp pos)
|
||||
(marker-buffer pos)
|
||||
(or (find-buffer-visiting file)
|
||||
(find-file-noselect file))))
|
||||
(with-current-buffer buffer
|
||||
(org-with-wide-buffer
|
||||
(goto-char pos)
|
||||
(beginning-of-line 1)
|
||||
(unless (looking-at-p re)
|
||||
(user-error "Invalid refile position, please clear the cache with `C-0 C-c C-w' before refiling"))))))))
|
||||
|
||||
(defun org-refile-new-child (parent-target child)
|
||||
"Use refile target PARENT-TARGET to add new CHILD below it."
|
||||
(unless parent-target
|
||||
(error "Cannot find parent for new node"))
|
||||
(let ((file (nth 1 parent-target))
|
||||
(pos (nth 3 parent-target))
|
||||
level)
|
||||
(with-current-buffer (or (find-buffer-visiting file)
|
||||
(find-file-noselect file))
|
||||
(org-with-wide-buffer
|
||||
(if pos
|
||||
(goto-char pos)
|
||||
(goto-char (point-max))
|
||||
(unless (bolp) (newline)))
|
||||
(when (looking-at org-outline-regexp)
|
||||
(setq level (funcall outline-level))
|
||||
(org-end-of-subtree t t))
|
||||
(org-back-over-empty-lines)
|
||||
(insert "\n" (make-string
|
||||
(if pos (org-get-valid-level level 1) 1) ?*)
|
||||
" " child "\n")
|
||||
(beginning-of-line 0)
|
||||
(list (concat (car parent-target) "/" child) file "" (point))))))
|
||||
|
||||
(defun org-olpath-completing-read (prompt collection &rest args)
|
||||
"Read an outline path like a file name."
|
||||
(let ((thetable collection))
|
||||
(apply #'completing-read
|
||||
prompt
|
||||
(lambda (string predicate &optional flag)
|
||||
(cond
|
||||
((eq flag nil) (try-completion string thetable))
|
||||
((eq flag t)
|
||||
(let ((l (length string)))
|
||||
(mapcar (lambda (x)
|
||||
(let ((r (substring x l))
|
||||
(f (if (string-match " ([^)]*)$" x)
|
||||
(match-string 0 x)
|
||||
"")))
|
||||
(if (string-match "/" r)
|
||||
(concat string (substring r 0 (match-end 0)) f)
|
||||
x)))
|
||||
(all-completions string thetable predicate))))
|
||||
;; Exact match?
|
||||
((eq flag 'lambda) (assoc string thetable))))
|
||||
args)))
|
||||
|
||||
(provide 'org-refile)
|
||||
|
||||
;; Local variables:
|
||||
;; generated-autoload-file: "org-loaddefs.el"
|
||||
;; End:
|
||||
|
||||
;;; org-refile.el ends here
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue